about summary refs log tree commit diff stats
path: root/apps/braces.subx
diff options
context:
space:
mode:
Diffstat (limited to 'apps/braces.subx')
-rw-r--r--apps/braces.subx359
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