about summary refs log tree commit diff stats
path: root/apps/mu.subx
diff options
context:
space:
mode:
Diffstat (limited to 'apps/mu.subx')
-rw-r--r--apps/mu.subx102
1 files changed, 92 insertions, 10 deletions
diff --git a/apps/mu.subx b/apps/mu.subx
index 241163fd..e82bda50 100644
--- a/apps/mu.subx
+++ b/apps/mu.subx
@@ -408,10 +408,12 @@ Typeinfo-id:  # type-id
 #   2. the output var: a constant containing the byte offset; convenient for code-generation
 Typeinfo-fields:  # (handle table string {(handle var), (handle var)})
   4/imm32
-Typeinfo-next:  # (handle typeinfo)
+Typeinfo-total-size-in-bytes:  # int
   8/imm32
-Typeinfo-size:  # (addr int)
+Typeinfo-next:  # (handle typeinfo)
   0xc/imm32
+Typeinfo-size:  # (addr int)
+  0x10/imm32
 
 == code
 
@@ -2023,6 +2025,54 @@ test-convert-function-and-type-definition:
     5d/pop-to-ebp
     c3/return
 
+test-convert-function-with-local-var-with-user-defined-type:
+    # . 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)
+    c7 0/subop/copy *Next-block-index 1/imm32
+    #
+    (write _test-input-stream "fn foo {\n")
+    (write _test-input-stream "  var a: t\n")
+    (write _test-input-stream "}\n")
+    (write _test-input-stream "type t {\n")
+    (write _test-input-stream "  x: int\n")
+    (write _test-input-stream "  y: int\n")
+    (write _test-input-stream "}\n")
+    # convert
+    (convert-mu _test-input-buffered-file _test-output-buffered-file)
+    (flush _test-output-buffered-file)
+#?     # dump _test-output-stream {{{
+#?     (write 2 "^")
+#?     (write-stream 2 _test-output-stream)
+#?     (write 2 "$\n")
+#?     (rewind-stream _test-output-stream)
+#?     # }}}
+    # check output
+    (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
+    (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
+    (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-with-user-defined-type/3")
+    (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
+    (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
+    (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
+    (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-function-with-local-var-with-user-defined-type/8")
+    (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-with-user-defined-type/12")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 #######################################################
 # Parsing
 #######################################################
@@ -2618,6 +2668,10 @@ $parse-var-with-type:write-register:
     }
 $parse-var-with-type:save-type:
     (parse-type Heap *(ebp+0xc))  # => eax
+#?     (write-buffered Stderr "saving to var ")
+#?     (print-int32-buffered Stderr %edi)
+#?     (write-buffered Stderr Newline)
+#?     (flush Stderr)
     89/<- *(edi+4) 0/r32/eax  # Var-type
 $parse-var-with-type:end:
     # return result
@@ -4951,7 +5005,7 @@ $find-or-create-typeinfo:create:
       89/<- *(eax+4) 1/r32/ecx
       # result->next = Program->types
       8b/-> *_Program-types 1/r32/ecx
-      89/<- *(eax+8) 1/r32/ecx  # Typeinfo-next
+      89/<- *(eax+0xc) 1/r32/ecx  # Typeinfo-next
       # Program->types = result
       89/<- *_Program-types 0/r32/eax
     }
@@ -4981,7 +5035,7 @@ find-typeinfo:  # t: type-id -> result/eax: (handle typeinfo)
       39/compare *eax 1/r32/ecx  # Typeinfo-id
       0f 84/jump-if-= $find-or-create-typeinfo:end/disp32
       # curr = curr->next
-      8b/-> *(eax+8) 0/r32/eax
+      8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-next
       #
       eb/jump loop/disp8
     }
@@ -5099,6 +5153,12 @@ $populate-mu-type:line-loop:
       0f 85/jump-if-!= break/disp32
       # var v/esi: (handle var) = parse-var-with-type(word-slice, first-line)
       (parse-var-with-type %edx %ecx)  # => eax
+#?       (write-buffered Stderr "populate-mu-type: ")
+#?       (write-buffered Stderr *eax)  # Var-name
+#?       (write-buffered Stderr " at ")
+#?       (print-int32-buffered Stderr %eax)
+#?       (write-buffered Stderr Newline)
+#?       (flush Stderr)
       89/<- %esi 0/r32/eax
       # var r/eax: (addr {(handle var) (handle var)})
 #?       (write-buffered Stderr "populate-mu-type: typeinfo: ")
@@ -5132,13 +5192,21 @@ $populate-mu-type:line-loop:
 #?       (flush Stderr)
       89/<- *(eax+0xc) 3/r32/ebx
       # curr-offset += size-of(v)
+#?       (write-buffered Stderr "elem ")
+#?       (write-buffered Stderr *eax)  # Var-name
       50/push-eax
-      (size-of %eax)  # => eax
+      (size-of %esi)  # => eax
+#?       (write-buffered Stderr ": ")
+#?       (print-int32-buffered Stderr %eax)  # Var-name
+#?       (write-buffered Stderr Newline)
+#?       (flush Stderr)
       01/add-to %ebx 0/r32/eax
       58/pop-to-eax
       #
       e9/jump loop/disp32
     }
+    # persist the total size of the type
+    89/<- *(edi+8) 3/r32/ebx  # Typeinfo-total-size-in-bytes
 $populate-mu-type:end:
     # . reclaim locals
     81 0/subop/add %esp 0x214/imm32
@@ -5215,19 +5283,33 @@ $check-mu-types:end:
     5d/pop-to-ebp
     c3/return
 
-size-of:  # v: (addr var) -> result/eax: int
+size-of:  # v: (handle var) -> result/eax: int
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
+    # . save registers
+    51/push-ecx
+    # ecx = v->type
+    8b/-> *(ebp+8) 1/r32/ecx
+    8b/-> *(ecx+4) 1/r32/ecx  # Var-type
     # if v is a literal, return 0
-    8b/-> *(ebp+8) 0/r32/eax
-    8b/-> *(eax+4) 0/r32/eax  # Var-type
-    81 7/subop/compare *eax 0/imm32  # Tree-left
+    81 7/subop/compare *ecx 0/imm32  # Tree-left
     b8/copy-to-eax 0/imm32
     74/jump-if-= $size-of:end/disp8
-    # hard-coded since we only support 'int' types for now
+    # if v has a user-defined type, return its size
+    # TODO: support non-atom type
+    (find-typeinfo *ecx)  # => eax
+    {
+      3d/compare-eax-and 0/imm32
+      74/jump-if-= break/disp8
+      8b/-> *(eax+8) 0/r32/eax  # Typeinfo-total-size-in-bytes
+      eb/jump $size-of:end/disp8
+    }
+    # otherwise return the word size
     b8/copy-to-eax 4/imm32
 $size-of:end:
+    # . restore registers
+    59/pop-to-ecx
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp