about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xapps/mubin57992 -> 60284 bytes
-rw-r--r--apps/mu.subx162
2 files changed, 159 insertions, 3 deletions
diff --git a/apps/mu b/apps/mu
index 9f6c251d..a09943a1 100755
--- a/apps/mu
+++ b/apps/mu
Binary files differdiff --git a/apps/mu.subx b/apps/mu.subx
index 4bfdb6a6..3cff705d 100644
--- a/apps/mu.subx
+++ b/apps/mu.subx
@@ -701,13 +701,14 @@ populate-mu-function-header:  # first-line : (address stream byte), out : (addre
     #     if (name == '->') break
     #     assert(name != '}')
     #     var v : (address var) = parse-var-with-type(name, first-line)
-    #     out->inouts = new-list(v, out->inouts)
+    #     out->inouts = append(out->inouts, v)
     #   ## outputs
     #   while true
     #     ## name
     #     name = next-word(first-line)
     #     assert(name not in '{' '}' '->')
     #     var v : (address var) = parse-var-with-type(name, first-line)
+    #     out->outputs = append(out->outputs, v)
     #   done:
     #
     # . prologue
@@ -758,7 +759,7 @@ populate-mu-function-header:  # first-line : (address stream byte), out : (addre
       0f 85/jump-if-not-equal $populate-mu-function-header:abort/disp32
       #
       (parse-var-with-type %ecx *(ebp+8))
-      (new-list Heap %eax *(edi+8))  # Function-inouts
+      (append-list Heap %eax *(edi+8))  # Function-inouts
       89/<- *(edi+8) 0/r32/eax  # Function-inouts
       e9/jump loop/disp32
     }
@@ -779,7 +780,7 @@ populate-mu-function-header:  # first-line : (address stream byte), out : (addre
       0f 85/jump-if-not-equal $populate-mu-function-header:abort/disp32
       #
       (parse-var-with-type %ecx *(ebp+8))
-      (new-list Heap %eax *(edi+0xc))  # Function-outputs
+      (append-list Heap %eax *(edi+0xc))  # Function-outputs
       89/<- *(edi+0xc) 0/r32/eax  # Function-outputs
       e9/jump loop/disp32
     }
@@ -829,6 +830,125 @@ $populate-mu-function-header:abort:
     cd/syscall  0x80/imm8
     # never gets here
 
