diff options
-rw-r--r-- | apps/tile/word.mu | 15 | ||||
-rw-r--r-- | baremetal/shell/eval.mu | 111 | ||||
-rw-r--r-- | baremetal/shell/word.mu | 23 |
3 files changed, 119 insertions, 30 deletions
diff --git a/apps/tile/word.mu b/apps/tile/word.mu index 224c876c..b4f5000b 100644 --- a/apps/tile/word.mu +++ b/apps/tile/word.mu @@ -111,21 +111,6 @@ fn word-length _self: (addr word) -> _/eax: int { return result } -fn first-word _in: (addr handle word), out: (addr handle word) { - var curr-ah/esi: (addr handle word) <- copy _in - var curr/eax: (addr word) <- lookup *curr-ah - var prev/edi: (addr handle word) <- copy 0 - { - prev <- get curr, prev - var curr/eax: (addr word) <- lookup *prev - compare curr, 0 - break-if-= - copy-object prev, curr-ah - loop - } - copy-object curr-ah, out -} - fn final-word _in: (addr handle word), out: (addr handle word) { var curr-h: (handle word) var curr-ah/esi: (addr handle word) <- address curr-h diff --git a/baremetal/shell/eval.mu b/baremetal/shell/eval.mu index 2c56705a..0dc4aee9 100644 --- a/baremetal/shell/eval.mu +++ b/baremetal/shell/eval.mu @@ -214,12 +214,28 @@ fn evaluate-sub _curr: (addr word), end: (addr word), out: (addr value-stack), t var is-break?/eax: boolean <- stream-data-equal? curr-stream, "break" compare is-break?, 0/false break-if-= + # if curr == end, clear stack and break + # (TODO: move this into skip-rest-of-group) + compare curr, end + { + break-if-!= + clear-value-stack out + break $evaluate-sub:loop + } # 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 + # if '}' isn't found before end, we're rendering a word that isn't executed + # skip everything else and clear stack + var close-found?/eax: boolean <- word-equal? curr, "}" + compare close-found?, 0/false + { + break-if-!= + clear-value-stack out + } loop $evaluate-sub:loop } { @@ -408,13 +424,15 @@ fn skip-word _curr: (addr word), end: (addr word), out: (addr handle word) { copy-object result-ah, out } +# find next "}" from curr +# if you hit 'end' before "}", return null 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 + compare result-val, 0 break-if-= { var open?/eax: boolean <- word-equal? result-val, "{" @@ -430,6 +448,12 @@ fn skip-rest-of-group _curr: (addr word), end: (addr word), out: (addr handle wo break-if-= $skip-rest-of-group:loop bracket-count <- decrement } + compare result-val, end + { + break-if-!= + clear-object out + return + } result-ah <- get result-val, next loop } @@ -442,7 +466,9 @@ fn scan-to-start-of-group _curr: (addr word), end: (addr word), out: (addr handl var result-ah/esi: (addr handle word) <- get curr, prev $scan-to-start-of-group:loop: { var result-val/eax: (addr word) <- lookup *result-ah - compare result-val, end + compare result-val, 0 + break-if-= + compare result-val, end # not sure what error-detection should happen here break-if-= { var open?/eax: boolean <- word-equal? result-val, "{" @@ -780,6 +806,87 @@ fn test-eval-conditional-skips-nested-group { # TODO: test error-handling on: # 1 2 > -> } +# incomplete group rendering at 'break' +fn test-eval-break-incomplete { + # in + var in-storage: line + var in/esi: (addr line) <- address in-storage + parse-line "3 { 4 break", 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 + # break clears stack when final word + var len/eax: int <- value-stack-length out + check-ints-equal len, 0, "F - test-eval-break-incomplete stack size" +} + +# incomplete group rendering after 'break' +fn test-eval-break-incomplete-2 { + # 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 + # break clears stack when final word +#? dump-stack out + var len/eax: int <- value-stack-length out +#? draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, len, 0xc/red, 0/black + check-ints-equal len, 0, "F - test-eval-break-incomplete-2 stack size" +} + +# complete group rendering at 'break' +fn test-eval-break-incomplete-3 { + # in + var in-storage: line + var in/esi: (addr line) <- address in-storage + parse-line "{ 3 break 4 } 5", in + # end = 'break' + var w-ah/edx: (addr handle word) <- get in, data + var end-h: (handle word) + var end-ah/ecx: (addr handle word) <- address end-h + skip-one-word w-ah, end-ah + skip-one-word end-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 + # break clears stack when final word + var len/eax: int <- value-stack-length out + check-ints-equal len, 0, "F - test-eval-break-incomplete-3 stack size" +} + +# { 1 break 2 } 3 => empty +# ^ +# +# { 1 break 2 } 3 => empty +# ^ +# +# { 1 break 2 } 3 => 1 3 +# ^ + # break skips to next containing `}` fn test-eval-break { # in diff --git a/baremetal/shell/word.mu b/baremetal/shell/word.mu index 315a9cc1..ad57d040 100644 --- a/baremetal/shell/word.mu +++ b/baremetal/shell/word.mu @@ -101,6 +101,11 @@ fn copy-word-contents-before-cursor _src-ah: (addr handle word), _dest-ah: (addr fn word-equal? _self: (addr word), s: (addr array byte) -> _/eax: boolean { var self/esi: (addr word) <- copy _self + { + compare self, 0 + break-if-!= + return 0/false + } var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data var data/eax: (addr gap-buffer) <- lookup *data-ah var result/eax: boolean <- gap-buffer-equal? data, s @@ -127,19 +132,11 @@ fn word-length _self: (addr word) -> _/eax: int { return result } -fn first-word _in: (addr handle word), out: (addr handle word) { - var curr-ah/esi: (addr handle word) <- copy _in - var curr/eax: (addr word) <- lookup *curr-ah - var prev/edi: (addr handle word) <- copy 0 - { - prev <- get curr, prev - var curr/eax: (addr word) <- lookup *prev - compare curr, 0 - break-if-= - copy-object prev, curr-ah - loop - } - copy-object curr-ah, out +fn skip-one-word _in: (addr handle word), out: (addr handle word) { + var in/eax: (addr handle word) <- copy _in + var curr/eax: (addr word) <- lookup *in + var next/eax: (addr handle word) <- get curr, next + copy-object next, out # modify 'out' right at the end, just in case it's same as 'in' } fn final-word _in: (addr handle word), out: (addr handle word) { |