From a0deaa1cb1920339b0e10cb53c8806c35ed94445 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 19 Sep 2020 09:02:40 -0700 Subject: 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 --- apps/tile/gap-buffer.mu | 256 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 219 insertions(+), 37 deletions(-) (limited to 'apps/tile/gap-buffer.mu') 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 +} +} -- cgit 1.4.1-2-gfad0 2ef151ad86e2003ad0e2bfb09f3d4c2d'>^
6808ff7d ^
1f7e3c05 ^
6808ff7d ^




a17f9186 ^
6808ff7d ^

a17f9186 ^
6808ff7d ^

9cfd925a ^
1ead3562 ^
15f79a66 ^
6808ff7d ^
15f79a66 ^




acc4792d ^
ff8d96ae ^
69e418d7 ^
1ead3562 ^
69e418d7 ^
991d76f3 ^



69e418d7 ^



ff8d96ae ^


1ead3562 ^
455fbac6 ^
ff8d96ae ^
8a3d101e ^
ff8d96ae ^
bb33c5e8 ^
c4e143d6 ^





ff8d96ae ^

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99