diff options
author | Kartik Agaram <vc@akkartik.com> | 2019-11-28 23:20:39 -0800 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2019-11-28 23:20:39 -0800 |
commit | 31ed455886aefa1403d3fca2e2041a1786e75f2c (patch) | |
tree | f856066b22e5d5873fd608d70ddde3338ef56b76 /apps | |
parent | 0c24aa334e419789a40f44f61d889928f0154030 (diff) | |
download | mu-31ed455886aefa1403d3fca2e2041a1786e75f2c.tar.gz |
5773
Rudimentary support for parsing variable declarations.
Diffstat (limited to 'apps')
-rwxr-xr-x | apps/mu | bin | 56081 -> 57373 bytes | |||
-rw-r--r-- | apps/mu.subx | 205 |
2 files changed, 205 insertions, 0 deletions
diff --git a/apps/mu b/apps/mu index 5fede48e..a198cfa0 100755 --- a/apps/mu +++ b/apps/mu Binary files differdiff --git a/apps/mu.subx b/apps/mu.subx index 4a449e67..d9fbac97 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -795,6 +795,211 @@ $populate-mu-function-header:abort: cd/syscall 0x80/imm8 # never gets here +# format for variables with types +# x : int +# x: int +parse-var-with-type: # name: slice, first-line: (address stream) -> result/eax: (address var) + # pseudocode: + # var v : (address var) = allocate(Heap, Var-size) + # var s : slice + # next-token-from-slice(name->start, name->end, '/', s) + # if (slice-ends-with(s, ":")) + # decrement s->end + # v->name = slice-to-string(s) + # ## register + # next-token-from-slice(s->end, name->end, '/', s) + # if (!slice-empty?(s)) + # v->register = slice-to-string(s) + # ## type + # s = next-word-or-sexpression(first-line) + # assert(type not in '{' '}' '->') + # if (slice-equal?(type, ":")) { + # s = next-word-or-sexpression(first-line) + # assert(type not in '{' '}' '->') + # } + # type = type-for(s) + # v->type = type + # return v + # + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 51/push-ecx + 52/push-edx + 53/push-ebx + 56/push-esi + 57/push-edi + # var result/edi : (address var) = allocate(Heap, Var-size) + (allocate Heap *Var-size) + 89/<- %edi 0/r32/eax + # esi = name + 8b/-> *(ebp+8) 6/r32/esi + # var s/ecx : slice + 68/push 0/imm32/end + 68/push 0/imm32/start + 89/<- %ecx 4/r32/esp + # save v->name + (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' + # . end/edx = s->end + 8b/-> *(ecx+4) 2/r32/edx + # . if s ends with ':', decrement s->end + { + 8b/-> *(ecx+4) 0/r32/eax + 48/decrement-eax + 8a/copy-byte *eax 3/r32/BL + 81 4/subop/and %ebx 0xff/imm32 + 81 7/subop/compare %ebx 0x3a/imm32/colon + 75/jump-if-not-equal break/disp8 + 89/<- *(ecx+4) 0/r32/eax + } + (slice-to-string Heap %ecx) # => eax + 89/<- *edi 0/r32/eax # Var-name + # save v->register + (next-token-from-slice %edx *(esi+4) 0x2f %ecx) # end, name->end, '/' + # if (!slice-empty?(s)) v->register = slice-to-string(s) + { + (slice-empty? %ecx) + 3d/compare-eax-and 0/imm32 + 75/jump-if-not-equal break/disp8 + (slice-to-string Heap %ecx) + 89/<- *(edi+0x10) 0/r32/eax # Var-register + } + # save v->type + (next-word *(ebp+0xc) %ecx) # TODO: support type s-expressions + # if (word-slice == '{') abort + (slice-equal? %ecx "{") # => eax + 3d/compare-eax-and 0/imm32 + 0f 85/jump-if-not-equal $parse-var-with-type:abort/disp32 + # if (word-slice == '->') abort + (slice-equal? %ecx "->") # => eax + 3d/compare-eax-and 0/imm32 + 0f 85/jump-if-not-equal $parse-var-with-type:abort/disp32 + # if (word-slice == '}') abort + (slice-equal? %ecx "}") # => eax + 3d/compare-eax-and 0/imm32 + 0f 85/jump-if-not-equal $parse-var-with-type:abort/disp32 + # if (slice-equal?(type, ":")) skip + (slice-equal? %ecx ":") + { + 3d/compare-eax-and 0/imm32 + 74/jump-if-equal break/disp8 + (next-word *(ebp+0xc) %ecx) + # if (word-slice == '{') abort + (slice-equal? %ecx "{") # => eax + 3d/compare-eax-and 0/imm32 + 0f 85/jump-if-not-equal $parse-var-with-type:abort/disp32 + # if (word-slice == '->') abort + (slice-equal? %ecx "->") # => eax + 3d/compare-eax-and 0/imm32 + 0f 85/jump-if-not-equal $parse-var-with-type:abort/disp32 + # if (word-slice == '}') abort + (slice-equal? %ecx "}") # => eax + 3d/compare-eax-and 0/imm32 + 0f 85/jump-if-not-equal $parse-var-with-type:abort/disp32 + eb/jump $parse-var-with-type:end/disp8 + } + (type-for %ecx) + 89/<- *(edi+4) 0/r32/eax # Var-type +$parse-var-with-type:end: + # return result + 89/<- %eax 7/r32/edi + # . restore registers + 5f/pop-to-edi + 5e/pop-to-esi + 5b/pop-to-ebx + 5a/pop-to-edx + 59/pop-to-ecx + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +$parse-var-with-type:abort: + # error("function header not in form 'fn <name> {'") + (write-buffered Stderr "var should have form 'name: type' in '") + (flush Stderr) + (rewind-stream *(ebp+0xc)) + (write-stream 2 *(ebp+0xc)) + (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 + +type-for: # name: slice -> result/eax: type-tree + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers +$type-for:end: + b8/copy-to-eax 1/imm32/int + # . restore registers + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +test-parse-var-with-type: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # (eax..ecx) = "x:" + b8/copy-to-eax "x:"/imm32 + 8b/-> *eax 1/r32/ecx + 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 05/add-to-eax 4/imm32 + # var slice/ecx = {eax, ecx} + 51/push-ecx + 50/push-eax + 89/<- %ecx 4/r32/esp + # _test-input-stream contains "int" + (clear-stream _test-input-stream) + (clear-stream _test-input-buffered-file->buffer) + (write _test-input-stream "int") + # + (parse-var-with-type %ecx _test-input-buffered-file) + 8b/-> *eax 2/r32/edx # Var-name + (check-string-equal %edx "x" "F - test-var-with-type/name") + 8b/-> *(eax+4) 2/r32/edx # Var-type + (check-ints-equal %edx 1 "F - test-var-with-type/type") + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +test-parse-var-with-type-and-register: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # (eax..ecx) = "x/eax" + b8/copy-to-eax "x/eax"/imm32 + 8b/-> *eax 1/r32/ecx + 8d/copy-address *(eax+ecx+4) 1/r32/ecx + 05/add-to-eax 4/imm32 + # var slice/ecx = {eax, ecx} + 51/push-ecx + 50/push-eax + 89/<- %ecx 4/r32/esp + # _test-input-stream contains ": int" + (clear-stream _test-input-stream) + (clear-stream _test-input-buffered-file->buffer) + (write _test-input-stream ": int") + # + (parse-var-with-type %ecx _test-input-buffered-file) + 8b/-> *eax 2/r32/edx # Var-name + (check-string-equal %edx "x" "F - test-var-with-type-and-register/name") + 8b/-> *(eax+0x10) 2/r32/edx # Var-register + (check-string-equal %edx "eax" "F - test-var-with-type-and-register/register") + 8b/-> *(eax+4) 2/r32/edx # Var-type + (check-ints-equal %edx 1 "F - test-var-with-type-and-register/type") + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + # identifier starts with a letter or '$' or '_' # no constraints at the moment on later letters # all we really want to do so far is exclude '{', '}' and '->' |