about summary refs log tree commit diff stats
path: root/baremetal
diff options
context:
space:
mode:
Diffstat (limited to 'baremetal')
-rw-r--r--baremetal/shell/eval.mu95
1 files changed, 93 insertions, 2 deletions
diff --git a/baremetal/shell/eval.mu b/baremetal/shell/eval.mu
index 1d9e084a..d3525a0f 100644
--- a/baremetal/shell/eval.mu
+++ b/baremetal/shell/eval.mu
@@ -196,6 +196,18 @@ fn evaluate _in: (addr line), end: (addr word), out: (addr value-stack) {
         }
         break $evaluate:process-word
       }
+      {
+        var is-group-start?/eax: boolean <- stream-data-equal? curr-stream, "break"
+        compare is-group-start?, 0/false
+        break-if-=
+        # scan ahead to containing '}'
+        var next-word: (handle word)
+        var next-word-ah/eax: (addr handle word) <- address next-word
+        skip-rest-of-group curr, end, next-word-ah
+        var _curr/eax: (addr word) <- lookup *next-word-ah
+        curr <- copy _curr
+        loop $evaluate:loop
+      }
       ## TEMPORARY HACKS; we're trying to avoid turning this into Forth
       {
         var is-dup?/eax: boolean <- stream-data-equal? curr-stream, "dup"
@@ -333,7 +345,7 @@ fn skip-word _curr: (addr word), end: (addr word), out: (addr handle word) {
   var curr/eax: (addr word) <- copy _curr
   var bracket-count/ecx: int <- copy 0
   var result-ah/esi: (addr handle word) <- get curr, next
-  $skip-word:loop: {
+  {
     var result-val/eax: (addr word) <- lookup *result-ah
     compare result-val, end
     break-if-=
@@ -355,7 +367,35 @@ fn skip-word _curr: (addr word), end: (addr word), out: (addr handle word) {
       }
     }
     compare bracket-count, 0
-    break-if-= $skip-word:loop
+    break-if-=
+    result-ah <- get result-val, next
+    loop
+  }
+  copy-object result-ah, out
+}
+
+fn skip-rest-of-group _curr: (addr word), end: (addr word), out: (addr handle word) {
+  var curr/eax: (addr word) <- copy _curr
+  var bracket-count/ecx: int <- copy 0
+  var result-ah/esi: (addr handle word) <- get curr, next
+  $skip-rest-of-group:loop: {
+    var result-val/eax: (addr word) <- lookup *result-ah
+    compare result-val, end
+    break-if-=
+    {
+      var open?/eax: boolean <- word-equal? result-val, "{"
+      compare open?, 0/false
+      break-if-=
+      bracket-count <- increment
+    }
+    {
+      var close?/eax: boolean <- word-equal? result-val, "}"
+      compare close?, 0/false
+      break-if-=
+      compare bracket-count, 0
+      break-if-= $skip-rest-of-group:loop
+      bracket-count <- decrement
+    }
     result-ah <- get result-val, next
     loop
   }
@@ -677,3 +717,54 @@ fn test-eval-conditional-skips-nested-group {
 
 # TODO: test error-handling on:
 #   1 2 > -> }
+
+# break skips to next `}`
+fn test-eval-break {
+  # in
+  var in-storage: line
+  var in/esi: (addr line) <- address in-storage
+  parse-line "3 { 4 break 5 } +", in
+  # end
+  var w-ah/eax: (addr handle word) <- get in, data
+  var end-h: (handle word)
+  var end-ah/ecx: (addr handle word) <- address end-h
+  final-word w-ah, end-ah
+  var end/eax: (addr word) <- lookup *end-ah
+  # out
+  var out-storage: value-stack
+  var out/edi: (addr value-stack) <- address out-storage
+  initialize-value-stack out, 8
+  #
+  evaluate in, end, out
+  # result is 3+4, not 4+5
+  var len/eax: int <- value-stack-length out
+  check-ints-equal len, 1, "F - test-eval-break stack size"
+  var n/xmm0: float <- pop-number-from-value-stack out
+  var n2/eax: int <- convert n
+  check-ints-equal n2, 7, "F - test-eval-break result"
+}
+
+fn test-eval-break-nested {
+  # in
+  var in-storage: line
+  var in/esi: (addr line) <- address in-storage
+  parse-line "3 { 4 break { 5 } 6 } +", in
+  # end
+  var w-ah/eax: (addr handle word) <- get in, data
+  var end-h: (handle word)
+  var end-ah/ecx: (addr handle word) <- address end-h
+  final-word w-ah, end-ah
+  var end/eax: (addr word) <- lookup *end-ah
+  # out
+  var out-storage: value-stack
+  var out/edi: (addr value-stack) <- address out-storage
+  initialize-value-stack out, 8
+  #
+  evaluate in, end, out
+  # result is 3+4, skipping remaining numbers
+  var len/eax: int <- value-stack-length out
+  check-ints-equal len, 1, "F - test-eval-break-nested stack size"
+  var n/xmm0: float <- pop-number-from-value-stack out
+  var n2/eax: int <- convert n
+  check-ints-equal n2, 7, "F - test-eval-break-nested result"
+}