diff options
-rwxr-xr-x | apps/mu | bin | 81109 -> 82516 bytes | |||
-rw-r--r-- | apps/mu.subx | 135 |
2 files changed, 130 insertions, 5 deletions
diff --git a/apps/mu b/apps/mu index bc1e2e1b..f7a10326 100755 --- a/apps/mu +++ b/apps/mu Binary files differdiff --git a/apps/mu.subx b/apps/mu.subx index f8a26a4a..71247e12 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -1749,7 +1749,7 @@ $parse-type-tree:end: next-mu-token: # in: (addr stream byte), out: (addr slice) # pseudocode: # start: - # skip-chars-matching(in, ' ') + # skip-chars-matching-whitespace(in) # if in->read >= in->write # end of in # out = {0, 0} # return @@ -1780,6 +1780,10 @@ next-mu-token: # in: (addr stream byte), out: (addr slice) # curr-byte = in->data[in->read] # if curr-byte == ' ' # break + # if curr-byte == '\r' + # break + # if curr-byte == '\n' + # break # if curr-byte == '(' # break # if curr-byte == ')' @@ -1817,8 +1821,7 @@ next-mu-token: # in: (addr stream byte), out: (addr slice) # edi = out 8b/-> *(ebp+0xc) 7/r32/edi $next-mu-token:start: - # skip-chars-matching(in, ' ') - (skip-chars-matching %esi 0x20) # ' ' + (skip-chars-matching-whitespace %esi) $next-mu-token:check0: # if (in->read >= in->write) return out = {0, 0} # . ecx = in->read @@ -1908,6 +1911,12 @@ $next-mu-token:regular-word-without-metadata: # if (c == ' ') break 3d/compare-eax-and 0x20/imm32/space 74/jump-if-= break/disp8 + # if (c == '\r') break + 3d/compare-eax-and 0xd/imm32/carriage-return + 74/jump-if-= break/disp8 + # if (c == '\n') break + 3d/compare-eax-and 0xa/imm32/newline + 74/jump-if-= break/disp8 # if (c == '(') break 3d/compare-eax-and 0x28/imm32/open-paren 0f 84/jump-if-= break/disp32 @@ -2799,9 +2808,121 @@ parse-mu-var-def: # line : (addr stream byte), vars : (addr stack (handle var)) 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers + 51/push-ecx + 52/push-edx + # var word-slice/ecx : slice + 68/push 0/imm32/end + 68/push 0/imm32/start + 89/<- %ecx 4/r32/esp + # var v/edx : (handle var) = parse-var-with-type(line) + (next-word *(ebp+8) %ecx) + (parse-var-with-type %ecx *(ebp+8)) # => eax + 89/<- %edx 0/r32/eax + # either v has no register and there's no more to this line + 8b/-> *(edx+0x10) 0/r32/eax # Var-register + 3d/compare-eax-and 0/imm32 + { + 75/jump-if-not-equal break/disp8 + # TODO: ensure that there's nothing else on this line + (new-vardef Heap %edx) # => eax + eb/jump $parse-mu-var-def:end/disp8 + } + # or v has a register and there's more to this line + { + 74/jump-if-equal break/disp8 + # ensure that the next word is '<-' + (next-word *(ebp+8) %ecx) + (slice-equal? %ecx "<-") # => eax + 3d/compare-eax-and 0/imm32 + 74/jump-if-equal $parse-mu-var-def:abort/disp8 + # + (new-regvardef Heap %edx) # => eax + (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) + } $parse-mu-var-def:end: # . reclaim locals + 81 0/subop/add %esp 8/imm32 # . restore registers + 5a/pop-to-edx + 59/pop-to-ecx + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +$parse-mu-var-def:abort: + (rewind-stream *(ebp+8)) + # error("register variable requires a valid instruction to initialize but got '" line "'\n") + (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") + (flush Stderr) + (write-stream 2 *(ebp+8)) + (write-buffered Stderr "'\n") + (flush Stderr) + # . syscall(exit, 1) + bb/copy-to-ebx 1/imm32 + b8/copy-to-eax 1/imm32/exit + cd/syscall 0x80/imm8 + # never gets here + +test-parse-mu-var-def: + # 'var n: int' + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # setup + (clear-stream _test-input-stream) + (write _test-input-stream "n: int\n") # caller has consumed the 'var' + # var vars/ecx : (stack (addr var) 4) + 81 5/subop/subtract %esp 0x10/imm32 + 68/push 0x10/imm32/length + 68/push 0/imm32/top + 89/<- %ecx 4/r32/esp + (clear-stack %ecx) + # convert + (parse-mu-var-def _test-input-stream %ecx) # => eax + # check result + (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is vardef + 8b/-> *(eax+4) 0/r32/eax # Vardef-var + (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name + (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register + # TODO: ensure stack-offset is -4 + # TODO: ensure block-depth is 1 + # ensure type is int + 8b/-> *(eax+4) 0/r32/eax # Var-type + (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-left + (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0") # Tree-right + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +test-parse-mu-reg-var-def: + # 'var n/eax: int <- copy 0' + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # setup + (clear-stream _test-input-stream) + (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' + # var vars/ecx : (stack (addr var) 4) + 81 5/subop/subtract %esp 0x10/imm32 + 68/push 0x10/imm32/length + 68/push 0/imm32/top + 89/<- %ecx 4/r32/esp + (clear-stack %ecx) + # convert + (parse-mu-var-def _test-input-stream %ecx) # => eax + # check result + (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is regvardef + 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-var + (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/var-name") # Var-name + (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/var-register") # Var-register + # TODO: ensure stack-offset is -4 + # TODO: ensure block-depth is 1 + # ensure type is int + 8b/-> *(eax+4) 0/r32/eax # Var-type + (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/var-type:0") # Tree-left + (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/var-type:0") # Tree-right # . epilogue 89/<- %esp 5/r32/ebp 5d/pop-to-ebp @@ -2901,6 +3022,7 @@ add-operation-and-inputs-to-stmt: # stmt : (handle stmt), line : (addr stream b 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers + 50/push-eax 51/push-ecx 57/push-edi # edi = stmt @@ -2937,6 +3059,7 @@ $add-operation-and-inputs-to-stmt:end: # . restore registers 5f/pop-to-edi 59/pop-to-ecx + 58/pop-to-eax # . epilogue 89/<- %esp 5/r32/ebp 5d/pop-to-ebp @@ -2946,7 +3069,8 @@ $add-operation-and-inputs-to-stmt:abort: # error("invalid statement '" line "'\n") (rewind-stream *(ebp+8)) (write-buffered Stderr "invalid identifier '") - (write-stream Stderr *(ebp+8)) + (flush Stderr) + (write-stream 2 *(ebp+8)) (write-buffered Stderr "'\n") (flush Stderr) # . syscall(exit, 1) @@ -3235,8 +3359,9 @@ test-parse-mu-stmt: # (push %ecx %edx) # convert - (parse-mu-stmt _test-input-stream %ecx) + (parse-mu-stmt _test-input-stream %ecx) # => eax # check result + (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation # edx : (handle list var) = result->inouts 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts |