From a8fb537a88fdbe77cdcbaa05ee28d1cad94550da Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Wed, 21 Apr 2021 08:28:00 -0700 Subject: . --- html/101screen.subx.html | 8 +- html/102keyboard.subx.html | 6 +- html/103grapheme.subx.html | 8 +- html/104test.subx.html | 6 +- html/105string-equal.subx.html | 8 +- html/106stream.subx.html | 8 +- html/108write.subx.html | 8 +- html/109stream-equal.subx.html | 8 +- html/112read-byte.subx.html | 8 +- html/113write-stream.subx.html | 8 +- html/115write-byte.subx.html | 8 +- html/117write-int-hex.subx.html | 8 +- html/118parse-hex-int.subx.html | 8 +- html/120allocate.subx.html | 8 +- html/121new-stream.subx.html | 8 +- html/123slice.subx.html | 8 +- html/124next-token.subx.html | 8 +- html/126write-int-decimal.subx.html | 8 +- html/127next-word.subx.html | 8 +- html/301array-equal.subx.html | 6 +- html/302stack_allocate.subx.html | 6 +- html/308allocate-array.subx.html | 6 +- html/309stream.subx.html | 6 +- html/310copy-bytes.subx.html | 6 +- html/311decimal-int.subx.html | 6 +- html/312copy.subx.html | 6 +- html/313index-bounds-check.subx.html | 6 +- html/314divide.subx.html | 6 +- html/315stack-debug.subx.html | 135 + html/400.mu.html | 143 +- html/403unicode.mu.html | 6 +- html/408float.mu.html | 6 +- html/411string.mu.html | 6 +- html/412render-float-decimal.mu.html | 12 +- html/500fake-screen.mu.html | 580 + html/500text-screen.mu.html | 443 - html/501draw-text.mu.html | 220 +- html/502test.mu.html | 6 +- html/503manhattan-line.mu.html | 6 +- html/504test-screen.mu.html | 92 +- html/boot.subx.html | 1351 +- html/ex1.mu.html | 8 +- html/ex1.subx.html | 79 - html/ex10.mu.html | 22 +- html/ex2.mu.html | 14 +- html/ex2.subx.html | 91 - html/ex3.mu.html | 14 +- html/ex4.mu.html | 16 +- html/ex5.mu.html | 18 +- html/ex6.mu.html | 34 +- html/ex7.mu.html | 26 +- html/ex8.mu.html | 12 +- html/ex9.mu.html | 16 +- html/life.mu.html | 10 +- html/linux/000init.subx.html | 6 +- html/linux/101_write.subx.html | 8 +- html/linux/102test.subx.html | 8 +- html/linux/103kernel-string-equal.subx.html | 8 +- html/linux/104new-segment.subx.html | 8 +- html/linux/105string-equal.subx.html | 8 +- html/linux/106stream.subx.html | 8 +- html/linux/107trace.subx.html | 8 +- html/linux/108write.subx.html | 8 +- html/linux/109stream-equal.subx.html | 8 +- html/linux/110stop.subx.html | 8 +- html/linux/111read.subx.html | 8 +- html/linux/112read-byte.subx.html | 8 +- html/linux/113write-stream.subx.html | 8 +- html/linux/114error.subx.html | 8 +- html/linux/115write-byte.subx.html | 8 +- html/linux/116write-buffered.subx.html | 8 +- html/linux/117write-int-hex.subx.html | 8 +- html/linux/118parse-hex-int.subx.html | 8 +- html/linux/119error-byte.subx.html | 8 +- html/linux/120allocate.subx.html | 8 +- html/linux/121new-stream.subx.html | 8 +- html/linux/122read-line.subx.html | 8 +- html/linux/123slice.subx.html | 8 +- html/linux/124next-token.subx.html | 8 +- html/linux/125write-stream-data.subx.html | 8 +- html/linux/126write-int-decimal.subx.html | 8 +- html/linux/127next-word.subx.html | 8 +- html/linux/128subx-words.subx.html | 8 +- html/linux/129emit-hex.subx.html | 8 +- html/linux/130emit.subx.html | 8 +- html/linux/131table.subx.html | 8 +- html/linux/132slurp.subx.html | 8 +- html/linux/133subx-widths.subx.html | 8 +- html/linux/134emit-hex-array.subx.html | 8 +- html/linux/135next-word-or-string.subx.html | 8 +- html/linux/201register-names.subx.html | 6 +- html/linux/202write-int.subx.html | 8 +- html/linux/203stack.subx.html | 8 +- html/linux/301array-equal.subx.html | 6 +- html/linux/302stack_allocate.subx.html | 6 +- html/linux/303kernel-string.subx.html | 6 +- html/linux/304screen.subx.html | 6 +- html/linux/305keyboard.subx.html | 6 +- html/linux/306files.subx.html | 6 +- html/linux/307size.subx.html | 6 +- html/linux/308allocate-array.subx.html | 6 +- html/linux/309stream.subx.html | 6 +- html/linux/310copy-bytes.subx.html | 6 +- html/linux/311decimal-int.subx.html | 6 +- html/linux/312copy.subx.html | 6 +- html/linux/313index-bounds-check.subx.html | 6 +- html/linux/314divide.subx.html | 6 +- html/linux/315slice.subx.html | 6 +- html/linux/400.mu.html | 6 +- html/linux/401test.mu.html | 6 +- html/linux/402time.mu.html | 6 +- html/linux/403unicode.mu.html | 6 +- html/linux/404stream.mu.html | 6 +- html/linux/405screen.mu.html | 6 +- html/linux/406int32.mu.html | 6 +- html/linux/407right-justify.mu.html | 6 +- html/linux/408float.mu.html | 6 +- html/linux/409print-float-hex.mu.html | 6 +- html/linux/410file.mu.html | 6 +- html/linux/411string.mu.html | 6 +- html/linux/412print-float-decimal.mu.html | 6 +- html/linux/advent2020/1a.mu.html | 6 +- html/linux/advent2020/1b.mu.html | 6 +- html/linux/advent2020/2a.mu.html | 6 +- html/linux/advent2020/2b.mu.html | 6 +- html/linux/advent2020/3a.mu.html | 6 +- html/linux/advent2020/3b.mu.html | 6 +- html/linux/advent2020/4a.mu.html | 6 +- html/linux/advent2020/4b.mu.html | 6 +- html/linux/advent2020/5a.mu.html | 6 +- html/linux/advent2020/5b.mu.html | 6 +- html/linux/arith.mu.html | 6 +- html/linux/assort.subx.html | 10 +- html/linux/bootstrap/000organization.cc.html | 8 +- html/linux/bootstrap/001help.cc.html | 8 +- html/linux/bootstrap/002test.cc.html | 8 +- html/linux/bootstrap/003trace.cc.html | 8 +- html/linux/bootstrap/003trace.test.cc.html | 8 +- html/linux/bootstrap/010vm.cc.html | 8 +- html/linux/bootstrap/011run.cc.html | 10 +- html/linux/bootstrap/012elf.cc.html | 8 +- html/linux/bootstrap/013direct_addressing.cc.html | 8 +- .../linux/bootstrap/014indirect_addressing.cc.html | 8 +- .../bootstrap/015immediate_addressing.cc.html | 8 +- html/linux/bootstrap/016index_addressing.cc.html | 8 +- html/linux/bootstrap/017jump_disp8.cc.html | 8 +- html/linux/bootstrap/018jump_disp32.cc.html | 8 +- html/linux/bootstrap/019functions.cc.html | 8 +- html/linux/bootstrap/020byte_addressing.cc.html | 8 +- html/linux/bootstrap/021div.cc.html | 8 +- html/linux/bootstrap/022float.cc.html | 8 +- html/linux/bootstrap/029syscalls.cc.html | 8 +- html/linux/bootstrap/030translate.cc.html | 8 +- html/linux/bootstrap/031transforms.cc.html | 8 +- html/linux/bootstrap/032operands.cc.html | 1126 +- html/linux/bootstrap/033check_operands.cc.html | 1270 +- .../bootstrap/034check_operand_bounds.cc.html | 12 +- .../bootstrap/035compute_segment_address.cc.html | 8 +- html/linux/bootstrap/036labels.cc.html | 12 +- html/linux/bootstrap/037global_variables.cc.html | 10 +- html/linux/bootstrap/038literal_strings.cc.html | 10 +- html/linux/bootstrap/039debug.cc.html | 8 +- html/linux/bootstrap/040tests.cc.html | 8 +- html/linux/braces.subx.html | 16 +- html/linux/calls.subx.html | 14 +- html/linux/crenshaw2-1.subx.html | 10 +- html/linux/crenshaw2-1b.subx.html | 10 +- html/linux/dquotes.subx.html | 10 +- html/linux/ex1.mu.html | 6 +- html/linux/ex1.subx.html | 8 +- html/linux/ex10.subx.html | 10 +- html/linux/ex11.subx.html | 10 +- html/linux/ex12.subx.html | 10 +- html/linux/ex13.subx.html | 10 +- html/linux/ex14.subx.html | 10 +- html/linux/ex2.mu.html | 6 +- html/linux/ex2.subx.html | 8 +- html/linux/ex3.2.mu.html | 6 +- html/linux/ex3.mu.html | 6 +- html/linux/ex3.subx.html | 10 +- html/linux/ex4.subx.html | 8 +- html/linux/ex5.subx.html | 10 +- html/linux/ex6.subx.html | 10 +- html/linux/ex7.subx.html | 10 +- html/linux/ex8.subx.html | 10 +- html/linux/ex9.subx.html | 10 +- html/linux/factorial.mu.html | 8 +- html/linux/factorial.subx.html | 10 +- html/linux/factorial2.subx.html | 10 +- html/linux/factorial3.subx.html | 10 +- html/linux/factorial4.subx.html | 10 +- html/linux/hello.mu.html | 6 +- html/linux/hex.subx.html | 10 +- html/linux/mu-init-test.subx.html | 6 +- html/linux/mu-init.subx.html | 6 +- html/linux/mu.subx.html | 70817 ++++++++++--------- html/linux/pack.subx.html | 10 +- html/linux/parse-int.mu.html | 6 +- html/linux/print-file.mu.html | 6 +- html/linux/random.subx.html | 10 +- html/linux/raytracing/1.mu.html | 6 +- html/linux/raytracing/2.mu.html | 6 +- html/linux/raytracing/3.mu.html | 6 +- html/linux/raytracing/color.mu.html | 6 +- html/linux/raytracing/ray.mu.html | 6 +- html/linux/raytracing/vec.mu.html | 6 +- html/linux/rpn.mu.html | 6 +- html/linux/sigils.subx.html | 10 +- html/linux/subx-params.subx.html | 6 +- html/linux/survey_baremetal.subx.html | 10 +- html/linux/survey_elf.subx.html | 10 +- html/linux/tests.subx.html | 10 +- html/linux/texture.mu.html | 6 +- html/linux/tile/box.mu.html | 6 +- html/linux/tile/data.mu.html | 6 +- html/linux/tile/environment.mu.html | 6 +- html/linux/tile/float-stack.mu.html | 6 +- html/linux/tile/gap-buffer.mu.html | 6 +- html/linux/tile/grapheme-stack.mu.html | 6 +- html/linux/tile/main.mu.html | 6 +- html/linux/tile/rpn.mu.html | 6 +- html/linux/tile/surface.mu.html | 6 +- html/linux/tile/table.mu.html | 6 +- html/linux/tile/value-stack.mu.html | 6 +- html/linux/tile/value.mu.html | 6 +- html/linux/tile/word.mu.html | 6 +- html/linux/tui.mu.html | 6 +- html/mu-init.subx.html | 10 +- html/rpn.mu.html | 22 +- html/shell/cell.mu.html | 221 +- html/shell/eval.mu.html | 808 - html/shell/evaluate.mu.html | 1648 +- html/shell/gap-buffer.mu.html | 2104 +- html/shell/global.mu.html | 2546 +- html/shell/grapheme-stack.mu.html | 130 +- html/shell/life.mu.html | 308 + html/shell/main.mu.html | 198 +- html/shell/parse.mu.html | 368 +- html/shell/print.mu.html | 689 +- html/shell/read.mu.html | 8 +- html/shell/sandbox.mu.html | 1634 +- html/shell/tokenize.mu.html | 1143 +- html/shell/trace.mu.html | 2994 +- 243 files changed, 47168 insertions(+), 45738 deletions(-) create mode 100644 html/315stack-debug.subx.html create mode 100644 html/500fake-screen.mu.html delete mode 100644 html/500text-screen.mu.html delete mode 100644 html/ex1.subx.html delete mode 100644 html/ex2.subx.html delete mode 100644 html/shell/eval.mu.html create mode 100644 html/shell/life.mu.html (limited to 'html') diff --git a/html/101screen.subx.html b/html/101screen.subx.html index a71f6afb..4ce0397a 100644 --- a/html/101screen.subx.html +++ b/html/101screen.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/106stream.subx.html b/html/106stream.subx.html index 01f83b8c..8af354dc 100644 --- a/html/106stream.subx.html +++ b/html/106stream.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/108write.subx.html b/html/108write.subx.html index d1bc4070..4249e689 100644 --- a/html/108write.subx.html +++ b/html/108write.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/109stream-equal.subx.html b/html/109stream-equal.subx.html index 203c2049..95af3eba 100644 --- a/html/109stream-equal.subx.html +++ b/html/109stream-equal.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/112read-byte.subx.html b/html/112read-byte.subx.html index 7d1dd982..8ec265a5 100644 --- a/html/112read-byte.subx.html +++ b/html/112read-byte.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/113write-stream.subx.html b/html/113write-stream.subx.html index bbc72493..0a221564 100644 --- a/html/113write-stream.subx.html +++ b/html/113write-stream.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/115write-byte.subx.html b/html/115write-byte.subx.html index df6d9863..a2e626f2 100644 --- a/html/115write-byte.subx.html +++ b/html/115write-byte.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/117write-int-hex.subx.html b/html/117write-int-hex.subx.html index 754e1696..50fba74e 100644 --- a/html/117write-int-hex.subx.html +++ b/html/117write-int-hex.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/120allocate.subx.html b/html/120allocate.subx.html index 84f65426..7f280d61 100644 --- a/html/120allocate.subx.html +++ b/html/120allocate.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/121new-stream.subx.html b/html/121new-stream.subx.html index fe952139..38e1f288 100644 --- a/html/121new-stream.subx.html +++ b/html/121new-stream.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/123slice.subx.html b/html/123slice.subx.html index 6e7a15a2..7ad2d84e 100644 --- a/html/123slice.subx.html +++ b/html/123slice.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/124next-token.subx.html b/html/124next-token.subx.html index 21660396..61923f29 100644 --- a/html/124next-token.subx.html +++ b/html/124next-token.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/126write-int-decimal.subx.html b/html/126write-int-decimal.subx.html index b77ab267..02126064 100644 --- a/html/126write-int-decimal.subx.html +++ b/html/126write-int-decimal.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/127next-word.subx.html b/html/127next-word.subx.html index 7305ad06..29049a37 100644 --- a/html/127next-word.subx.html +++ b/html/127next-word.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/301array-equal.subx.html b/html/301array-equal.subx.html index f516d9d2..c80d945b 100644 --- a/html/301array-equal.subx.html +++ b/html/301array-equal.subx.html @@ -7,11 +7,11 @@ - + + + + + +https://github.com/akkartik/mu/blob/main/315stack-debug.subx +
+ 1 # The stack shouldn't grow into the code area.
+ 2 
+ 3 == code
+ 4 
+ 5 check-stack:
+ 6     # . prologue
+ 7     55/push-ebp
+ 8     89/<- %ebp 4/r32/esp
+ 9     # . save registers
+10     50/push-eax
+11     #
+12     89/<- %eax 4/r32/esp
+13     81 7/subop/compare %eax 0x48600/imm32
+14     {
+15       7f/jump-if-> break/disp8
+16       (abort "stack overflow")
+17     }
+18 $check-stack:end:
+19     # . restore registers
+20     58/pop-to-eax
+21     # . epilogue
+22     89/<- %esp 5/r32/ebp
+23     5d/pop-to-ebp
+24     c3/return
+25 
+26 show-stack-state:
+27     # . prologue
+28     55/push-ebp
+29     89/<- %ebp 4/r32/esp
+30     # . save registers
+31     50/push-eax
+32     51/push-ecx
+33     52/push-edx
+34     #
+35     89/<- %edx 4/r32/esp
+36     # save old cursor position
+37     (cursor-position 0)  # => eax, ecx
+38     # print at top-right
+39     (set-cursor-position 0 0x70 0)
+40     (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 0xf 0xc)
+41     # restore cursor position
+42     (set-cursor-position %eax %ecx)
+43 $check-stack:end:
+44     # . restore registers
+45     5a/pop-to-edx
+46     59/pop-to-ecx
+47     58/pop-to-eax
+48     # . epilogue
+49     89/<- %esp 5/r32/ebp
+50     5d/pop-to-ebp
+51     c3/return
+52 
+53 # Helper for debugging deeply recursive calls without logs or traces.
+54 # Turn it on, insert calls in the right places, and you get a terse sense of
+55 # important parts of the call stack. A poor sophont's stack trace.
+56 debug-print:  # x: (addr array byte), fg: int, bg: int    # x is very short; usually a single character
+57     # . prologue
+58     55/push-ebp
+59     89/<- %ebp 4/r32/esp
+60     #
+61     {
+62       81 7/subop/compare *Really-debug-print 0/imm32/false
+63       74/jump-if-= break/disp8
+64       (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 *(ebp+8) *(ebp+0xc) *(ebp+0x10))
+65     }
+66 $debug-print:end:
+67     # . epilogue
+68     89/<- %esp 5/r32/ebp
+69     5d/pop-to-ebp
+70     c3/return
+71 
+72 == data
+73 Really-debug-print:
+74   0/imm32/false
+
+ + + diff --git a/html/400.mu.html b/html/400.mu.html index 0a224eac..a27ffed8 100644 --- a/html/400.mu.html +++ b/html/400.mu.html @@ -7,11 +7,11 @@ - + + + + + +https://github.com/akkartik/mu/blob/main/500fake-screen.mu +
+  1 # Testable primitives for writing to screen.
+  2 #
+  3 # Mu mostly uses the screen for text, but it builds it out of pixel graphics
+  4 # and a bitmap font. There is no support for a blinking cursor, scrolling and
+  5 # so on.
+  6 #
+  7 # Fake screens are primarily for testing text-mode prints. However, they do
+  8 # support some rudimentary pixel operations as well. Caveats:
+  9 #
+ 10 # - Drawing pixels atop text or vice versa is not supported. Results in a fake
+ 11 #   screen will not mimic real screens in these situations.
+ 12 # - Fake screens currently also assume a fixed-width 8x16 font.
+ 13 
+ 14 type screen {
+ 15   # text mode
+ 16   width: int
+ 17   height: int
+ 18   data: (handle array screen-cell)
+ 19   cursor-x: int  # [0..width)
+ 20   cursor-y: int  # [0..height)
+ 21   # pixel graphics
+ 22   pixels: (handle array byte)
+ 23 }
+ 24 
+ 25 type screen-cell {
+ 26   data: grapheme
+ 27   color: int
+ 28   background-color: int
+ 29 }
+ 30 
+ 31 fn initialize-screen _screen: (addr screen), width: int, height: int, pixel-graphics?: boolean {
+ 32   var screen/esi: (addr screen) <- copy _screen
+ 33   var tmp/eax: int <- copy 0
+ 34   var dest/edi: (addr int) <- copy 0
+ 35   # screen->width = width
+ 36   dest <- get screen, width
+ 37   tmp <- copy width
+ 38   copy-to *dest, tmp
+ 39   # screen->height = height
+ 40   dest <- get screen, height
+ 41   tmp <- copy height
+ 42   copy-to *dest, tmp
+ 43   # populate screen->data
+ 44   {
+ 45     var data-ah/edi: (addr handle array screen-cell) <- get screen, data
+ 46     var capacity/eax: int <- copy width
+ 47     capacity <- multiply height
+ 48     populate data-ah, capacity
+ 49   }
+ 50   # if necessary, populate screen->pixels
+ 51   {
+ 52     compare pixel-graphics?, 0/false
+ 53     break-if-=
+ 54     var pixels-ah/edi: (addr handle array byte) <- get screen, pixels
+ 55     var capacity/eax: int <- copy width
+ 56     capacity <- shift-left 3/log2-font-width
+ 57     capacity <- multiply height
+ 58     capacity <- shift-left 4/log2-font-height
+ 59     populate pixels-ah, capacity
+ 60   }
+ 61   # screen->cursor-x = 0
+ 62   dest <- get screen, cursor-x
+ 63   copy-to *dest, 0
+ 64   # screen->cursor-y = 0
+ 65   dest <- get screen, cursor-y
+ 66   copy-to *dest, 0
+ 67 }
+ 68 
+ 69 # in graphemes
+ 70 fn screen-size _screen: (addr screen) -> _/eax: int, _/ecx: int {
+ 71   var screen/esi: (addr screen) <- copy _screen
+ 72   var width/eax: int <- copy 0
+ 73   var height/ecx: int <- copy 0
+ 74   compare screen, 0
+ 75   {
+ 76     break-if-!=
+ 77     return 0x80/128, 0x30/48
+ 78   }
+ 79   # fake screen
+ 80   var tmp/edx: (addr int) <- get screen, width
+ 81   width <- copy *tmp
+ 82   tmp <- get screen, height
+ 83   height <- copy *tmp
+ 84   return width, height
+ 85 }
+ 86 
+ 87 # testable screen primitive
+ 88 fn draw-grapheme _screen: (addr screen), g: grapheme, x: int, y: int, color: int, background-color: int {
+ 89   var screen/esi: (addr screen) <- copy _screen
+ 90   {
+ 91     compare screen, 0
+ 92     break-if-!=
+ 93     draw-grapheme-on-real-screen g, x, y, color, background-color
+ 94     return
+ 95   }
+ 96   # fake screen
+ 97   var idx/ecx: int <- screen-cell-index screen, x, y
+ 98   var data-ah/eax: (addr handle array screen-cell) <- get screen, data
+ 99   var data/eax: (addr array screen-cell) <- lookup *data-ah
+100   var offset/ecx: (offset screen-cell) <- compute-offset data, idx
+101   var dest-cell/ecx: (addr screen-cell) <- index data, offset
+102   var dest-grapheme/eax: (addr grapheme) <- get dest-cell, data
+103   var g2/edx: grapheme <- copy g
+104   copy-to *dest-grapheme, g2
+105   var dest-color/eax: (addr int) <- get dest-cell, color
+106   var src-color/edx: int <- copy color
+107   copy-to *dest-color, src-color
+108   dest-color <- get dest-cell, background-color
+109   src-color <- copy background-color
+110   copy-to *dest-color, src-color
+111 }
+112 
+113 # we can't really render non-ASCII yet, but when we do we'll be ready
+114 fn draw-code-point screen: (addr screen), c: code-point, x: int, y: int, color: int, background-color: int {
+115   var g/eax: grapheme <- copy c
+116   draw-grapheme screen, g, x, y, color, background-color
+117 }
+118 
+119 # not really needed for a real screen, though it shouldn't do any harm
+120 fn screen-cell-index _screen: (addr screen), x: int, y: int -> _/ecx: int {
+121   var screen/esi: (addr screen) <- copy _screen
+122   {
+123     compare x, 0
+124     break-if->=
+125     abort "screen-cell-index: negative x"
+126   }
+127   {
+128     var xmax/eax: (addr int) <- get screen, width
+129     var xcurr/ecx: int <- copy x
+130     compare xcurr, *xmax
+131     break-if-<
+132     abort "screen-cell-index: x too high"
+133   }
+134   {
+135     compare y, 0
+136     break-if->=
+137     abort "screen-cell-index: negative y"
+138   }
+139   {
+140     var ymax/eax: (addr int) <- get screen, height
+141     var ycurr/ecx: int <- copy y
+142     compare ycurr, *ymax
+143     break-if-<
+144     abort "screen-cell-index: y too high"
+145   }
+146   var width-addr/eax: (addr int) <- get screen, width
+147   var result/ecx: int <- copy y
+148   result <- multiply *width-addr
+149   result <- add x
+150   return result
+151 }
+152 
+153 fn cursor-position _screen: (addr screen) -> _/eax: int, _/ecx: int {
+154   var screen/esi: (addr screen) <- copy _screen
+155   {
+156     compare screen, 0
+157     break-if-!=
+158     var x/eax: int <- copy 0
+159     var y/ecx: int <- copy 0
+160     x, y <- cursor-position-on-real-screen
+161     return x, y
+162   }
+163   # fake screen
+164   var cursor-x-addr/eax: (addr int) <- get screen, cursor-x
+165   var cursor-y-addr/ecx: (addr int) <- get screen, cursor-y
+166   return *cursor-x-addr, *cursor-y-addr
+167 }
+168 
+169 fn set-cursor-position _screen: (addr screen), x: int, y: int {
+170   var screen/esi: (addr screen) <- copy _screen
+171   {
+172     compare screen, 0
+173     break-if-!=
+174     set-cursor-position-on-real-screen x, y
+175     return
+176   }
+177   # fake screen
+178   # ignore x < 0
+179   {
+180     compare x, 0
+181     break-if->=
+182     return
+183   }
+184   # ignore x >= width
+185   {
+186     var width-addr/eax: (addr int) <- get screen, width
+187     var width/eax: int <- copy *width-addr
+188     compare x, width
+189     break-if-<=
+190     return
+191   }
+192   # ignore y < 0
+193   {
+194     compare y, 0
+195     break-if->=
+196     return
+197   }
+198   # ignore y >= height
+199   {
+200     var height-addr/eax: (addr int) <- get screen, height
+201     var height/eax: int <- copy *height-addr
+202     compare y, height
+203     break-if-<
+204     return
+205   }
+206   # screen->cursor-x = x
+207   var dest/edi: (addr int) <- get screen, cursor-x
+208   var src/eax: int <- copy x
+209   copy-to *dest, src
+210   # screen->cursor-y = y
+211   dest <- get screen, cursor-y
+212   src <- copy y
+213   copy-to *dest, src
+214 }
+215 
+216 fn draw-cursor screen: (addr screen), g: grapheme {
+217   {
+218     compare screen, 0
+219     break-if-!=
+220     draw-cursor-on-real-screen g
+221     return
+222   }
+223   # fake screen
+224   var cursor-x/eax: int <- copy 0
+225   var cursor-y/ecx: int <- copy 0
+226   cursor-x, cursor-y <- cursor-position screen
+227   draw-grapheme screen, g, cursor-x, cursor-y, 0/fg, 7/bg
+228 }
+229 
+230 fn clear-screen _screen: (addr screen) {
+231   var screen/esi: (addr screen) <- copy _screen
+232   {
+233     compare screen, 0
+234     break-if-!=
+235     clear-real-screen
+236     return
+237   }
+238   # fake screen
+239   set-cursor-position screen, 0, 0
+240   var y/eax: int <- copy 0
+241   var height/ecx: (addr int) <- get screen, height
+242   {
+243     compare y, *height
+244     break-if->=
+245     var x/edx: int <- copy 0
+246     var width/ebx: (addr int) <- get screen, width
+247     {
+248       compare x, *width
+249       break-if->=
+250       draw-code-point screen, 0x20/space, x, y, 0/fg=black, 0/bg=black
+251       x <- increment
+252       loop
+253     }
+254     y <- increment
+255     loop
+256   }
+257   set-cursor-position screen, 0, 0
+258   var pixels-ah/eax: (addr handle array byte) <- get screen, pixels
+259   var pixels/eax: (addr array byte) <- lookup *pixels-ah
+260   var i/ecx: int <- copy 0
+261   var max/edx: int <- length pixels
+262   {
+263     compare i, max
+264     break-if->=
+265     var curr/eax: (addr byte) <- index pixels, i
+266     var zero/ebx: byte <- copy 0
+267     copy-byte-to *curr, zero
+268     i <- increment
+269     loop
+270   }
+271 }
+272 
+273 fn fake-screen-empty? _screen: (addr screen) -> _/eax: boolean {
+274   var screen/esi: (addr screen) <- copy _screen
+275   var y/eax: int <- copy 0
+276   var height/ecx: (addr int) <- get screen, height
+277   {
+278     compare y, *height
+279     break-if->=
+280     var x/edx: int <- copy 0
+281     var width/ebx: (addr int) <- get screen, width
+282     {
+283       compare x, *width
+284       break-if->=
+285       var g/eax: grapheme <- screen-grapheme-at screen, x, y
+286       {
+287         compare g, 0
+288         break-if-=
+289         compare g, 0x20/space
+290         break-if-=
+291         return 0/false
+292       }
+293       x <- increment
+294       loop
+295     }
+296     y <- increment
+297     loop
+298   }
+299   var pixels-ah/eax: (addr handle array byte) <- get screen, pixels
+300   var pixels/eax: (addr array byte) <- lookup *pixels-ah
+301   var y/ebx: int <- copy 0
+302   var height-addr/edx: (addr int) <- get screen, height
+303   var height/edx: int <- copy *height-addr
+304   height <- shift-left 4/log2-font-height
+305   {
+306     compare y, height
+307     break-if->=
+308     var width-addr/edx: (addr int) <- get screen, width
+309     var width/edx: int <- copy *width-addr
+310     width <- shift-left 3/log2-font-width
+311     var x/edi: int <- copy 0
+312     {
+313       compare x, width
+314       break-if->=
+315       var idx/ecx: int <- pixel-index screen, x, y
+316       var color-addr/ecx: (addr byte) <- index pixels, idx
+317       var color/ecx: byte <- copy-byte *color-addr
+318       compare color, 0
+319       {
+320         break-if-=
+321         return 0/false
+322       }
+323       x <- increment
+324       loop
+325     }
+326     y <- increment
+327     loop
+328   }
+329   return 1/true
+330 }
+331 
+332 fn clear-rect _screen: (addr screen), xmin: int, ymin: int, xmax: int, ymax: int, background-color: int {
+333   var screen/esi: (addr screen) <- copy _screen
+334   {
+335     compare screen, 0
+336     break-if-!=
+337     clear-rect-on-real-screen xmin, ymin, xmax, ymax, background-color
+338     return
+339   }
+340   # fake screen
+341   set-cursor-position screen, 0, 0
+342   var y/eax: int <- copy ymin
+343   var ymax/ecx: int <- copy ymax
+344   {
+345     compare y, ymax
+346     break-if->=
+347     var x/edx: int <- copy xmin
+348     var xmax/ebx: int <- copy xmax
+349     {
+350       compare x, xmax
+351       break-if->=
+352       draw-code-point screen, 0x20/space, x, y, 0/fg, background-color
+353       x <- increment
+354       loop
+355     }
+356     y <- increment
+357     loop
+358   }
+359   set-cursor-position screen, 0, 0
+360 }
+361 
+362 # there's no grapheme that guarantees to cover every pixel, so we'll bump down
+363 # to pixels for a real screen
+364 fn clear-real-screen {
+365   var y/eax: int <- copy 0
+366   {
+367     compare y, 0x300/screen-height=768
+368     break-if->=
+369     var x/edx: int <- copy 0
+370     {
+371       compare x, 0x400/screen-width=1024
+372       break-if->=
+373       pixel-on-real-screen x, y, 0/color=black
+374       x <- increment
+375       loop
+376     }
+377     y <- increment
+378     loop
+379   }
+380 }
+381 
+382 fn clear-rect-on-real-screen xmin: int, ymin: int, xmax: int, ymax: int, background-color: int {
+383   var y/eax: int <- copy ymin
+384   y <- shift-left 4/log2-font-height
+385   var ymax/ecx: int <- copy ymax
+386   ymax <- shift-left 4/log2-font-height
+387   {
+388     compare y, ymax
+389     break-if->=
+390     var x/edx: int <- copy xmin
+391     x <- shift-left 3/log2-font-width
+392     var xmax/ebx: int <- copy xmax
+393     xmax <- shift-left 3/log2-font-width
+394     {
+395       compare x, xmax
+396       break-if->=
+397       pixel-on-real-screen x, y, background-color
+398       x <- increment
+399       loop
+400     }
+401     y <- increment
+402     loop
+403   }
+404 }
+405 
+406 fn screen-grapheme-at _screen: (addr screen), x: int, y: int -> _/eax: grapheme {
+407   var screen/esi: (addr screen) <- copy _screen
+408   var idx/ecx: int <- screen-cell-index screen, x, y
+409   var result/eax: grapheme <- screen-grapheme-at-idx screen, idx
+410   return result
+411 }
+412 
+413 fn screen-grapheme-at-idx _screen: (addr screen), idx-on-stack: int -> _/eax: grapheme {
+414   var screen/esi: (addr screen) <- copy _screen
+415   var data-ah/eax: (addr handle array screen-cell) <- get screen, data
+416   var data/eax: (addr array screen-cell) <- lookup *data-ah
+417   var idx/ecx: int <- copy idx-on-stack
+418   var offset/ecx: (offset screen-cell) <- compute-offset data, idx
+419   var cell/eax: (addr screen-cell) <- index data, offset
+420   var src/eax: (addr grapheme) <- get cell, data
+421   return *src
+422 }
+423 
+424 fn screen-color-at _screen: (addr screen), x: int, y: int -> _/eax: int {
+425   var screen/esi: (addr screen) <- copy _screen
+426   var idx/ecx: int <- screen-cell-index screen, x, y
+427   var result/eax: int <- screen-color-at-idx screen, idx
+428   return result
+429 }
+430 
+431 fn screen-color-at-idx _screen: (addr screen), idx-on-stack: int -> _/eax: int {
+432   var screen/esi: (addr screen) <- copy _screen
+433   var data-ah/eax: (addr handle array screen-cell) <- get screen, data
+434   var data/eax: (addr array screen-cell) <- lookup *data-ah
+435   var idx/ecx: int <- copy idx-on-stack
+436   var offset/ecx: (offset screen-cell) <- compute-offset data, idx
+437   var cell/eax: (addr screen-cell) <- index data, offset
+438   var src/eax: (addr int) <- get cell, color
+439   var result/eax: int <- copy *src
+440   return result
+441 }
+442 
+443 fn screen-background-color-at _screen: (addr screen), x: int, y: int -> _/eax: int {
+444   var screen/esi: (addr screen) <- copy _screen
+445   var idx/ecx: int <- screen-cell-index screen, x, y
+446   var result/eax: int <- screen-background-color-at-idx screen, idx
+447   return result
+448 }
+449 
+450 fn screen-background-color-at-idx _screen: (addr screen), idx-on-stack: int -> _/eax: int {
+451   var screen/esi: (addr screen) <- copy _screen
+452   var data-ah/eax: (addr handle array screen-cell) <- get screen, data
+453   var data/eax: (addr array screen-cell) <- lookup *data-ah
+454   var idx/ecx: int <- copy idx-on-stack
+455   var offset/ecx: (offset screen-cell) <- compute-offset data, idx
+456   var cell/eax: (addr screen-cell) <- index data, offset
+457   var src/eax: (addr int) <- get cell, background-color
+458   var result/eax: int <- copy *src
+459   return result
+460 }
+461 
+462 fn pixel screen: (addr screen), x: int, y: int, color: int {
+463   {
+464     compare screen, 0
+465     break-if-!=
+466     pixel-on-real-screen x, y, color
+467     return
+468   }
+469   # fake screen
+470   var screen/esi: (addr screen) <- copy screen
+471   var pixels-ah/eax: (addr handle array byte) <- get screen, pixels
+472   var pixels/eax: (addr array byte) <- lookup *pixels-ah
+473   {
+474     compare pixels, 0
+475     break-if-!=
+476     abort "pixel graphics not enabled for this screen"
+477   }
+478   var idx/ecx: int <- pixel-index screen, x, y
+479   var dest/ecx: (addr byte) <- index pixels, idx
+480   var src/eax: byte <- copy-byte color
+481   copy-byte-to *dest, src
+482 }
+483 
+484 fn pixel-index _screen: (addr screen), x: int, y: int -> _/ecx: int {
+485   var screen/esi: (addr screen) <- copy _screen
+486   {
+487     compare x, 0
+488     break-if->=
+489     abort "screen-cell-index: negative x"
+490   }
+491   {
+492     var xmax-a/eax: (addr int) <- get screen, width
+493     var xmax/eax: int <- copy *xmax-a
+494     xmax <- shift-left 3/log2-font-width
+495     compare x, xmax
+496     break-if-<
+497     abort "screen-cell-index: x too high"
+498   }
+499   {
+500     compare y, 0
+501     break-if->=
+502     abort "screen-cell-index: negative y"
+503   }
+504   {
+505     var ymax-a/eax: (addr int) <- get screen, height
+506     var ymax/eax: int <- copy *ymax-a
+507     ymax <- shift-left 4/log2-font-height
+508     compare y, ymax
+509     break-if-<
+510     abort "screen-cell-index: y too high"
+511   }
+512   var width-addr/eax: (addr int) <- get screen, width
+513   var result/ecx: int <- copy y
+514   result <- multiply *width-addr
+515   result <- shift-left 3/log2-font-width
+516   result <- add x
+517   return result
+518 }
+
+ + + diff --git a/html/500text-screen.mu.html b/html/500text-screen.mu.html deleted file mode 100644 index 5b94d956..00000000 --- a/html/500text-screen.mu.html +++ /dev/null @@ -1,443 +0,0 @@ - - - - -Mu - 500text-screen.mu - - - - - - - - - - -https://github.com/akkartik/mu/blob/main/500text-screen.mu -
-  1 # Testable primitives for writing text to screen.
-  2 # (Mu doesn't yet have testable primitives for graphics.)
-  3 #
-  4 # Unlike the top-level, this text mode has no scrolling.
-  5 
-  6 # coordinates here don't match top-level
-  7 # Here we're consistent with graphics mode. Top-level is consistent with
-  8 # terminal emulators.
-  9 type screen {
- 10   width: int
- 11   height: int
- 12   data: (handle array screen-cell)
- 13   cursor-x: int
- 14   cursor-y: int
- 15 }
- 16 
- 17 type screen-cell {
- 18   data: grapheme
- 19   color: int
- 20   background-color: int
- 21 }
- 22 
- 23 fn initialize-screen _screen: (addr screen), width: int, height: int {
- 24   var screen/esi: (addr screen) <- copy _screen
- 25   var tmp/eax: int <- copy 0
- 26   var dest/edi: (addr int) <- copy 0
- 27   # screen->width = width
- 28   dest <- get screen, width
- 29   tmp <- copy width
- 30   copy-to *dest, tmp
- 31   # screen->height = height
- 32   dest <- get screen, height
- 33   tmp <- copy height
- 34   copy-to *dest, tmp
- 35   # screen->data = new screen-cell[width*height]
- 36   {
- 37     var data-addr/edi: (addr handle array screen-cell) <- get screen, data
- 38     tmp <- multiply width
- 39     populate data-addr, tmp
- 40   }
- 41   # screen->cursor-x = 0
- 42   dest <- get screen, cursor-x
- 43   copy-to *dest, 0
- 44   # screen->cursor-y = 0
- 45   dest <- get screen, cursor-y
- 46   copy-to *dest, 0
- 47 }
- 48 
- 49 # in graphemes
- 50 fn screen-size _screen: (addr screen) -> _/eax: int, _/ecx: int {
- 51   var screen/esi: (addr screen) <- copy _screen
- 52   var width/eax: int <- copy 0
- 53   var height/ecx: int <- copy 0
- 54   compare screen, 0
- 55   {
- 56     break-if-!=
- 57     return 0x80/128, 0x30/48
- 58   }
- 59   # fake screen
- 60   var tmp/edx: (addr int) <- get screen, width
- 61   width <- copy *tmp
- 62   tmp <- get screen, height
- 63   height <- copy *tmp
- 64   return width, height
- 65 }
- 66 
- 67 # testable screen primitive
- 68 fn draw-grapheme _screen: (addr screen), g: grapheme, x: int, y: int, color: int, background-color: int {
- 69   var screen/esi: (addr screen) <- copy _screen
- 70   {
- 71     compare screen, 0
- 72     break-if-!=
- 73     draw-grapheme-on-real-screen g, x, y, color, background-color
- 74     return
- 75   }
- 76   # fake screen
- 77   var idx/ecx: int <- screen-cell-index screen, x, y
- 78   var data-ah/eax: (addr handle array screen-cell) <- get screen, data
- 79   var data/eax: (addr array screen-cell) <- lookup *data-ah
- 80   var offset/ecx: (offset screen-cell) <- compute-offset data, idx
- 81   var dest-cell/ecx: (addr screen-cell) <- index data, offset
- 82   var dest-grapheme/eax: (addr grapheme) <- get dest-cell, data
- 83   var g2/edx: grapheme <- copy g
- 84   copy-to *dest-grapheme, g2
- 85   var dest-color/eax: (addr int) <- get dest-cell, color
- 86   var src-color/edx: int <- copy color
- 87   copy-to *dest-color, src-color
- 88   dest-color <- get dest-cell, background-color
- 89   src-color <- copy background-color
- 90   copy-to *dest-color, src-color
- 91 }
- 92 
- 93 # we can't really render non-ASCII yet, but when we do we'll be ready
- 94 fn draw-code-point screen: (addr screen), c: code-point, x: int, y: int, color: int, background-color: int {
- 95   var g/eax: grapheme <- copy c
- 96   draw-grapheme screen, g, x, y, color, background-color
- 97 }
- 98 
- 99 # not really needed for a real screen, though it shouldn't do any harm
-100 fn screen-cell-index _screen: (addr screen), x: int, y: int -> _/ecx: int {
-101   var screen/esi: (addr screen) <- copy _screen
-102   # only one bounds check isn't automatically handled
-103   {
-104     var xmax/eax: (addr int) <- get screen, width
-105     var xcurr/ecx: int <- copy x
-106     compare xcurr, *xmax
-107     break-if-<
-108     abort "tried to print out of screen bounds"
-109   }
-110   var width-addr/eax: (addr int) <- get screen, width
-111   var result/ecx: int <- copy y
-112   result <- multiply *width-addr
-113   result <- add x
-114   return result
-115 }
-116 
-117 fn cursor-position _screen: (addr screen) -> _/eax: int, _/ecx: int {
-118   var screen/esi: (addr screen) <- copy _screen
-119   {
-120     compare screen, 0
-121     break-if-!=
-122     var x/eax: int <- copy 0
-123     var y/ecx: int <- copy 0
-124     x, y <- cursor-position-on-real-screen
-125     return x, y
-126   }
-127   # fake screen
-128   var cursor-x-addr/eax: (addr int) <- get screen, cursor-x
-129   var cursor-y-addr/ecx: (addr int) <- get screen, cursor-y
-130   return *cursor-x-addr, *cursor-y-addr
-131 }
-132 
-133 fn set-cursor-position _screen: (addr screen), x: int, y: int {
-134   var screen/esi: (addr screen) <- copy _screen
-135   {
-136     compare screen, 0
-137     break-if-!=
-138     set-cursor-position-on-real-screen x, y
-139     return
-140   }
-141   # fake screen
-142   # ignore x < 0
-143   {
-144     compare x, 0
-145     break-if->=
-146     return
-147   }
-148   # ignore x >= width
-149   {
-150     var width-addr/eax: (addr int) <- get screen, width
-151     var width/eax: int <- copy *width-addr
-152     compare x, width
-153     break-if-<=
-154     return
-155   }
-156   # ignore y < 0
-157   {
-158     compare y, 0
-159     break-if->=
-160     return
-161   }
-162   # ignore y >= height
-163   {
-164     var height-addr/eax: (addr int) <- get screen, height
-165     var height/eax: int <- copy *height-addr
-166     compare y, height
-167     break-if-<
-168     return
-169   }
-170   # screen->cursor-x = x
-171   var dest/edi: (addr int) <- get screen, cursor-x
-172   var src/eax: int <- copy x
-173   copy-to *dest, src
-174   # screen->cursor-y = y
-175   dest <- get screen, cursor-y
-176   src <- copy y
-177   copy-to *dest, src
-178 }
-179 
-180 fn draw-cursor screen: (addr screen), g: grapheme {
-181   {
-182     compare screen, 0
-183     break-if-!=
-184     draw-cursor-on-real-screen g
-185     return
-186   }
-187   # fake screen
-188   var cursor-x/eax: int <- copy 0
-189   var cursor-y/ecx: int <- copy 0
-190   cursor-x, cursor-y <- cursor-position screen
-191   draw-grapheme screen, g, cursor-x, cursor-y, 0/fg, 7/bg
-192 }
-193 
-194 fn clear-screen _screen: (addr screen) {
-195   var screen/esi: (addr screen) <- copy _screen
-196   {
-197     compare screen, 0
-198     break-if-!=
-199     clear-real-screen
-200     return
-201   }
-202   # fake screen
-203   set-cursor-position screen, 0, 0
-204   var y/eax: int <- copy 0
-205   var height/ecx: (addr int) <- get screen, height
-206   {
-207     compare y, *height
-208     break-if->=
-209     var x/edx: int <- copy 0
-210     var width/ebx: (addr int) <- get screen, width
-211     {
-212       compare x, *width
-213       break-if->=
-214       draw-code-point screen, 0x20/space, x, y, 0/fg=black, 0/bg=black
-215       x <- increment
-216       loop
-217     }
-218     y <- increment
-219     loop
-220   }
-221   set-cursor-position screen, 0, 0
-222 }
-223 
-224 fn fake-screen-empty? _screen: (addr screen) -> _/eax: boolean {
-225   var screen/esi: (addr screen) <- copy _screen
-226   var y/eax: int <- copy 0
-227   var height/ecx: (addr int) <- get screen, height
-228   {
-229     compare y, *height
-230     break-if->=
-231     var x/edx: int <- copy 0
-232     var width/ebx: (addr int) <- get screen, width
-233     {
-234       compare x, *width
-235       break-if->=
-236       var g/eax: grapheme <- screen-grapheme-at screen, x, y
-237       {
-238         compare g, 0
-239         break-if-=
-240         compare g, 0x20/space
-241         break-if-=
-242         return 0/false
-243       }
-244       x <- increment
-245       loop
-246     }
-247     y <- increment
-248     loop
-249   }
-250   return 1/true
-251 }
-252 
-253 fn clear-rect _screen: (addr screen), xmin: int, ymin: int, xmax: int, ymax: int, background-color: int {
-254   var screen/esi: (addr screen) <- copy _screen
-255   {
-256     compare screen, 0
-257     break-if-!=
-258     clear-rect-on-real-screen xmin, ymin, xmax, ymax, background-color
-259     return
-260   }
-261   # fake screen
-262   set-cursor-position screen, 0, 0
-263   var y/eax: int <- copy ymin
-264   var ymax/ecx: int <- copy ymax
-265   {
-266     compare y, ymax
-267     break-if->=
-268     var x/edx: int <- copy xmin
-269     var xmax/ebx: int <- copy xmax
-270     {
-271       compare x, xmax
-272       break-if->=
-273       draw-code-point screen, 0x20/space, x, y, 0/fg, background-color
-274       x <- increment
-275       loop
-276     }
-277     y <- increment
-278     loop
-279   }
-280   set-cursor-position screen, 0, 0
-281 }
-282 
-283 # there's no grapheme that guarantees to cover every pixel, so we'll bump down
-284 # to pixels for a real screen
-285 fn clear-real-screen {
-286   var y/eax: int <- copy 0
-287   {
-288     compare y, 0x300/screen-height=768
-289     break-if->=
-290     var x/edx: int <- copy 0
-291     {
-292       compare x, 0x400/screen-width=1024
-293       break-if->=
-294       pixel-on-real-screen x, y, 0/color=black
-295       x <- increment
-296       loop
-297     }
-298     y <- increment
-299     loop
-300   }
-301 }
-302 
-303 fn clear-rect-on-real-screen xmin: int, ymin: int, xmax: int, ymax: int, background-color: int {
-304   var y/eax: int <- copy ymin
-305   y <- shift-left 4/log-font-height
-306   var ymax/ecx: int <- copy ymax
-307   ymax <- shift-left 4/log-font-height
-308   {
-309     compare y, ymax
-310     break-if->=
-311     var x/edx: int <- copy xmin
-312     x <- shift-left 3/log-font-width
-313     var xmax/ebx: int <- copy xmax
-314     xmax <- shift-left 3/log-font-width
-315     {
-316       compare x, xmax
-317       break-if->=
-318       pixel-on-real-screen x, y, background-color
-319       x <- increment
-320       loop
-321     }
-322     y <- increment
-323     loop
-324   }
-325 }
-326 
-327 fn screen-grapheme-at _screen: (addr screen), x: int, y: int -> _/eax: grapheme {
-328   var screen/esi: (addr screen) <- copy _screen
-329   var idx/ecx: int <- screen-cell-index screen, x, y
-330   var result/eax: grapheme <- screen-grapheme-at-idx screen, idx
-331   return result
-332 }
-333 
-334 fn screen-grapheme-at-idx _screen: (addr screen), idx-on-stack: int -> _/eax: grapheme {
-335   var screen/esi: (addr screen) <- copy _screen
-336   var data-ah/eax: (addr handle array screen-cell) <- get screen, data
-337   var data/eax: (addr array screen-cell) <- lookup *data-ah
-338   var idx/ecx: int <- copy idx-on-stack
-339   var offset/ecx: (offset screen-cell) <- compute-offset data, idx
-340   var cell/eax: (addr screen-cell) <- index data, offset
-341   var src/eax: (addr grapheme) <- get cell, data
-342   return *src
-343 }
-344 
-345 fn screen-color-at _screen: (addr screen), x: int, y: int -> _/eax: int {
-346   var screen/esi: (addr screen) <- copy _screen
-347   var idx/ecx: int <- screen-cell-index screen, x, y
-348   var result/eax: int <- screen-color-at-idx screen, idx
-349   return result
-350 }
-351 
-352 fn screen-color-at-idx _screen: (addr screen), idx-on-stack: int -> _/eax: int {
-353   var screen/esi: (addr screen) <- copy _screen
-354   var data-ah/eax: (addr handle array screen-cell) <- get screen, data
-355   var data/eax: (addr array screen-cell) <- lookup *data-ah
-356   var idx/ecx: int <- copy idx-on-stack
-357   var offset/ecx: (offset screen-cell) <- compute-offset data, idx
-358   var cell/eax: (addr screen-cell) <- index data, offset
-359   var src/eax: (addr int) <- get cell, color
-360   var result/eax: int <- copy *src
-361   return result
-362 }
-363 
-364 fn screen-background-color-at _screen: (addr screen), x: int, y: int -> _/eax: int {
-365   var screen/esi: (addr screen) <- copy _screen
-366   var idx/ecx: int <- screen-cell-index screen, x, y
-367   var result/eax: int <- screen-background-color-at-idx screen, idx
-368   return result
-369 }
-370 
-371 fn screen-background-color-at-idx _screen: (addr screen), idx-on-stack: int -> _/eax: int {
-372   var screen/esi: (addr screen) <- copy _screen
-373   var data-ah/eax: (addr handle array screen-cell) <- get screen, data
-374   var data/eax: (addr array screen-cell) <- lookup *data-ah
-375   var idx/ecx: int <- copy idx-on-stack
-376   var offset/ecx: (offset screen-cell) <- compute-offset data, idx
-377   var cell/eax: (addr screen-cell) <- index data, offset
-378   var src/eax: (addr int) <- get cell, background-color
-379   var result/eax: int <- copy *src
-380   return result
-381 }
-
- - - diff --git a/html/501draw-text.mu.html b/html/501draw-text.mu.html index ef722598..bc18cb25 100644 --- a/html/501draw-text.mu.html +++ b/html/501draw-text.mu.html @@ -7,11 +7,11 @@ - + - - - - -https://github.com/akkartik/mu/blob/main/ex1.subx -
- 1 # The simplest possible program: just an infinite loop.
- 2 # All is well if your computer clears screen and hangs without restarting.
- 3 # On an emulator the window may get bigger to accomodate the higher-resolution
- 4 # graphics mode.
- 5 #
- 6 # To build a disk image:
- 7 #   ./translate_subx boot.subx ex1.subx   # emits disk.img
- 8 # To run:
- 9 #   qemu-system-i386 disk.img
-10 # Or:
-11 #   bochs -f bochsrc                      # bochsrc loads disk.img
-12 
-13 == code
-14 
-15 Entry:
-16   {
-17     eb/jump loop/disp8
-18   }
-19 
-20 # vim:ft=subx
-
- - - diff --git a/html/ex10.mu.html b/html/ex10.mu.html index 502e6b2c..ac6dd059 100644 --- a/html/ex10.mu.html +++ b/html/ex10.mu.html @@ -7,11 +7,11 @@ - + - - - - -https://github.com/akkartik/mu/blob/main/ex2.subx -
- 1 # Test out the video mode by filling in the screen with pixels.
- 2 #
- 3 # To build a disk image:
- 4 #   ./translate_subx boot.subx ex2.subx   # emits disk.img
- 5 # To run:
- 6 #   qemu-system-i386 disk.img
- 7 # Or:
- 8 #   bochs -f bochsrc                      # bochsrc loads disk.img
- 9 
-10 == code
-11 
-12 Entry:
-13   # ecx <- start of video memory
-14   8b/-> *Video-memory-addr 1/r32/ecx
-15 
-16   # eax <- final pixel of video memory
-17   8d/copy-address *(ecx + 0x0bffff) 0/r32/eax  # 0xbffff = 1024*768 - 1
-18 
-19   # for each pixel in video memory
-20   {
-21     39/compare %eax 1/r32/ecx
-22     7c/jump-if-< break/disp8
-23     # write its column number to it
-24     88/byte<- *eax 0/r32/AL
-25     48/decrement-eax
-26     eb/jump loop/disp8
-27   }
-28 
-29   # hang indefinitely
-30   {
-31     eb/jump loop/disp8
-32   }
-
- - - diff --git a/html/ex3.mu.html b/html/ex3.mu.html index 77e4d705..b7217423 100644 --- a/html/ex3.mu.html +++ b/html/ex3.mu.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/104new-segment.subx.html b/html/linux/104new-segment.subx.html index 995ff7d8..d5b54d53 100644 --- a/html/linux/104new-segment.subx.html +++ b/html/linux/104new-segment.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/105string-equal.subx.html b/html/linux/105string-equal.subx.html index 1a41c469..2b663186 100644 --- a/html/linux/105string-equal.subx.html +++ b/html/linux/105string-equal.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/107trace.subx.html b/html/linux/107trace.subx.html index da49bc51..78b7cc4a 100644 --- a/html/linux/107trace.subx.html +++ b/html/linux/107trace.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/109stream-equal.subx.html b/html/linux/109stream-equal.subx.html index 5eac5530..3c1a4d2b 100644 --- a/html/linux/109stream-equal.subx.html +++ b/html/linux/109stream-equal.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/110stop.subx.html b/html/linux/110stop.subx.html index 2b1dd4c5..313eeeda 100644 --- a/html/linux/110stop.subx.html +++ b/html/linux/110stop.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/111read.subx.html b/html/linux/111read.subx.html index 3355afa6..cd5cf06a 100644 --- a/html/linux/111read.subx.html +++ b/html/linux/111read.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/112read-byte.subx.html b/html/linux/112read-byte.subx.html index db00e159..2147fee6 100644 --- a/html/linux/112read-byte.subx.html +++ b/html/linux/112read-byte.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/115write-byte.subx.html b/html/linux/115write-byte.subx.html index b3c93d42..def2113b 100644 --- a/html/linux/115write-byte.subx.html +++ b/html/linux/115write-byte.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/117write-int-hex.subx.html b/html/linux/117write-int-hex.subx.html index 751383ea..0696130b 100644 --- a/html/linux/117write-int-hex.subx.html +++ b/html/linux/117write-int-hex.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/119error-byte.subx.html b/html/linux/119error-byte.subx.html index d5f02960..90df6185 100644 --- a/html/linux/119error-byte.subx.html +++ b/html/linux/119error-byte.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/120allocate.subx.html b/html/linux/120allocate.subx.html index 55e556b5..0d20d419 100644 --- a/html/linux/120allocate.subx.html +++ b/html/linux/120allocate.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/121new-stream.subx.html b/html/linux/121new-stream.subx.html index 2c7184ad..b19387fe 100644 --- a/html/linux/121new-stream.subx.html +++ b/html/linux/121new-stream.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/122read-line.subx.html b/html/linux/122read-line.subx.html index 6f5ac71a..66d9a605 100644 --- a/html/linux/122read-line.subx.html +++ b/html/linux/122read-line.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/123slice.subx.html b/html/linux/123slice.subx.html index 0b436c17..f36dbcc7 100644 --- a/html/linux/123slice.subx.html +++ b/html/linux/123slice.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/124next-token.subx.html b/html/linux/124next-token.subx.html index bc498103..8c325489 100644 --- a/html/linux/124next-token.subx.html +++ b/html/linux/124next-token.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/125write-stream-data.subx.html b/html/linux/125write-stream-data.subx.html index 0bedb01f..e904e850 100644 --- a/html/linux/125write-stream-data.subx.html +++ b/html/linux/125write-stream-data.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/126write-int-decimal.subx.html b/html/linux/126write-int-decimal.subx.html index 8cb7fe01..89305e38 100644 --- a/html/linux/126write-int-decimal.subx.html +++ b/html/linux/126write-int-decimal.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/128subx-words.subx.html b/html/linux/128subx-words.subx.html index 817afca9..1b9c1fdd 100644 --- a/html/linux/128subx-words.subx.html +++ b/html/linux/128subx-words.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/129emit-hex.subx.html b/html/linux/129emit-hex.subx.html index 77e67c86..4bb744bc 100644 --- a/html/linux/129emit-hex.subx.html +++ b/html/linux/129emit-hex.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/130emit.subx.html b/html/linux/130emit.subx.html index 1344aad8..c4cb6193 100644 --- a/html/linux/130emit.subx.html +++ b/html/linux/130emit.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/131table.subx.html b/html/linux/131table.subx.html index 8c3eeb53..4f51356a 100644 --- a/html/linux/131table.subx.html +++ b/html/linux/131table.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/132slurp.subx.html b/html/linux/132slurp.subx.html index 3bcdb688..1554d6a4 100644 --- a/html/linux/132slurp.subx.html +++ b/html/linux/132slurp.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/133subx-widths.subx.html b/html/linux/133subx-widths.subx.html index f7bf5a9f..4c5cc558 100644 --- a/html/linux/133subx-widths.subx.html +++ b/html/linux/133subx-widths.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/134emit-hex-array.subx.html b/html/linux/134emit-hex-array.subx.html index 837a6d1a..7e3162ef 100644 --- a/html/linux/134emit-hex-array.subx.html +++ b/html/linux/134emit-hex-array.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/135next-word-or-string.subx.html b/html/linux/135next-word-or-string.subx.html index a4a349f5..82eac623 100644 --- a/html/linux/135next-word-or-string.subx.html +++ b/html/linux/135next-word-or-string.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/201register-names.subx.html b/html/linux/201register-names.subx.html index 1b96cc2f..1e3d1600 100644 --- a/html/linux/201register-names.subx.html +++ b/html/linux/201register-names.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/203stack.subx.html b/html/linux/203stack.subx.html index 23f6143d..490d9af0 100644 --- a/html/linux/203stack.subx.html +++ b/html/linux/203stack.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/301array-equal.subx.html b/html/linux/301array-equal.subx.html index 9b77c7d0..383bb2c4 100644 --- a/html/linux/301array-equal.subx.html +++ b/html/linux/301array-equal.subx.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/bootstrap/010vm.cc.html b/html/linux/bootstrap/010vm.cc.html index f60b6abf..3fce4515 100644 --- a/html/linux/bootstrap/010vm.cc.html +++ b/html/linux/bootstrap/010vm.cc.html @@ -7,17 +7,17 @@ - + diff --git a/html/linux/bootstrap/015immediate_addressing.cc.html b/html/linux/bootstrap/015immediate_addressing.cc.html index 6d5b873b..4ef0974b 100644 --- a/html/linux/bootstrap/015immediate_addressing.cc.html +++ b/html/linux/bootstrap/015immediate_addressing.cc.html @@ -7,15 +7,15 @@ - + @@ -93,7 +93,7 @@ if ('onhashchange' in window) { 35 trace(3, "transform") << "-- check argument bounds" << end(); 36 for (int i = 0; i < SIZE(code.lines); ++i) { 37 const line& inst = code.lines.at(i); - 38 for (int j = first_argument(inst); j < SIZE(inst.words); ++j) + 38 for (int j = first_argument(inst); j < SIZE(inst.words); ++j) 39 check_argument_bounds(inst.words.at(j)); 40 if (trace_contains_errors()) return; // stop at the first mal-formed instruction 41 } @@ -103,7 +103,7 @@ if ('onhashchange' in window) { 45 for (map<string, uint32_t>::iterator p = Operand_bound.begin(); p != Operand_bound.end(); ++p) { 46 if (!has_argument_metadata(w, p->first)) continue; 47 if (!looks_like_hex_int(w.data)) continue; // later transforms are on their own to do their own bounds checking - 48 int32_t x = parse_int(w.data); + 48 int32_t x = parse_int(w.data); 49 if (x >= 0) { 50 if (p->first == "disp8" || p->first == "disp16") { 51 if (static_cast<uint32_t>(x) >= p->second/2) diff --git a/html/linux/bootstrap/035compute_segment_address.cc.html b/html/linux/bootstrap/035compute_segment_address.cc.html index a71afcf6..1d582cac 100644 --- a/html/linux/bootstrap/035compute_segment_address.cc.html +++ b/html/linux/bootstrap/035compute_segment_address.cc.html @@ -7,11 +7,11 @@ - + diff --git a/html/linux/bootstrap/036labels.cc.html b/html/linux/bootstrap/036labels.cc.html index 2068cf7c..4d2043e8 100644 --- a/html/linux/bootstrap/036labels.cc.html +++ b/html/linux/bootstrap/036labels.cc.html @@ -7,11 +7,11 @@ - + @@ -95,7 +95,7 @@ if ('onhashchange' in window) { 37 CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000001 opcode: 05"); 38 } 39 - 40 :(before "End looks_like_hex_int(s) Detectors") + 40 :(before "End looks_like_hex_int(s) Detectors") 41 if (SIZE(s) == 2) return true; 42 43 :(code) @@ -218,7 +218,7 @@ if ('onhashchange' in window) { 160 // ensure labels look sufficiently different from raw hex 161 check_valid_name(label); 162 if (trace_contains_errors()) return; -163 if (contains_any_argument_metadata(curr)) +163 if (contains_any_argument_metadata(curr)) 164 raise << "'" << to_string(inst) << "': label definition (':') not allowed in argument\n" << end(); 165 if (j > 0) 166 raise << "'" << to_string(inst) << "': labels can only be the first word in a line.\n" << end(); diff --git a/html/linux/bootstrap/037global_variables.cc.html b/html/linux/bootstrap/037global_variables.cc.html index ea37783f..74e38041 100644 --- a/html/linux/bootstrap/037global_variables.cc.html +++ b/html/linux/bootstrap/037global_variables.cc.html @@ -7,17 +7,17 @@ - + @@ -64,7 +64,7 @@ if ('onhashchange' in window) { 3 # except that we support hex digits. 4 # 5 # To run: - 6 # $ bootstrap/bootstrap translate [01]*.subx apps/crenshaw2-1.subx -o apps/crenshaw2-1 + 6 # $ bootstrap/bootstrap translate [01]*.subx crenshaw2-1.subx -o crenshaw2-1 7 # $ echo '3' |bootstrap/bootstrap run crenshaw2-1 8 # Expected output: 9 # # syscall(exit, 3) diff --git a/html/linux/crenshaw2-1b.subx.html b/html/linux/crenshaw2-1b.subx.html index f7efb75a..ac50b5ef 100644 --- a/html/linux/crenshaw2-1b.subx.html +++ b/html/linux/crenshaw2-1b.subx.html @@ -7,11 +7,11 @@ - + @@ -64,7 +64,7 @@ if ('onhashchange' in window) { 3 # except that we support hex numbers of multiple digits. 4 # 5 # To run: - 6 # $ bootstrap/bootstrap translate [01]*.subx apps/crenshaw2-1b.subx -o apps/crenshaw2-1b + 6 # $ bootstrap/bootstrap translate [01]*.subx crenshaw2-1b.subx -o crenshaw2-1b 7 # $ echo '1a' |bootstrap/bootstrap run crenshaw2-1b 8 # Expected output: 9 # # syscall(exit, 1a) diff --git a/html/linux/dquotes.subx.html b/html/linux/dquotes.subx.html index ddb58221..0c607fff 100644 --- a/html/linux/dquotes.subx.html +++ b/html/linux/dquotes.subx.html @@ -7,11 +7,11 @@ - + @@ -60,7 +60,7 @@ if ('onhashchange' in window) { 1 # String comparison: return 1 iff the two args passed in at the commandline are equal. 2 # 3 # To run: - 4 # $ bootstrap/bootstrap translate apps/ex10.subx -o apps/ex10 + 4 # $ bootstrap/bootstrap translate ex10.subx -o ex10 5 # $ bootstrap/bootstrap run ex10 abc abd 6 # Expected result: 7 # $ echo $? diff --git a/html/linux/ex11.subx.html b/html/linux/ex11.subx.html index f8e0e243..820fca50 100644 --- a/html/linux/ex11.subx.html +++ b/html/linux/ex11.subx.html @@ -7,11 +7,11 @@ - + @@ -68,7 +68,7 @@ if ('onhashchange' in window) { 6 # a null-terminated 'kernel string' with a size-prefixed 'SubX string'. 7 # 8 # To run: - 9 # $ bootstrap/bootstrap translate apps/ex11.subx -o apps/ex11 + 9 # $ bootstrap/bootstrap translate ex11.subx -o ex11 10 # $ bootstrap/bootstrap run ex11 # runs a series of tests 11 # ...... # all tests pass 12 # diff --git a/html/linux/ex12.subx.html b/html/linux/ex12.subx.html index 0f9a3d61..1c413f5f 100644 --- a/html/linux/ex12.subx.html +++ b/html/linux/ex12.subx.html @@ -7,11 +7,11 @@ - + @@ -59,7 +59,7 @@ if ('onhashchange' in window) { 2 # Create a new segment using mmap, save the address, write to it. 3 # 4 # To run: - 5 # $ bootstrap/bootstrap translate apps/ex12.subx -o apps/ex12 + 5 # $ bootstrap/bootstrap translate ex12.subx -o ex12 6 # $ bootstrap/bootstrap run ex12 7 # You shouldn't get a segmentation fault. 8 diff --git a/html/linux/ex13.subx.html b/html/linux/ex13.subx.html index c45a725c..fc2b8c54 100644 --- a/html/linux/ex13.subx.html +++ b/html/linux/ex13.subx.html @@ -7,11 +7,11 @@ - + @@ -59,7 +59,7 @@ if ('onhashchange' in window) { 1 # Compare 3 and 3. 2 # 3 # To run: - 4 # $ bootstrap/bootstrap translate apps/ex13.subx -o apps/ex13 + 4 # $ bootstrap/bootstrap translate ex13.subx -o ex13 5 # $ bootstrap/bootstrap run ex13 6 # Expected result: 7 # $ echo $? diff --git a/html/linux/ex14.subx.html b/html/linux/ex14.subx.html index 2cb2a12e..ebd18a5e 100644 --- a/html/linux/ex14.subx.html +++ b/html/linux/ex14.subx.html @@ -7,11 +7,11 @@ - + @@ -59,7 +59,7 @@ if ('onhashchange' in window) { 1 # Multiply 2 numbers. 2 # 3 # To run: - 4 # $ bootstrap/bootstrap translate apps/ex14.subx -o apps/ex14 + 4 # $ bootstrap/bootstrap translate ex14.subx -o ex14 5 # $ bootstrap/bootstrap run ex14 6 # Expected result: 7 # $ echo $? diff --git a/html/linux/ex2.mu.html b/html/linux/ex2.mu.html index 0c4275ff..933ac81e 100644 --- a/html/linux/ex2.mu.html +++ b/html/linux/ex2.mu.html @@ -7,11 +7,11 @@ - + @@ -58,7 +58,7 @@ if ('onhashchange' in window) { 1 # Read a character from stdin, save it to a local on the stack, write it to stdout. 2 # 3 # To run: - 4 # $ bootstrap/bootstrap translate apps/ex5.subx -o apps/ex5 + 4 # $ bootstrap/bootstrap translate ex5.subx -o ex5 5 # $ bootstrap/bootstrap run ex5 6 7 == code diff --git a/html/linux/ex6.subx.html b/html/linux/ex6.subx.html index cb3c8696..fec86cca 100644 --- a/html/linux/ex6.subx.html +++ b/html/linux/ex6.subx.html @@ -7,11 +7,11 @@ - + @@ -58,7 +58,7 @@ if ('onhashchange' in window) { 1 # Print out a (global variable) string to stdout. 2 # 3 # To run: - 4 # $ bootstrap/bootstrap translate apps/ex6.subx -o apps/ex6 + 4 # $ bootstrap/bootstrap translate ex6.subx -o ex6 5 # $ bootstrap/bootstrap run ex6 6 # Hello, world! 7 diff --git a/html/linux/ex7.subx.html b/html/linux/ex7.subx.html index a0ff1387..4ca7de43 100644 --- a/html/linux/ex7.subx.html +++ b/html/linux/ex7.subx.html @@ -7,11 +7,11 @@ - + @@ -62,7 +62,7 @@ if ('onhashchange' in window) { 5 # the character read. 6 # 7 # To run: - 8 # $ bootstrap/bootstrap translate apps/ex7.subx -o apps/ex7 + 8 # $ bootstrap/bootstrap translate ex7.subx -o ex7 9 # $ bootstrap/bootstrap run ex7 10 # Expected result: 11 # $ echo $? diff --git a/html/linux/ex8.subx.html b/html/linux/ex8.subx.html index c30fac4f..b015bcf6 100644 --- a/html/linux/ex8.subx.html +++ b/html/linux/ex8.subx.html @@ -7,11 +7,11 @@ - + @@ -60,7 +60,7 @@ if ('onhashchange' in window) { 1 # Example reading commandline arguments: compute length of first arg. 2 # 3 # To run: - 4 # $ bootstrap/bootstrap translate apps/ex8.subx -o apps/ex8 + 4 # $ bootstrap/bootstrap translate ex8.subx -o ex8 5 # $ bootstrap/bootstrap run ex8 abc de fghi 6 # Expected result: 7 # $ echo $? diff --git a/html/linux/ex9.subx.html b/html/linux/ex9.subx.html index 019a2c60..12833b11 100644 --- a/html/linux/ex9.subx.html +++ b/html/linux/ex9.subx.html @@ -7,11 +7,11 @@ - + @@ -62,7 +62,7 @@ if ('onhashchange' in window) { 4 # letter of second arg. 5 # 6 # To run: - 7 # $ bootstrap/bootstrap translate apps/ex9.subx -o apps/ex9 + 7 # $ bootstrap/bootstrap translate ex9.subx -o ex9 8 # $ bootstrap/bootstrap run ex9 z x 9 # Expected result: 10 # $ echo $? diff --git a/html/linux/factorial.mu.html b/html/linux/factorial.mu.html index 1d811ae7..565568f7 100644 --- a/html/linux/factorial.mu.html +++ b/html/linux/factorial.mu.html @@ -7,11 +7,11 @@ - + @@ -61,7 +61,7 @@ if ('onhashchange' in window) { 1 ## compute the factorial of 5, and print the result 2 # 3 # To run: - 4 # $ bootstrap/bootstrap translate [01]*.subx apps/factorial.subx -o apps/factorial + 4 # $ bootstrap/bootstrap translate [01]*.subx factorial.subx -o factorial 5 # $ bootstrap/bootstrap run factorial 6 # Expected result: 7 # $ echo $? diff --git a/html/linux/factorial2.subx.html b/html/linux/factorial2.subx.html index 7324ae73..afb7aca5 100644 --- a/html/linux/factorial2.subx.html +++ b/html/linux/factorial2.subx.html @@ -7,11 +7,11 @@ - + @@ -64,7 +64,7 @@ if ('onhashchange' in window) { 3 # comments between '#' and newline. 4 # 5 # To run: - 6 # $ bootstrap/bootstrap translate [01]*.subx apps/subx-params.subx apps/hex.subx -o apps/hex + 6 # $ bootstrap/bootstrap translate [01]*.subx subx-params.subx hex.subx -o hex 7 # $ echo '80 81 82 # comment' |bootstrap/bootstrap run hex |xxd - 8 # Expected output: 9 # 00000000: 8081 82 diff --git a/html/linux/mu-init-test.subx.html b/html/linux/mu-init-test.subx.html index 2c86d221..4f766387 100644 --- a/html/linux/mu-init-test.subx.html +++ b/html/linux/mu-init-test.subx.html @@ -7,11 +7,11 @@ - + @@ -59,7 +59,7 @@ if ('onhashchange' in window) { 1 # Repeatedly read 32-bit numbers from /dev/random, print them to stdout. 2 # 3 # To run: - 4 # $ bootstrap/bootstrap translate [01]*.subx apps/random.subx -o apps/random + 4 # $ bootstrap/bootstrap translate [01]*.subx random.subx -o random 5 # $ bootstrap/bootstrap run random 6 7 == code 0x09000000 diff --git a/html/linux/raytracing/1.mu.html b/html/linux/raytracing/1.mu.html index 97c5cf39..ce86778a 100644 --- a/html/linux/raytracing/1.mu.html +++ b/html/linux/raytracing/1.mu.html @@ -7,11 +7,11 @@ - + @@ -62,7 +62,7 @@ if ('onhashchange' in window) { 2 # all functions starting with 'test-'. 3 # 4 # To build: - 5 # $ bootstrap/bootstrap translate [01]*.subx apps/subx-params.subx apps/tests.subx -o apps/tests + 5 # $ bootstrap/bootstrap translate [01]*.subx subx-params.subx tests.subx -o tests 6 7 == code 8 # instruction effective address register displacement immediate diff --git a/html/linux/texture.mu.html b/html/linux/texture.mu.html index 05d11331..f3aa6013 100644 --- a/html/linux/texture.mu.html +++ b/html/linux/texture.mu.html @@ -7,11 +7,11 @@ - + - - - - -https://github.com/akkartik/mu/blob/main/shell/eval.mu -
-  1 # env is an alist of ((sym . val) (sym . val) ...)
-  2 # we never modify `in` or `env`
-  3 fn evaluate _in: (addr handle cell), out: (addr handle cell), env-h: (handle cell), trace: (addr trace) {
-  4   var in/esi: (addr handle cell) <- copy _in
-  5 +-- 12 lines: # trace "evaluate " in " in environment " env -----------------------------------------------------------------------------------------------------------------------------
- 17   trace-lower trace
- 18   var in-addr/eax: (addr cell) <- lookup *in
- 19   {
- 20     var nil?/eax: boolean <- nil? in-addr
- 21     compare nil?, 0/false
- 22     break-if-=
- 23     # nil is a literal
- 24     trace-text trace, "eval", "nil"
- 25     copy-object _in, out
- 26     trace-higher trace
- 27     return
- 28   }
- 29   var in-type/ecx: (addr int) <- get in-addr, type
- 30   compare *in-type, 1/number
- 31   {
- 32     break-if-!=
- 33     # numbers are literals
- 34     trace-text trace, "eval", "number"
- 35     copy-object _in, out
- 36     trace-higher trace
- 37     return
- 38   }
- 39   compare *in-type, 2/symbol
- 40   {
- 41     break-if-!=
- 42     trace-text trace, "eval", "symbol"
- 43     lookup-symbol in-addr, out, env-h, trace
- 44     trace-higher trace
- 45     return
- 46   }
- 47   # in-addr is a syntax tree
- 48   $evaluate:anonymous-function: {
- 49     # trees starting with "fn" are anonymous functions and therefore literals
- 50     var expr/esi: (addr cell) <- copy in-addr
- 51     # if its first elem is not "fn", break
- 52     var first-ah/ecx: (addr handle cell) <- get in-addr, left
- 53     var first/eax: (addr cell) <- lookup *first-ah
- 54     var fn?/eax: boolean <- fn? first
- 55     compare fn?, 0/false
- 56     break-if-=
- 57     #
- 58     trace-text trace, "eval", "anonymous function"
- 59     copy-object _in, out
- 60     trace-higher trace
- 61     return
- 62   }
- 63   trace-text trace, "eval", "function call"
- 64   trace-text trace, "eval", "evaluating list elements"
- 65   var evaluated-list-storage: (handle cell)
- 66   var evaluated-list-ah/esi: (addr handle cell) <- address evaluated-list-storage
- 67   var curr-out-ah/edx: (addr handle cell) <- copy evaluated-list-ah
- 68   var curr/ecx: (addr cell) <- copy in-addr
- 69   $evaluate-list:loop: {
- 70     allocate-pair curr-out-ah
- 71     var nil?/eax: boolean <- nil? curr
- 72     compare nil?, 0/false
- 73     break-if-!=
- 74     # eval left
- 75     var curr-out/eax: (addr cell) <- lookup *curr-out-ah
- 76     var left-out-ah/edi: (addr handle cell) <- get curr-out, left
- 77     var left-ah/esi: (addr handle cell) <- get curr, left
- 78     evaluate left-ah, left-out-ah, env-h, trace
- 79     #
- 80     curr-out-ah <- get curr-out, right
- 81     var right-ah/eax: (addr handle cell) <- get curr, right
- 82     var right/eax: (addr cell) <- lookup *right-ah
- 83     curr <- copy right
- 84     loop
- 85   }
- 86   var evaluated-list/eax: (addr cell) <- lookup *evaluated-list-ah
- 87   var function-ah/ecx: (addr handle cell) <- get evaluated-list, left
- 88   var args-ah/edx: (addr handle cell) <- get evaluated-list, right
- 89 #?   dump-cell args-ah
- 90 #?   abort "aaa"
- 91   apply function-ah, args-ah, out, env-h, trace
- 92   trace-higher trace
- 93 +--  9 lines: # trace "=> " out ---------------------------------------------------------------------------------------------------------------------------------------------------------
-102 }
-103 
-104 fn apply _f-ah: (addr handle cell), args-ah: (addr handle cell), out: (addr handle cell), env-h: (handle cell), trace: (addr trace) {
-105   var f-ah/eax: (addr handle cell) <- copy _f-ah
-106   var _f/eax: (addr cell) <- lookup *f-ah
-107   var f/esi: (addr cell) <- copy _f
-108   # call primitive functions
-109   {
-110     var f-type/eax: (addr int) <- get f, type
-111     compare *f-type, 4/primitive-function
-112     break-if-!=
-113     apply-primitive f, args-ah, out, env-h, trace
-114     return
-115   }
-116   # if it's not a primitive function it must be an anonymous function
-117 +-- 12 lines: # trace "apply anonymous function " f " in environment " env --------------------------------------------------------------------------------------------------------------
-129   trace-lower trace
-130   {
-131     var f-type/ecx: (addr int) <- get f, type
-132     compare *f-type, 0/pair
-133     break-if-!=
-134     var first-ah/eax: (addr handle cell) <- get f, left
-135     var first/eax: (addr cell) <- lookup *first-ah
-136     var fn?/eax: boolean <- fn? first
-137     compare fn?, 0/false
-138     break-if-=
-139     var rest-ah/esi: (addr handle cell) <- get f, right
-140     var rest/eax: (addr cell) <- lookup *rest-ah
-141     var params-ah/ecx: (addr handle cell) <- get rest, left
-142     var body-ah/eax: (addr handle cell) <- get rest, right
-143     apply-function params-ah, args-ah, body-ah, out, env-h, trace
-144     trace-higher trace
-145     return
-146   }
-147   error trace, "unknown function"
-148 }
-149 
-150 fn apply-function params-ah: (addr handle cell), args-ah: (addr handle cell), _body-ah: (addr handle cell), out: (addr handle cell), env-h: (handle cell), trace: (addr trace) {
-151   # push bindings for params to env
-152   var new-env-storage: (handle cell)
-153   var new-env-ah/esi: (addr handle cell) <- address new-env-storage
-154   push-bindings params-ah, args-ah, env-h, new-env-ah, trace
-155   # eval all expressions in body, writing result to `out` each time
-156   var body-ah/ecx: (addr handle cell) <- copy _body-ah
-157   $apply-function:body: {
-158     var body/eax: (addr cell) <- lookup *body-ah
-159     # stop when body is nil
-160     {
-161       var body-nil?/eax: boolean <- nil? body
-162       compare body-nil?, 0/false
-163       break-if-!= $apply-function:body
-164     }
-165     # evaluate each expression, writing result to `out`
-166     {
-167       var curr-ah/eax: (addr handle cell) <- get body, left
-168       evaluate curr-ah, out, *new-env-ah, trace
-169     }
-170     #
-171     body-ah <- get body, right
-172     loop
-173   }
-174   # `out` contains result of evaluating final expression
-175 }
-176 
-177 # Bind params to corresponding args and add the bindings to old-env. Return
-178 # the result in env-ah.
-179 #
-180 # We never modify old-env, but we point to it. This way other parts of the
-181 # interpreter can continue using old-env, and everything works harmoniously
-182 # even though no cells are copied around.
-183 #
-184 # env should always be a DAG (ignoring internals of values). It doesn't have
-185 # to be a tree (some values may be shared), but there are also no cycles.
-186 #
-187 # Learn more: https://en.wikipedia.org/wiki/Persistent_data_structure
-188 fn push-bindings _params-ah: (addr handle cell), _args-ah: (addr handle cell), old-env-h: (handle cell), env-ah: (addr handle cell), trace: (addr trace) {
-189   var params-ah/edx: (addr handle cell) <- copy _params-ah
-190   var args-ah/ebx: (addr handle cell) <- copy _args-ah
-191   var _params/eax: (addr cell) <- lookup *params-ah
-192   var params/esi: (addr cell) <- copy _params
-193   {
-194     var params-nil?/eax: boolean <- nil? params
-195     compare params-nil?, 0/false
-196     break-if-=
-197     # nil is a literal
-198     trace-text trace, "eval", "done with push-bindings"
-199     copy-handle old-env-h, env-ah
-200     return
-201   }
-202   # Params can only be symbols or pairs. Args can be anything.
-203 +-- 14 lines: # trace "pushing bindings from " params " to " args -----------------------------------------------------------------------------------------------------------------------
-217   trace-lower trace
-218   var params-type/eax: (addr int) <- get params, type
-219   compare *params-type, 2/symbol
-220   {
-221     break-if-!=
-222     trace-text trace, "eval", "symbol; binding to all remaining args"
-223     # create a new binding
-224     var new-binding-storage: (handle cell)
-225     var new-binding-ah/eax: (addr handle cell) <- address new-binding-storage
-226     new-pair new-binding-ah, *params-ah, *args-ah
-227     # push it to env
-228     new-pair env-ah, *new-binding-ah, old-env-h
-229     trace-higher trace
-230     return
-231   }
-232   compare *params-type, 0/pair
-233   {
-234     break-if-=
-235     error trace, "cannot bind a non-symbol"
-236     trace-higher trace
-237     return
-238   }
-239   var _args/eax: (addr cell) <- lookup *args-ah
-240   var args/edi: (addr cell) <- copy _args
-241   # params is now a pair, so args must be also
-242   var args-type/eax: (addr int) <- get args, type
-243   compare *args-type, 0/pair
-244   {
-245     break-if-=
-246     error trace, "args not in a proper list"
-247     trace-higher trace
-248     return
-249   }
-250   var intermediate-env-storage: (handle cell)
-251   var intermediate-env-ah/edx: (addr handle cell) <- address intermediate-env-storage
-252   var first-param-ah/eax: (addr handle cell) <- get params, left
-253   var first-arg-ah/ecx: (addr handle cell) <- get args, left
-254   push-bindings first-param-ah, first-arg-ah, old-env-h, intermediate-env-ah, trace
-255   var remaining-params-ah/eax: (addr handle cell) <- get params, right
-256   var remaining-args-ah/ecx: (addr handle cell) <- get args, right
-257   push-bindings remaining-params-ah, remaining-args-ah, *intermediate-env-ah, env-ah, trace
-258   trace-higher trace
-259 }
-260 
-261 fn apply-primitive _f: (addr cell), args-ah: (addr handle cell), out: (addr handle cell), env-h: (handle cell), trace: (addr trace) {
-262   var f/esi: (addr cell) <- copy _f
-263   var f-index/eax: (addr int) <- get f, index-data
-264   {
-265     compare *f-index, 1/add
-266     break-if-!=
-267     apply-add args-ah, out, env-h, trace
-268     return
-269   }
-270   abort "unknown primitive function"
-271 }
-272 
-273 fn apply-add _args-ah: (addr handle cell), out: (addr handle cell), env-h: (handle cell), trace: (addr trace) {
-274   trace-text trace, "eval", "apply +"
-275   var args-ah/eax: (addr handle cell) <- copy _args-ah
-276   var _args/eax: (addr cell) <- lookup *args-ah
-277   var args/esi: (addr cell) <- copy _args
-278   var _env/eax: (addr cell) <- lookup env-h
-279   var env/edi: (addr cell) <- copy _env
-280   # TODO: check that args is a pair
-281   var empty-args?/eax: boolean <- nil? args
-282   compare empty-args?, 0/false
-283   {
-284     break-if-=
-285     error trace, "+ needs 2 args but got 0"
-286     return
-287   }
-288   # args->left->value
-289   var first-ah/eax: (addr handle cell) <- get args, left
-290   var first/eax: (addr cell) <- lookup *first-ah
-291   var first-type/ecx: (addr int) <- get first, type
-292   compare *first-type, 1/number
-293   {
-294     break-if-=
-295     error trace, "first arg for + is not a number"
-296     return
-297   }
-298   var first-value/ecx: (addr float) <- get first, number-data
-299   # args->right->left->value
-300   var right-ah/eax: (addr handle cell) <- get args, right
-301 #?   dump-cell right-ah
-302 #?   abort "aaa"
-303   var right/eax: (addr cell) <- lookup *right-ah
-304   # TODO: check that right is a pair
-305   var second-ah/eax: (addr handle cell) <- get right, left
-306   var second/eax: (addr cell) <- lookup *second-ah
-307   var second-type/edx: (addr int) <- get second, type
-308   compare *second-type, 1/number
-309   {
-310     break-if-=
-311     error trace, "second arg for + is not a number"
-312     return
-313   }
-314   var second-value/edx: (addr float) <- get second, number-data
-315   # add
-316   var result/xmm0: float <- copy *first-value
-317   result <- add *second-value
-318   new-float out, result
-319 }
-320 
-321 fn lookup-symbol sym: (addr cell), out: (addr handle cell), env-h: (handle cell), trace: (addr trace) {
-322   # trace sym
-323   {
-324     var stream-storage: (stream byte 0x40)
-325     var stream/ecx: (addr stream byte) <- address stream-storage
-326     write stream, "look up "
-327     var sym2/eax: (addr cell) <- copy sym
-328     var sym-data-ah/eax: (addr handle stream byte) <- get sym2, text-data
-329     var sym-data/eax: (addr stream byte) <- lookup *sym-data-ah
-330     rewind-stream sym-data
-331     write-stream stream, sym-data
-332     write stream, " in "
-333     var env-ah/eax: (addr handle cell) <- address env-h
-334     print-cell env-ah, stream, 0/no-trace
-335     trace trace, "eval", stream
-336   }
-337   trace-lower trace
-338   var _env/eax: (addr cell) <- lookup env-h
-339   var env/ebx: (addr cell) <- copy _env
-340   # if env is not a list, abort
-341   {
-342     var env-type/ecx: (addr int) <- get env, type
-343     compare *env-type, 0/pair
-344     break-if-=
-345     error trace, "eval found a non-list environment"
-346     trace-higher trace
-347     return
-348   }
-349   # if env is nil, look up in globals
-350   {
-351     var env-nil?/eax: boolean <- nil? env
-352     compare env-nil?, 0/false
-353     break-if-=
-354     lookup-symbol-in-hardcoded-globals sym, out, trace
-355     trace-higher trace
-356 +-- 13 lines: # trace "=> " out " (global)" ---------------------------------------------------------------------------------------------------------------------------------------------
-369     return
-370   }
-371   # check car
-372   var env-head-storage: (handle cell)
-373   var env-head-ah/eax: (addr handle cell) <- address env-head-storage
-374   car env, env-head-ah, 0/no-trace
-375   var _env-head/eax: (addr cell) <- lookup *env-head-ah
-376   var env-head/ecx: (addr cell) <- copy _env-head
-377   # if car is not a list, abort
-378   {
-379     var env-head-type/eax: (addr int) <- get env-head, type
-380     compare *env-head-type, 0/pair
-381     break-if-=
-382     error trace, "environment is not a list of (key . value) pairs"
-383     trace-higher trace
-384     return
-385   }
-386   # check key
-387   var curr-key-storage: (handle cell)
-388   var curr-key-ah/eax: (addr handle cell) <- address curr-key-storage
-389   car env-head, curr-key-ah, trace
-390   var curr-key/eax: (addr cell) <- lookup *curr-key-ah
-391   # if key is not a symbol, abort
-392   {
-393     var curr-key-type/eax: (addr int) <- get curr-key, type
-394     compare *curr-key-type, 2/symbol
-395     break-if-=
-396     error trace, "environment contains a binding for a non-symbol"
-397     trace-higher trace
-398     return
-399   }
-400   # if key matches sym, return val
-401   var match?/eax: boolean <- cell-isomorphic? curr-key, sym, trace
-402   compare match?, 0/false
-403   {
-404     break-if-=
-405     cdr env-head, out, 0/no-trace
-406 +-- 13 lines: # trace "=> " out " (match)" ----------------------------------------------------------------------------------------------------------------------------------------------
-419     trace-higher trace
-420     return
-421   }
-422   # otherwise recurse
-423   var env-tail-storage: (handle cell)
-424   var env-tail-ah/eax: (addr handle cell) <- address env-tail-storage
-425   cdr env, env-tail-ah, trace
-426   lookup-symbol sym, out, *env-tail-ah, trace
-427   trace-higher trace
-428 +-- 13 lines: # trace "=> " out " (recurse)" --------------------------------------------------------------------------------------------------------------------------------------------
-441 }
-442 
-443 fn lookup-symbol-in-hardcoded-globals _sym: (addr cell), out: (addr handle cell), trace: (addr trace) {
-444   var sym/eax: (addr cell) <- copy _sym
-445   var sym-data-ah/eax: (addr handle stream byte) <- get sym, text-data
-446   var _sym-data/eax: (addr stream byte) <- lookup *sym-data-ah
-447   var sym-data/esi: (addr stream byte) <- copy _sym-data
-448   {
-449     var add?/eax: boolean <- stream-data-equal? sym-data, "+"
-450     compare add?, 0/false
-451     break-if-=
-452     new-primitive-function out, 1/add
-453     trace-text trace, "eval", "global +"
-454     return
-455   }
-456   # otherwise error "unbound symbol: ", sym
-457   var stream-storage: (stream byte 0x40)
-458   var stream/ecx: (addr stream byte) <- address stream-storage
-459   write stream, "unbound symbol: "
-460   rewind-stream sym-data
-461   write-stream stream, sym-data
-462   trace trace, "error", stream
-463 }
-464 
-465 fn test-lookup-symbol-in-env {
-466   # tmp = (a . 3)
-467   var val-storage: (handle cell)
-468   var val-ah/ecx: (addr handle cell) <- address val-storage
-469   new-integer val-ah, 3
-470   var key-storage: (handle cell)
-471   var key-ah/edx: (addr handle cell) <- address key-storage
-472   new-symbol key-ah, "a"
-473   var env-storage: (handle cell)
-474   var env-ah/ebx: (addr handle cell) <- address env-storage
-475   new-pair env-ah, *key-ah, *val-ah
-476   # env = ((a . 3))
-477   var nil-storage: (handle cell)
-478   var nil-ah/ecx: (addr handle cell) <- address nil-storage
-479   allocate-pair nil-ah
-480   new-pair env-ah, *env-ah, *nil-ah
-481   # lookup sym(a) in env tmp
-482   var tmp-storage: (handle cell)
-483   var tmp-ah/edx: (addr handle cell) <- address tmp-storage
-484   new-symbol tmp-ah, "a"
-485   var in/eax: (addr cell) <- lookup *tmp-ah
-486   lookup-symbol in, tmp-ah, *env-ah, 0/no-trace
-487   var result/eax: (addr cell) <- lookup *tmp-ah
-488   var result-type/edx: (addr int) <- get result, type
-489   check-ints-equal *result-type, 1/number, "F - test-lookup-symbol-in-env/0"
-490   var result-value-addr/eax: (addr float) <- get result, number-data
-491   var result-value/eax: int <- convert *result-value-addr
-492   check-ints-equal result-value, 3, "F - test-lookup-symbol-in-env/1"
-493 }
-494 
-495 fn test-lookup-symbol-in-hardcoded-globals {
-496   # env = nil
-497   var nil-storage: (handle cell)
-498   var nil-ah/ecx: (addr handle cell) <- address nil-storage
-499   allocate-pair nil-ah
-500   # lookup sym(a), env
-501   var tmp-storage: (handle cell)
-502   var tmp-ah/ebx: (addr handle cell) <- address tmp-storage
-503   new-symbol tmp-ah, "+"
-504   var in/eax: (addr cell) <- lookup *tmp-ah
-505   lookup-symbol in, tmp-ah, *nil-ah, 0/no-trace
-506   var result/eax: (addr cell) <- lookup *tmp-ah
-507   var result-type/edx: (addr int) <- get result, type
-508   check-ints-equal *result-type, 4/primitive-function, "F - test-lookup-symbol-in-hardcoded-globals/0"
-509   var result-value/eax: (addr int) <- get result, index-data
-510   check-ints-equal *result-value, 1/add, "F - test-lookup-symbol-in-hardcoded-globals/1"
-511 }
-512 
-513 fn car _in: (addr cell), out: (addr handle cell), trace: (addr trace) {
-514   trace-text trace, "eval", "car"
-515   trace-lower trace
-516   var in/eax: (addr cell) <- copy _in
-517   # if in is not a list, abort
-518   {
-519     var in-type/ecx: (addr int) <- get in, type
-520     compare *in-type, 0/pair
-521     break-if-=
-522     error trace, "car on a non-list"
-523     trace-higher trace
-524     return
-525   }
-526   # if in is nil, abort
-527   {
-528     var in-nil?/eax: boolean <- nil? in
-529     compare in-nil?, 0/false
-530     break-if-=
-531     error trace, "car on nil"
-532     trace-higher trace
-533     return
-534   }
-535   var in-left/eax: (addr handle cell) <- get in, left
-536   copy-object in-left, out
-537   trace-higher trace
-538   return
-539 }
-540 
-541 fn cdr _in: (addr cell), out: (addr handle cell), trace: (addr trace) {
-542   trace-text trace, "eval", "cdr"
-543   trace-lower trace
-544   var in/eax: (addr cell) <- copy _in
-545   # if in is not a list, abort
-546   {
-547     var in-type/ecx: (addr int) <- get in, type
-548     compare *in-type, 0/pair
-549     break-if-=
-550     error trace, "car on a non-list"
-551     trace-higher trace
-552     return
-553   }
-554   # if in is nil, abort
-555   {
-556     var in-nil?/eax: boolean <- nil? in
-557     compare in-nil?, 0/false
-558     break-if-=
-559     error trace, "car on nil"
-560     trace-higher trace
-561     return
-562   }
-563   var in-right/eax: (addr handle cell) <- get in, right
-564   copy-object in-right, out
-565   trace-higher trace
-566   return
-567 }
-568 
-569 fn cell-isomorphic? _a: (addr cell), _b: (addr cell), trace: (addr trace) -> _/eax: boolean {
-570   trace-text trace, "eval", "cell-isomorphic?"
-571   trace-lower trace
-572   var a/esi: (addr cell) <- copy _a
-573   var b/edi: (addr cell) <- copy _b
-574   # if types don't match, return false
-575   var a-type-addr/eax: (addr int) <- get a, type
-576   var b-type-addr/ecx: (addr int) <- get b, type
-577   var b-type/ecx: int <- copy *b-type-addr
-578   compare b-type, *a-type-addr
-579   {
-580     break-if-=
-581     trace-higher trace
-582     trace-text trace, "eval", "=> false (type)"
-583     return 0/false
-584   }
-585   # if types are number, compare number-data
-586   # TODO: exactly comparing floats is a bad idea
-587   compare b-type, 1/number
-588   {
-589     break-if-!=
-590     var a-val-addr/eax: (addr float) <- get a, number-data
-591     var b-val-addr/ecx: (addr float) <- get b, number-data
-592     var a-val/xmm0: float <- copy *a-val-addr
-593     compare a-val, *b-val-addr
-594     {
-595       break-if-=
-596       trace-higher trace
-597       trace-text trace, "eval", "=> false (numbers)"
-598       return 0/false
-599     }
-600     trace-higher trace
-601     trace-text trace, "eval", "=> true (numbers)"
-602     return 1/true
-603   }
-604   compare b-type, 2/symbol
-605   {
-606     break-if-!=
-607     var b-val-ah/eax: (addr handle stream byte) <- get b, text-data
-608     var _b-val/eax: (addr stream byte) <- lookup *b-val-ah
-609     var b-val/ecx: (addr stream byte) <- copy _b-val
-610     var a-val-ah/eax: (addr handle stream byte) <- get a, text-data
-611     var a-val/eax: (addr stream byte) <- lookup *a-val-ah
-612     var tmp-array: (handle array byte)
-613     var tmp-ah/edx: (addr handle array byte) <- address tmp-array
-614     rewind-stream a-val
-615     stream-to-array a-val, tmp-ah
-616     var tmp/eax: (addr array byte) <- lookup *tmp-ah
-617     var match?/eax: boolean <- stream-data-equal? b-val, tmp
-618     trace-higher trace
-619     {
-620       compare match?, 0/false
-621       break-if-=
-622       trace-text trace, "eval", "=> true (symbols)"
-623     }
-624     {
-625       compare match?, 0/false
-626       break-if-!=
-627       trace-text trace, "eval", "=> false (symbols)"
-628     }
-629     return match?
-630   }
-631   # if a is nil, b should be nil
-632   {
-633     # (assumes nil? returns 0 or 1)
-634     var _b-nil?/eax: boolean <- nil? b
-635     var b-nil?/ecx: boolean <- copy _b-nil?
-636     var a-nil?/eax: boolean <- nil? a
-637     # a == nil and b == nil => return true
-638     {
-639       compare a-nil?, 0/false
-640       break-if-=
-641       compare b-nil?, 0/false
-642       break-if-=
-643       trace-higher trace
-644       trace-text trace, "eval", "=> true (nils)"
-645       return 1/true
-646     }
-647     # a == nil => return false
-648     {
-649       compare a-nil?, 0/false
-650       break-if-=
-651       trace-higher trace
-652       trace-text trace, "eval", "=> false (b != nil)"
-653       return 0/false
-654     }
-655     # b == nil => return false
-656     {
-657       compare b-nil?, 0/false
-658       break-if-=
-659       trace-higher trace
-660       trace-text trace, "eval", "=> false (a != nil)"
-661       return 0/false
-662     }
-663   }
-664   # a and b are pairs
-665   var a-tmp-storage: (handle cell)
-666   var a-tmp-ah/edx: (addr handle cell) <- address a-tmp-storage
-667   var b-tmp-storage: (handle cell)
-668   var b-tmp-ah/ebx: (addr handle cell) <- address b-tmp-storage
-669   # if cars aren't equal, return false
-670   car a, a-tmp-ah, trace
-671   car b, b-tmp-ah, trace
-672   {
-673     var _a-tmp/eax: (addr cell) <- lookup *a-tmp-ah
-674     var a-tmp/ecx: (addr cell) <- copy _a-tmp
-675     var b-tmp/eax: (addr cell) <- lookup *b-tmp-ah
-676     var result/eax: boolean <- cell-isomorphic? a-tmp, b-tmp, trace
-677     compare result, 0/false
-678     break-if-!=
-679     trace-higher trace
-680     trace-text trace, "eval", "=> false (car mismatch)"
-681     return 0/false
-682   }
-683   # recurse on cdrs
-684   cdr a, a-tmp-ah, trace
-685   cdr b, b-tmp-ah, trace
-686   var _a-tmp/eax: (addr cell) <- lookup *a-tmp-ah
-687   var a-tmp/ecx: (addr cell) <- copy _a-tmp
-688   var b-tmp/eax: (addr cell) <- lookup *b-tmp-ah
-689   var result/eax: boolean <- cell-isomorphic? a-tmp, b-tmp, trace
-690   trace-higher trace
-691   return result
-692 }
-693 
-694 fn fn? _x: (addr cell) -> _/eax: boolean {
-695   var x/esi: (addr cell) <- copy _x
-696   var type/eax: (addr int) <- get x, type
-697   compare *type, 2/symbol
-698   {
-699     break-if-=
-700     return 0/false
-701   }
-702   var contents-ah/eax: (addr handle stream byte) <- get x, text-data
-703   var contents/eax: (addr stream byte) <- lookup *contents-ah
-704   var result/eax: boolean <- stream-data-equal? contents, "fn"
-705   return result
-706 }
-707 
-708 fn test-evaluate-is-well-behaved {
-709   var t-storage: trace
-710   var t/esi: (addr trace) <- address t-storage
-711   initialize-trace t, 0x10, 0/visible  # we don't use trace UI
-712   # env = nil
-713   var env-storage: (handle cell)
-714   var env-ah/ecx: (addr handle cell) <- address env-storage
-715   allocate-pair env-ah
-716   # eval sym(a), nil env
-717   var tmp-storage: (handle cell)
-718   var tmp-ah/edx: (addr handle cell) <- address tmp-storage
-719   new-symbol tmp-ah, "a"
-720   evaluate tmp-ah, tmp-ah, *env-ah, t
-721   # doesn't die
-722   check-trace-contains t, "error", "unbound symbol: a", "F - test-evaluate-is-well-behaved"
-723 }
-724 
-725 fn test-evaluate-number {
-726   # env = nil
-727   var env-storage: (handle cell)
-728   var env-ah/ecx: (addr handle cell) <- address env-storage
-729   allocate-pair env-ah
-730   # tmp = 3
-731   var tmp-storage: (handle cell)
-732   var tmp-ah/edx: (addr handle cell) <- address tmp-storage
-733   new-integer tmp-ah, 3
-734   evaluate tmp-ah, tmp-ah, *env-ah, 0/no-trace
-735   #
-736   var result/eax: (addr cell) <- lookup *tmp-ah
-737   var result-type/edx: (addr int) <- get result, type
-738   check-ints-equal *result-type, 1/number, "F - test-evaluate-number/0"
-739   var result-value-addr/eax: (addr float) <- get result, number-data
-740   var result-value/eax: int <- convert *result-value-addr
-741   check-ints-equal result-value, 3, "F - test-evaluate-number/1"
-742 }
-743 
-744 fn test-evaluate-symbol {
-745   # tmp = (a . 3)
-746   var val-storage: (handle cell)
-747   var val-ah/ecx: (addr handle cell) <- address val-storage
-748   new-integer val-ah, 3
-749   var key-storage: (handle cell)
-750   var key-ah/edx: (addr handle cell) <- address key-storage
-751   new-symbol key-ah, "a"
-752   var env-storage: (handle cell)
-753   var env-ah/ebx: (addr handle cell) <- address env-storage
-754   new-pair env-ah, *key-ah, *val-ah
-755   # env = ((a . 3))
-756   var nil-storage: (handle cell)
-757   var nil-ah/ecx: (addr handle cell) <- address nil-storage
-758   allocate-pair nil-ah
-759   new-pair env-ah, *env-ah, *nil-ah
-760   # eval sym(a), env
-761   var tmp-storage: (handle cell)
-762   var tmp-ah/edx: (addr handle cell) <- address tmp-storage
-763   new-symbol tmp-ah, "a"
-764   evaluate tmp-ah, tmp-ah, *env-ah, 0/no-trace
-765   var result/eax: (addr cell) <- lookup *tmp-ah
-766   var result-type/edx: (addr int) <- get result, type
-767   check-ints-equal *result-type, 1/number, "F - test-evaluate-symbol/0"
-768   var result-value-addr/eax: (addr float) <- get result, number-data
-769   var result-value/eax: int <- convert *result-value-addr
-770   check-ints-equal result-value, 3, "F - test-evaluate-symbol/1"
-771 }
-772 
-773 fn test-evaluate-primitive-function {
-774   var nil-storage: (handle cell)
-775   var nil-ah/ecx: (addr handle cell) <- address nil-storage
-776   allocate-pair nil-ah
-777   var add-storage: (handle cell)
-778   var add-ah/ebx: (addr handle cell) <- address add-storage
-779   new-symbol add-ah, "+"
-780   # eval +, nil env
-781   var tmp-storage: (handle cell)
-782   var tmp-ah/esi: (addr handle cell) <- address tmp-storage
-783   evaluate add-ah, tmp-ah, *nil-ah, 0/no-trace
-784   #
-785   var result/eax: (addr cell) <- lookup *tmp-ah
-786   var result-type/edx: (addr int) <- get result, type
-787   check-ints-equal *result-type, 4/primitive-function, "F - test-evaluate-primitive-function/0"
-788   var result-value/eax: (addr int) <- get result, index-data
-789   check-ints-equal *result-value, 1/add, "F - test-evaluate-primitive-function/1"
-790 }
-791 
-792 fn test-evaluate-primitive-function-call {
-793   var t-storage: trace
-794   var t/edi: (addr trace) <- address t-storage
-795   initialize-trace t, 0x100, 0/visible  # we don't use trace UI
-796   #
-797   var nil-storage: (handle cell)
-798   var nil-ah/ecx: (addr handle cell) <- address nil-storage
-799   allocate-pair nil-ah
-800   var one-storage: (handle cell)
-801   var one-ah/edx: (addr handle cell) <- address one-storage
-802   new-integer one-ah, 1
-803   var add-storage: (handle cell)
-804   var add-ah/ebx: (addr handle cell) <- address add-storage
-805   new-symbol add-ah, "+"
-806   # eval (+ 1 1), nil env
-807   var tmp-storage: (handle cell)
-808   var tmp-ah/esi: (addr handle cell) <- address tmp-storage
-809   new-pair tmp-ah, *one-ah, *nil-ah
-810   new-pair tmp-ah, *one-ah, *tmp-ah
-811   new-pair tmp-ah, *add-ah, *tmp-ah
-812 #?   dump-cell tmp-ah
-813   evaluate tmp-ah, tmp-ah, *nil-ah, t
-814 #?   dump-trace t
-815   #
-816   var result/eax: (addr cell) <- lookup *tmp-ah
-817   var result-type/edx: (addr int) <- get result, type
-818   check-ints-equal *result-type, 1/number, "F - test-evaluate-primitive-function-call/0"
-819   var result-value-addr/eax: (addr float) <- get result, number-data
-820   var result-value/eax: int <- convert *result-value-addr
-821   check-ints-equal result-value, 2, "F - test-evaluate-primitive-function-call/1"
-822 }
-
- - - diff --git a/html/shell/evaluate.mu.html b/html/shell/evaluate.mu.html index 5db98eff..7f41f64a 100644 --- a/html/shell/evaluate.mu.html +++ b/html/shell/evaluate.mu.html @@ -7,11 +7,11 @@ - + + + + + +https://github.com/akkartik/mu/blob/main/shell/life.mu +
+  1 fn state _grid: (addr array boolean), x: int, y: int -> _/eax: boolean {
+  2   # clip at the edge
+  3   compare x, 0
+  4   {
+  5     break-if->=
+  6     return 0/false
+  7   }
+  8   compare y, 0
+  9   {
+ 10     break-if->=
+ 11     return 0/false
+ 12   }
+ 13   compare x, 0x100/width
+ 14   {
+ 15     break-if-<
+ 16     return 0/false
+ 17   }
+ 18   compare y, 0xc0/height
+ 19   {
+ 20     break-if-<
+ 21     return 0/false
+ 22   }
+ 23   var idx/eax: int <- copy y
+ 24   idx <- shift-left 8/log2width
+ 25   idx <- add x
+ 26   var grid/esi: (addr array boolean) <- copy _grid
+ 27   var result/eax: (addr boolean) <- index grid, idx
+ 28   return *result
+ 29 }
+ 30 
+ 31 fn set-state _grid: (addr array boolean), x: int, y: int, val: boolean {
+ 32   # don't bother checking bounds
+ 33   var idx/eax: int <- copy y
+ 34   idx <- shift-left 8/log2width
+ 35   idx <- add x
+ 36   var grid/esi: (addr array boolean) <- copy _grid
+ 37   var result/eax: (addr boolean) <- index grid, idx
+ 38   var src/ecx: boolean <- copy val
+ 39   copy-to *result, src
+ 40 }
+ 41 
+ 42 fn num-live-neighbors grid: (addr array boolean), x: int, y: int -> _/eax: int {
+ 43   var result/edi: int <- copy 0
+ 44   # row above: zig
+ 45   decrement y
+ 46   decrement x
+ 47   var s/eax: boolean <- state grid, x, y
+ 48   {
+ 49     compare s, 0/false
+ 50     break-if-=
+ 51     result <- increment
+ 52   }
+ 53   increment x
+ 54   s <- state grid, x, y
+ 55   {
+ 56     compare s, 0/false
+ 57     break-if-=
+ 58     result <- increment
+ 59   }
+ 60   increment x
+ 61   s <- state grid, x, y
+ 62   {
+ 63     compare s, 0/false
+ 64     break-if-=
+ 65     result <- increment
+ 66   }
+ 67   # curr row: zag
+ 68   increment y
+ 69   s <- state grid, x, y
+ 70   {
+ 71     compare s, 0/false
+ 72     break-if-=
+ 73     result <- increment
+ 74   }
+ 75   subtract-from x, 2
+ 76   s <- state grid, x, y
+ 77   {
+ 78     compare s, 0/false
+ 79     break-if-=
+ 80     result <- increment
+ 81   }
+ 82   # row below: zig
+ 83   increment y
+ 84   s <- state grid, x, y
+ 85   {
+ 86     compare s, 0/false
+ 87     break-if-=
+ 88     result <- increment
+ 89   }
+ 90   increment x
+ 91   s <- state grid, x, y
+ 92   {
+ 93     compare s, 0/false
+ 94     break-if-=
+ 95     result <- increment
+ 96   }
+ 97   increment x
+ 98   s <- state grid, x, y
+ 99   {
+100     compare s, 0/false
+101     break-if-=
+102     result <- increment
+103   }
+104   return result
+105 }
+106 
+107 fn step old-grid: (addr array boolean), new-grid: (addr array boolean) {
+108   var y/ecx: int <- copy 0
+109   {
+110     compare y, 0xc0/height
+111     break-if->=
+112     var x/edx: int <- copy 0
+113     {
+114       compare x, 0x100/width
+115       break-if->=
+116       var n/eax: int <- num-live-neighbors old-grid, x, y
+117       # if neighbors < 2, die of loneliness
+118       {
+119         compare n, 2
+120         break-if->=
+121         set-state new-grid, x, y, 0/dead
+122       }
+123       # if neighbors > 3, die of overcrowding
+124       {
+125         compare n, 3
+126         break-if-<=
+127         set-state new-grid, x, y, 0/dead
+128       }
+129       # if neighbors = 2, preserve state
+130       {
+131         compare n, 2
+132         break-if-!=
+133         var old-state/eax: boolean <- state old-grid, x, y
+134         set-state new-grid, x, y, old-state
+135       }
+136       # if neighbors = 3, cell quickens to life
+137       {
+138         compare n, 3
+139         break-if-!=
+140         set-state new-grid, x, y, 1/live
+141       }
+142       x <- increment
+143       loop
+144     }
+145     y <- increment
+146     loop
+147   }
+148 }
+149 
+150 # color a square of size 'side' starting at x*side, y*side
+151 fn render-square _x: int, _y: int, color: int {
+152   var y/edx: int <- copy _y
+153   y <- shift-left 2/log2side
+154   var side/ebx: int <- copy 1
+155   side <- shift-left 2/log2side
+156   var ymax/ecx: int <- copy y
+157   ymax <- add side
+158   {
+159     compare y, ymax
+160     break-if->=
+161     {
+162       var x/eax: int <- copy _x
+163       x <- shift-left 2/log2side
+164       var xmax/ecx: int <- copy x
+165       xmax <- add side
+166       {
+167         compare x, xmax
+168         break-if->=
+169         pixel-on-real-screen x, y, color
+170         x <- increment
+171         loop
+172       }
+173     }
+174     y <- increment
+175     loop
+176   }
+177 }
+178 
+179 fn render grid: (addr array boolean) {
+180   var y/ecx: int <- copy 0
+181   {
+182     compare y, 0xc0/height
+183     break-if->=
+184     var x/edx: int <- copy 0
+185     {
+186       compare x, 0x100/width
+187       break-if->=
+188       var state/eax: boolean <- state grid, x, y
+189       compare state, 0/false
+190       {
+191         break-if-=
+192         render-square x, y, 3/cyan
+193       }
+194       compare state, 0/false
+195       {
+196         break-if-!=
+197         render-square x, y, 0/black
+198       }
+199       x <- increment
+200       loop
+201     }
+202     y <- increment
+203     loop
+204   }
+205 }
+206 
+207 fn life {
+208 #?   # allocate on the stack
+209 #?   var grid1-storage: (array boolean 0xc000)  # width * height
+210 #?   var grid1/esi: (addr array boolean) <- address grid1-storage
+211 #?   var grid2-storage: (array boolean 0xc000)  # width * height
+212 #?   var grid2/edi: (addr array boolean) <- address grid2-storage
+213   # allocate on the heap
+214   var grid1-storage: (handle array boolean)
+215   var grid1-ah/eax: (addr handle array boolean) <- address grid1-storage
+216   populate grid1-ah, 0xc000  # width * height
+217   var _grid1/eax: (addr array boolean) <- lookup *grid1-ah
+218   var grid1/esi: (addr array boolean) <- copy _grid1
+219   var grid2-storage: (handle array boolean)
+220   var grid2-ah/eax: (addr handle array boolean) <- address grid2-storage
+221   populate grid2-ah, 0xc000  # width * height
+222   var _grid2/eax: (addr array boolean) <- lookup *grid2-ah
+223   var grid2/edi: (addr array boolean) <- copy _grid2
+224   # initialize grid1
+225   set-state grid1, 0x80, 0x5f, 1/live
+226   set-state grid1, 0x81, 0x5f, 1/live
+227   set-state grid1, 0x7f, 0x60, 1/live
+228   set-state grid1, 0x80, 0x60, 1/live
+229   set-state grid1, 0x80, 0x61, 1/live
+230   # render grid1
+231   render grid1
+232   {
+233     var key/eax: byte <- read-key 0/keyboard
+234     compare key, 0
+235 #?     loop-if-=  # press key to step
+236     break-if-!=  # press key to quit  # comment this out to run under bochs; I'm not sure why there's a newline in the keyboard buffer
+237     # iter: grid1 -> grid2
+238     step grid1, grid2
+239     render grid2
+240     # iter: grid2 -> grid1
+241     step grid2, grid1
+242     render grid1
+243     loop
+244   }
+245 }
+
+ + + diff --git a/html/shell/main.mu.html b/html/shell/main.mu.html index 91dd6dfe..0be4b1cd 100644 --- a/html/shell/main.mu.html +++ b/html/shell/main.mu.html @@ -7,17 +7,18 @@ - + @@ -61,21 +62,21 @@ if ('onhashchange' in window) { 3 # they always have text-data. 4 5 fn tokenize in: (addr gap-buffer), out: (addr stream cell), trace: (addr trace) { - 6 trace-text trace, "read", "tokenize" - 7 trace-lower trace - 8 rewind-gap-buffer in + 6 trace-text trace, "read", "tokenize" + 7 trace-lower trace + 8 rewind-gap-buffer in 9 var token-storage: cell 10 var token/edx: (addr cell) <- address token-storage 11 { - 12 skip-whitespace-from-gap-buffer in - 13 var done?/eax: boolean <- gap-buffer-scan-done? in + 12 skip-whitespace-from-gap-buffer in + 13 var done?/eax: boolean <- gap-buffer-scan-done? in 14 compare done?, 0/false 15 break-if-!= 16 # initialize token data each iteration to avoid aliasing 17 var dest-ah/eax: (addr handle stream byte) <- get token, text-data 18 populate-stream dest-ah, 0x40/max-token-size 19 # - 20 next-token in, token, trace + 20 next-token in, token, trace 21 var error?/eax: boolean <- has-errors? trace 22 compare error?, 0/false 23 { @@ -85,560 +86,622 @@ if ('onhashchange' in window) { 27 write-to-stream out, token # shallow-copy text-data 28 loop 29 } - 30 trace-higher trace + 30 trace-higher trace 31 } 32 - 33 fn next-token in: (addr gap-buffer), _out-cell: (addr cell), trace: (addr trace) { - 34 trace-text trace, "read", "next-token" - 35 trace-lower trace - 36 var out-cell/eax: (addr cell) <- copy _out-cell - 37 var out-ah/eax: (addr handle stream byte) <- get out-cell, text-data - 38 var _out/eax: (addr stream byte) <- lookup *out-ah - 39 var out/edi: (addr stream byte) <- copy _out - 40 $next-token:body: { - 41 clear-stream out - 42 skip-whitespace-from-gap-buffer in - 43 var g/eax: grapheme <- peek-from-gap-buffer in - 44 { - 45 var stream-storage: (stream byte 0x40) - 46 var stream/esi: (addr stream byte) <- address stream-storage - 47 write stream, "next: " - 48 var gval/eax: int <- copy g - 49 write-int32-hex stream, gval - 50 trace trace, "read", stream - 51 } - 52 # digit - 53 { - 54 var digit?/eax: boolean <- decimal-digit? g - 55 compare digit?, 0/false - 56 break-if-= - 57 next-number-token in, out, trace - 58 break $next-token:body - 59 } - 60 # other symbol char - 61 { - 62 var symbol?/eax: boolean <- symbol-grapheme? g - 63 compare symbol?, 0/false - 64 break-if-= - 65 next-symbol-token in, out, trace - 66 break $next-token:body - 67 } - 68 # brackets are always single-char tokens - 69 { - 70 var bracket?/eax: boolean <- bracket-grapheme? g - 71 compare bracket?, 0/false - 72 break-if-= - 73 var g/eax: grapheme <- read-from-gap-buffer in - 74 next-bracket-token g, out, trace - 75 break $next-token:body - 76 } - 77 # non-symbol operators - 78 { - 79 var operator?/eax: boolean <- operator-grapheme? g - 80 compare operator?, 0/false - 81 break-if-= - 82 next-operator-token in, out, trace - 83 break $next-token:body + 33 fn test-tokenize-dotted-list { + 34 # in: "(a . b)" + 35 var in-storage: gap-buffer + 36 var in/esi: (addr gap-buffer) <- address in-storage + 37 initialize-gap-buffer in, 0x10 + 38 add-code-point-at-gap in, 0x28/open-paren + 39 add-code-point-at-gap in, 0x61/a + 40 add-code-point-at-gap in, 0x20/space + 41 add-code-point-at-gap in, 0x2e/dot + 42 add-code-point-at-gap in, 0x20/space + 43 add-code-point-at-gap in, 0x62/b + 44 add-code-point-at-gap in, 0x29/close-paren + 45 # + 46 var stream-storage: (stream cell 0x10) + 47 var stream/edi: (addr stream cell) <- address stream-storage + 48 # + 49 tokenize in, stream, 0/no-trace + 50 # + 51 var curr-token-storage: cell + 52 var curr-token/ebx: (addr cell) <- address curr-token-storage + 53 read-from-stream stream, curr-token + 54 var open-paren?/eax: boolean <- open-paren-token? curr-token + 55 check open-paren?, "F - test-tokenize-dotted-list: open paren" + 56 read-from-stream stream, curr-token # skip a + 57 read-from-stream stream, curr-token + 58 var dot?/eax: boolean <- dot-token? curr-token + 59 check dot?, "F - test-tokenize-dotted-list: dot" + 60 read-from-stream stream, curr-token # skip b + 61 read-from-stream stream, curr-token + 62 var close-paren?/eax: boolean <- close-paren-token? curr-token + 63 check close-paren?, "F - test-tokenize-dotted-list: close paren" + 64 } + 65 + 66 fn next-token in: (addr gap-buffer), _out-cell: (addr cell), trace: (addr trace) { + 67 trace-text trace, "read", "next-token" + 68 trace-lower trace + 69 var out-cell/eax: (addr cell) <- copy _out-cell + 70 var out-ah/eax: (addr handle stream byte) <- get out-cell, text-data + 71 var _out/eax: (addr stream byte) <- lookup *out-ah + 72 var out/edi: (addr stream byte) <- copy _out + 73 $next-token:body: { + 74 clear-stream out + 75 skip-whitespace-from-gap-buffer in + 76 var g/eax: grapheme <- peek-from-gap-buffer in + 77 { + 78 var stream-storage: (stream byte 0x40) + 79 var stream/esi: (addr stream byte) <- address stream-storage + 80 write stream, "next: " + 81 var gval/eax: int <- copy g + 82 write-int32-hex stream, gval + 83 trace trace, "read", stream 84 } - 85 } - 86 trace-higher trace - 87 var stream-storage: (stream byte 0x40) - 88 var stream/eax: (addr stream byte) <- address stream-storage - 89 write stream, "=> " - 90 rewind-stream out - 91 write-stream stream, out - 92 trace trace, "read", stream - 93 } - 94 - 95 fn next-symbol-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { - 96 trace-text trace, "read", "looking for a symbol" - 97 trace-lower trace - 98 $next-symbol-token:loop: { - 99 var done?/eax: boolean <- gap-buffer-scan-done? in -100 compare done?, 0/false -101 break-if-!= -102 var g/eax: grapheme <- peek-from-gap-buffer in -103 { -104 var stream-storage: (stream byte 0x40) -105 var stream/esi: (addr stream byte) <- address stream-storage -106 write stream, "next: " -107 var gval/eax: int <- copy g -108 write-int32-hex stream, gval -109 trace trace, "read", stream -110 } -111 # if non-symbol, return -112 { -113 var symbol-grapheme?/eax: boolean <- symbol-grapheme? g -114 compare symbol-grapheme?, 0/false -115 break-if-!= -116 trace-text trace, "read", "stop" -117 break $next-symbol-token:loop -118 } -119 var g/eax: grapheme <- read-from-gap-buffer in -120 write-grapheme out, g -121 loop -122 } -123 trace-higher trace -124 var stream-storage: (stream byte 0x40) -125 var stream/esi: (addr stream byte) <- address stream-storage -126 write stream, "=> " -127 rewind-stream out -128 write-stream stream, out -129 trace trace, "read", stream -130 } -131 -132 fn next-operator-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { -133 trace-text trace, "read", "looking for a operator" -134 trace-lower trace -135 $next-operator-token:loop: { -136 var done?/eax: boolean <- gap-buffer-scan-done? in -137 compare done?, 0/false -138 break-if-!= -139 var g/eax: grapheme <- peek-from-gap-buffer in -140 { -141 var stream-storage: (stream byte 0x40) -142 var stream/esi: (addr stream byte) <- address stream-storage -143 write stream, "next: " -144 var gval/eax: int <- copy g -145 write-int32-hex stream, gval -146 trace trace, "read", stream -147 } -148 # if non-operator, return -149 { -150 var operator-grapheme?/eax: boolean <- operator-grapheme? g -151 compare operator-grapheme?, 0/false -152 break-if-!= -153 trace-text trace, "read", "stop" -154 break $next-operator-token:loop -155 } -156 var g/eax: grapheme <- read-from-gap-buffer in -157 write-grapheme out, g -158 loop -159 } -160 trace-higher trace -161 var stream-storage: (stream byte 0x40) -162 var stream/esi: (addr stream byte) <- address stream-storage -163 write stream, "=> " -164 rewind-stream out -165 write-stream stream, out -166 trace trace, "read", stream -167 } -168 -169 fn next-number-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { -170 trace-text trace, "read", "looking for a number" -171 trace-lower trace -172 $next-number-token:loop: { -173 var done?/eax: boolean <- gap-buffer-scan-done? in -174 compare done?, 0/false -175 break-if-!= -176 var g/eax: grapheme <- peek-from-gap-buffer in -177 { -178 var stream-storage: (stream byte 0x40) -179 var stream/esi: (addr stream byte) <- address stream-storage -180 write stream, "next: " -181 var gval/eax: int <- copy g -182 write-int32-hex stream, gval -183 trace trace, "read", stream -184 } -185 # if not symbol grapheme, return -186 { -187 var symbol-grapheme?/eax: boolean <- symbol-grapheme? g -188 compare symbol-grapheme?, 0/false -189 break-if-!= -190 trace-text trace, "read", "stop" -191 break $next-number-token:loop -192 } -193 # if not digit grapheme, abort -194 { -195 var digit?/eax: boolean <- decimal-digit? g -196 compare digit?, 0/false -197 break-if-!= -198 error trace, "invalid number" -199 return -200 } -201 trace-text trace, "read", "append" -202 var g/eax: grapheme <- read-from-gap-buffer in -203 write-grapheme out, g -204 loop -205 } -206 trace-higher trace -207 } -208 -209 fn next-bracket-token g: grapheme, out: (addr stream byte), trace: (addr trace) { -210 trace-text trace, "read", "bracket" -211 write-grapheme out, g -212 var stream-storage: (stream byte 0x40) -213 var stream/esi: (addr stream byte) <- address stream-storage -214 write stream, "=> " -215 rewind-stream out -216 write-stream stream, out -217 trace trace, "read", stream -218 } -219 -220 fn symbol-grapheme? g: grapheme -> _/eax: boolean { -221 ## whitespace -222 compare g, 9/tab -223 { -224 break-if-!= -225 return 0/false -226 } -227 compare g, 0xa/newline -228 { -229 break-if-!= -230 return 0/false -231 } -232 compare g, 0x20/space -233 { -234 break-if-!= -235 return 0/false -236 } -237 ## quotes -238 compare g, 0x22/double-quote -239 { -240 break-if-!= -241 return 0/false -242 } -243 compare g, 0x60/backquote -244 { -245 break-if-!= -246 return 0/false -247 } -248 ## brackets -249 compare g, 0x28/open-paren -250 { -251 break-if-!= -252 return 0/false -253 } -254 compare g, 0x29/close-paren -255 { -256 break-if-!= -257 return 0/false -258 } -259 compare g, 0x5b/open-square-bracket -260 { -261 break-if-!= -262 return 0/false -263 } -264 compare g, 0x5d/close-square-bracket -265 { -266 break-if-!= -267 return 0/false -268 } -269 compare g, 0x7b/open-curly-bracket -270 { -271 break-if-!= -272 return 0/false -273 } -274 compare g, 0x7d/close-curly-bracket -275 { -276 break-if-!= -277 return 0/false -278 } -279 # - other punctuation -280 # '!' is a symbol char -281 compare g, 0x23/hash -282 { -283 break-if-!= -284 return 0/false -285 } -286 # '$' is a symbol char -287 compare g, 0x25/percent + 85 # digit + 86 { + 87 var digit?/eax: boolean <- decimal-digit? g + 88 compare digit?, 0/false + 89 break-if-= + 90 next-number-token in, out, trace + 91 break $next-token:body + 92 } + 93 # other symbol char + 94 { + 95 var symbol?/eax: boolean <- symbol-grapheme? g + 96 compare symbol?, 0/false + 97 break-if-= + 98 next-symbol-token in, out, trace + 99 break $next-token:body +100 } +101 # brackets are always single-char tokens +102 { +103 var bracket?/eax: boolean <- bracket-grapheme? g +104 compare bracket?, 0/false +105 break-if-= +106 var g/eax: grapheme <- read-from-gap-buffer in +107 next-bracket-token g, out, trace +108 break $next-token:body +109 } +110 # non-symbol operators +111 { +112 var operator?/eax: boolean <- operator-grapheme? g +113 compare operator?, 0/false +114 break-if-= +115 next-operator-token in, out, trace +116 break $next-token:body +117 } +118 } +119 trace-higher trace +120 var stream-storage: (stream byte 0x40) +121 var stream/eax: (addr stream byte) <- address stream-storage +122 write stream, "=> " +123 rewind-stream out +124 write-stream stream, out +125 trace trace, "read", stream +126 } +127 +128 fn next-symbol-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { +129 trace-text trace, "read", "looking for a symbol" +130 trace-lower trace +131 $next-symbol-token:loop: { +132 var done?/eax: boolean <- gap-buffer-scan-done? in +133 compare done?, 0/false +134 break-if-!= +135 var g/eax: grapheme <- peek-from-gap-buffer in +136 { +137 var stream-storage: (stream byte 0x40) +138 var stream/esi: (addr stream byte) <- address stream-storage +139 write stream, "next: " +140 var gval/eax: int <- copy g +141 write-int32-hex stream, gval +142 trace trace, "read", stream +143 } +144 # if non-symbol, return +145 { +146 var symbol-grapheme?/eax: boolean <- symbol-grapheme? g +147 compare symbol-grapheme?, 0/false +148 break-if-!= +149 trace-text trace, "read", "stop" +150 break $next-symbol-token:loop +151 } +152 var g/eax: grapheme <- read-from-gap-buffer in +153 write-grapheme out, g +154 loop +155 } +156 trace-higher trace +157 var stream-storage: (stream byte 0x40) +158 var stream/esi: (addr stream byte) <- address stream-storage +159 write stream, "=> " +160 rewind-stream out +161 write-stream stream, out +162 trace trace, "read", stream +163 } +164 +165 fn next-operator-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { +166 trace-text trace, "read", "looking for a operator" +167 trace-lower trace +168 $next-operator-token:loop: { +169 var done?/eax: boolean <- gap-buffer-scan-done? in +170 compare done?, 0/false +171 break-if-!= +172 var g/eax: grapheme <- peek-from-gap-buffer in +173 { +174 var stream-storage: (stream byte 0x40) +175 var stream/esi: (addr stream byte) <- address stream-storage +176 write stream, "next: " +177 var gval/eax: int <- copy g +178 write-int32-hex stream, gval +179 trace trace, "read", stream +180 } +181 # if non-operator, return +182 { +183 var operator-grapheme?/eax: boolean <- operator-grapheme? g +184 compare operator-grapheme?, 0/false +185 break-if-!= +186 trace-text trace, "read", "stop" +187 break $next-operator-token:loop +188 } +189 var g/eax: grapheme <- read-from-gap-buffer in +190 write-grapheme out, g +191 loop +192 } +193 trace-higher trace +194 var stream-storage: (stream byte 0x40) +195 var stream/esi: (addr stream byte) <- address stream-storage +196 write stream, "=> " +197 rewind-stream out +198 write-stream stream, out +199 trace trace, "read", stream +200 } +201 +202 fn next-number-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { +203 trace-text trace, "read", "looking for a number" +204 trace-lower trace +205 $next-number-token:loop: { +206 var done?/eax: boolean <- gap-buffer-scan-done? in +207 compare done?, 0/false +208 break-if-!= +209 var g/eax: grapheme <- peek-from-gap-buffer in +210 { +211 var stream-storage: (stream byte 0x40) +212 var stream/esi: (addr stream byte) <- address stream-storage +213 write stream, "next: " +214 var gval/eax: int <- copy g +215 write-int32-hex stream, gval +216 trace trace, "read", stream +217 } +218 # if not symbol grapheme, return +219 { +220 var symbol-grapheme?/eax: boolean <- symbol-grapheme? g +221 compare symbol-grapheme?, 0/false +222 break-if-!= +223 trace-text trace, "read", "stop" +224 break $next-number-token:loop +225 } +226 # if not digit grapheme, abort +227 { +228 var digit?/eax: boolean <- decimal-digit? g +229 compare digit?, 0/false +230 break-if-!= +231 error trace, "invalid number" +232 return +233 } +234 trace-text trace, "read", "append" +235 var g/eax: grapheme <- read-from-gap-buffer in +236 write-grapheme out, g +237 loop +238 } +239 trace-higher trace +240 } +241 +242 fn next-bracket-token g: grapheme, out: (addr stream byte), trace: (addr trace) { +243 trace-text trace, "read", "bracket" +244 write-grapheme out, g +245 var stream-storage: (stream byte 0x40) +246 var stream/esi: (addr stream byte) <- address stream-storage +247 write stream, "=> " +248 rewind-stream out +249 write-stream stream, out +250 trace trace, "read", stream +251 } +252 +253 fn symbol-grapheme? g: grapheme -> _/eax: boolean { +254 ## whitespace +255 compare g, 9/tab +256 { +257 break-if-!= +258 return 0/false +259 } +260 compare g, 0xa/newline +261 { +262 break-if-!= +263 return 0/false +264 } +265 compare g, 0x20/space +266 { +267 break-if-!= +268 return 0/false +269 } +270 ## quotes +271 compare g, 0x22/double-quote +272 { +273 break-if-!= +274 return 0/false +275 } +276 compare g, 0x60/backquote +277 { +278 break-if-!= +279 return 0/false +280 } +281 ## brackets +282 compare g, 0x28/open-paren +283 { +284 break-if-!= +285 return 0/false +286 } +287 compare g, 0x29/close-paren 288 { 289 break-if-!= 290 return 0/false 291 } -292 compare g, 0x26/ampersand +292 compare g, 0x5b/open-square-bracket 293 { 294 break-if-!= 295 return 0/false 296 } -297 compare g, 0x27/single-quote +297 compare g, 0x5d/close-square-bracket 298 { 299 break-if-!= 300 return 0/false 301 } -302 compare g, 0x2a/asterisk +302 compare g, 0x7b/open-curly-bracket 303 { 304 break-if-!= 305 return 0/false 306 } -307 compare g, 0x2b/plus +307 compare g, 0x7d/close-curly-bracket 308 { 309 break-if-!= 310 return 0/false 311 } -312 compare g, 0x2c/comma -313 { -314 break-if-!= -315 return 0/false -316 } -317 compare g, 0x2d/dash # '-' not allowed in symbols -318 { -319 break-if-!= -320 return 0/false -321 } -322 compare g, 0x2e/period -323 { -324 break-if-!= -325 return 0/false -326 } -327 compare g, 0x2f/slash -328 { -329 break-if-!= -330 return 0/false -331 } -332 compare g, 0x3a/colon -333 { -334 break-if-!= -335 return 0/false -336 } -337 compare g, 0x3b/semi-colon -338 { -339 break-if-!= -340 return 0/false -341 } -342 compare g, 0x3c/less-than -343 { -344 break-if-!= -345 return 0/false -346 } -347 compare g, 0x3d/equal -348 { -349 break-if-!= -350 return 0/false -351 } -352 compare g, 0x3e/greater-than -353 { -354 break-if-!= -355 return 0/false -356 } -357 # '?' is a symbol char -358 compare g, 0x40/at-sign -359 { -360 break-if-!= -361 return 0/false -362 } -363 compare g, 0x5c/backslash -364 { -365 break-if-!= -366 return 0/false -367 } -368 compare g, 0x5e/caret -369 { -370 break-if-!= -371 return 0/false -372 } -373 # '_' is a symbol char -374 compare g, 0x7c/vertical-line -375 { -376 break-if-!= -377 return 0/false -378 } -379 compare g, 0x7e/tilde -380 { -381 break-if-!= -382 return 0/false -383 } -384 return 1/true -385 } -386 -387 fn bracket-grapheme? g: grapheme -> _/eax: boolean { -388 compare g, 0x28/open-paren -389 { -390 break-if-!= -391 return 1/true -392 } -393 compare g, 0x29/close-paren -394 { -395 break-if-!= -396 return 1/true -397 } -398 compare g, 0x5b/open-square-bracket -399 { -400 break-if-!= -401 return 1/true -402 } -403 compare g, 0x5d/close-square-bracket -404 { -405 break-if-!= -406 return 1/true -407 } -408 compare g, 0x7b/open-curly-bracket -409 { -410 break-if-!= -411 return 1/true -412 } -413 compare g, 0x7d/close-curly-bracket -414 { -415 break-if-!= -416 return 1/true -417 } -418 return 0/false -419 } -420 -421 fn operator-grapheme? g: grapheme -> _/eax: boolean { -422 # '$' is a symbol char -423 compare g, 0x25/percent -424 { -425 break-if-!= -426 return 1/false -427 } -428 compare g, 0x26/ampersand -429 { -430 break-if-!= -431 return 1/true -432 } -433 compare g, 0x27/single-quote -434 { -435 break-if-!= -436 return 1/true -437 } -438 compare g, 0x2a/asterisk -439 { -440 break-if-!= -441 return 1/true -442 } -443 compare g, 0x2b/plus -444 { -445 break-if-!= -446 return 1/true -447 } -448 compare g, 0x2c/comma -449 { -450 break-if-!= -451 return 1/true -452 } -453 compare g, 0x2d/dash # '-' not allowed in symbols -454 { -455 break-if-!= -456 return 1/true -457 } -458 compare g, 0x2e/period -459 { -460 break-if-!= -461 return 1/true -462 } -463 compare g, 0x2f/slash -464 { -465 break-if-!= -466 return 1/true -467 } -468 compare g, 0x3a/colon -469 { -470 break-if-!= -471 return 1/true -472 } -473 compare g, 0x3b/semi-colon -474 { -475 break-if-!= -476 return 1/true -477 } -478 compare g, 0x3c/less-than -479 { -480 break-if-!= -481 return 1/true -482 } -483 compare g, 0x3d/equal -484 { -485 break-if-!= -486 return 1/true -487 } -488 compare g, 0x3e/greater-than -489 { -490 break-if-!= -491 return 1/true -492 } -493 # '?' is a symbol char -494 compare g, 0x40/at-sign -495 { -496 break-if-!= -497 return 1/true -498 } -499 compare g, 0x5c/backslash -500 { -501 break-if-!= -502 return 1/true -503 } -504 compare g, 0x5e/caret -505 { -506 break-if-!= -507 return 1/true -508 } -509 # '_' is a symbol char -510 compare g, 0x7c/vertical-line -511 { -512 break-if-!= -513 return 1/true -514 } -515 compare g, 0x7e/tilde -516 { -517 break-if-!= -518 return 1/true -519 } -520 return 0/false -521 } -522 -523 fn number-token? _in: (addr cell) -> _/eax: boolean { -524 var in/eax: (addr cell) <- copy _in -525 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data -526 var in-data/eax: (addr stream byte) <- lookup *in-data-ah -527 rewind-stream in-data -528 var g/eax: grapheme <- read-grapheme in-data -529 var result/eax: boolean <- decimal-digit? g -530 return result -531 } -532 -533 fn bracket-token? _in: (addr cell) -> _/eax: boolean { -534 var in/eax: (addr cell) <- copy _in -535 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data -536 var in-data/eax: (addr stream byte) <- lookup *in-data-ah -537 rewind-stream in-data -538 var g/eax: grapheme <- read-grapheme in-data -539 var result/eax: boolean <- bracket-grapheme? g -540 return result -541 } -542 -543 fn quote-token? _in: (addr cell) -> _/eax: boolean { -544 var in/eax: (addr cell) <- copy _in -545 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data -546 var in-data/eax: (addr stream byte) <- lookup *in-data-ah -547 rewind-stream in-data -548 var g/eax: grapheme <- read-grapheme in-data -549 compare g, 0x27/single-quote -550 { -551 break-if-!= -552 return 1/true -553 } -554 return 0/false -555 } -556 -557 fn open-paren-token? _in: (addr cell) -> _/eax: boolean { -558 var in/eax: (addr cell) <- copy _in -559 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data -560 var in-data/eax: (addr stream byte) <- lookup *in-data-ah -561 rewind-stream in-data -562 var g/eax: grapheme <- read-grapheme in-data -563 compare g, 0x28/open-paren -564 { -565 break-if-!= -566 return 1/true -567 } -568 return 0/false -569 } -570 -571 fn close-paren-token? _in: (addr cell) -> _/eax: boolean { -572 var in/eax: (addr cell) <- copy _in -573 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data -574 var in-data/eax: (addr stream byte) <- lookup *in-data-ah -575 rewind-stream in-data -576 var g/eax: grapheme <- read-grapheme in-data -577 compare g, 0x29/open-paren -578 { -579 break-if-!= -580 return 1/true -581 } -582 return 0/false -583 } +312 # - other punctuation +313 # '!' is a symbol char +314 compare g, 0x23/hash +315 { +316 break-if-!= +317 return 0/false +318 } +319 # '$' is a symbol char +320 compare g, 0x25/percent +321 { +322 break-if-!= +323 return 0/false +324 } +325 compare g, 0x26/ampersand +326 { +327 break-if-!= +328 return 0/false +329 } +330 compare g, 0x27/single-quote +331 { +332 break-if-!= +333 return 0/false +334 } +335 compare g, 0x2a/asterisk +336 { +337 break-if-!= +338 return 0/false +339 } +340 compare g, 0x2b/plus +341 { +342 break-if-!= +343 return 0/false +344 } +345 compare g, 0x2c/comma +346 { +347 break-if-!= +348 return 0/false +349 } +350 compare g, 0x2d/dash # '-' not allowed in symbols +351 { +352 break-if-!= +353 return 0/false +354 } +355 compare g, 0x2e/period +356 { +357 break-if-!= +358 return 0/false +359 } +360 compare g, 0x2f/slash +361 { +362 break-if-!= +363 return 0/false +364 } +365 compare g, 0x3a/colon +366 { +367 break-if-!= +368 return 0/false +369 } +370 compare g, 0x3b/semi-colon +371 { +372 break-if-!= +373 return 0/false +374 } +375 compare g, 0x3c/less-than +376 { +377 break-if-!= +378 return 0/false +379 } +380 compare g, 0x3d/equal +381 { +382 break-if-!= +383 return 0/false +384 } +385 compare g, 0x3e/greater-than +386 { +387 break-if-!= +388 return 0/false +389 } +390 # '?' is a symbol char +391 compare g, 0x40/at-sign +392 { +393 break-if-!= +394 return 0/false +395 } +396 compare g, 0x5c/backslash +397 { +398 break-if-!= +399 return 0/false +400 } +401 compare g, 0x5e/caret +402 { +403 break-if-!= +404 return 0/false +405 } +406 # '_' is a symbol char +407 compare g, 0x7c/vertical-line +408 { +409 break-if-!= +410 return 0/false +411 } +412 compare g, 0x7e/tilde +413 { +414 break-if-!= +415 return 0/false +416 } +417 return 1/true +418 } +419 +420 fn bracket-grapheme? g: grapheme -> _/eax: boolean { +421 compare g, 0x28/open-paren +422 { +423 break-if-!= +424 return 1/true +425 } +426 compare g, 0x29/close-paren +427 { +428 break-if-!= +429 return 1/true +430 } +431 compare g, 0x5b/open-square-bracket +432 { +433 break-if-!= +434 return 1/true +435 } +436 compare g, 0x5d/close-square-bracket +437 { +438 break-if-!= +439 return 1/true +440 } +441 compare g, 0x7b/open-curly-bracket +442 { +443 break-if-!= +444 return 1/true +445 } +446 compare g, 0x7d/close-curly-bracket +447 { +448 break-if-!= +449 return 1/true +450 } +451 return 0/false +452 } +453 +454 fn operator-grapheme? g: grapheme -> _/eax: boolean { +455 # '$' is a symbol char +456 compare g, 0x25/percent +457 { +458 break-if-!= +459 return 1/false +460 } +461 compare g, 0x26/ampersand +462 { +463 break-if-!= +464 return 1/true +465 } +466 compare g, 0x27/single-quote +467 { +468 break-if-!= +469 return 1/true +470 } +471 compare g, 0x2a/asterisk +472 { +473 break-if-!= +474 return 1/true +475 } +476 compare g, 0x2b/plus +477 { +478 break-if-!= +479 return 1/true +480 } +481 compare g, 0x2c/comma +482 { +483 break-if-!= +484 return 1/true +485 } +486 compare g, 0x2d/dash # '-' not allowed in symbols +487 { +488 break-if-!= +489 return 1/true +490 } +491 compare g, 0x2e/period +492 { +493 break-if-!= +494 return 1/true +495 } +496 compare g, 0x2f/slash +497 { +498 break-if-!= +499 return 1/true +500 } +501 compare g, 0x3a/colon +502 { +503 break-if-!= +504 return 1/true +505 } +506 compare g, 0x3b/semi-colon +507 { +508 break-if-!= +509 return 1/true +510 } +511 compare g, 0x3c/less-than +512 { +513 break-if-!= +514 return 1/true +515 } +516 compare g, 0x3d/equal +517 { +518 break-if-!= +519 return 1/true +520 } +521 compare g, 0x3e/greater-than +522 { +523 break-if-!= +524 return 1/true +525 } +526 # '?' is a symbol char +527 compare g, 0x40/at-sign +528 { +529 break-if-!= +530 return 1/true +531 } +532 compare g, 0x5c/backslash +533 { +534 break-if-!= +535 return 1/true +536 } +537 compare g, 0x5e/caret +538 { +539 break-if-!= +540 return 1/true +541 } +542 # '_' is a symbol char +543 compare g, 0x7c/vertical-line +544 { +545 break-if-!= +546 return 1/true +547 } +548 compare g, 0x7e/tilde +549 { +550 break-if-!= +551 return 1/true +552 } +553 return 0/false +554 } +555 +556 fn number-token? _in: (addr cell) -> _/eax: boolean { +557 var in/eax: (addr cell) <- copy _in +558 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data +559 var in-data/eax: (addr stream byte) <- lookup *in-data-ah +560 rewind-stream in-data +561 var g/eax: grapheme <- read-grapheme in-data +562 var result/eax: boolean <- decimal-digit? g +563 return result +564 } +565 +566 fn bracket-token? _in: (addr cell) -> _/eax: boolean { +567 var in/eax: (addr cell) <- copy _in +568 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data +569 var in-data/eax: (addr stream byte) <- lookup *in-data-ah +570 rewind-stream in-data +571 var g/eax: grapheme <- read-grapheme in-data +572 var result/eax: boolean <- bracket-grapheme? g +573 return result +574 } +575 +576 fn quote-token? _in: (addr cell) -> _/eax: boolean { +577 var in/eax: (addr cell) <- copy _in +578 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data +579 var in-data/eax: (addr stream byte) <- lookup *in-data-ah +580 rewind-stream in-data +581 var g/eax: grapheme <- read-grapheme in-data +582 compare g, 0x27/single-quote +583 { +584 break-if-!= +585 return 1/true +586 } +587 return 0/false +588 } +589 +590 fn open-paren-token? _in: (addr cell) -> _/eax: boolean { +591 var in/eax: (addr cell) <- copy _in +592 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data +593 var _in-data/eax: (addr stream byte) <- lookup *in-data-ah +594 var in-data/ecx: (addr stream byte) <- copy _in-data +595 rewind-stream in-data +596 var g/eax: grapheme <- read-grapheme in-data +597 compare g, 0x28/open-paren +598 { +599 break-if-!= +600 var result/eax: boolean <- stream-empty? in-data +601 return result +602 } +603 return 0/false +604 } +605 +606 fn close-paren-token? _in: (addr cell) -> _/eax: boolean { +607 var in/eax: (addr cell) <- copy _in +608 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data +609 var _in-data/eax: (addr stream byte) <- lookup *in-data-ah +610 var in-data/ecx: (addr stream byte) <- copy _in-data +611 rewind-stream in-data +612 var g/eax: grapheme <- read-grapheme in-data +613 compare g, 0x29/close-paren +614 { +615 break-if-!= +616 var result/eax: boolean <- stream-empty? in-data +617 return result +618 } +619 return 0/false +620 } +621 +622 fn dot-token? _in: (addr cell) -> _/eax: boolean { +623 var in/eax: (addr cell) <- copy _in +624 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data +625 var _in-data/eax: (addr stream byte) <- lookup *in-data-ah +626 var in-data/ecx: (addr stream byte) <- copy _in-data +627 rewind-stream in-data +628 var g/eax: grapheme <- read-grapheme in-data +629 compare g, 0x2e/dot +630 { +631 break-if-!= +632 var result/eax: boolean <- stream-empty? in-data +633 return result +634 } +635 return 0/false +636 } +637 +638 fn test-dot-token { +639 var tmp-storage: (handle cell) +640 var tmp-ah/eax: (addr handle cell) <- address tmp-storage +641 new-symbol tmp-ah, "." +642 var tmp/eax: (addr cell) <- lookup *tmp-ah +643 var result/eax: boolean <- dot-token? tmp +644 check result, "F - test-dot-token" +645 } diff --git a/html/shell/trace.mu.html b/html/shell/trace.mu.html index ddf1f8b0..057a39ac 100644 --- a/html/shell/trace.mu.html +++ b/html/shell/trace.mu.html @@ -7,11 +7,11 @@ - +