+test-function-header-with-arg:
+    # 'foo n : int {'
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # setup
+    (clear-stream _test-input-stream)
+    (write _test-input-stream "foo n : int {\n")
+    # result/ecx : (address function)
+    2b/subtract-> *Function-size 4/r32/esp
+    89/<- %ecx 4/r32/esp
+    (zero-out %ecx *Function-size)
+    # convert
+    (populate-mu-function-header _test-input-stream %ecx)
+    # check result
+    (check-string-equal *ecx "foo" "F - test-function-header-with-arg/name")  # Function-name
+    # edx : (address list var) = result->inouts
+    8b/-> *(ecx+8) 2/r32/edx  # Function-inouts
+    # ebx : (address var) = result->inouts->value
+    8b/-> *edx 3/r32/ebx  # List-value
+    (check-string-equal *ebx "n" "F - test-function-header-with-arg/inout:0")  # Var-name
+    (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/inout:0/type")  # Var-type
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+test-function-header-with-multiple-args:
+    # 'fn foo a: int, b: int, c: int {'
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # setup
+    (clear-stream _test-input-stream)
+    (write _test-input-stream "foo a: int, b: int c: int {\n")
+    # result/ecx : (address function)
+    2b/subtract-> *Function-size 4/r32/esp
+    89/<- %ecx 4/r32/esp
+    (zero-out %ecx *Function-size)
+    # convert
+    (populate-mu-function-header _test-input-stream %ecx)
+    # check result
+    (check-string-equal *ecx "foo")  # Function-name
+    # edx : (address list var) = result->inouts
+    8b/-> *(ecx+8) 2/r32/edx  # Function-inouts
+    # ebx : (address var) = result->inouts->value
+    8b/-> *edx 3/r32/ebx  # List-value
+    (check-string-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
+    (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/inout:0/type")  # Var-type
+    # edx = result->inouts->next
+    8b/-> *(edx+4) 2/r32/edx  # List-next
+    # ebx = result->inouts->next->value
+    8b/-> *edx 3/r32/ebx  # List-value
+    (check-string-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
+    (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/inout:1/type")  # Var-type
+    # edx = result->inouts->next->next
+    8b/-> *(edx+4) 2/r32/edx  # List-next
+    # ebx = result->inouts->next->next->value
+    8b/-> *edx 3/r32/ebx  # List-value
+    (check-string-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
+    (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/inout:2/type")  # Var-type
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+test-function-with-multiple-args-and-outputs:
+    # fn foo a: int, b: int, c: int -> x: int, y: int {
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # setup
+    (clear-stream _test-input-stream)
+    (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx : int {\n")
+    # result/ecx : (address function)
+    2b/subtract-> *Function-size 4/r32/esp
+    89/<- %ecx 4/r32/esp
+    (zero-out %ecx *Function-size)
+    # convert
+    (populate-mu-function-header _test-input-stream %ecx)
+    # check result
+    (check-string-equal *ecx "foo")  # Function-name
+    # edx : (address list var) = result->inouts
+    8b/-> *(ecx+8) 2/r32/edx  # Function-inouts
+    # ebx : (address var) = result->inouts->value
+    8b/-> *edx 3/r32/ebx  # List-value
+    (check-string-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
+    (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/inout:0/type")  # Var-type
+    # edx = result->inouts->next
+    8b/-> *(edx+4) 2/r32/edx  # List-next
+    # ebx = result->inouts->next->value
+    8b/-> *edx 3/r32/ebx  # List-value
+    (check-string-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
+    (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/inout:1/type")  # Var-type
+    # edx = result->inouts->next->next
+    8b/-> *(edx+4) 2/r32/edx  # List-next
+    # ebx = result->inouts->next->next->value
+    8b/-> *edx 3/r32/ebx  # List-value
+    (check-string-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
+    (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/inout:2/type")  # Var-type
+    # edx : (address list var) = result->outputs
+    8b/-> *(ecx+0xc) 2/r32/edx  # Function-outputs
+    # ebx : (address var) = result->outputs->value
+    8b/-> *edx 3/r32/ebx  # List-value
+    (check-string-equal *ebx "x" "F - test-function-header-with-multiple-args/output:0")  # Var-name
+    (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/output:0/type")  # Var-type
+    (check-string-equal *(ebx+0x10) "ecx" "F - test-function-header-with-arg/output:0/register")  # Var-register
+    # edx = result->outputs->next
+    8b/-> *(edx+4) 2/r32/edx  # List-next
+    # ebx = result->outputs->next->value
+    8b/-> *edx 3/r32/ebx  # List-value
+    (check-string-equal *ebx "y" "F - test-function-header-with-multiple-args/output:1")  # Var-name
+    (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/output:1/type")  # Var-type
+    (check-string-equal *(ebx+0x10) "edx" "F - test-function-header-with-arg/output:0/register")  # Var-register
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 # format for variables with types
 #   x : int
 #   x: int
@@ -1762,6 +1882,42 @@ $new-list:end:
     5d/pop-to-ebp
     c3/return
 
+append-list:  # ad: allocation-descriptor, value: _type, list: (address list _type) -> result/eax : (address list _type)
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    51/push-ecx
+    #
+    (allocate *(ebp+8) *List-size)  # => eax
+    8b/-> *(ebp+0xc) 1/r32/ecx
+    89/<- *eax 1/r32/ecx  # List-value
+    # if (list == null) return result
+    81 7/subop/compare *(ebp+0x10) 0/imm32
+    74/jump-if-equal $new-list:end/disp8
+    # otherwise append
+    # var curr/ecx = list
+    8b/-> *(ebp+0x10) 1/r32/ecx
+    # while (curr->next != null) curr = curr->next
+    {
+      81 7/subop/compare *(ecx+4) 0/imm32  # List-next
+      74/jump-if-equal break/disp8
+      # curr = curr->next
+      8b/-> *(ecx+4) 1/r32/ecx
+      eb/jump loop/disp8
+    }
+    # curr->next = result
+    89/<- *(ecx+4) 0/r32/eax
+    # return list
+    8b/-> *(ebp+0x10) 0/r32/eax
+$append-list:end:
+    # . restore registers
+    59/pop-to-ecx
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 #######################################################
 # Type-checking
 #######################################################