diff options
Diffstat (limited to 'apps/braces.subx')
-rw-r--r-- | apps/braces.subx | 359 |
1 files changed, 0 insertions, 359 deletions
diff --git a/apps/braces.subx b/apps/braces.subx deleted file mode 100644 index d6b8f0f4..00000000 --- a/apps/braces.subx +++ /dev/null @@ -1,359 +0,0 @@ -# Structured control flow using break/loop rather than jump. -# -# To run (on Linux): -# $ ./translate_subx init.linux [012]*.subx apps/subx-params.subx apps/braces.subx -# $ mv a.elf apps/braces -# -# Example 1: -# $ cat x.subx -# { -# 7c/jump-if-< break/disp8 -# 74/jump-if-= loop/disp8 -# } -# $ cat x.subx |apps/braces -# _loop1: -# 7c/jump-if-< _break1/disp8 -# 74/jump-if-= _loop1/disp8 -# _break1: -# -# Example 2: -# $ cat x.subx -# { -# 7c/jump-if-< break/disp8 -# } -# { -# 74/jump-if-= loop/disp8 -# } -# $ cat x.subx |apps/braces -# _loop1: -# 7c/jump-if-< _break1/disp8 -# _break1: -# _loop2: -# 74/jump-if-= _loop2/disp8 -# _break2: -# -# Example 3: -# $ cat x.subx -# { -# { -# 74/jump-if-= loop/disp8 -# } -# 7c/jump-if-< loop/disp8 -# } -# $ cat x.subx |apps/braces -# _loop1: -# _loop2: -# 74/jump-if-= _loop2/disp8 -# _break2: -# 7c/jump-if-< _loop1/disp8 -# _break1: - -== code - -Entry: # run tests if necessary, a REPL if not - # . prologue - 89/<- %ebp 4/r32/esp - # initialize heap - (new-segment *Heap-size Heap) - # if (argc <= 1) goto interactive - 81 7/subop/compare *ebp 1/imm32 - 7e/jump-if-<= $subx-braces-main:interactive/disp8 - # if (argv[1] != "test")) goto interactive - (kernel-string-equal? *(ebp+8) "test") # => eax - 3d/compare-eax-and 0/imm32/false - 74/jump-if-= $subx-braces-main:interactive/disp8 - # - (run-tests) - # syscall(exit, *Num-test-failures) - 8b/-> *Num-test-failures 3/r32/ebx - eb/jump $subx-braces-main:end/disp8 -$subx-braces-main:interactive: - (subx-braces Stdin Stdout) - # syscall(exit, 0) - bb/copy-to-ebx 0/imm32 -$subx-braces-main:end: - e8/call syscall_exit/disp32 - -subx-braces: # in: (addr buffered-file), out: (addr buffered-file) - # pseudocode: - # var line: (stream byte 512) - # var label-stack: (stack int 32) # at most 32 levels of nesting - # var next-label-id: int = 1 - # while true - # clear-stream(line) - # read-line-buffered(in, line) - # if (line->write == 0) break # end of file - # skip-chars-matching-whitespace(line) - # if line->data[line->read] == '{' - # print(out, "_loop" next-label-id ":\n") - # push(label-stack, next-label-id) - # ++next-label-id - # continue - # if line->data[line->read] == '}' - # var top = pop(label-stack) - # print(out, "_break" top ":\n") - # continue - # while true - # var word-slice: (addr slice) = next-word-or-string(line) - # if slice-empty?(word-slice) # end of line - # break - # if slice-starts-with?(word-slice, "#") # comment - # continue - # if slice-starts-with?(word-slice, "break/") - # var top = top(label-stack) - # print(out, "_break" top) - # word-slice->start += len("break") - # else if slice-starts-with?(word-slice, "loop/") - # var top = top(label-stack) - # print(out, "_loop" top) - # word-slice->start += len("loop") - # print(out, word-slice " ") - # print(out, "\n") - # flush(out) - # . prologue - 55/push-ebp - 89/<- %ebp 4/r32/esp - # . save registers - 50/push-eax - 51/push-ecx - 52/push-edx - 53/push-ebx - 56/push-esi - 57/push-edi - # esi = in - 8b/-> *(ebp+8) 6/r32/esi - # var line/ecx: (stream byte 512) - 81 5/subop/subtract %esp 0x200/imm32 - 68/push 0x200/imm32/length - 68/push 0/imm32/read - 68/push 0/imm32/write - 89/<- %ecx 4/r32/esp - # var label-stack/edx: (stack int 32) - 81 5/subop/subtract %esp 0x80/imm32 - 68/push 0x80/imm32/length - 68/push 0/imm32/top - 89/<- %edx 4/r32/esp - # var next-label-id/ebx: int = 1 - c7 0/subop/copy %ebx 1/imm32 - # var word-slice/edi: slice - 68/push 0/imm32/end - 68/push 0/imm32/start - 89/<- %edi 4/r32/esp -$subx-braces:line-loop: - (clear-stream %ecx) - (read-line-buffered %esi %ecx) -$subx-braces:check0: - # if (line->write == 0) break - 81 7/subop/compare *ecx 0/imm32 - 0f 84/jump-if-= $subx-braces:break/disp32 - (skip-chars-matching-whitespace %ecx) -$subx-braces:check-for-curly-open: - # if (line->data[line->read] != '{') goto next check - # . eax = line->data[line->read] - 8b/-> *(ecx+4) 0/r32/eax - 8a/copy-byte *(ecx+eax+0xc) 0/r32/AL - 81 4/subop/and %eax 0xff/imm32 - # . if (eax != '{') continue - 3d/compare-eax-and 0x7b/imm32/open-curly - 0f 85/jump-if-!= $subx-braces:check-for-curly-closed/disp32 -$subx-braces:emit-curly-open: - # print(out, "_loop" next-label-id ":") - (write-buffered *(ebp+0xc) "_loop") - (write-int32-hex-buffered *(ebp+0xc) %ebx) - (write-buffered *(ebp+0xc) ":") - # push(label-stack, next-label-id) - (push %edx %ebx) - # ++next-label-id - ff 0/subop/increment %ebx - # continue - e9/jump $subx-braces:next-line/disp32 -$subx-braces:check-for-curly-closed: - # if (line->data[line->read] != '}') goto next check - 3d/compare-eax-and 0x7d/imm32/close-curly - 0f 85/jump-if-= $subx-braces:word-loop/disp32 -$subx-braces:emit-curly-closed: - # eax = pop(label-stack) - (pop %edx) - # print(out, "_break" eax ":") - (write-buffered *(ebp+0xc) "_break") - (write-int32-hex-buffered *(ebp+0xc) %eax) - (write-buffered *(ebp+0xc) ":") - # continue - e9/jump $subx-braces:next-line/disp32 -$subx-braces:word-loop: - (next-word-or-string %ecx %edi) -$subx-braces:check1: - # if (slice-empty?(word-slice)) break - (slice-empty? %edi) - 3d/compare-eax-and 0/imm32/false - 0f 85/jump-if-!= $subx-braces:next-line/disp32 -$subx-braces:check-for-comment: - # if (slice-starts-with?(word-slice, "#")) continue - # . eax = *word-slice->start - 8b/-> *edi 0/r32/eax - 8a/copy-byte *eax 0/r32/AL - 81 4/subop/and %eax 0xff/imm32 - # . if (eax == '#') continue - 3d/compare-eax-and 0x23/imm32/hash - 74/jump-if-= $subx-braces:word-loop/disp8 -$subx-braces:check-for-break: - # if (!slice-starts-with?(word-slice, "break/")) goto next check - # . eax = slice-starts-with?(word-slice, "break/") - (slice-starts-with? %edi "break/") - # . if (eax == false) goto next check - 3d/compare-eax-and 0/imm32/false - 74/jump-if-= $subx-braces:check-for-loop/disp8 -$subx-braces:emit-break: - (top %edx) - # print(out, "_break" eax) - (write-buffered *(ebp+0xc) "_break") - (write-int32-hex-buffered *(ebp+0xc) %eax) - # word-slice->start += len("break") - 81 0/subop/add *edi 5/imm32/strlen - # emit rest of word as usual - eb/jump $subx-braces:emit-word-slice/disp8 -$subx-braces:check-for-loop: - # if (!slice-starts-with?(word-slice, "loop/")) emit word - # . eax = slice-starts-with?(word-slice, "loop/") - (slice-starts-with? %edi "loop/") - # . if (eax == false) goto next check - 3d/compare-eax-and 0/imm32/false - 74/jump-if-= $subx-braces:emit-word-slice/disp8 -$subx-braces:emit-loop: - (top %edx) - # print(out, "_loop" eax) - (write-buffered *(ebp+0xc) "_loop") - (write-int32-hex-buffered *(ebp+0xc) %eax) - # word-slice->start += len("loop") - 81 0/subop/add *edi 4/imm32/strlen - # fall through -$subx-braces:emit-word-slice: - # print(out, word-slice " ") - (write-slice-buffered *(ebp+0xc) %edi) - (write-buffered *(ebp+0xc) Space) - # loop to next word - e9/jump $subx-braces:word-loop/disp32 -$subx-braces:next-line: - # print(out, "\n") - (write-buffered *(ebp+0xc) Newline) - # loop to next line - e9/jump $subx-braces:line-loop/disp32 -$subx-braces:break: - (flush *(ebp+0xc)) -$subx-braces:end: - # . reclaim locals - 81 0/subop/add %esp 0x29c/imm32 - # . restore registers - 5f/pop-to-edi - 5e/pop-to-esi - 5b/pop-to-ebx - 5a/pop-to-edx - 59/pop-to-ecx - 58/pop-to-eax - # . epilogue - 89/<- %esp 5/r32/ebp - 5d/pop-to-ebp - c3/return - -test-subx-braces-passes-most-words-through: - # . prologue - 55/push-ebp - 89/<- %ebp 4/r32/esp - # setup - (clear-stream _test-input-stream) - (clear-stream _test-output-stream) - (clear-stream $_test-input-buffered-file->buffer) - (clear-stream $_test-output-buffered-file->buffer) - # test - (write _test-input-stream "== abcd 0x1") - (subx-braces _test-input-buffered-file _test-output-buffered-file) - # check that the line just passed through - (flush _test-output-buffered-file) -#? # dump _test-output-stream {{{ -#? (write 2 "^") -#? (write-stream 2 _test-output-stream) -#? (write 2 "$\n") -#? # }}} - (check-stream-equal _test-output-stream "== abcd 0x1 \n" "F - test-subx-braces-passes-most-words-through") - # . epilogue - 89/<- %esp 5/r32/ebp - 5d/pop-to-ebp - c3/return - -test-subx-braces-1: - # input: - # { - # ab break/imm32 - # cd loop/imm32 - # } - # - # output: - # _loop1: - # ab _break1/imm32 - # cd _loop1/imm32 - # _break1: - # - # . prologue - 55/push-ebp - 89/<- %ebp 4/r32/esp - # setup - (clear-stream _test-input-stream) - (clear-stream _test-output-stream) - (clear-stream $_test-input-buffered-file->buffer) - (clear-stream $_test-output-buffered-file->buffer) - # test - (write _test-input-stream "{\nab break/imm32\ncd loop/imm32\n}") - (subx-braces _test-input-buffered-file _test-output-buffered-file) - # check that the line just passed through - (flush _test-output-buffered-file) -#? # dump _test-output-stream {{{ -#? (write 2 "^") -#? (write-stream 2 _test-output-stream) -#? (write 2 "$\n") -#? # }}} - (check-stream-equal _test-output-stream "_loop0x00000001:\nab _break0x00000001/imm32 \ncd _loop0x00000001/imm32 \n_break0x00000001:\n" "F - test-subx-braces-1") - # . epilogue - 89/<- %esp 5/r32/ebp - 5d/pop-to-ebp - c3/return - -test-subx-braces-2: - # input: - # { - # { - # ab break/imm32 - # } - # cd loop/imm32 - # } - # - # output: - # _loop1: - # _loop2: - # ab _break2/imm32 - # _break2: - # cd _loop1/imm32 - # _break1: - # - # . prologue - 55/push-ebp - 89/<- %ebp 4/r32/esp - # setup - (clear-stream _test-input-stream) - (clear-stream _test-output-stream) - (clear-stream $_test-input-buffered-file->buffer) - (clear-stream $_test-output-buffered-file->buffer) - # test - (write _test-input-stream "{\n{\nab break/imm32\n}\ncd loop/imm32\n}") - (subx-braces _test-input-buffered-file _test-output-buffered-file) - # check that the line just passed through - (flush _test-output-buffered-file) -#? # dump _test-output-stream {{{ -#? (write 2 "^") -#? (write-stream 2 _test-output-stream) -#? (write 2 "$\n") -#? # }}} - (check-stream-equal _test-output-stream "_loop0x00000001:\n_loop0x00000002:\nab _break0x00000002/imm32 \n_break0x00000002:\ncd _loop0x00000001/imm32 \n_break0x00000001:\n" "F - test-subx-braces-2") - # . epilogue - 89/<- %esp 5/r32/ebp - 5d/pop-to-ebp - c3/return |