about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-06-06 12:39:03 -0700
committerKartik K. Agaram <vc@akkartik.com>2021-06-06 12:39:03 -0700
commit8014210316809c9d59adc015ecc181337b42cf19 (patch)
treecec2c2a98bc5f4277ce8aa63b30774e7bfc7e29b
parent3bdf3b1a7f146998078975e2f7c1d5e887f84e9f (diff)
downloadmu-8014210316809c9d59adc015ecc181337b42cf19.tar.gz
shell: support negative integer literals
We still don't support _any_ fractional literals, positive or negative.
-rw-r--r--shell/gap-buffer.mu19
-rw-r--r--shell/sandbox.mu18
-rw-r--r--shell/tokenize.mu97
3 files changed, 133 insertions, 1 deletions
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
 }