diff options
-rw-r--r-- | baremetal/112read-byte.subx | 75 | ||||
-rw-r--r-- | baremetal/310copy-bytes.subx | 99 | ||||
-rw-r--r-- | baremetal/312copy.subx | 13 | ||||
-rw-r--r-- | baremetal/400.mu | 10 | ||||
-rw-r--r-- | baremetal/411string.mu | 125 | ||||
-rw-r--r-- | baremetal/shell/value.mu | 51 |
6 files changed, 370 insertions, 3 deletions
diff --git a/baremetal/112read-byte.subx b/baremetal/112read-byte.subx index 64666e9b..0c9af75b 100644 --- a/baremetal/112read-byte.subx +++ b/baremetal/112read-byte.subx @@ -45,4 +45,79 @@ $read-byte:abort: } # never gets here +== data + +_test-input-stream: # (stream byte) + # current write index + 0/imm32 + # current read index + 0/imm32 + # size + 0x400/imm32 # 1024 bytes + # data (64 lines x 16 bytes/line) + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + # . . vim:nowrap:textwidth=0 diff --git a/baremetal/310copy-bytes.subx b/baremetal/310copy-bytes.subx index 26fc807e..2586a53f 100644 --- a/baremetal/310copy-bytes.subx +++ b/baremetal/310copy-bytes.subx @@ -56,3 +56,102 @@ $copy-bytes:end: 89/<- %esp 5/r32/ebp 5d/pop-to-ebp c3/return + +stream-to-array: # in: (addr stream _), out: (addr handle array _) + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 50/push-eax + 51/push-ecx + 52/push-edx + 56/push-esi + # esi = s + 8b/-> *(ebp+8) 6/r32/esi + # var len/ecx: int = s->write - s->read + 8b/-> *esi 1/r32/ecx + 2b/subtract *(esi+4) 1/r32/ecx + # allocate + (allocate-array Heap %ecx *(ebp+0xc)) + # var in/edx: (addr byte) = s->data + s->read + 8b/-> *(esi+4) 2/r32/edx + 8d/copy-address *(esi+edx+0xc) 2/r32/edx + # var dest/eax: (addr byte) = data for out + 8b/-> *(ebp+0xc) 0/r32/eax + (lookup *eax *(eax+4)) # => eax + 8d/copy-address *(eax+4) 0/r32/eax + # + (copy-bytes %edx %eax %ecx) +$stream-to-array:end: + # . restore registers + 5e/pop-to-esi + 5a/pop-to-edx + 59/pop-to-ecx + 58/pop-to-eax + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +test-stream-to-array: + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # setup + (clear-stream _test-input-stream) + (write _test-input-stream "abc") + # skip something + (read-byte _test-input-stream) # => eax + # var out/ecx: (handle array byte) + 68/push 0/imm32 + 68/push 0/imm32 + 89/<- %ecx 4/r32/esp + # + (stream-to-array _test-input-stream %ecx) + (lookup *ecx *(ecx+4)) # => eax + (check-strings-equal %eax "bc") + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +# like stream-to-array but ignore surrounding quotes +# we might do other stuff here later +unquote-stream-to-array: # in: (addr stream _), out: (addr handle array _) + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 50/push-eax + 51/push-ecx + 52/push-edx + 56/push-esi + # esi = s + 8b/-> *(ebp+8) 6/r32/esi + # var len/ecx: int = s->write - s->read - 2 + 8b/-> *esi 1/r32/ecx + 2b/subtract *(esi+4) 1/r32/ecx + 81 7/subop/compare %ecx 2/imm32 + 7c/jump-if-< $unquote-stream-to-array:end/disp8 + 81 5/subop/subtract %ecx 2/imm32 + # allocate + (allocate-array Heap %ecx *(ebp+0xc)) + # var in/edx: (addr byte) = s->data + s->read + 1 + 8b/-> *(esi+4) 2/r32/edx + 8d/copy-address *(esi+edx+0xd) 2/r32/edx # Stream-data + 1 + # var dest/eax: (addr byte) = data for out + 8b/-> *(ebp+0xc) 0/r32/eax + (lookup *eax *(eax+4)) # => eax + 8d/copy-address *(eax+4) 0/r32/eax + # + (copy-bytes %edx %eax %ecx) +$unquote-stream-to-array:end: + # . restore registers + 5e/pop-to-esi + 5a/pop-to-edx + 59/pop-to-ecx + 58/pop-to-eax + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return diff --git a/baremetal/312copy.subx b/baremetal/312copy.subx new file mode 100644 index 00000000..d2a6f661 --- /dev/null +++ b/baremetal/312copy.subx @@ -0,0 +1,13 @@ +== code + +copy-array-object: # src: (addr array T), dest-ah: (addr handle array T) + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + (copy-array Heap *(ebp+8) *(ebp+0xc)) +$copy-array-object:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return diff --git a/baremetal/400.mu b/baremetal/400.mu index d2b84ad1..99195b2c 100644 --- a/baremetal/400.mu +++ b/baremetal/400.mu @@ -12,6 +12,8 @@ sig read-key kbd: (addr keyboard) -> _/eax: byte sig count-test-failure sig num-test-failures -> _/eax: int +sig check-strings-equal s: (addr array byte), expected: (addr array byte), msg: (addr array byte) + # streams sig clear-stream f: (addr stream _) sig rewind-stream f: (addr stream _) @@ -57,5 +59,13 @@ sig to-decimal-digit in: grapheme -> _/eax: int sig next-word line: (addr stream byte), out: (addr slice) # skips '#' comments sig next-raw-word line: (addr stream byte), out: (addr slice) # does not skip '#' comments sig stream-empty? s: (addr stream _) -> _/eax: boolean +sig stream-full? s: (addr stream _) -> _/eax: boolean +sig stream-to-array in: (addr stream _), out: (addr handle array _) +sig unquote-stream-to-array in: (addr stream _), out: (addr handle array _) +sig stream-first s: (addr stream byte) -> _/eax: byte +sig stream-final s: (addr stream byte) -> _/eax: byte + +#sig copy-bytes src: (addr byte), dest: (addr byte), n: int +sig copy-array-object src: (addr array _), dest-ah: (addr handle array _) sig integer-divide a: int, b: int -> _/eax: int, _/edx: int diff --git a/baremetal/411string.mu b/baremetal/411string.mu new file mode 100644 index 00000000..cf0471ac --- /dev/null +++ b/baremetal/411string.mu @@ -0,0 +1,125 @@ +# read up to 'len' graphemes after skipping the first 'start' ones +fn substring in: (addr array byte), start: int, len: int, out-ah: (addr handle array byte) { + var in-stream: (stream byte 0x100) + var in-stream-addr/esi: (addr stream byte) <- address in-stream + write in-stream-addr, in + var out-stream: (stream byte 0x100) + var out-stream-addr/edi: (addr stream byte) <- address out-stream + $substring:core: { + # skip 'start' graphemes + var i/eax: int <- copy 0 + { + compare i, start + break-if->= + { + var dummy/eax: grapheme <- read-grapheme in-stream-addr + compare dummy, 0xffffffff/end-of-file + break-if-= $substring:core + } + i <- increment + loop + } + # copy 'len' graphemes + i <- copy 0 + { + compare i, len + break-if->= + { + var g/eax: grapheme <- read-grapheme in-stream-addr + compare g, 0xffffffff/end-of-file + break-if-= $substring:core + write-grapheme out-stream-addr, g + } + i <- increment + loop + } + } + stream-to-array out-stream-addr, out-ah +} + +fn test-substring { + var out-h: (handle array byte) + var out-ah/edi: (addr handle array byte) <- address out-h + # prefix substrings + substring 0, 0, 3, out-ah + var out/eax: (addr array byte) <- lookup *out-ah + check-strings-equal out, "", "F - test-substring/null" + substring "", 0, 3, out-ah + var out/eax: (addr array byte) <- lookup *out-ah +#? print-string-to-real-screen out +#? print-string-to-real-screen "\n" + check-strings-equal out, "", "F - test-substring/empty" + # + substring "abcde", 0, 3, out-ah + var out/eax: (addr array byte) <- lookup *out-ah +#? print-string-to-real-screen out +#? print-string-to-real-screen "\n" + check-strings-equal out, "abc", "F - test-substring/truncate" + # + substring "abcde", 0, 5, out-ah + var out/eax: (addr array byte) <- lookup *out-ah + check-strings-equal out, "abcde", "F - test-substring/all" + # + substring "abcde", 0, 7, out-ah + var out/eax: (addr array byte) <- lookup *out-ah + check-strings-equal out, "abcde", "F - test-substring/too-small" + # substrings outside string + substring "abcde", 6, 1, out-ah + var out/eax: (addr array byte) <- lookup *out-ah + check-strings-equal out, "", "F - test-substring/start-too-large" + # trim prefix + substring "", 2, 3, out-ah + var out/eax: (addr array byte) <- lookup *out-ah + check-strings-equal out, "", "F - test-substring/middle-empty" + # + substring "abcde", 1, 2, out-ah + var out/eax: (addr array byte) <- lookup *out-ah + check-strings-equal out, "bc", "F - test-substring/middle-truncate" + # + substring "abcde", 1, 4, out-ah + var out/eax: (addr array byte) <- lookup *out-ah + check-strings-equal out, "bcde", "F - test-substring/middle-all" + # + substring "abcde", 1, 5, out-ah + var out/eax: (addr array byte) <- lookup *out-ah + check-strings-equal out, "bcde", "F - test-substring/middle-too-small" +} + +fn split-string in: (addr array byte), delim: grapheme, out: (addr handle array (handle array byte)) { + var in-stream: (stream byte 0x100) + var in-stream-addr/esi: (addr stream byte) <- address in-stream + write in-stream-addr, in + var tokens-stream: (stream (handle array byte) 0x100) + var tokens-stream-addr/edi: (addr stream (handle array byte)) <- address tokens-stream + var curr-stream: (stream byte 0x100) + var curr-stream-addr/ecx: (addr stream byte) <- address curr-stream + $split-string:core: { + var g/eax: grapheme <- read-grapheme in-stream-addr + compare g, 0xffffffff + break-if-= +#? print-grapheme-to-real-screen g +#? print-string-to-real-screen "\n" + compare g, delim + { + break-if-!= + # token complete; flush + var token: (handle array byte) + var token-ah/eax: (addr handle array byte) <- address token + stream-to-array curr-stream-addr, token-ah + write-to-stream tokens-stream-addr, token-ah + clear-stream curr-stream-addr + loop $split-string:core + } + write-grapheme curr-stream-addr, g + loop + } + stream-to-array tokens-stream-addr, out +} + +fn test-split-string { + var out-h: (handle array (handle array byte)) + var out-ah/edi: (addr handle array (handle array byte)) <- address out-h + # prefix substrings + split-string "bab", 0x61, out-ah + # no crash +} diff --git a/baremetal/shell/value.mu b/baremetal/shell/value.mu index 4a14c758..64b1d772 100644 --- a/baremetal/shell/value.mu +++ b/baremetal/shell/value.mu @@ -4,9 +4,6 @@ type value { number-data: float # if type = 0 text-data: (handle array byte) # if type = 1 array-data: (handle array value) # if type = 2 - file-data: (handle buffered-file) # if type = 3 - filename: (handle array byte) # if type = 3 - screen-data: (handle screen) # if type = 4 } fn initialize-value-with-integer _self: (addr value), n: int { @@ -82,3 +79,51 @@ fn test-render-number { check-ints-equal new-x, 3, "F - test-render-number: result" # we won't bother testing the background colors; lots of flexibility there } + +fn initialize-value-with-string _self: (addr value), s: (addr array byte) { + var self/esi: (addr value) <- copy _self + var type/eax: (addr int) <- get self, type + copy-to *type, 1/string + var dest/eax: (addr handle array byte) <- get self, text-data + copy-array-object s, dest +} + +fn render-string screen: (addr screen), _val: (addr array byte), x: int, y: int -> _/eax: int { + var val/esi: (addr array byte) <- copy _val + compare val, 0 + { + break-if-!= + return x + } + var orig-len/ecx: int <- length val + # truncate to 12 graphemes + # TODO: more sophisticated interactive rendering + var truncated: (handle array byte) + var truncated-ah/eax: (addr handle array byte) <- address truncated + substring val, 0, 0xc, truncated-ah + var _truncated-string/eax: (addr array byte) <- lookup *truncated-ah + var truncated-string/edx: (addr array byte) <- copy _truncated-string + var len/ebx: int <- length truncated-string + draw-code-point screen, 0x22/double-quote, x, y, 7/fg, 0/bg + increment x + var new-x/eax: int <- draw-text-rightward-over-full-screen screen, truncated-string, x, y, 7/fg, 0/bg + compare len, orig-len + { + break-if-= + new-x <- draw-text-rightward-over-full-screen screen, "...", new-x, y, 7/fg, 0/bg + } + draw-code-point screen, 0x22/double-quote, new-x, y, 7/fg, 0/bg + new-x <- increment + return new-x +} + +fn test-render-string { + # setup: screen + var screen-on-stack: screen + var screen/edi: (addr screen) <- address screen-on-stack + initialize-screen screen, 0x20, 4 + # strings render with quotes + var new-x/eax: int <- render-string screen, "abc", 0/x, 0/y + check-screen-row screen, 0/y, "\"abc\"", "F - test-render-string" + check-ints-equal new-x, 5, "F - test-render-string: result" +} |