about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-01-26 23:44:40 -0800
committerKartik Agaram <vc@akkartik.com>2020-01-26 23:44:40 -0800
commitf39eeb3af36d94adaa42de33b9243c05bc97de87 (patch)
tree00bb8090722b82a8e87a134b0be6717e8119a5bf
parent0c1f023acfa6406af22683620f9adbe78a5b39f5 (diff)
downloadmu-f39eeb3af36d94adaa42de33b9243c05bc97de87.tar.gz
5921
-rwxr-xr-xapps/mubin81109 -> 82516 bytes
-rw-r--r--apps/mu.subx135
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