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