about summary refs log tree commit diff stats
path: root/baremetal/shell
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-02-12 23:18:33 -0800
committerKartik K. Agaram <vc@akkartik.com>2021-02-12 23:49:00 -0800
commit378ffca74c7a1428431da5d4572b70731d41074d (patch)
treebea0d3e0571d5350ab928e66de656b2ff2a49f4b /baremetal/shell
parent97a77434c5950d7a491f77ec2543fcad3157c460 (diff)
downloadmu-378ffca74c7a1428431da5d4572b70731d41074d.tar.gz
7730 - baremetal/shell: boolean values
In the process I found a bug in the Mu compiler. Limitations of just asserting
the emitted code but not running it.
Diffstat (limited to 'baremetal/shell')
-rw-r--r--baremetal/shell/eval.mu158
-rw-r--r--baremetal/shell/value-stack.mu49
-rw-r--r--baremetal/shell/value.mu29
3 files changed, 226 insertions, 10 deletions
diff --git a/baremetal/shell/eval.mu b/baremetal/shell/eval.mu
index ad077129..d9b45b28 100644
--- a/baremetal/shell/eval.mu
+++ b/baremetal/shell/eval.mu
@@ -54,7 +54,7 @@ fn evaluate _in: (addr line), end: (addr word), out: (addr value-stack) {
       ### if curr-stream is an operator, perform it
       {
         var is-add?/eax: boolean <- stream-data-equal? curr-stream, "+"
-        compare is-add?, 0
+        compare is-add?, 0/false
         break-if-=
         var _b/xmm0: float <- pop-number-from-value-stack out
         var b/xmm1: float <- copy _b
@@ -65,7 +65,7 @@ fn evaluate _in: (addr line), end: (addr word), out: (addr value-stack) {
       }
       {
         var is-sub?/eax: boolean <- stream-data-equal? curr-stream, "-"
-        compare is-sub?, 0
+        compare is-sub?, 0/false
         break-if-=
         var _b/xmm0: float <- pop-number-from-value-stack out
         var b/xmm1: float <- copy _b
@@ -76,7 +76,7 @@ fn evaluate _in: (addr line), end: (addr word), out: (addr value-stack) {
       }
       {
         var is-mul?/eax: boolean <- stream-data-equal? curr-stream, "*"
-        compare is-mul?, 0
+        compare is-mul?, 0/false
         break-if-=
         var _b/xmm0: float <- pop-number-from-value-stack out
         var b/xmm1: float <- copy _b
@@ -87,7 +87,7 @@ fn evaluate _in: (addr line), end: (addr word), out: (addr value-stack) {
       }
       {
         var is-div?/eax: boolean <- stream-data-equal? curr-stream, "/"
-        compare is-div?, 0
+        compare is-div?, 0/false
         break-if-=
         var _b/xmm0: float <- pop-number-from-value-stack out
         var b/xmm1: float <- copy _b
@@ -98,17 +98,65 @@ fn evaluate _in: (addr line), end: (addr word), out: (addr value-stack) {
       }
       {
         var is-sqrt?/eax: boolean <- stream-data-equal? curr-stream, "sqrt"
-        compare is-sqrt?, 0
+        compare is-sqrt?, 0/false
         break-if-=
         var a/xmm0: float <- pop-number-from-value-stack out
         a <- square-root a
         push-number-to-value-stack out, a
         break $evaluate:process-word
       }
+      {
+        var is-lesser?/eax: boolean <- stream-data-equal? curr-stream, "<"
+        compare is-lesser?, 0/false
+        break-if-=
+        var _b/xmm0: float <- pop-number-from-value-stack out
+        var b/xmm1: float <- copy _b
+        var a/xmm0: float <- pop-number-from-value-stack out
+        compare a, b
+        {
+          break-if-float<
+          push-boolean-to-value-stack out, 0/false
+          break $evaluate:process-word
+        }
+        push-boolean-to-value-stack out, 1/true
+        break $evaluate:process-word
+      }
+      {
+        var is-greater?/eax: boolean <- stream-data-equal? curr-stream, ">"
+        compare is-greater?, 0/false
+        break-if-=
+        var _b/xmm0: float <- pop-number-from-value-stack out
+        var b/xmm1: float <- copy _b
+        var a/xmm0: float <- pop-number-from-value-stack out
+        compare a, b
+        {
+          break-if-float>
+          push-boolean-to-value-stack out, 0/false
+          break $evaluate:process-word
+        }
+        push-boolean-to-value-stack out, 1/true
+        break $evaluate:process-word
+      }
+      {
+        var is-equal?/eax: boolean <- stream-data-equal? curr-stream, "=="  # TODO support non-numbers
+        compare is-equal?, 0/false
+        break-if-=
+        var _b/xmm0: float <- pop-number-from-value-stack out
+        var b/xmm1: float <- copy _b
+        var a/xmm0: float <- pop-number-from-value-stack out
+        compare a, b
+        {
+          break-if-=
+          push-boolean-to-value-stack out, 0/false
+          break $evaluate:process-word
+        }
+        push-boolean-to-value-stack out, 1/true
+        break $evaluate:process-word
+      }
       ## HACKS: we're trying to avoid turning this into Forth
       {
         var is-dup?/eax: boolean <- stream-data-equal? curr-stream, "dup"
-        compare is-dup?, 0
+        compare is-dup?, 0/false
         break-if-=
         # read src-val from out
         var out2/esi: (addr value-stack) <- copy out
@@ -133,7 +181,7 @@ fn evaluate _in: (addr line), end: (addr word), out: (addr value-stack) {
       }
       {
         var is-swap?/eax: boolean <- stream-data-equal? curr-stream, "swap"
-        compare is-swap?, 0
+        compare is-swap?, 0/false
         break-if-=
         # read top-val from out
         var out2/esi: (addr value-stack) <- copy out
@@ -291,3 +339,99 @@ fn test-eval-string {
   var text/eax: (addr array byte) <- lookup *text-ah
   check-strings-equal text, "abc", "F - test-eval-string result"
 }
+
+fn test-eval-compare-lesser {
+  # in
+  var in-storage: line
+  var in/esi: (addr line) <- address in-storage
+  parse-line "1 2 <", 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
+  #
+  var len/eax: int <- value-stack-length out
+  check-ints-equal len, 1, "F - test-eval-compare-lesser stack size"
+  var result/eax: boolean <- pop-boolean-from-value-stack out
+  check result, "F - test-eval-compare-lesser result"
+}
+
+fn test-eval-compare-greater {
+  # in
+  var in-storage: line
+  var in/esi: (addr line) <- address in-storage
+  parse-line "2 1 >", 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
+  #
+  var len/eax: int <- value-stack-length out
+  check-ints-equal len, 1, "F - test-eval-compare-greater stack size"
+  var result/eax: boolean <- pop-boolean-from-value-stack out
+  check result, "F - test-eval-compare-greater result"
+}
+
+fn test-eval-compare-equal-fails {
+  # in
+  var in-storage: line
+  var in/esi: (addr line) <- address in-storage
+  parse-line "1 2 ==", 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
+  #
+  var len/eax: int <- value-stack-length out
+  check-ints-equal len, 1, "F - test-eval-compare-equal-fails stack size"
+  var result/eax: boolean <- pop-boolean-from-value-stack out
+  check-not result, "F - test-eval-compare-equal-fails result"
+}
+
+fn test-eval-compare-equal {
+  # in
+  var in-storage: line
+  var in/esi: (addr line) <- address in-storage
+  parse-line "2 2 ==", 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
+  #
+  var len/eax: int <- value-stack-length out
+  check-ints-equal len, 1, "F - test-eval-compare-equal stack size"
+  var result/eax: boolean <- pop-boolean-from-value-stack out
+  check result, "F - test-eval-compare-equal result"
+}
diff --git a/baremetal/shell/value-stack.mu b/baremetal/shell/value-stack.mu
index 1ea4180f..ee1ae3f9 100644
--- a/baremetal/shell/value-stack.mu
+++ b/baremetal/shell/value-stack.mu
@@ -67,6 +67,22 @@ fn push-array-to-value-stack _self: (addr value-stack), val: (handle array value
   increment *top-addr
 }
 
+fn push-boolean-to-value-stack _self: (addr value-stack), _val: boolean {
+  var self/esi: (addr value-stack) <- copy _self
+  var top-addr/ecx: (addr int) <- get self, top
+  var data-ah/edx: (addr handle array value) <- get self, data
+  var data/eax: (addr array value) <- lookup *data-ah
+  var top/edx: int <- copy *top-addr
+  var dest-offset/edx: (offset value) <- compute-offset data, top
+  var dest-addr/edx: (addr value) <- index data, dest-offset
+  var dest-addr2/eax: (addr boolean) <- get dest-addr, boolean-data
+  var val/esi: boolean <- copy _val
+  copy-to *dest-addr2, val
+  increment *top-addr
+  var type-addr/eax: (addr int) <- get dest-addr, type
+  copy-to *type-addr, 3/boolean
+}
+
 fn push-value-stack _self: (addr value-stack), val: (addr value) {
   var self/esi: (addr value-stack) <- copy _self
   var top-addr/ecx: (addr int) <- get self, top
@@ -85,9 +101,7 @@ fn pop-number-from-value-stack _self: (addr value-stack) -> _/xmm0: float {
   {
     compare *top-addr, 0
     break-if->
-    var minus-one/eax: int <- copy -1
-    var minus-one-f/xmm0: float <- convert minus-one
-    return minus-one-f
+    abort "pop number: empty stack"
   }
   decrement *top-addr
   var data-ah/edx: (addr handle array value) <- get self, data
@@ -99,6 +113,24 @@ fn pop-number-from-value-stack _self: (addr value-stack) -> _/xmm0: float {
   return *result-addr2
 }
 
+fn pop-boolean-from-value-stack _self: (addr value-stack) -> _/eax: boolean {
+  var self/esi: (addr value-stack) <- copy _self
+  var top-addr/ecx: (addr int) <- get self, top
+  {
+    compare *top-addr, 0
+    break-if->
+    abort "pop boolean: empty stack"
+  }
+  decrement *top-addr
+  var data-ah/edx: (addr handle array value) <- get self, data
+  var data/eax: (addr array value) <- lookup *data-ah
+  var top/edx: int <- copy *top-addr
+  var dest-offset/edx: (offset value) <- compute-offset data, top
+  var result-addr/eax: (addr value) <- index data, dest-offset
+  var result-addr2/eax: (addr boolean) <- get result-addr, boolean-data
+  return *result-addr2
+}
+
 fn value-stack-empty? _self: (addr value-stack) -> _/eax: boolean {
   var self/esi: (addr value-stack) <- copy _self
   var top/eax: (addr int) <- get self, top
@@ -139,3 +171,14 @@ fn save-lines in-h: (handle array (handle array byte)), _out-ah: (addr handle ar
     loop
   }
 }
+
+fn test-boolean {
+  var stack-storage: value-stack
+  var stack/esi: (addr value-stack) <- address stack-storage
+  push-boolean-to-value-stack stack, 0/false
+  var result/eax: boolean <- pop-boolean-from-value-stack stack
+  check-not result, "F - test-boolean/false"
+  push-boolean-to-value-stack stack, 1/true
+  var result/eax: boolean <- pop-boolean-from-value-stack stack
+  check result, "F - test-boolean/true"
+}
diff --git a/baremetal/shell/value.mu b/baremetal/shell/value.mu
index 4a93227e..5b5ec142 100644
--- a/baremetal/shell/value.mu
+++ b/baremetal/shell/value.mu
@@ -4,6 +4,7 @@ type value {
   number-data: float  # if type = 0
   text-data: (handle array byte)  # if type = 1
   array-data: (handle array value)  # if type = 2
+  boolean-data: boolean  # if type = 3
 }
 
 # top-level? is a hack just for numbers
@@ -29,6 +30,13 @@ fn render-value screen: (addr screen), _val: (addr value), x: int, y: int, top-l
     var new-x/eax: int <- render-array screen, val-array, x, y
     return new-x
   }
+  compare *val-type, 3/boolean
+  {
+    break-if-!=
+    var val/eax: (addr boolean) <- get val, boolean-data
+    var new-x/eax: int <- render-boolean screen, *val, x, y
+    return new-x
+  }
   # render ints by default for now
   var val-num/eax: (addr float) <- get val, number-data
   var new-x/eax: int <- render-number screen, *val-num, x, y, top-level?
@@ -232,3 +240,24 @@ fn test-render-array {
   check-screen-row screen, 0/y, "[0 1 2]", "F - test-render-array"
   check-ints-equal new-x, 7, "F - test-render-array: result"
 }
+
+fn initialize-value-with-boolean _self: (addr value), _b: boolean {
+  var self/esi: (addr value) <- copy _self
+  var type/eax: (addr int) <- get self, type
+  copy-to *type, 3/boolean
+  var dest/edi: (addr boolean) <- get self, boolean-data
+  var b/esi: boolean <- copy _b
+  copy-to *dest, b
+}
+
+fn render-boolean screen: (addr screen), val: boolean, x: int, y: int -> _/eax: int {
+  var new-x/eax: int <- copy 0
+  compare val, 0/false
+  {
+    break-if-=
+    new-x <- draw-text-rightward-over-full-screen screen, "true", new-x, y, 7/fg, 0/bg
+    return new-x
+  }
+  new-x <- draw-text-rightward-over-full-screen screen, "false", new-x, y, 7/fg, 0/bg
+  return new-x
+}