diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2021-08-22 23:06:51 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2021-08-22 23:06:51 -0700 |
commit | 2d2c46da5c8886f369de27a3a2793cf3e2335a16 (patch) | |
tree | e7c69521791329437ef4e07dd1f0de8add0d25a1 | |
parent | 791a71e27eb7a4c906c4454b6a49643a98662df6 (diff) | |
download | mu-2d2c46da5c8886f369de27a3a2793cf3e2335a16.tar.gz |
another long-overdue bugfix
If I forgot a 'var', Mu would interpret the ':' in the var declaration as a named block, and all parsing after would be thrown off. Perhaps I should use separate characters for defining blocks vs vars.
-rwxr-xr-x | linux/mu | bin | 610870 -> 611784 bytes | |||
-rw-r--r-- | linux/mu.subx | 90 |
2 files changed, 87 insertions, 3 deletions
diff --git a/linux/mu b/linux/mu index d7bd4eb9..0f9798a7 100755 --- a/linux/mu +++ b/linux/mu Binary files differdiff --git a/linux/mu.subx b/linux/mu.subx index 16097264..d66348d3 100644 --- a/linux/mu.subx +++ b/linux/mu.subx @@ -1988,6 +1988,50 @@ test-stmt-with-unknown-var: 5d/pop-to-ebp c3/return +test-stmt-with-missing-var-keyword: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # setup + (clear-stream _test-input-stream) + (clear-stream $_test-input-buffered-file->buffer) + (clear-stream _test-output-stream) + (clear-stream $_test-output-buffered-file->buffer) + (clear-stream _test-error-stream) + (clear-stream $_test-error-buffered-file->buffer) + # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 68/push 0/imm32 + 68/push 0/imm32 + 89/<- %edx 4/r32/esp + (tailor-exit-descriptor %edx 0x10) + # + (write _test-input-stream "fn foo {\n") + (write _test-input-stream " x: int\n") + (write _test-input-stream "}\n") + # convert + (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + # registers except esp clobbered at this point + # restore ed + 89/<- %edx 4/r32/esp + (flush _test-output-buffered-file) + (flush _test-error-buffered-file) +#? # dump _test-error-stream {{{ +#? (write 2 "^") +#? (write-stream 2 _test-error-stream) +#? (write 2 "$\n") +#? (rewind-stream _test-error-stream) +#? # }}} + # check output + (check-stream-equal _test-output-stream "" "F - test-stmt-with-missing-var-keyword: output should be empty") + (check-next-stream-line-equal _test-error-stream "fn foo: unexpected ':'; did you forget a 'var'?" "F - test-stmt-with-missing-var-keyword: error message") + # check that stop(1) was called + (check-ints-equal *(edx+4) 2 "F - test-stmt-with-missing-var-keyword: exit status") + # don't restore from ebp + 81 0/subop/add %esp 8/imm32 + # . epilogue + 5d/pop-to-ebp + c3/return + test-stmt-with-invalid-identifier: # . prologue 55/push-ebp @@ -18204,7 +18248,8 @@ parse-mu-block: # in: (addr buffered-file), vars: (addr stack live-var), fn: (a # else if slice-equal?(word-slice, "}") # break # else if slice-ends-with?(word-slice, ":") - # # TODO: error-check the rest of 'line' + # if !slice-equal?(next-mu-token(line), "{") + # abort # --word-slice->end to skip ':' # named-block = parse-mu-named-block(word-slice, in, vars, fn) # append-to-block(out-addr, named-block) @@ -18320,8 +18365,8 @@ $parse-mu-block:check-for-named-block: # . if (eax != ':') break 3d/compare-eax-and 0x3a/imm32/colon 0f 85/jump-if-!= break/disp32 - # TODO: error-check the rest of 'line' - # + # if next-mu-token(line) != "{", abort + (check-next-token-is-open-curly %ecx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c)) # skip ':' ff 1/subop/decrement *(edx+4) # Slice-end # var tmp/eax: (handle block) @@ -18399,6 +18444,45 @@ $parse-mu-block:abort: (stop *(ebp+0x1c) 1) # never gets here +check-next-token-is-open-curly: # line: (addr stream byte), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 50/push-eax + 52/push-edx + # var word-slice/edx: slice + 68/push 0/imm32/end + 68/push 0/imm32/start + 89/<- %edx 4/r32/esp + # word-slice = next-mu-token(line) + (next-mu-token *(ebp+8) %edx) + # if !slice-equal?(word-slice, "{") abort + (slice-equal? %edx "{") # => eax + 3d/compare-eax-and 0/imm32/false + 0f 84/jump-if-= $check-next-token-is-open-curly:abort/disp32 +$check-next-token-is-open-curly:end: + # . reclaim locals + 81 0/subop/add %esp 8/imm32 + # . restore registers + 5a/pop-to-edx + 58/pop-to-eax + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +$check-next-token-is-open-curly:abort: + # error("fn " fn ": unexpected ':'; did you forget a 'var'?") + (write-buffered *(ebp+0x10) "fn ") + 8b/-> *(ebp+0xc) 0/r32/eax + (lookup *eax *(eax+4)) # Function-name Function-name => eax + (write-buffered *(ebp+0x10) %eax) + (write-buffered *(ebp+0x10) ": unexpected ':'; did you forget a 'var'?\n") + (flush *(ebp+0x10)) + (stop *(ebp+0x14) 1) + # never gets here + new-block-name: # fn: (addr function), out: (addr handle var) # . prologue 55/push-ebp |