From 378ffca74c7a1428431da5d4572b70731d41074d Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 12 Feb 2021 23:18:33 -0800 Subject: 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. --- baremetal/shell/eval.mu | 158 +++++++++++++++++++++++++++++++++++++++-- baremetal/shell/value-stack.mu | 49 ++++++++++++- baremetal/shell/value.mu | 29 ++++++++ 3 files changed, 226 insertions(+), 10 deletions(-) (limited to 'baremetal') 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 +} -- cgit 1.4.1-2-gfad0