diff options
author | Kartik Agaram <vc@akkartik.com> | 2020-09-19 09:02:40 -0700 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2020-09-19 09:02:40 -0700 |
commit | a0deaa1cb1920339b0e10cb53c8806c35ed94445 (patch) | |
tree | c304675358923b461995f47474179168a0417fa0 /apps/tile/gap-buffer.mu | |
parent | c9093dbb083f4d96b985d87a526ac16cf9ab54a2 (diff) | |
download | mu-a0deaa1cb1920339b0e10cb53c8806c35ed94445.tar.gz |
6801 - snapshot: RPN structured editor
There's some worrisome memory corruption here between the call to max-stack-depth and the callee picking up its args. All this code is incredibly ugly as I start to wrestle with the challenges of structured editors. I keep wanting to keep business logic separate from rendering, but there are feedback loops from wanting to know where to render the cursor. And I haven't even started trying to avoid full-screen renders yet. That'll complect things even more. For now the data path for every iteration of the render loop is: process key compute max depth needed (or any other global information needed for rendering) render
Diffstat (limited to 'apps/tile/gap-buffer.mu')
-rw-r--r-- | apps/tile/gap-buffer.mu | 256 |
1 files changed, 219 insertions, 37 deletions
diff --git a/apps/tile/gap-buffer.mu b/apps/tile/gap-buffer.mu index 9d6b7161..1503690b 100644 --- a/apps/tile/gap-buffer.mu +++ b/apps/tile/gap-buffer.mu @@ -11,6 +11,22 @@ fn initialize-gap-buffer _self: (addr gap-buffer) { initialize-grapheme-stack right, 0x10 } +# just for tests +fn initialize-gap-buffer-with self: (addr gap-buffer), s: (addr array byte) { + initialize-gap-buffer self + var stream-storage: (stream byte 0x10) + var stream/ecx: (addr stream byte) <- address stream-storage + write stream, s + { + var done?/eax: boolean <- stream-empty? stream + compare done?, 0 # false + break-if-!= + var g/eax: grapheme <- read-grapheme stream + add-grapheme-at-gap self, g + loop + } +} + fn render-gap-buffer screen: (addr screen), _gap: (addr gap-buffer) { var gap/esi: (addr gap-buffer) <- copy _gap var left/eax: (addr grapheme-stack) <- get gap, left @@ -30,49 +46,26 @@ fn gap-buffer-length _gap: (addr gap-buffer) -> result/eax: int { result <- add left-length } -# dump stack to screen from bottom to top -# don't move the cursor or anything -fn render-stack-from-bottom _self: (addr grapheme-stack), screen: (addr screen) { - var self/esi: (addr grapheme-stack) <- copy _self - var data-ah/edi: (addr handle array grapheme) <- get self, data - var _data/eax: (addr array grapheme) <- lookup *data-ah - var data/edi: (addr array grapheme) <- copy _data - var top-addr/ecx: (addr int) <- get self, top - var i/eax: int <- copy 0 - { - compare i, *top-addr - break-if->= - var g/edx: (addr grapheme) <- index data, i - print-grapheme screen, *g - i <- increment - loop - } +fn add-grapheme-at-gap _self: (addr gap-buffer), g: grapheme { + var self/esi: (addr gap-buffer) <- copy _self + var left/eax: (addr grapheme-stack) <- get self, left + push-grapheme-stack left, g } -# dump stack to screen from top to bottom -# don't move the cursor or anything -fn render-stack-from-top _self: (addr grapheme-stack), screen: (addr screen) { - var self/esi: (addr grapheme-stack) <- copy _self - var data-ah/edi: (addr handle array grapheme) <- get self, data - var _data/eax: (addr array grapheme) <- lookup *data-ah - var data/edi: (addr array grapheme) <- copy _data - var top-addr/ecx: (addr int) <- get self, top - var i/eax: int <- copy *top-addr - i <- decrement +fn gap-to-start self: (addr gap-buffer) { { - compare i, 0 - break-if-< - var g/edx: (addr grapheme) <- index data, i - print-grapheme screen, *g - i <- decrement - loop + var curr/eax: grapheme <- gap-left self + compare curr, -1 + loop-if-!= } } -fn add-grapheme-at-gap _self: (addr gap-buffer), g: grapheme { - var self/esi: (addr gap-buffer) <- copy _self - var left/eax: (addr grapheme-stack) <- get self, left - push-grapheme-stack left, g +fn gap-to-end self: (addr gap-buffer) { + { + var curr/eax: grapheme <- gap-right self + compare curr, -1 + loop-if-!= + } } fn gap-right _self: (addr gap-buffer) -> result/eax: grapheme { @@ -112,6 +105,79 @@ $gap-left:body: { } } +fn gap-buffer-equal? _self: (addr gap-buffer), s: (addr array byte) -> result/eax: boolean { +$gap-buffer-equal?:body: { + var self/esi: (addr gap-buffer) <- copy _self + # complication: graphemes may be multiple bytes + # so don't rely on length + # instead turn the expected result into a stream and arrange to read from it in order + var stream-storage: (stream byte 0x10) + var expected-stream/ecx: (addr stream byte) <- address stream-storage + write expected-stream, s + # compare left + var left/edx: (addr grapheme-stack) <- get self, left + result <- prefix-match? left, expected-stream + compare result, 0 # false + break-if-= $gap-buffer-equal?:body + # compare right + var right/edx: (addr grapheme-stack) <- get self, right + result <- suffix-match? right, expected-stream + compare result, 0 # false + break-if-= $gap-buffer-equal?:body + # ensure there's nothing left over + result <- stream-empty? expected-stream +} +} + +fn test-gap-buffer-equal-from-end? { + var _g: gap-buffer + var g/esi: (addr gap-buffer) <- address _g + initialize-gap-buffer g + # + var c/eax: grapheme <- copy 0x61 # 'a' + add-grapheme-at-gap g, c + add-grapheme-at-gap g, c + add-grapheme-at-gap g, c + # gap is at end (right is empty) + var _result/eax: boolean <- gap-buffer-equal? g, "aaa" + var result/eax: int <- copy _result + check-ints-equal result, 1, "F - test-gap-buffer-equal-from-end?" +} + +fn test-gap-buffer-equal-from-middle? { + var _g: gap-buffer + var g/esi: (addr gap-buffer) <- address _g + initialize-gap-buffer g + # + var c/eax: grapheme <- copy 0x61 # 'a' + add-grapheme-at-gap g, c + add-grapheme-at-gap g, c + add-grapheme-at-gap g, c + var dummy/eax: grapheme <- gap-left g + # gap is in the middle + var _result/eax: boolean <- gap-buffer-equal? g, "aaa" + var result/eax: int <- copy _result + check-ints-equal result, 1, "F - test-gap-buffer-equal-from-middle?" +} + +fn test-gap-buffer-equal-from-start? { + var _g: gap-buffer + var g/esi: (addr gap-buffer) <- address _g + initialize-gap-buffer g + # + var c/eax: grapheme <- copy 0x61 # 'a' + add-grapheme-at-gap g, c + add-grapheme-at-gap g, c + add-grapheme-at-gap g, c + var dummy/eax: grapheme <- gap-left g + dummy <- gap-left g + dummy <- gap-left g + # gap is at the start + var _result/eax: boolean <- gap-buffer-equal? g, "aaa" + var result/eax: int <- copy _result + check-ints-equal result, 1, "F - test-gap-buffer-equal-from-start?" +} + type grapheme-stack { data: (handle array grapheme) top: int @@ -125,6 +191,20 @@ fn initialize-grapheme-stack _self: (addr grapheme-stack), n: int { copy-to *top, 0 } +fn grapheme-stack-empty? _self: (addr grapheme-stack) -> result/eax: boolean { +$grapheme-stack-empty?:body: { + var self/esi: (addr grapheme-stack) <- copy _self + var top/eax: (addr int) <- get self, top + compare *top, 0 + { + break-if-= + result <- copy 1 # false + break $grapheme-stack-empty?:body + } + result <- copy 0 # false +} +} + 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 @@ -155,3 +235,105 @@ $pop-grapheme-stack:body: { val <- copy *result-addr } } + +# dump stack to screen from bottom to top +# don't move the cursor or anything +fn render-stack-from-bottom _self: (addr grapheme-stack), screen: (addr screen) { + var self/esi: (addr grapheme-stack) <- copy _self + var data-ah/edi: (addr handle array grapheme) <- get self, data + var _data/eax: (addr array grapheme) <- lookup *data-ah + var data/edi: (addr array grapheme) <- copy _data + var top-addr/ecx: (addr int) <- get self, top + var i/eax: int <- copy 0 + { + compare i, *top-addr + break-if->= + var g/edx: (addr grapheme) <- index data, i + print-grapheme screen, *g + i <- increment + loop + } +} + +# dump stack to screen from top to bottom +# don't move the cursor or anything +fn render-stack-from-top _self: (addr grapheme-stack), screen: (addr screen) { + var self/esi: (addr grapheme-stack) <- copy _self + var data-ah/edi: (addr handle array grapheme) <- get self, data + var _data/eax: (addr array grapheme) <- lookup *data-ah + var data/edi: (addr array grapheme) <- copy _data + var top-addr/ecx: (addr int) <- get self, top + var i/eax: int <- copy *top-addr + i <- decrement + { + compare i, 0 + break-if-< + var g/edx: (addr grapheme) <- index data, i + print-grapheme screen, *g + i <- decrement + loop + } +} + +# compare from bottom +# beware: modifies 'stream', which must be disposed of after a false result +fn prefix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> result/eax: boolean { +$prefix-match?:body: { + var self/esi: (addr grapheme-stack) <- copy _self + var data-ah/edi: (addr handle array grapheme) <- get self, data + var _data/eax: (addr array grapheme) <- lookup *data-ah + var data/edi: (addr array grapheme) <- copy _data + var top-addr/ecx: (addr int) <- get self, top + var i/ebx: int <- copy 0 + { + compare i, *top-addr + break-if->= + # if curr != expected, return false + { + var curr-a/edx: (addr grapheme) <- index data, i + var expected/eax: grapheme <- read-grapheme s + { + compare expected, *curr-a + break-if-= + result <- copy 0 # false + break $prefix-match?:body + } + } + i <- increment + loop + } + result <- copy 1 # true +} +} + +# compare from bottom +# beware: modifies 'stream', which must be disposed of after a false result +fn suffix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> result/eax: boolean { +$suffix-match?:body: { + var self/esi: (addr grapheme-stack) <- copy _self + var data-ah/edi: (addr handle array grapheme) <- get self, data + var _data/eax: (addr array grapheme) <- lookup *data-ah + var data/edi: (addr array grapheme) <- copy _data + var top-addr/eax: (addr int) <- get self, top + var i/ebx: int <- copy *top-addr + i <- decrement + { + compare i, 0 + break-if-< + { + var curr-a/edx: (addr grapheme) <- index data, i + var expected/eax: grapheme <- read-grapheme s + # if curr != expected, return false + { + compare expected, *curr-a + break-if-= + result <- copy 0 # false + break $suffix-match?:body + } + } + i <- decrement + loop + } + result <- copy 1 # true +} +} |