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