https://github.com/akkartik/mu/blob/main/shell/grapheme-stack.mu
1
2
3 type grapheme-stack {
4 data: (handle array grapheme)
5 top: int
6 }
7
8 fn initialize-grapheme-stack _self: (addr grapheme-stack), n: int {
9 var self/esi: (addr grapheme-stack) <- copy _self
10 var d/edi: (addr handle array grapheme) <- get self, data
11 populate d, n
12 var top/eax: (addr int) <- get self, top
13 copy-to *top, 0
14 }
15
16 fn clear-grapheme-stack _self: (addr grapheme-stack) {
17 var self/esi: (addr grapheme-stack) <- copy _self
18 var top/eax: (addr int) <- get self, top
19 copy-to *top, 0
20 }
21
22 fn grapheme-stack-empty? _self: (addr grapheme-stack) -> _/eax: boolean {
23 var self/esi: (addr grapheme-stack) <- copy _self
24 var top/eax: (addr int) <- get self, top
25 compare *top, 0
26 {
27 break-if-!=
28 return 1/true
29 }
30 return 0/false
31 }
32
33 fn grapheme-stack-length _self: (addr grapheme-stack) -> _/eax: int {
34 var self/esi: (addr grapheme-stack) <- copy _self
35 var top/eax: (addr int) <- get self, top
36 return *top
37 }
38
39 fn push-grapheme-stack _self: (addr grapheme-stack), _val: grapheme {
40 var self/esi: (addr grapheme-stack) <- copy _self
41 var top-addr/ecx: (addr int) <- get self, top
42 var data-ah/edx: (addr handle array grapheme) <- get self, data
43 var data/eax: (addr array grapheme) <- lookup *data-ah
44 var top/edx: int <- copy *top-addr
45 var dest-addr/edx: (addr grapheme) <- index data, top
46 var val/eax: grapheme <- copy _val
47 copy-to *dest-addr, val
48 add-to *top-addr, 1
49 }
50
51 fn pop-grapheme-stack _self: (addr grapheme-stack) -> _/eax: grapheme {
52 var self/esi: (addr grapheme-stack) <- copy _self
53 var top-addr/ecx: (addr int) <- get self, top
54 {
55 compare *top-addr, 0
56 break-if->
57 return -1
58 }
59 subtract-from *top-addr, 1
60 var data-ah/edx: (addr handle array grapheme) <- get self, data
61 var data/eax: (addr array grapheme) <- lookup *data-ah
62 var top/edx: int <- copy *top-addr
63 var result-addr/eax: (addr grapheme) <- index data, top
64 return *result-addr
65 }
66
67 fn copy-grapheme-stack _src: (addr grapheme-stack), dest: (addr grapheme-stack) {
68 var src/esi: (addr grapheme-stack) <- copy _src
69 var data-ah/edi: (addr handle array grapheme) <- get src, data
70 var _data/eax: (addr array grapheme) <- lookup *data-ah
71 var data/edi: (addr array grapheme) <- copy _data
72 var top-addr/ecx: (addr int) <- get src, top
73 var i/eax: int <- copy 0
74 {
75 compare i, *top-addr
76 break-if->=
77 var g/edx: (addr grapheme) <- index data, i
78 push-grapheme-stack dest, *g
79 i <- increment
80 loop
81 }
82 }
83
84
85
86 fn render-stack-from-bottom-wrapping-right-then-down screen: (addr screen), _self: (addr grapheme-stack), xmin: int, ymin: int, xmax: int, ymax: int, _x: int, _y: int -> _/eax: int, _/ecx: int {
87 var self/esi: (addr grapheme-stack) <- copy _self
88 var data-ah/edi: (addr handle array grapheme) <- get self, data
89 var _data/eax: (addr array grapheme) <- lookup *data-ah
90 var data/edi: (addr array grapheme) <- copy _data
91 var x/eax: int <- copy _x
92 var y/ecx: int <- copy _y
93 var top-addr/edx: (addr int) <- get self, top
94 var i/ebx: int <- copy 0
95 {
96 compare i, *top-addr
97 break-if->=
98 {
99 var g/edx: (addr grapheme) <- index data, i
100 x, y <- render-grapheme screen, *g, xmin, ymin, xmax, ymax, x, y, 3/fg=cyan, 0/bg
101 }
102 i <- increment
103 loop
104 }
105 return x, y
106 }
107
108
109 fn render-stack-from-bottom screen: (addr screen), self: (addr grapheme-stack), x: int, y: int -> _/eax: int {
110 var _width/eax: int <- copy 0
111 var _height/ecx: int <- copy 0
112 _width, _height <- screen-size screen
113 var width/edx: int <- copy _width
114 var height/ebx: int <- copy _height
115 var x2/eax: int <- copy 0
116 var y2/ecx: int <- copy 0
117 x2, y2 <- render-stack-from-bottom-wrapping-right-then-down screen, self, x, y, width, height, x, y
118 return x2
119 }
120
121
122
123 fn render-stack-from-top-wrapping-right-then-down screen: (addr screen), _self: (addr grapheme-stack), xmin: int, ymin: int, xmax: int, ymax: int, _x: int, _y: int, render-cursor?: boolean -> _/eax: int, _/ecx: int {
124 var self/esi: (addr grapheme-stack) <- copy _self
125 var data-ah/edi: (addr handle array grapheme) <- get self, data
126 var _data/eax: (addr array grapheme) <- lookup *data-ah
127 var data/edi: (addr array grapheme) <- copy _data
128 var x/eax: int <- copy _x
129 var y/ecx: int <- copy _y
130 var top-addr/edx: (addr int) <- get self, top
131 var i/ebx: int <- copy *top-addr
132 i <- decrement
133
134 {
135 compare render-cursor?, 0/false
136 break-if-=
137 compare i, 0
138 break-if-<
139 {
140 var g/edx: (addr grapheme) <- index data, i
141 x, y <- render-grapheme screen, *g, xmin, ymin, xmax, ymax, x, y, 3/fg=cyan, 7/bg=cursor
142 }
143 i <- decrement
144 }
145
146 {
147 compare i, 0
148 break-if-<
149 {
150 var g/edx: (addr grapheme) <- index data, i
151 x, y <- render-grapheme screen, *g, xmin, ymin, xmax, ymax, x, y, 3/fg=cyan, 0/bg=cursor
152 }
153 i <- decrement
154 loop
155 }
156 return x, y
157 }
158
159
160 fn render-stack-from-top screen: (addr screen), self: (addr grapheme-stack), x: int, y: int, render-cursor?: boolean -> _/eax: int {
161 var _width/eax: int <- copy 0
162 var _height/ecx: int <- copy 0
163 _width, _height <- screen-size screen
164 var width/edx: int <- copy _width
165 var height/ebx: int <- copy _height
166 var x2/eax: int <- copy 0
167 var y2/ecx: int <- copy 0
168 x2, y2 <- render-stack-from-top-wrapping-right-then-down screen, self, x, y, width, height, x, y, render-cursor?
169 return x2
170 }
171
172 fn test-render-grapheme-stack {
173
174 var gs-storage: grapheme-stack
175 var gs/edi: (addr grapheme-stack) <- address gs-storage
176 initialize-grapheme-stack gs, 5
177 var g/eax: grapheme <- copy 0x61/a
178 push-grapheme-stack gs, g
179 g <- copy 0x62/b
180 push-grapheme-stack gs, g
181 g <- copy 0x63/c
182 push-grapheme-stack gs, g
183
184 var screen-on-stack: screen
185 var screen/esi: (addr screen) <- address screen-on-stack
186 initialize-screen screen, 5, 4
187
188 var x/eax: int <- render-stack-from-bottom screen, gs, 0/x, 0/y
189 check-screen-row screen, 0/y, "abc ", "F - test-render-grapheme-stack from bottom"
190 check-ints-equal x, 3, "F - test-render-grapheme-stack from bottom: result"
191 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-render-grapheme-stack from bottom: bg"
192
193 var x/eax: int <- render-stack-from-top screen, gs, 0/x, 1/y, 0/cursor=false
194 check-screen-row screen, 1/y, "cba ", "F - test-render-grapheme-stack from top without cursor"
195 check-ints-equal x, 3, "F - test-render-grapheme-stack from top without cursor: result"
196 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-render-grapheme-stack from top without cursor: bg"
197
198 var x/eax: int <- render-stack-from-top screen, gs, 0/x, 2/y, 1/cursor=true
199 check-screen-row screen, 2/y, "cba ", "F - test-render-grapheme-stack from top with cursor"
200 check-ints-equal x, 3, "F - test-render-grapheme-stack from top without cursor: result"
201 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "| ", "F - test-render-grapheme-stack from top with cursor: bg"
202 }
203
204
205
206 fn prefix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> _/eax: boolean {
207 var self/esi: (addr grapheme-stack) <- copy _self
208 var data-ah/edi: (addr handle array grapheme) <- get self, data
209 var _data/eax: (addr array grapheme) <- lookup *data-ah
210 var data/edi: (addr array grapheme) <- copy _data
211 var top-addr/ecx: (addr int) <- get self, top
212 var i/ebx: int <- copy 0
213 {
214 compare i, *top-addr
215 break-if->=
216
217 {
218 var curr-a/edx: (addr grapheme) <- index data, i
219 var expected/eax: grapheme <- read-grapheme s
220 {
221 compare expected, *curr-a
222 break-if-=
223 return 0/false
224 }
225 }
226 i <- increment
227 loop
228 }
229 return 1
230 }
231
232
233
234 fn suffix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> _/eax: boolean {
235 var self/esi: (addr grapheme-stack) <- copy _self
236 var data-ah/edi: (addr handle array grapheme) <- get self, data
237 var _data/eax: (addr array grapheme) <- lookup *data-ah
238 var data/edi: (addr array grapheme) <- copy _data
239 var top-addr/eax: (addr int) <- get self, top
240 var i/ebx: int <- copy *top-addr
241 i <- decrement
242 {
243 compare i, 0
244 break-if-<
245 {
246 var curr-a/edx: (addr grapheme) <- index data, i
247 var expected/eax: grapheme <- read-grapheme s
248
249 {
250 compare expected, *curr-a
251 break-if-=
252 return 0/false
253 }
254 }
255 i <- decrement
256 loop
257 }
258 return 1
259 }
260
261 fn grapheme-stack-is-decimal-integer? _self: (addr grapheme-stack) -> _/eax: boolean {
262 var self/esi: (addr grapheme-stack) <- copy _self
263 var data-ah/eax: (addr handle array grapheme) <- get self, data
264 var _data/eax: (addr array grapheme) <- lookup *data-ah
265 var data/edx: (addr array grapheme) <- copy _data
266 var top-addr/ecx: (addr int) <- get self, top
267 var i/ebx: int <- copy 0
268 var result/eax: boolean <- copy 1/true
269 $grapheme-stack-is-integer?:loop: {
270 compare i, *top-addr
271 break-if->=
272 var g/edx: (addr grapheme) <- index data, i
273 result <- decimal-digit? *g
274 compare result, 0/false
275 break-if-=
276 i <- increment
277 loop
278 }
279 return result
280 }