diff options
-rw-r--r-- | baremetal/shell/gap-buffer.mu | 163 | ||||
-rw-r--r-- | baremetal/shell/grapheme-stack.mu | 6 |
2 files changed, 168 insertions, 1 deletions
diff --git a/baremetal/shell/gap-buffer.mu b/baremetal/shell/gap-buffer.mu index 4ec78789..f077c3d9 100644 --- a/baremetal/shell/gap-buffer.mu +++ b/baremetal/shell/gap-buffer.mu @@ -3,6 +3,9 @@ type gap-buffer { left: grapheme-stack right: grapheme-stack + # some fields for scanning incrementally through a gap-buffer + left-read-index: int + right-read-index: int } fn initialize-gap-buffer _self: (addr gap-buffer), max-word-size: int { @@ -399,7 +402,12 @@ fn gap-index _self: (addr gap-buffer), _n: int -> _/eax: grapheme { break-if->= var data-ah/eax: (addr handle array grapheme) <- get right, data var data/eax: (addr array grapheme) <- lookup *data-ah - var result/eax: (addr grapheme) <- index data, n + # idx = right->len - n - 1 + var idx/ebx: int <- copy n + idx <- subtract *right-len-a + idx <- negate + idx <- subtract 1 + var result/eax: (addr grapheme) <- index data, idx return *result } # error @@ -435,6 +443,34 @@ fn test-gap-buffers-equal? { check-not result, "F - test-gap-buffers-equal? - not equal 3" } +fn test-gap-buffer-index { + var gap-storage: gap-buffer + var gap/esi: (addr gap-buffer) <- address gap-storage + initialize-gap-buffer-with gap, "abc" + # gap is at end, all contents are in left + var g/eax: grapheme <- gap-index gap, 0 + var x/ecx: int <- copy g + check-ints-equal x, 0x61/a, "F - test-gap-index/left-1" + var g/eax: grapheme <- gap-index gap, 1 + var x/ecx: int <- copy g + check-ints-equal x, 0x62/b, "F - test-gap-index/left-2" + var g/eax: grapheme <- gap-index gap, 2 + var x/ecx: int <- copy g + check-ints-equal x, 0x63/c, "F - test-gap-index/left-3" + # now check when everything is to the right + gap-to-start gap + rewind-gap-buffer gap + var g/eax: grapheme <- gap-index gap, 0 + var x/ecx: int <- copy g + check-ints-equal x, 0x61/a, "F - test-gap-index/right-1" + var g/eax: grapheme <- gap-index gap, 1 + var x/ecx: int <- copy g + check-ints-equal x, 0x62/b, "F - test-gap-index/right-2" + var g/eax: grapheme <- gap-index gap, 2 + var x/ecx: int <- copy g + check-ints-equal x, 0x63/c, "F - test-gap-index/right-3" +} + fn copy-gap-buffer _src-ah: (addr handle gap-buffer), _dest-ah: (addr handle gap-buffer) { # obtain src-a, dest-a var src-ah/eax: (addr handle gap-buffer) <- copy _src-ah @@ -537,3 +573,128 @@ fn test-render-gap-buffer-with-cursor-at-start { # abc check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "| ", "F - test-render-gap-buffer-with-cursor-at-start: bg" } + +## some primitives for scanning through a gap buffer +# don't modify the gap buffer while scanning +# this includes moving the cursor around + +# restart scan without affecting gap-buffer contents +fn rewind-gap-buffer _self: (addr gap-buffer) { + var self/esi: (addr gap-buffer) <- copy _self + var dest/eax: (addr int) <- get self, left-read-index + copy-to *dest, 0 + dest <- get self, right-read-index + copy-to *dest, 0 +} + +fn gap-buffer-scan-done? _self: (addr gap-buffer) -> _/eax: boolean { + var self/esi: (addr gap-buffer) <- copy _self + # more in left? + var left/eax: (addr grapheme-stack) <- get self, left + var left-size/eax: int <- grapheme-stack-length left + var left-read-index/ecx: (addr int) <- get self, left-read-index + compare *left-read-index, left-size + { + break-if->= + return 0/false + } + # more in right? + var right/eax: (addr grapheme-stack) <- get self, right + var right-size/eax: int <- grapheme-stack-length right + var right-read-index/ecx: (addr int) <- get self, right-read-index + compare *right-read-index, right-size + { + break-if->= + return 0/false + } + # + return 1/true +} + +fn read-from-gap-buffer _self: (addr gap-buffer) -> _/eax: grapheme { + var self/esi: (addr gap-buffer) <- copy _self + # more in left? + var left/ecx: (addr grapheme-stack) <- get self, left + var left-size/eax: int <- grapheme-stack-length left + var left-read-index-a/edx: (addr int) <- get self, left-read-index + compare *left-read-index-a, left-size + { + break-if->= + var left-data-ah/eax: (addr handle array grapheme) <- get left, data + var left-data/eax: (addr array grapheme) <- lookup *left-data-ah + var left-read-index/ecx: int <- copy *left-read-index-a + var result/eax: (addr grapheme) <- index left-data, left-read-index + increment *left-read-index-a + return *result + } + # more in right? + var right/ecx: (addr grapheme-stack) <- get self, right + var _right-size/eax: int <- grapheme-stack-length right + var right-size/ebx: int <- copy _right-size + var right-read-index-a/edx: (addr int) <- get self, right-read-index + compare *right-read-index-a, right-size + { + break-if->= + # read the right from reverse + var right-data-ah/eax: (addr handle array grapheme) <- get right, data + var right-data/eax: (addr array grapheme) <- lookup *right-data-ah + var right-read-index/ebx: int <- copy right-size + right-read-index <- subtract *right-read-index-a + right-read-index <- subtract 1 + var result/eax: (addr grapheme) <- index right-data, right-read-index + increment *right-read-index-a + return *result + } + # if we get here there's nothing left + return 0/nul +} + +fn test-read-from-gap-buffer { + var gap-storage: gap-buffer + var gap/esi: (addr gap-buffer) <- address gap-storage + initialize-gap-buffer-with gap, "abc" + # gap is at end, all contents are in left + var done?/eax: boolean <- gap-buffer-scan-done? gap + check-not done?, "F - test-read-from-gap-buffer/left-1/done" + var g/eax: grapheme <- read-from-gap-buffer gap + var x/ecx: int <- copy g + check-ints-equal x, 0x61/a, "F - test-read-from-gap-buffer/left-1" + var done?/eax: boolean <- gap-buffer-scan-done? gap + check-not done?, "F - test-read-from-gap-buffer/left-2/done" + var g/eax: grapheme <- read-from-gap-buffer gap + var x/ecx: int <- copy g + check-ints-equal x, 0x62/b, "F - test-read-from-gap-buffer/left-2" + var done?/eax: boolean <- gap-buffer-scan-done? gap + check-not done?, "F - test-read-from-gap-buffer/left-3/done" + var g/eax: grapheme <- read-from-gap-buffer gap + var x/ecx: int <- copy g + check-ints-equal x, 0x63/c, "F - test-read-from-gap-buffer/left-3" + var done?/eax: boolean <- gap-buffer-scan-done? gap + check done?, "F - test-read-from-gap-buffer/left-4/done" + var g/eax: grapheme <- read-from-gap-buffer gap + var x/ecx: int <- copy g + check-ints-equal x, 0/nul, "F - test-read-from-gap-buffer/left-4" + # now check when everything is to the right + gap-to-start gap + rewind-gap-buffer gap + var done?/eax: boolean <- gap-buffer-scan-done? gap + check-not done?, "F - test-read-from-gap-buffer/right-1/done" + var g/eax: grapheme <- read-from-gap-buffer gap + var x/ecx: int <- copy g + check-ints-equal x, 0x61/a, "F - test-read-from-gap-buffer/right-1" + var done?/eax: boolean <- gap-buffer-scan-done? gap + check-not done?, "F - test-read-from-gap-buffer/right-2/done" + var g/eax: grapheme <- read-from-gap-buffer gap + var x/ecx: int <- copy g + check-ints-equal x, 0x62/b, "F - test-read-from-gap-buffer/right-2" + var done?/eax: boolean <- gap-buffer-scan-done? gap + check-not done?, "F - test-read-from-gap-buffer/right-3/done" + var g/eax: grapheme <- read-from-gap-buffer gap + var x/ecx: int <- copy g + check-ints-equal x, 0x63/c, "F - test-read-from-gap-buffer/right-3" + var done?/eax: boolean <- gap-buffer-scan-done? gap + check done?, "F - test-read-from-gap-buffer/right-4/done" + var g/eax: grapheme <- read-from-gap-buffer gap + var x/ecx: int <- copy g + check-ints-equal x, 0/nul, "F - test-read-from-gap-buffer/right-4" +} diff --git a/baremetal/shell/grapheme-stack.mu b/baremetal/shell/grapheme-stack.mu index 8a4bbd0a..ad8fbc24 100644 --- a/baremetal/shell/grapheme-stack.mu +++ b/baremetal/shell/grapheme-stack.mu @@ -30,6 +30,12 @@ fn grapheme-stack-empty? _self: (addr grapheme-stack) -> _/eax: boolean { return 0/false } +fn grapheme-stack-length _self: (addr grapheme-stack) -> _/eax: int { + var self/esi: (addr grapheme-stack) <- copy _self + var top/eax: (addr int) <- get self, top + return *top +} + fn push-grapheme-stack _self: (addr grapheme-stack), _val: grapheme { var self/esi: (addr grapheme-stack) <- copy _self var top-addr/ecx: (addr int) <- get self, top |