diff options
Diffstat (limited to 'apps/mu.subx')
-rw-r--r-- | apps/mu.subx | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/apps/mu.subx b/apps/mu.subx index 7da28859..a2286913 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -666,6 +666,139 @@ test-convert-function-with-arg: 5d/pop-to-ebp c3/return +test-function-with-redefined-name: + # . 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 "}\n") + (write _test-input-stream "fn foo {\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-function-with-redefined-name: output should be empty") + (check-next-stream-line-equal _test-error-stream "fn foo defined more than once" "F - test-function-with-redefined-name: error message") + # check that stop(1) was called + (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name: exit status") + # don't restore from ebp + 81 0/subop/add %esp 8/imm32 + # . epilogue + 5d/pop-to-ebp + c3/return + +test-function-with-redefined-name-2: + # . 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 "}\n") + (write _test-input-stream "sig foo\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-function-with-redefined-name-2: output should be empty") + (check-next-stream-line-equal _test-error-stream "fn foo defined more than once" "F - test-function-with-redefined-name-2: error message") + # check that stop(1) was called + (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-2: exit status") + # don't restore from ebp + 81 0/subop/add %esp 8/imm32 + # . epilogue + 5d/pop-to-ebp + c3/return + +test-function-with-redefined-name-3: + # . 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 "sig foo\n") + (write _test-input-stream "fn foo {\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-function-with-redefined-name-3: output should be empty") + (check-next-stream-line-equal _test-error-stream "fn foo defined more than once" "F - test-function-with-redefined-name-3: error message") + # check that stop(1) was called + (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-3: exit status") + # don't restore from ebp + 81 0/subop/add %esp 8/imm32 + # . epilogue + 5d/pop-to-ebp + c3/return + test-function-with-inout-in-register: # . prologue 55/push-ebp @@ -13594,6 +13727,17 @@ populate-mu-function-header: # first-line: (addr stream byte), out: (addr funct (slice-equal? %ecx "}") # => eax 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 + # if word-slice already defined, abort + (function-exists? %ecx) # => eax + 3d/compare-eax-and 0/imm32/false + 0f 85/jump-if-!= $populate-mu-function-header:error-duplicate/disp32 + # + (slice-starts-with? %ecx "break") # => eax + 3d/compare-eax-and 0/imm32/false + 0f 85/jump-if-!= $populate-mu-function-header:error-break/disp32 + (slice-starts-with? %ecx "loop") # => eax + 3d/compare-eax-and 0/imm32/false + 0f 85/jump-if-!= $populate-mu-function-header:error-loop/disp32 # save function name (slice-to-string Heap %ecx %edi) # Function-name # save function inouts @@ -13750,6 +13894,26 @@ $populate-mu-function-header:error4: (stop *(ebp+0x18) 1) # never gets here +$populate-mu-function-header:error-duplicate: + (write-buffered *(ebp+0x14) "fn ") + (write-slice-buffered *(ebp+0x14) %ecx) + (write-buffered *(ebp+0x14) " defined more than once\n") + (flush *(ebp+0x14)) + (stop *(ebp+0x18) 1) + # never gets here + +$populate-mu-function-header:error-break: + (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n") + (flush *(ebp+0x14)) + (stop *(ebp+0x18) 1) + # never gets here + +$populate-mu-function-header:error-loop: + (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n") + (flush *(ebp+0x14)) + (stop *(ebp+0x18) 1) + # never gets here + # scenarios considered: # ✓ fn foo # ✗ fn foo { @@ -13818,6 +13982,17 @@ populate-mu-function-signature: # first-line: (addr stream byte), out: (addr fu (slice-equal? %ecx "}") # => eax 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 + # if word-slice already defined, abort + (function-exists? %ecx) # => eax + 3d/compare-eax-and 0/imm32/false + 0f 85/jump-if-!= $populate-mu-function-signature:error-duplicate/disp32 + # + (slice-starts-with? %ecx "break") # => eax + 3d/compare-eax-and 0/imm32/false + 0f 85/jump-if-!= $populate-mu-function-signature:error-break/disp32 + (slice-starts-with? %ecx "loop") # => eax + 3d/compare-eax-and 0/imm32/false + 0f 85/jump-if-!= $populate-mu-function-signature:error-loop/disp32 # save function name (slice-to-string Heap %ecx %edi) # Function-name # save function inouts @@ -13947,6 +14122,86 @@ $populate-mu-function-signature:error3: (stop *(ebp+0x14) 1) # never gets here +$populate-mu-function-signature:error-duplicate: + (write-buffered *(ebp+0x10) "fn ") + (write-slice-buffered *(ebp+0x10) %ecx) + (write-buffered *(ebp+0x10) " defined more than once\n") + (flush *(ebp+0x10)) + (stop *(ebp+0x14) 1) + # never gets here + +$populate-mu-function-signature:error-break: + (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n") + (flush *(ebp+0x14)) + (stop *(ebp+0x18) 1) + # never gets here + +$populate-mu-function-signature:error-loop: + (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n") + (flush *(ebp+0x14)) + (stop *(ebp+0x18) 1) + # never gets here + +function-exists?: # s: (addr slice) -> result/eax: boolean + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 51/push-ecx + # var curr/ecx: (addr function) = functions + (lookup *_Program-functions *_Program-functions->payload) # => eax + 89/<- %ecx 0/r32/eax + { + # if (curr == null) break + 81 7/subop/compare %ecx 0/imm32 + 74/jump-if-= break/disp8 + # if (curr->name == s) return true + { + (lookup *ecx *(ecx+4)) # Function-name Function-name => eax + (slice-equal? *(ebp+8) %eax) # => eax + 3d/compare-eax-and 0/imm32/false + 74/jump-if-= break/disp8 + b8/copy-to-eax 1/imm32/true + e9/jump $function-exists?:end/disp32 + } + # curr = curr->next + (lookup *(ecx+0x20) *(ecx+0x24)) # Function-next Function-next => eax + 89/<- %ecx 0/r32/eax + # + eb/jump loop/disp8 + } + # var curr/ecx: (addr function) = signatures + (lookup *_Program-signatures *_Program-signatures->payload) # => eax + 89/<- %ecx 0/r32/eax + { + # if (curr == null) break + 81 7/subop/compare %ecx 0/imm32 + 74/jump-if-= break/disp8 + # if (curr->name == s) return true + { + (lookup *ecx *(ecx+4)) # Function-name Function-name => eax + (slice-equal? *(ebp+8) %eax) # => eax + 3d/compare-eax-and 0/imm32/false + 74/jump-if-= break/disp8 + b8/copy-to-eax 1/imm32/true + eb/jump $function-exists?:end/disp8 + } + # curr = curr->next + (lookup *(ecx+0x20) *(ecx+0x24)) # Function-next Function-next => eax + 89/<- %ecx 0/r32/eax + # + eb/jump loop/disp8 + } + # return false + b8/copy-to-eax 0/imm32/false +$function-exists?:end: + # . restore registers + 59/pop-to-ecx + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + test-function-header-with-arg: # . prologue 55/push-ebp @@ -13954,6 +14209,12 @@ test-function-header-with-arg: # setup 8b/-> *Primitive-type-ids 0/r32/eax 89/<- *Type-id 0/r32/eax # stream-write + c7 0/subop/copy *_Program-functions 0/imm32 + c7 0/subop/copy *_Program-functions->payload 0/imm32 + c7 0/subop/copy *_Program-types 0/imm32 + c7 0/subop/copy *_Program-types->payload 0/imm32 + c7 0/subop/copy *_Program-signatures 0/imm32 + c7 0/subop/copy *_Program-signatures->payload 0/imm32 (clear-stream _test-input-stream) (write _test-input-stream "foo n: int {\n") # var result/ecx: function @@ -13994,6 +14255,12 @@ test-function-header-with-multiple-args: # setup 8b/-> *Primitive-type-ids 0/r32/eax 89/<- *Type-id 0/r32/eax # stream-write + c7 0/subop/copy *_Program-functions 0/imm32 + c7 0/subop/copy *_Program-functions->payload 0/imm32 + c7 0/subop/copy *_Program-types 0/imm32 + c7 0/subop/copy *_Program-types->payload 0/imm32 + c7 0/subop/copy *_Program-signatures 0/imm32 + c7 0/subop/copy *_Program-signatures->payload 0/imm32 (clear-stream _test-input-stream) (write _test-input-stream "foo a: int, b: int c: int {\n") # result/ecx: function @@ -14067,6 +14334,12 @@ test-function-header-with-multiple-args-and-outputs: # setup 8b/-> *Primitive-type-ids 0/r32/eax 89/<- *Type-id 0/r32/eax # stream-write + c7 0/subop/copy *_Program-functions 0/imm32 + c7 0/subop/copy *_Program-functions->payload 0/imm32 + c7 0/subop/copy *_Program-types 0/imm32 + c7 0/subop/copy *_Program-types->payload 0/imm32 + c7 0/subop/copy *_Program-signatures 0/imm32 + c7 0/subop/copy *_Program-signatures->payload 0/imm32 (clear-stream _test-input-stream) (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n") # result/ecx: function |