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, highlight-matching-open-paren?: boolean, open-paren-depth: int -> _/eax: int, _/ecx: int {
87 var self/esi: (addr grapheme-stack) <- copy _self
88 var matching-open-paren-index/edx: int <- get-matching-open-paren-index self, highlight-matching-open-paren?, open-paren-depth
89 var data-ah/edi: (addr handle array grapheme) <- get self, data
90 var _data/eax: (addr array grapheme) <- lookup *data-ah
91 var data/edi: (addr array grapheme) <- copy _data
92 var x/eax: int <- copy _x
93 var y/ecx: int <- copy _y
94 var top-addr/esi: (addr int) <- get self, top
95 var i/ebx: int <- copy 0
96 {
97 compare i, *top-addr
98 break-if->=
99 {
100 var g/esi: (addr grapheme) <- index data, i
101 var fg: int
102 copy-to fg, 3/cyan
103 {
104 compare i, matching-open-paren-index
105 break-if-!=
106 copy-to fg, 0xf/highlight
107 }
108 x, y <- render-grapheme screen, *g, xmin, ymin, xmax, ymax, x, y, fg, 0/bg
109 }
110 i <- increment
111 loop
112 }
113 return x, y
114 }
115
116
117 fn render-stack-from-bottom screen: (addr screen), self: (addr grapheme-stack), x: int, y: int, highlight-matching-open-paren?: boolean, open-paren-depth: int -> _/eax: int {
118 var _width/eax: int <- copy 0
119 var _height/ecx: int <- copy 0
120 _width, _height <- screen-size screen
121 var width/edx: int <- copy _width
122 var height/ebx: int <- copy _height
123 var x2/eax: int <- copy 0
124 var y2/ecx: int <- copy 0
125 x2, y2 <- render-stack-from-bottom-wrapping-right-then-down screen, self, x, y, width, height, x, y, highlight-matching-open-paren?, open-paren-depth
126 return x2
127 }
128
129
130
131 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 {
132 var self/esi: (addr grapheme-stack) <- copy _self
133 var matching-close-paren-index/edx: int <- get-matching-close-paren-index self, render-cursor?
134 var data-ah/eax: (addr handle array grapheme) <- get self, data
135 var _data/eax: (addr array grapheme) <- lookup *data-ah
136 var data/edi: (addr array grapheme) <- copy _data
137 var x/eax: int <- copy _x
138 var y/ecx: int <- copy _y
139 var top-addr/ebx: (addr int) <- get self, top
140 var i/ebx: int <- copy *top-addr
141 i <- decrement
142
143 {
144 compare render-cursor?, 0/false
145 break-if-=
146 compare i, 0
147 break-if-<
148 var g/esi: (addr grapheme) <- index data, i
149 x, y <- render-grapheme screen, *g, xmin, ymin, xmax, ymax, x, y, 3/fg=cyan, 7/bg=cursor
150 i <- decrement
151 }
152
153 {
154 compare i, 0
155 break-if-<
156
157 var fg: int
158 copy-to fg, 3/cyan
159 compare i, matching-close-paren-index
160 {
161 break-if-!=
162 copy-to fg, 0xf/highlight
163 }
164
165 var g/esi: (addr grapheme) <- index data, i
166 x, y <- render-grapheme screen, *g, xmin, ymin, xmax, ymax, x, y, fg, 0/bg=cursor
167 i <- decrement
168 loop
169 }
170 return x, y
171 }
172
173
174 fn render-stack-from-top screen: (addr screen), self: (addr grapheme-stack), x: int, y: int, render-cursor?: boolean -> _/eax: int {
175 var _width/eax: int <- copy 0
176 var _height/ecx: int <- copy 0
177 _width, _height <- screen-size screen
178 var width/edx: int <- copy _width
179 var height/ebx: int <- copy _height
180 var x2/eax: int <- copy 0
181 var y2/ecx: int <- copy 0
182 x2, y2 <- render-stack-from-top-wrapping-right-then-down screen, self, x, y, width, height, x, y, render-cursor?
183 return x2
184 }
185
186 fn test-render-grapheme-stack {
187
188 var gs-storage: grapheme-stack
189 var gs/edi: (addr grapheme-stack) <- address gs-storage
190 initialize-grapheme-stack gs, 5
191 var g/eax: grapheme <- copy 0x61/a
192 push-grapheme-stack gs, g
193 g <- copy 0x62/b
194 push-grapheme-stack gs, g
195 g <- copy 0x63/c
196 push-grapheme-stack gs, g
197
198 var screen-on-stack: screen
199 var screen/esi: (addr screen) <- address screen-on-stack
200 initialize-screen screen, 5, 4
201
202 var x/eax: int <- render-stack-from-bottom screen, gs, 0/x, 0/y, 0/no-highlight-matching-open-paren, 0/open-paren-depth
203 check-screen-row screen, 0/y, "abc ", "F - test-render-grapheme-stack from bottom"
204 check-ints-equal x, 3, "F - test-render-grapheme-stack from bottom: result"
205 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-render-grapheme-stack from bottom: bg"
206
207 var x/eax: int <- render-stack-from-top screen, gs, 0/x, 1/y, 0/cursor=false
208 check-screen-row screen, 1/y, "cba ", "F - test-render-grapheme-stack from top without cursor"
209 check-ints-equal x, 3, "F - test-render-grapheme-stack from top without cursor: result"
210 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-render-grapheme-stack from top without cursor: bg"
211
212 var x/eax: int <- render-stack-from-top screen, gs, 0/x, 2/y, 1/cursor=true
213 check-screen-row screen, 2/y, "cba ", "F - test-render-grapheme-stack from top with cursor"
214 check-ints-equal x, 3, "F - test-render-grapheme-stack from top with cursor: result"
215 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "| ", "F - test-render-grapheme-stack from top with cursor: bg"
216 }
217
218 fn test-render-grapheme-stack-while-highlighting-matching-close-paren {
219
220 var gs-storage: grapheme-stack
221 var gs/edi: (addr grapheme-stack) <- address gs-storage
222 initialize-grapheme-stack gs, 5
223 var g/eax: grapheme <- copy 0x29/close-paren
224 push-grapheme-stack gs, g
225 g <- copy 0x62/b
226 push-grapheme-stack gs, g
227 g <- copy 0x28/open-paren
228 push-grapheme-stack gs, g
229
230 var screen-on-stack: screen
231 var screen/esi: (addr screen) <- address screen-on-stack
232 initialize-screen screen, 5, 4
233
234 var x/eax: int <- render-stack-from-top screen, gs, 0/x, 2/y, 1/cursor=true
235 check-screen-row screen, 2/y, "(b) ", "F - test-render-grapheme-stack-while-highlighting-matching-close-paren"
236 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "| ", "F - test-render-grapheme-stack-while-highlighting-matching-close-paren: cursor"
237 check-screen-row-in-color screen, 0xf/fg=white, 2/y, " ) ", "F - test-render-grapheme-stack-while-highlighting-matching-close-paren: matching paren"
238 }
239
240 fn test-render-grapheme-stack-while-highlighting-matching-close-paren-2 {
241
242 var gs-storage: grapheme-stack
243 var gs/edi: (addr grapheme-stack) <- address gs-storage
244 initialize-grapheme-stack gs, 0x10
245 var g/eax: grapheme <- copy 0x63/c
246 push-grapheme-stack gs, g
247 g <- copy 0x20/space
248 push-grapheme-stack gs, g
249 g <- copy 0x29/close-paren
250 push-grapheme-stack gs, g
251 g <- copy 0x29/close-paren
252 push-grapheme-stack gs, g
253 g <- copy 0x62/b
254 push-grapheme-stack gs, g
255 g <- copy 0x28/open-paren
256 push-grapheme-stack gs, g
257 g <- copy 0x20/space
258 push-grapheme-stack gs, g
259 g <- copy 0x61/a
260 push-grapheme-stack gs, g
261 g <- copy 0x28/open-paren
262 push-grapheme-stack gs, g
263
264 var screen-on-stack: screen
265 var screen/esi: (addr screen) <- address screen-on-stack
266 initialize-screen screen, 5, 4
267
268 var x/eax: int <- render-stack-from-top screen, gs, 0/x, 2/y, 1/cursor=true
269 check-screen-row screen, 2/y, "(a (b)) c ", "F - test-render-grapheme-stack-while-highlighting-matching-close-paren-2"
270 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "| ", "F - test-render-grapheme-stack-while-highlighting-matching-close-paren-2: cursor"
271 check-screen-row-in-color screen, 0xf/fg=white, 2/y, " ) ", "F - test-render-grapheme-stack-while-highlighting-matching-close-paren-2: matching paren"
272 }
273
274 fn test-render-grapheme-stack-while-highlighting-matching-open-paren-with-close-paren-at-end {
275
276 var gs-storage: grapheme-stack
277 var gs/edi: (addr grapheme-stack) <- address gs-storage
278 initialize-grapheme-stack gs, 5
279 var g/eax: grapheme <- copy 0x28/open-paren
280 push-grapheme-stack gs, g
281 g <- copy 0x62/b
282 push-grapheme-stack gs, g
283 g <- copy 0x29/close-paren
284 push-grapheme-stack gs, g
285
286 var screen-on-stack: screen
287 var screen/esi: (addr screen) <- address screen-on-stack
288 initialize-screen screen, 5, 4
289
290 var x/eax: int <- render-stack-from-bottom screen, gs, 0/x, 2/y, 1/highlight-matching-open-paren, 1/open-paren-depth
291 check-screen-row screen, 2/y, "(b) ", "F - test-render-grapheme-stack-while-highlighting-matching-open-paren-with-close-paren-at-end"
292 check-screen-row-in-color screen, 0xf/fg=white, 2/y, "( ", "F - test-render-grapheme-stack-while-highlighting-matching-open-paren-with-close-paren-at-end: matching paren"
293 }
294
295 fn test-render-grapheme-stack-while-highlighting-matching-open-paren-with-close-paren-at-end-2 {
296
297 var gs-storage: grapheme-stack
298 var gs/edi: (addr grapheme-stack) <- address gs-storage
299 initialize-grapheme-stack gs, 0x10
300 var g/eax: grapheme <- copy 0x61/a
301 push-grapheme-stack gs, g
302 g <- copy 0x28/open-paren
303 push-grapheme-stack gs, g
304 g <- copy 0x28/open-paren
305 push-grapheme-stack gs, g
306 g <- copy 0x62/b
307 push-grapheme-stack gs, g
308 g <- copy 0x29/close-paren
309 push-grapheme-stack gs, g
310 g <- copy 0x29/close-paren
311 push-grapheme-stack gs, g
312
313 var screen-on-stack: screen
314 var screen/esi: (addr screen) <- address screen-on-stack
315 initialize-screen screen, 5, 4
316
317 var x/eax: int <- render-stack-from-bottom screen, gs, 0/x, 2/y, 1/highlight-matching-open-paren, 1/open-paren-depth
318 check-screen-row screen, 2/y, "a((b)) ", "F - test-render-grapheme-stack-while-highlighting-matching-open-paren-with-close-paren-at-end-2"
319 check-screen-row-in-color screen, 0xf/fg=white, 2/y, " ( ", "F - test-render-grapheme-stack-while-highlighting-matching-open-paren-with-close-paren-at-end-2: matching paren"
320 }
321
322 fn test-render-grapheme-stack-while-highlighting-matching-open-paren {
323
324 var gs-storage: grapheme-stack
325 var gs/edi: (addr grapheme-stack) <- address gs-storage
326 initialize-grapheme-stack gs, 5
327 var g/eax: grapheme <- copy 0x28/open-paren
328 push-grapheme-stack gs, g
329 g <- copy 0x62/b
330 push-grapheme-stack gs, g
331
332 var screen-on-stack: screen
333 var screen/esi: (addr screen) <- address screen-on-stack
334 initialize-screen screen, 5, 4
335
336 var x/eax: int <- render-stack-from-bottom screen, gs, 0/x, 2/y, 1/highlight-matching-open-paren, 0/open-paren-depth
337 check-screen-row screen, 2/y, "(b ", "F - test-render-grapheme-stack-while-highlighting-matching-open-paren"
338 check-screen-row-in-color screen, 0xf/fg=white, 2/y, "( ", "F - test-render-grapheme-stack-while-highlighting-matching-open-paren: matching paren"
339 }
340
341 fn test-render-grapheme-stack-while-highlighting-matching-open-paren-2 {
342
343 var gs-storage: grapheme-stack
344 var gs/edi: (addr grapheme-stack) <- address gs-storage
345 initialize-grapheme-stack gs, 0x10
346 var g/eax: grapheme <- copy 0x61/a
347 push-grapheme-stack gs, g
348 g <- copy 0x28/open-paren
349 push-grapheme-stack gs, g
350 g <- copy 0x28/open-paren
351 push-grapheme-stack gs, g
352 g <- copy 0x62/b
353 push-grapheme-stack gs, g
354 g <- copy 0x29/close-paren
355 push-grapheme-stack gs, g
356
357 var screen-on-stack: screen
358 var screen/esi: (addr screen) <- address screen-on-stack
359 initialize-screen screen, 5, 4
360
361 var x/eax: int <- render-stack-from-bottom screen, gs, 0/x, 2/y, 1/highlight-matching-open-paren, 0/open-paren-depth
362 check-screen-row screen, 2/y, "a((b) ", "F - test-render-grapheme-stack-while-highlighting-matching-open-paren-2"
363 check-screen-row-in-color screen, 0xf/fg=white, 2/y, " ( ", "F - test-render-grapheme-stack-while-highlighting-matching-open-paren-2: matching paren"
364 }
365
366
367
368 fn get-matching-close-paren-index _self: (addr grapheme-stack), render-cursor?: boolean -> _/edx: int {
369 var self/esi: (addr grapheme-stack) <- copy _self
370 var top-addr/edx: (addr int) <- get self, top
371
372 compare render-cursor?, 0/false
373 {
374 break-if-!=
375 return *top-addr
376 }
377 var data-ah/eax: (addr handle array grapheme) <- get self, data
378 var data/eax: (addr array grapheme) <- lookup *data-ah
379 var i/ecx: int <- copy *top-addr
380
381 compare i, 0
382 {
383 break-if->
384 return *top-addr
385 }
386
387 i <- decrement
388 var g/esi: (addr grapheme) <- index data, i
389 compare *g, 0x28/open-paren
390 {
391 break-if-=
392 return *top-addr
393 }
394
395 var paren-count/ebx: int <- copy 1
396 i <- decrement
397 {
398 compare i, 0
399 break-if-<
400 var g/esi: (addr grapheme) <- index data, i
401 compare *g, 0x28/open-paren
402 {
403 break-if-!=
404 paren-count <- increment
405 }
406 compare *g, 0x29/close-paren
407 {
408 break-if-!=
409 compare paren-count, 1
410 {
411 break-if-!=
412 return i
413 }
414 paren-count <- decrement
415 }
416 i <- decrement
417 loop
418 }
419 return *top-addr
420 }
421
422
423
424 fn get-matching-open-paren-index _self: (addr grapheme-stack), control: boolean, depth: int -> _/edx: int {
425 var self/esi: (addr grapheme-stack) <- copy _self
426 var top-addr/edx: (addr int) <- get self, top
427
428 compare control, 0/false
429 {
430 break-if-!=
431 return *top-addr
432 }
433 var data-ah/eax: (addr handle array grapheme) <- get self, data
434 var data/eax: (addr array grapheme) <- lookup *data-ah
435 var i/ecx: int <- copy *top-addr
436
437 compare i, 0
438 {
439 break-if->
440 return *top-addr
441 }
442
443 var paren-count/ebx: int <- copy 0
444 i <- decrement
445 {
446 compare i, 0
447 break-if-<
448 var g/esi: (addr grapheme) <- index data, i
449 compare *g, 0x29/close-paren
450 {
451 break-if-!=
452 paren-count <- increment
453 }
454 compare *g, 0x28/open-paren
455 {
456 break-if-!=
457 compare paren-count, depth
458 {
459 break-if-!=
460 return i
461 }
462 paren-count <- decrement
463 }
464 i <- decrement
465 loop
466 }
467 return *top-addr
468 }
469
470
471
472 fn prefix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> _/eax: boolean {
473 var self/esi: (addr grapheme-stack) <- copy _self
474 var data-ah/edi: (addr handle array grapheme) <- get self, data
475 var _data/eax: (addr array grapheme) <- lookup *data-ah
476 var data/edi: (addr array grapheme) <- copy _data
477 var top-addr/ecx: (addr int) <- get self, top
478 var i/ebx: int <- copy 0
479 {
480 compare i, *top-addr
481 break-if->=
482
483 {
484 var curr-a/edx: (addr grapheme) <- index data, i
485 var expected/eax: grapheme <- read-grapheme s
486 {
487 compare expected, *curr-a
488 break-if-=
489 return 0/false
490 }
491 }
492 i <- increment
493 loop
494 }
495 return 1
496 }
497
498
499
500 fn suffix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> _/eax: boolean {
501 var self/esi: (addr grapheme-stack) <- copy _self
502 var data-ah/edi: (addr handle array grapheme) <- get self, data
503 var _data/eax: (addr array grapheme) <- lookup *data-ah
504 var data/edi: (addr array grapheme) <- copy _data
505 var top-addr/eax: (addr int) <- get self, top
506 var i/ebx: int <- copy *top-addr
507 i <- decrement
508 {
509 compare i, 0
510 break-if-<
511 {
512 var curr-a/edx: (addr grapheme) <- index data, i
513 var expected/eax: grapheme <- read-grapheme s
514
515 {
516 compare expected, *curr-a
517 break-if-=
518 return 0/false
519 }
520 }
521 i <- decrement
522 loop
523 }
524 return 1
525 }
526
527 fn grapheme-stack-is-decimal-integer? _self: (addr grapheme-stack) -> _/eax: boolean {
528 var self/esi: (addr grapheme-stack) <- copy _self
529 var data-ah/eax: (addr handle array grapheme) <- get self, data
530 var _data/eax: (addr array grapheme) <- lookup *data-ah
531 var data/edx: (addr array grapheme) <- copy _data
532 var top-addr/ecx: (addr int) <- get self, top
533 var i/ebx: int <- copy 0
534 var result/eax: boolean <- copy 1/true
535 $grapheme-stack-is-integer?:loop: {
536 compare i, *top-addr
537 break-if->=
538 var g/edx: (addr grapheme) <- index data, i
539 result <- decimal-digit? *g
540 compare result, 0/false
541 break-if-=
542 i <- increment
543 loop
544 }
545 return result
546 }