From da791479a0bd7f1d34c0ba06309cc1fb48bbe7a5 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Tue, 3 Nov 2020 14:04:35 -0800 Subject: 7165 All tasks of https://github.com/akkartik/mu/issues/45#issuecomment-719990879 should now be complete. --- 403unicode.mu | 2 +- 405screen.mu | 4 +- apps/arith.mu | 12 +++--- apps/mu | Bin 481604 -> 482587 bytes apps/mu.subx | 105 ++++++++++++++++++++++++++++++++++++++++--------- apps/raytracing/vec.mu | 2 +- apps/tile/word.mu | 2 +- 7 files changed, 97 insertions(+), 30 deletions(-) diff --git a/403unicode.mu b/403unicode.mu index b512fb4f..94710be6 100644 --- a/403unicode.mu +++ b/403unicode.mu @@ -369,7 +369,7 @@ fn test-shift-left-bytes-5 { # To run all tests, uncomment this and run: # $ ./translate_mu && ./a.elf -#? fn main -> r/ebx: int { +#? fn main -> _/ebx: int { #? run-tests #? r <- copy 0 #? } diff --git a/405screen.mu b/405screen.mu index a742cc7b..7007e704 100644 --- a/405screen.mu +++ b/405screen.mu @@ -1424,8 +1424,8 @@ fn test-check-screen-blinking { check-screen-row-in-blinking screen, 1, "a c", "F - test-check-screen-blinking" } -#? fn main -> exit-status/ebx: int { +#? fn main -> _/ebx: int { #? #? test-check-screen-color #? run-tests -#? exit-status <- copy 0 +#? return 0 #? } diff --git a/apps/arith.mu b/apps/arith.mu index 6fbd3745..2bfec1db 100644 --- a/apps/arith.mu +++ b/apps/arith.mu @@ -55,7 +55,7 @@ fn main -> _/ebx: int { return 0 } -fn simplify -> _/eax: int, _2/esi: grapheme { +fn simplify -> _/eax: int, _/esi: grapheme { # prime the pump var look/esi: grapheme <- get-char # do it @@ -64,7 +64,7 @@ fn simplify -> _/eax: int, _2/esi: grapheme { return result, look } -fn expression _look: grapheme -> _/eax: int, _2/esi: grapheme { +fn expression _look: grapheme -> _/eax: int, _/esi: grapheme { var look/esi: grapheme <- copy _look # read arg var result/eax: int <- copy 0 @@ -109,7 +109,7 @@ fn expression _look: grapheme -> _/eax: int, _2/esi: grapheme { return result, look } -fn term _look: grapheme -> _/eax: int, _2/esi: grapheme { +fn term _look: grapheme -> _/eax: int, _/esi: grapheme { var look/esi: grapheme <- copy _look # read arg look <- skip-spaces look @@ -154,7 +154,7 @@ fn term _look: grapheme -> _/eax: int, _2/esi: grapheme { return result, look } -fn factor _look: grapheme -> _/eax: int, _2/esi: grapheme { +fn factor _look: grapheme -> _/eax: int, _/esi: grapheme { var look/esi: grapheme <- copy _look # should be a no-op look <- skip-spaces look # if next char is not '(', parse a number @@ -202,13 +202,13 @@ fn is-add-or-sub? c: grapheme -> _/eax: boolean { return 0 # false } -fn operator _look: grapheme -> _/ecx: byte, _2/esi: grapheme { +fn operator _look: grapheme -> _/ecx: byte, _/esi: grapheme { var op/ecx: byte <- copy _look var look/esi: grapheme <- get-char return op, look } -fn num _look: grapheme -> _/eax: int, _2/esi: grapheme { +fn num _look: grapheme -> _/eax: int, _/esi: grapheme { var look/esi: grapheme <- copy _look var result/edi: int <- copy 0 { diff --git a/apps/mu b/apps/mu index 11b896d8..aa6bc3e8 100755 Binary files a/apps/mu and b/apps/mu differ diff --git a/apps/mu.subx b/apps/mu.subx index 2bf74e73..ec868027 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -21,7 +21,7 @@ # A program is a sequence of function and type definitions. # # Function example: -# fn foo n: int -> result/eax: int { +# fn foo n: int -> _/eax: int { # ... # } # @@ -35,7 +35,8 @@ # Variables not explicitly placed in a register are on the stack. # # Function inputs are always passed in memory (on the stack), while outputs -# are always returned in registers. +# are always returned in registers. Outputs can't be named; they use the +# dummy value '_'. # # Blocks mostly consist of statements. # @@ -757,7 +758,7 @@ test-convert-function-with-return-literal: (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) # - (write _test-input-stream "fn foo -> x/eax: int {\n") + (write _test-input-stream "fn foo -> _/eax: int {\n") (write _test-input-stream " return 0\n") (write _test-input-stream "}\n") # convert @@ -799,7 +800,7 @@ test-convert-function-with-return: (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) # - (write _test-input-stream "fn foo -> x/eax: int {\n") + (write _test-input-stream "fn foo -> _/eax: int {\n") (write _test-input-stream " var y: int\n") (write _test-input-stream " return y\n") (write _test-input-stream "}\n") @@ -844,7 +845,7 @@ test-convert-function-with-return-register: (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) # - (write _test-input-stream "fn foo -> x/eax: int {\n") + (write _test-input-stream "fn foo -> _/eax: int {\n") (write _test-input-stream " var y/eax: int <- copy 3\n") (write _test-input-stream " return y\n") (write _test-input-stream "}\n") @@ -880,6 +881,50 @@ test-convert-function-with-return-register: 5d/pop-to-ebp c3/return +test-function-with-named-output: + # . 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 -> x/eax: int {\n") + (write _test-input-stream " return 0\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-named-output: output should be empty") + (check-next-stream-line-equal _test-error-stream "fn foo: function outputs cannot be named; rename 'x' in the header to '_'" "F - test-function-with-named-output: error message") + # check that stop(1) was called + (check-ints-equal *(edx+4) 2 "F - test-function-with-named-output: exit status") + # don't restore from ebp + 81 0/subop/add %esp 8/imm32 + # . epilogue + 5d/pop-to-ebp + c3/return + test-return-with-wrong-type: # . prologue 55/push-ebp @@ -1687,7 +1732,7 @@ test-convert-function-call: (write _test-input-stream " var result/ebx: int <- foo\n") (write _test-input-stream " return result\n") (write _test-input-stream "}\n") - (write _test-input-stream "fn foo -> result/ebx: int {\n") + (write _test-input-stream "fn foo -> _/ebx: int {\n") (write _test-input-stream " var result/ebx: int <- copy 3\n") (write _test-input-stream " return result\n") (write _test-input-stream "}\n") @@ -2178,7 +2223,7 @@ test-convert-function-call-with-incorrect-output-type: (write _test-input-stream "fn f {\n") (write _test-input-stream " var x/eax: int <- g\n") (write _test-input-stream "}\n") - (write _test-input-stream "fn g -> a/eax: foo {\n") + (write _test-input-stream "fn g -> _/eax: foo {\n") (write _test-input-stream "}\n") # convert (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) @@ -2223,7 +2268,7 @@ test-convert-function-call-with-too-few-outputs: (write _test-input-stream "fn f {\n") (write _test-input-stream " g\n") (write _test-input-stream "}\n") - (write _test-input-stream "fn g -> a/eax: int {\n") + (write _test-input-stream "fn g -> _/eax: int {\n") (write _test-input-stream "}\n") # convert (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) @@ -2314,7 +2359,7 @@ test-convert-function-call-with-missing-output-register: (write _test-input-stream " var x: int\n") (write _test-input-stream " x <- g\n") (write _test-input-stream "}\n") - (write _test-input-stream "fn g -> a/eax: int {\n") + (write _test-input-stream "fn g -> _/eax: int {\n") (write _test-input-stream "}\n") # convert (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) @@ -2359,7 +2404,7 @@ test-convert-function-call-with-incorrect-output-register: (write _test-input-stream "fn f {\n") (write _test-input-stream " var x/ecx: int <- g\n") (write _test-input-stream "}\n") - (write _test-input-stream "fn g -> a/eax: int {\n") + (write _test-input-stream "fn g -> _/eax: int {\n") (write _test-input-stream "}\n") # convert (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) @@ -10110,7 +10155,7 @@ test-convert-function-with-return-register-and-local: (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) # - (write _test-input-stream "fn foo -> x/eax: int {\n") + (write _test-input-stream "fn foo -> _/eax: int {\n") (write _test-input-stream " var y/eax: int <- copy 3\n") (write _test-input-stream " var z/ecx: int <- copy 4\n") (write _test-input-stream " return y\n") @@ -10160,7 +10205,7 @@ test-convert-function-with-return-register-and-local-2: (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) # - (write _test-input-stream "fn foo -> x/eax: int {\n") + (write _test-input-stream "fn foo -> _/eax: int {\n") (write _test-input-stream " var y/eax: int <- copy 3\n") (write _test-input-stream " var z/ecx: int <- copy 4\n") (write _test-input-stream " return z\n") @@ -10210,7 +10255,7 @@ test-convert-function-with-return-float-register-and-local: (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) # - (write _test-input-stream "fn foo -> f/xmm1: float {\n") + (write _test-input-stream "fn foo -> _/xmm1: float {\n") (write _test-input-stream " var y/eax: int <- copy 3\n") (write _test-input-stream " var g/xmm0: float <- convert y\n") (write _test-input-stream " var h/xmm1: float <- convert y\n") @@ -10267,7 +10312,7 @@ test-convert-function-with-return-and-local-vars: (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) # - (write _test-input-stream "fn foo -> a/eax: int {\n") + (write _test-input-stream "fn foo -> _/eax: int {\n") (write _test-input-stream " {\n") (write _test-input-stream " var x: int\n") (write _test-input-stream " {\n") @@ -10579,7 +10624,7 @@ $parse-mu:error2: # ✗ fn foo x: { # ✓ fn foo x: int { # ✓ fn foo x: int { -# ✓ fn foo x: int -> y/eax: int { +# ✓ fn foo x: int -> _/eax: int { # TODO: # disallow outputs of type `(... addr ...)` # disallow inputs of type `(... addr ... addr ...)` @@ -10610,6 +10655,7 @@ populate-mu-function-header: # first-line: (addr stream byte), out: (addr funct # assert(word-slice not in '}' '->') # var v: (handle var) = parse-var-with-type(word-slice, first-line) # assert(v->register != null) + # assert(v->name == "_") # out->outputs = append(v, out->outputs) # done: # @@ -10719,6 +10765,11 @@ $populate-mu-function-header:check-for-out: (lookup *ebx *(ebx+4)) # => eax 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 + # assert(var->name == "_") + (lookup *eax *(eax+4)) # Var-name Var-name => eax + (string-equal? %eax "_") # => eax + 3d/compare-eax-and 0/imm32/false + 0f 84/jump-if-= $populate-mu-function-header:error4/disp32 # out->outputs = append(v, out->outputs) 8d/copy-address *(edi+0x10) 0/r32/eax # Function-outputs (append-list Heap *ebx *(ebx+4) *(edi+0x10) *(edi+0x14) %eax) # Function-outputs, Function-outputs @@ -10786,12 +10837,28 @@ $populate-mu-function-header:error3: (stop *(ebp+0x18) 1) # never gets here +$populate-mu-function-header:error4: + # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'") + (write-buffered *(ebp+0x14) "fn ") + 50/push-eax + (lookup *edi *(edi+4)) # Function-name Function-name => eax + (write-buffered *(ebp+0x14) %eax) + 58/pop-to-eax + (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '") + (lookup *ebx *(ebx+4)) # => eax + (lookup *eax *(eax+4)) # Var-name Var-name => eax + (write-buffered *(ebp+0x14) %eax) + (write-buffered *(ebp+0x14) "' in the header to '_'\n") + (flush *(ebp+0x14)) + (stop *(ebp+0x18) 1) + # never gets here + # scenarios considered: # ✓ fn foo # ✗ fn foo { # ✓ fn foo x # ✓ fn foo x: int -# ✓ fn foo x: int -> y/eax: int +# ✓ fn foo x: int -> _/eax: int # TODO: # disallow outputs of type `(... addr ...)` # disallow inputs of type `(... addr ... addr ...)` @@ -11104,7 +11171,7 @@ test-function-header-with-multiple-args-and-outputs: 8b/-> *Primitive-type-ids 0/r32/eax 89/<- *Type-id 0/r32/eax # stream-write (clear-stream _test-input-stream) - (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n") + (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n") # result/ecx: function 2b/subtract *Function-size 4/r32/esp 89/<- %ecx 4/r32/esp @@ -11173,7 +11240,7 @@ $test-function-header-with-multiple-args-and-outputs:out0: 89/<- %ebx 0/r32/eax # check v->name (lookup *ebx *(ebx+4)) # Var-name Var-name => eax - (check-strings-equal %eax "x" "F - test-function-header-with-multiple-args-and-outputs/output:0") + (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0") # check v->register (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") @@ -11191,7 +11258,7 @@ $test-function-header-with-multiple-args-and-outputs:out1: 89/<- %ebx 0/r32/eax # check v->name (lookup *ebx *(ebx+4)) # Var-name Var-name => eax - (check-strings-equal %eax "y" "F - test-function-header-with-multiple-args-and-outputs/output:1") + (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1") # check v->register (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register") diff --git a/apps/raytracing/vec.mu b/apps/raytracing/vec.mu index c93bab91..c641d2b2 100644 --- a/apps/raytracing/vec.mu +++ b/apps/raytracing/vec.mu @@ -128,7 +128,7 @@ fn vec3-length-squared _v: (addr vec3) -> _/xmm0: float { return result } -fn vec3-dot _v1: (addr vec3), _v2: (addr vec3) -> result/xmm0: float { +fn vec3-dot _v1: (addr vec3), _v2: (addr vec3) -> _/xmm0: float { } fn vec3-cross _v1: (addr vec3), _v2: (addr vec3), out: (addr vec3) { diff --git a/apps/tile/word.mu b/apps/tile/word.mu index c51c4bf4..64d03ff8 100644 --- a/apps/tile/word.mu +++ b/apps/tile/word.mu @@ -176,7 +176,7 @@ fn cursor-at-start? _self: (addr word) -> _/eax: boolean { return result } -fn cursor-at-end? _self: (addr word) -> result/eax: boolean { +fn cursor-at-end? _self: (addr word) -> _/eax: boolean { var self/esi: (addr word) <- copy _self var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data var data/eax: (addr gap-buffer) <- lookup *data-ah -- cgit 1.4.1-2-gfad0