From 8014210316809c9d59adc015ecc181337b42cf19 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sun, 6 Jun 2021 12:39:03 -0700 Subject: [PATCH] shell: support negative integer literals We still don't support _any_ fractional literals, positive or negative. --- shell/gap-buffer.mu | 19 +++++++++ shell/sandbox.mu | 18 +++++++++ shell/tokenize.mu | 97 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 133 insertions(+), 1 deletion(-) diff --git a/shell/gap-buffer.mu b/shell/gap-buffer.mu index 409089cf..88285a43 100644 --- a/shell/gap-buffer.mu +++ b/shell/gap-buffer.mu @@ -1115,6 +1115,25 @@ fn read-from-gap-buffer _self: (addr gap-buffer) -> _/eax: grapheme { return 0/nul } +fn put-back-from-gap-buffer _self: (addr gap-buffer) { + var self/esi: (addr gap-buffer) <- copy _self + # more in right? + var right/eax: (addr grapheme-stack) <- get self, right + var right-size/eax: int <- grapheme-stack-length right + var right-read-index-a/eax: (addr int) <- get self, right-read-index + compare *right-read-index-a, 0 + { + break-if-<= + decrement *right-read-index-a + return + } + # more in left? + var left/eax: (addr grapheme-stack) <- get self, left + var left-size/eax: int <- grapheme-stack-length left + var left-read-index-a/eax: (addr int) <- get self, left-read-index + decrement *left-read-index-a +} + fn test-read-from-gap-buffer { var gap-storage: gap-buffer var gap/esi: (addr gap-buffer) <- address gap-storage diff --git a/shell/sandbox.mu b/shell/sandbox.mu index 0aad5b44..67b89e75 100644 --- a/shell/sandbox.mu +++ b/shell/sandbox.mu @@ -740,6 +740,24 @@ fn test-run-integer { check-screen-row screen, 3/y, " => 1 ", "F - test-run-integer/2" } +fn test-run-negative-integer { + var sandbox-storage: sandbox + var sandbox/esi: (addr sandbox) <- address sandbox-storage + initialize-sandbox-with sandbox, "-1" + # eval + edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-tweak-screen + # setup: screen + var screen-on-stack: screen + var screen/edi: (addr screen) <- address screen-on-stack + initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics + # + render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor + # skip one line of padding + check-screen-row screen, 1/y, " -1 ", "F - test-run-negative-integer/0" + check-screen-row screen, 2/y, " ... ", "F - test-run-negative-integer/1" + check-screen-row screen, 3/y, " => -1 ", "F - test-run-negative-integer/2" +} + fn test-run-error-invalid-integer { var sandbox-storage: sandbox var sandbox/esi: (addr sandbox) <- address sandbox-storage diff --git a/shell/tokenize.mu b/shell/tokenize.mu index 03695c09..583dda89 100644 --- a/shell/tokenize.mu +++ b/shell/tokenize.mu @@ -30,6 +30,75 @@ fn tokenize in: (addr gap-buffer), out: (addr stream cell), trace: (addr trace) trace-higher trace } +fn test-tokenize-number { + var in-storage: gap-buffer + var in/esi: (addr gap-buffer) <- address in-storage + initialize-gap-buffer-with in, "123 a" + # + var stream-storage: (stream cell 0x10) + var stream/edi: (addr stream cell) <- address stream-storage + # + var trace-storage: trace + var trace/edx: (addr trace) <- address trace-storage + initialize-trace trace, 1/only-errors, 0x10/capacity, 0/visible + tokenize in, stream, trace + # + var curr-token-storage: cell + var curr-token/ebx: (addr cell) <- address curr-token-storage + read-from-stream stream, curr-token + var number?/eax: boolean <- number-token? curr-token + check number?, "F - test-tokenize-number" + var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data + var curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah + check-stream-equal curr-token-data, "123", "F - test-tokenize-number: value" +} + +fn test-tokenize-negative-number { + var in-storage: gap-buffer + var in/esi: (addr gap-buffer) <- address in-storage + initialize-gap-buffer-with in, "-123 a" + # + var stream-storage: (stream cell 0x10) + var stream/edi: (addr stream cell) <- address stream-storage + # + var trace-storage: trace + var trace/edx: (addr trace) <- address trace-storage + initialize-trace trace, 1/only-errors, 0x10/capacity, 0/visible + tokenize in, stream, trace + # + var curr-token-storage: cell + var curr-token/ebx: (addr cell) <- address curr-token-storage + read-from-stream stream, curr-token + var number?/eax: boolean <- number-token? curr-token + check number?, "F - test-tokenize-negative-number" + var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data + var curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah + check-stream-equal curr-token-data, "-123", "F - test-tokenize-negative-number: value" +} + +fn test-tokenize-number-followed-by-hyphen { + var in-storage: gap-buffer + var in/esi: (addr gap-buffer) <- address in-storage + initialize-gap-buffer-with in, "123-4 a" + # + var stream-storage: (stream cell 0x10) + var stream/edi: (addr stream cell) <- address stream-storage + # + var trace-storage: trace + var trace/edx: (addr trace) <- address trace-storage + initialize-trace trace, 1/only-errors, 0x10/capacity, 0/visible + tokenize in, stream, trace + # + var curr-token-storage: cell + var curr-token/ebx: (addr cell) <- address curr-token-storage + read-from-stream stream, curr-token + var number?/eax: boolean <- number-token? curr-token + check number?, "F - test-tokenize-number-followed-by-hyphen" + var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data + var curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah + check-stream-equal curr-token-data, "123", "F - test-tokenize-number-followed-by-hyphen: value" +} + fn test-tokenize-quote { var in-storage: gap-buffer var in/esi: (addr gap-buffer) <- address in-storage @@ -273,6 +342,19 @@ fn next-token in: (addr gap-buffer), _out-cell: (addr cell), trace: (addr trace) rest-of-line in, out, trace break $next-token:case } + # special-case: '-' + { + compare g, 0x2d/minus + break-if-!= + var dummy/eax: grapheme <- read-from-gap-buffer in # skip '-' + var g2/eax: grapheme <- peek-from-gap-buffer in + put-back-from-gap-buffer in + var digit?/eax: boolean <- decimal-digit? g2 + compare digit?, 0/false + break-if-= + next-number-token in, out, trace + break $next-token:case + } # digit { var digit?/eax: boolean <- decimal-digit? g @@ -458,6 +540,12 @@ fn next-operator-token in: (addr gap-buffer), out: (addr stream byte), trace: (a fn next-number-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { trace-text trace, "tokenize", "looking for a number" trace-lower trace + $next-number-token:check-minus: { + var g/eax: grapheme <- peek-from-gap-buffer in + compare g, 0x2d/minus + g <- read-from-gap-buffer in # consume + write-grapheme out, g + } $next-number-token:loop: { var done?/eax: boolean <- gap-buffer-scan-done? in compare done?, 0/false @@ -889,9 +977,16 @@ fn operator-grapheme? g: grapheme -> _/eax: boolean { fn number-token? _in: (addr cell) -> _/eax: boolean { var in/eax: (addr cell) <- copy _in var in-data-ah/eax: (addr handle stream byte) <- get in, text-data - var in-data/eax: (addr stream byte) <- lookup *in-data-ah + var _in-data/eax: (addr stream byte) <- lookup *in-data-ah + var in-data/ecx: (addr stream byte) <- copy _in-data rewind-stream in-data var g/eax: grapheme <- read-grapheme in-data + # if '-', read another + { + compare g, 0x2d/minus + break-if-!= + g <- read-grapheme in-data + } var result/eax: boolean <- decimal-digit? g return result }