https://github.com/akkartik/mu/blob/main/baremetal/shell/word.mu
1 type word {
2 scalar-data: (handle gap-buffer)
3 next: (handle word)
4 prev: (handle word)
5 }
6
7 fn initialize-word _self: (addr word) {
8 var self/esi: (addr word) <- copy _self
9 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
10 allocate data-ah
11 var data/eax: (addr gap-buffer) <- lookup *data-ah
12 initialize-gap-buffer data
13 }
14
15
16
17 fn initialize-word-with _self: (addr word), s: (addr array byte) {
18 var self/esi: (addr word) <- copy _self
19 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
20 allocate data-ah
21 var data/eax: (addr gap-buffer) <- lookup *data-ah
22 initialize-gap-buffer-with data, s
23 }
24
25 fn allocate-word-with _out: (addr handle word), s: (addr array byte) {
26 var out/eax: (addr handle word) <- copy _out
27 allocate out
28 var out-addr/eax: (addr word) <- lookup *out
29 initialize-word-with out-addr, s
30 }
31
32
33
34
35 fn append-word-with self-h: (handle word), s: (addr array byte) {
36 var self/eax: (addr word) <- lookup self-h
37 var next-ah/eax: (addr handle word) <- get self, next
38 allocate-word-with next-ah, s
39 var next/eax: (addr word) <- lookup *next-ah
40 var prev-ah/eax: (addr handle word) <- get next, prev
41 copy-handle self-h, prev-ah
42 }
43
44
45
46 fn prepend-word-with self-h: (handle word), s: (addr array byte) {
47 var self/eax: (addr word) <- lookup self-h
48 var prev-ah/eax: (addr handle word) <- get self, prev
49 allocate-word-with prev-ah, s
50 var prev/eax: (addr word) <- lookup *prev-ah
51 var next-ah/eax: (addr handle word) <- get prev, next
52 copy-handle self-h, next-ah
53 }
54
55
56
57 fn move-word-contents _src-ah: (addr handle word), _dest-ah: (addr handle word) {
58 var dest-ah/eax: (addr handle word) <- copy _dest-ah
59 var _dest/eax: (addr word) <- lookup *dest-ah
60 var dest/edi: (addr word) <- copy _dest
61 var src-ah/eax: (addr handle word) <- copy _src-ah
62 var _src/eax: (addr word) <- lookup *src-ah
63 var src/esi: (addr word) <- copy _src
64 cursor-to-start src
65 var src-data-ah/eax: (addr handle gap-buffer) <- get src, scalar-data
66 var src-data/eax: (addr gap-buffer) <- lookup *src-data-ah
67 var src-stack/ecx: (addr grapheme-stack) <- get src-data, right
68 {
69 var done?/eax: boolean <- grapheme-stack-empty? src-stack
70 compare done?, 0/false
71 break-if-!=
72 var g/eax: grapheme <- pop-grapheme-stack src-stack
73 add-grapheme-to-word dest, g
74 loop
75 }
76 }
77
78 fn copy-word-contents-before-cursor _src-ah: (addr handle word), _dest-ah: (addr handle word) {
79 var dest-ah/eax: (addr handle word) <- copy _dest-ah
80 var _dest/eax: (addr word) <- lookup *dest-ah
81 var dest/edi: (addr word) <- copy _dest
82 var src-ah/eax: (addr handle word) <- copy _src-ah
83 var src/eax: (addr word) <- lookup *src-ah
84 var src-data-ah/eax: (addr handle gap-buffer) <- get src, scalar-data
85 var src-data/eax: (addr gap-buffer) <- lookup *src-data-ah
86 var src-stack/ecx: (addr grapheme-stack) <- get src-data, left
87 var src-stack-data-ah/eax: (addr handle array grapheme) <- get src-stack, data
88 var _src-stack-data/eax: (addr array grapheme) <- lookup *src-stack-data-ah
89 var src-stack-data/edx: (addr array grapheme) <- copy _src-stack-data
90 var top-addr/ecx: (addr int) <- get src-stack, top
91 var i/eax: int <- copy 0
92 {
93 compare i, *top-addr
94 break-if->=
95 var g/edx: (addr grapheme) <- index src-stack-data, i
96 add-grapheme-to-word dest, *g
97 i <- increment
98 loop
99 }
100 }
101
102 fn word-equal? _self: (addr word), s: (addr array byte) -> _/eax: boolean {
103 var self/esi: (addr word) <- copy _self
104 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
105 var data/eax: (addr gap-buffer) <- lookup *data-ah
106 var result/eax: boolean <- gap-buffer-equal? data, s
107 return result
108 }
109
110 fn words-equal? _self: (addr word), _w: (addr word) -> _/eax: boolean {
111 var self/eax: (addr word) <- copy _self
112 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
113 var _data/eax: (addr gap-buffer) <- lookup *data-ah
114 var data/ecx: (addr gap-buffer) <- copy _data
115 var w/eax: (addr word) <- copy _w
116 var w-data-ah/eax: (addr handle gap-buffer) <- get w, scalar-data
117 var w-data/eax: (addr gap-buffer) <- lookup *w-data-ah
118 var result/eax: boolean <- gap-buffers-equal? data, w-data
119 return result
120 }
121
122 fn word-length _self: (addr word) -> _/eax: int {
123 var self/esi: (addr word) <- copy _self
124 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
125 var data/eax: (addr gap-buffer) <- lookup *data-ah
126 var result/eax: int <- gap-buffer-length data
127 return result
128 }
129
130 fn first-word _in: (addr handle word), out: (addr handle word) {
131 var curr-ah/esi: (addr handle word) <- copy _in
132 var curr/eax: (addr word) <- lookup *curr-ah
133 var prev/edi: (addr handle word) <- copy 0
134 {
135 prev <- get curr, prev
136 var curr/eax: (addr word) <- lookup *prev
137 compare curr, 0
138 break-if-=
139 copy-object prev, curr-ah
140 loop
141 }
142 copy-object curr-ah, out
143 }
144
145 fn final-word _in: (addr handle word), out: (addr handle word) {
146 var curr-h: (handle word)
147 var curr-ah/esi: (addr handle word) <- address curr-h
148 copy-object _in, curr-ah
149 var curr/eax: (addr word) <- copy 0
150 var next/edi: (addr handle word) <- copy 0
151 {
152 curr <- lookup *curr-ah
153 next <- get curr, next
154 curr <- lookup *next
155 compare curr, 0
156 break-if-=
157 copy-object next, curr-ah
158 loop
159 }
160 copy-object curr-ah, out
161 }
162
163 fn first-grapheme _self: (addr word) -> _/eax: grapheme {
164 var self/esi: (addr word) <- copy _self
165 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
166 var data/eax: (addr gap-buffer) <- lookup *data-ah
167 var result/eax: grapheme <- first-grapheme-in-gap-buffer data
168 return result
169 }
170
171 fn grapheme-before-cursor _self: (addr word) -> _/eax: grapheme {
172 var self/esi: (addr word) <- copy _self
173 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
174 var data/eax: (addr gap-buffer) <- lookup *data-ah
175 var result/eax: grapheme <- grapheme-before-cursor-in-gap-buffer data
176 return result
177 }
178
179 fn add-grapheme-to-word _self: (addr word), c: grapheme {
180 var self/esi: (addr word) <- copy _self
181 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
182 var data/eax: (addr gap-buffer) <- lookup *data-ah
183 add-grapheme-at-gap data, c
184 }
185
186 fn cursor-at-start? _self: (addr word) -> _/eax: boolean {
187 var self/esi: (addr word) <- copy _self
188 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
189 var data/eax: (addr gap-buffer) <- lookup *data-ah
190 var result/eax: boolean <- gap-at-start? data
191 return result
192 }
193
194 fn cursor-at-end? _self: (addr word) -> _/eax: boolean {
195 var self/esi: (addr word) <- copy _self
196 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
197 var data/eax: (addr gap-buffer) <- lookup *data-ah
198 var result/eax: boolean <- gap-at-end? data
199 return result
200 }
201
202 fn cursor-left _self: (addr word) {
203 var self/esi: (addr word) <- copy _self
204 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
205 var data/eax: (addr gap-buffer) <- lookup *data-ah
206 var dummy/eax: grapheme <- gap-left data
207 }
208
209 fn cursor-right _self: (addr word) {
210 var self/esi: (addr word) <- copy _self
211 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
212 var data/eax: (addr gap-buffer) <- lookup *data-ah
213 var dummy/eax: grapheme <- gap-right data
214 }
215
216 fn cursor-to-start _self: (addr word) {
217 var self/esi: (addr word) <- copy _self
218 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
219 var data/eax: (addr gap-buffer) <- lookup *data-ah
220 gap-to-start data
221 }
222
223 fn cursor-to-end _self: (addr word) {
224 var self/esi: (addr word) <- copy _self
225 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
226 var data/eax: (addr gap-buffer) <- lookup *data-ah
227 gap-to-end data
228 }
229
230 fn cursor-index _self: (addr word) -> _/eax: int {
231 var self/esi: (addr word) <- copy _self
232 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
233 var data/eax: (addr gap-buffer) <- lookup *data-ah
234 var result/eax: int <- index-of-gap data
235 return result
236 }
237
238 fn delete-before-cursor _self: (addr word) {
239 var self/esi: (addr word) <- copy _self
240 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
241 var data/eax: (addr gap-buffer) <- lookup *data-ah
242 delete-before-gap data
243 }
244
245 fn pop-after-cursor _self: (addr word) -> _/eax: grapheme {
246 var self/esi: (addr word) <- copy _self
247 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
248 var data/eax: (addr gap-buffer) <- lookup *data-ah
249 var result/eax: grapheme <- pop-after-gap data
250 return result
251 }
252
253 fn delete-next _self: (addr word) {
254 var self/esi: (addr word) <- copy _self
255 var next-ah/edi: (addr handle word) <- get self, next
256 var next/eax: (addr word) <- lookup *next-ah
257 compare next, 0
258 break-if-=
259 var next-next-ah/ecx: (addr handle word) <- get next, next
260 var self-ah/esi: (addr handle word) <- get next, prev
261 copy-object next-next-ah, next-ah
262 var new-next/eax: (addr word) <- lookup *next-next-ah
263 compare new-next, 0
264 break-if-=
265 var dest/eax: (addr handle word) <- get new-next, prev
266 copy-object self-ah, dest
267 }
268
269 fn render-word screen: (addr screen), _self: (addr word), x: int, y: int, render-cursor?: boolean -> _/eax: int {
270 var self/esi: (addr word) <- copy _self
271 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
272 var data/eax: (addr gap-buffer) <- lookup *data-ah
273 var result/eax: int <- render-gap-buffer screen, data, x, y, render-cursor?
274 return result
275 }
276
277 fn render-words screen: (addr screen), _words-ah: (addr handle word), x: int, y: int, cursor-word-addr: int -> _/eax: int {
278 var words-ah/eax: (addr handle word) <- copy _words-ah
279 var _words-a/eax: (addr word) <- lookup *words-ah
280 var words-a/ecx: (addr word) <- copy _words-a
281 compare words-a, 0
282 {
283 break-if-!=
284 return x
285 }
286
287 var render-cursor?/edx: boolean <- copy 0/false
288 {
289 compare cursor-word-addr, words-a
290 break-if-!=
291 render-cursor? <- copy 1/true
292 }
293 var next-x/eax: int <- render-word screen, words-a, x, y, render-cursor?
294 var space/edx: grapheme <- copy 0x20/space
295 draw-grapheme screen, space, next-x, y, 3/fg=cyan, 0/bg
296 next-x <- increment
297
298 var next-ah/ecx: (addr handle word) <- get words-a, next
299 next-x <- render-words screen, next-ah, next-x, y, cursor-word-addr
300 return next-x
301 }
302
303 fn test-render-words {
304
305 var w-storage: (handle word)
306 var w-ah/esi: (addr handle word) <- address w-storage
307 allocate-word-with w-ah, "aaa"
308 append-word-at-end-with w-ah, "bbb"
309 append-word-at-end-with w-ah, "ccc"
310 append-word-at-end-with w-ah, "ddd"
311
312 var screen-on-stack: screen
313 var screen/edi: (addr screen) <- address screen-on-stack
314 initialize-screen screen, 0x20, 4
315
316 var _w/eax: (addr word) <- lookup *w-ah
317 var w/ecx: (addr word) <- copy _w
318 var cursor-word/eax: int <- copy w
319 var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
320 check-screen-row screen, 0/y, "aaa bbb ccc ddd ", "F - test-render-words/0"
321 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-render-words/0 cursor"
322
323 cursor-left w
324 var cursor-word/eax: int <- copy w
325 var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
326 check-screen-row screen, 0/y, "aaa bbb ccc ddd ", "F - test-render-words/0"
327 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-render-words/1 cursor"
328
329 cursor-left w
330 var cursor-word/eax: int <- copy w
331 var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
332 check-screen-row screen, 0/y, "aaa bbb ccc ddd ", "F - test-render-words/0"
333 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-render-words/2 cursor"
334
335 cursor-left w
336 var cursor-word/eax: int <- copy w
337 var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
338 check-screen-row screen, 0/y, "aaa bbb ccc ddd ", "F - test-render-words/0"
339 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "| ", "F - test-render-words/3 cursor"
340
341 cursor-left w
342 var cursor-word/eax: int <- copy w
343 var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
344 check-screen-row screen, 0/y, "aaa bbb ccc ddd ", "F - test-render-words/0"
345 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "| ", "F - test-render-words/4 cursor"
346
347 var w2-ah/eax: (addr handle word) <- get w, next
348 var _w/eax: (addr word) <- lookup *w2-ah
349 var w/ecx: (addr word) <- copy _w
350 var cursor-word/eax: int <- copy w
351 var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
352 check-screen-row screen, 0/y, "aaa bbb ccc ddd ", "F - test-render-words/0"
353 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-render-words/5 cursor"
354
355 cursor-left w
356 cursor-left w
357 var cursor-word/eax: int <- copy w
358 var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
359 check-screen-row screen, 0/y, "aaa bbb ccc ddd ", "F - test-render-words/0"
360 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-render-words/6 cursor"
361
362 var w2-ah/eax: (addr handle word) <- get w, next
363 var _w/eax: (addr word) <- lookup *w2-ah
364 var w/ecx: (addr word) <- copy _w
365 cursor-left w
366 var cursor-word/eax: int <- copy w
367 var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
368 check-screen-row screen, 0/y, "aaa bbb ccc ddd ", "F - test-render-words/0"
369 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-render-words/7 cursor"
370 }
371
372 fn render-words-in-reverse screen: (addr screen), _words-ah: (addr handle word), x: int, y: int, cursor-word-addr: int -> _/eax: int {
373 var words-ah/eax: (addr handle word) <- copy _words-ah
374 var _words-a/eax: (addr word) <- lookup *words-ah
375 var words-a/ecx: (addr word) <- copy _words-a
376 compare words-a, 0
377 {
378 break-if-!=
379 return x
380 }
381
382 var next-ah/eax: (addr handle word) <- get words-a, next
383 var next-x/eax: int <- render-words-in-reverse screen, next-ah, x, y, cursor-word-addr
384
385 var render-cursor?/edx: boolean <- copy 0/false
386 {
387 compare cursor-word-addr, words-a
388 break-if-!=
389 render-cursor? <- copy 1/true
390 }
391 next-x <- render-word screen, words-a, next-x, y, render-cursor?
392 var space/ecx: grapheme <- copy 0x20/space
393 draw-grapheme screen, space, next-x, y, 3/fg=cyan, 0/bg
394 next-x <- increment
395 return next-x
396 }
397
398 fn test-render-words-in-reverse {
399
400 var w-storage: (handle word)
401 var w-ah/esi: (addr handle word) <- address w-storage
402 allocate-word-with w-ah, "aaa"
403 append-word-at-end-with w-ah, "bbb"
404 append-word-at-end-with w-ah, "ccc"
405 append-word-at-end-with w-ah, "ddd"
406
407 var screen-on-stack: screen
408 var screen/edi: (addr screen) <- address screen-on-stack
409 initialize-screen screen, 0x20, 4
410
411 var _w/eax: (addr word) <- lookup *w-ah
412 var w/ecx: (addr word) <- copy _w
413 var cursor-word/eax: int <- copy w
414 var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
415 check-screen-row screen, 0/y, "ddd ccc bbb aaa ", "F - test-render-words-in-reverse/0"
416 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-render-words-in-reverse/0 cursor"
417
418 cursor-left w
419 var cursor-word/eax: int <- copy w
420 var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
421 check-screen-row screen, 0/y, "ddd ccc bbb aaa ", "F - test-render-words-in-reverse/1"
422 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-render-words-in-reverse/1 cursor"
423
424 cursor-left w
425 var cursor-word/eax: int <- copy w
426 var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
427 check-screen-row screen, 0/y, "ddd ccc bbb aaa ", "F - test-render-words-in-reverse/2"
428 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-render-words-in-reverse/2 cursor"
429
430 cursor-left w
431 var cursor-word/eax: int <- copy w
432 var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
433 check-screen-row screen, 0/y, "ddd ccc bbb aaa ", "F - test-render-words-in-reverse/3"
434 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-render-words-in-reverse/3 cursor"
435
436 cursor-left w
437 var cursor-word/eax: int <- copy w
438 var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
439 check-screen-row screen, 0/y, "ddd ccc bbb aaa ", "F - test-render-words-in-reverse/4"
440 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-render-words-in-reverse/4 cursor"
441
442 var w2-ah/eax: (addr handle word) <- get w, next
443 var _w/eax: (addr word) <- lookup *w2-ah
444 var w/ecx: (addr word) <- copy _w
445 var cursor-word/eax: int <- copy w
446 var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
447 check-screen-row screen, 0/y, "ddd ccc bbb aaa ", "F - test-render-words-in-reverse/5"
448 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-render-words-in-reverse/5 cursor"
449
450 cursor-left w
451 cursor-left w
452 var cursor-word/eax: int <- copy w
453 var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
454 check-screen-row screen, 0/y, "ddd ccc bbb aaa ", "F - test-render-words-in-reverse/6"
455 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-render-words-in-reverse/6 cursor"
456
457 var w2-ah/eax: (addr handle word) <- get w, next
458 var _w/eax: (addr word) <- lookup *w2-ah
459 var w/ecx: (addr word) <- copy _w
460 cursor-left w
461 var cursor-word/eax: int <- copy w
462 var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
463 check-screen-row screen, 0/y, "ddd ccc bbb aaa ", "F - test-render-words-in-reverse/7"
464 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-render-words-in-reverse/7 cursor"
465 }
466
467
468
469
470 fn copy-words _src-ah: (addr handle word), _dest-ah: (addr handle word) {
471 var src-ah/eax: (addr handle word) <- copy _src-ah
472 var src-a/eax: (addr word) <- lookup *src-ah
473 compare src-a, 0
474 break-if-=
475
476 var dest-ah/edi: (addr handle word) <- copy _dest-ah
477 copy-word src-a, dest-ah
478
479 var rest: (handle word)
480 var rest-ah/ecx: (addr handle word) <- address rest
481 var next-src-ah/esi: (addr handle word) <- get src-a, next
482 copy-words next-src-ah, rest-ah
483 chain-words dest-ah, rest-ah
484 }
485
486 fn copy-words-in-reverse _src-ah: (addr handle word), _dest-ah: (addr handle word) {
487 var src-ah/eax: (addr handle word) <- copy _src-ah
488 var _src-a/eax: (addr word) <- lookup *src-ah
489 var src-a/esi: (addr word) <- copy _src-a
490 compare src-a, 0
491 break-if-=
492
493 var next-src-ah/ecx: (addr handle word) <- get src-a, next
494 var dest-ah/edi: (addr handle word) <- copy _dest-ah
495 copy-words-in-reverse next-src-ah, dest-ah
496
497 copy-word-at-end src-a, dest-ah
498 }
499
500 fn copy-word-at-end src: (addr word), _dest-ah: (addr handle word) {
501 var dest-ah/edi: (addr handle word) <- copy _dest-ah
502
503 var dest-a/eax: (addr word) <- lookup *dest-ah
504 compare dest-a, 0
505 {
506 break-if-!=
507 copy-word src, dest-ah
508 return
509 }
510
511 var new: (handle word)
512 var new-ah/ecx: (addr handle word) <- address new
513 copy-word src, new-ah
514
515 var curr-ah/edi: (addr handle word) <- copy dest-ah
516 {
517 var curr-a/eax: (addr word) <- lookup *curr-ah
518 var next-ah/ecx: (addr handle word) <- get curr-a, next
519 var next-a/eax: (addr word) <- lookup *next-ah
520 compare next-a, 0
521 break-if-=
522 curr-ah <- copy next-ah
523 loop
524 }
525 chain-words curr-ah, new-ah
526 }
527
528 fn append-word-at-end-with _dest-ah: (addr handle word), s: (addr array byte) {
529 var dest-ah/edi: (addr handle word) <- copy _dest-ah
530
531 var dest-a/eax: (addr word) <- lookup *dest-ah
532 compare dest-a, 0
533 {
534 break-if-!=
535 allocate-word-with dest-ah, s
536 return
537 }
538
539 var curr-ah/edi: (addr handle word) <- copy dest-ah
540 {
541 var curr-a/eax: (addr word) <- lookup *curr-ah
542 var next-ah/ecx: (addr handle word) <- get curr-a, next
543 var next-a/eax: (addr word) <- lookup *next-ah
544 compare next-a, 0
545 break-if-=
546 curr-ah <- copy next-ah
547 loop
548 }
549 append-word-with *curr-ah, s
550 }
551
552 fn copy-word _src-a: (addr word), _dest-ah: (addr handle word) {
553 var dest-ah/eax: (addr handle word) <- copy _dest-ah
554 allocate dest-ah
555 var _dest-a/eax: (addr word) <- lookup *dest-ah
556 var dest-a/eax: (addr word) <- copy _dest-a
557 initialize-word dest-a
558 var dest/edi: (addr handle gap-buffer) <- get dest-a, scalar-data
559 var src-a/eax: (addr word) <- copy _src-a
560 var src/eax: (addr handle gap-buffer) <- get src-a, scalar-data
561 copy-gap-buffer src, dest
562 }
563
564
565 fn append-word _self-ah: (addr handle word) {
566 var saved-self-storage: (handle word)
567 var saved-self/eax: (addr handle word) <- address saved-self-storage
568 copy-object _self-ah, saved-self
569 var self-ah/esi: (addr handle word) <- copy _self-ah
570 var _self/eax: (addr word) <- lookup *self-ah
571 var self/ebx: (addr word) <- copy _self
572
573 var new: (handle word)
574 var new-ah/ecx: (addr handle word) <- address new
575 allocate new-ah
576 var new-addr/eax: (addr word) <- lookup new
577 initialize-word new-addr
578
579 var src/esi: (addr handle word) <- get self, next
580 var dest/edi: (addr handle word) <- get new-addr, next
581 copy-object src, dest
582
583 {
584 var next-addr/eax: (addr word) <- lookup *src
585 compare next-addr, 0
586 break-if-=
587 dest <- get next-addr, prev
588 copy-object new-ah, dest
589 }
590
591 dest <- get new-addr, prev
592 var saved-self-ah/eax: (addr handle word) <- address saved-self-storage
593 copy-object saved-self-ah, dest
594
595 dest <- get self, next
596 copy-object new-ah, dest
597 }
598
599 fn chain-words _self-ah: (addr handle word), _next: (addr handle word) {
600 var self-ah/esi: (addr handle word) <- copy _self-ah
601 var _self/eax: (addr word) <- lookup *self-ah
602 var self/ecx: (addr word) <- copy _self
603 var dest/edx: (addr handle word) <- get self, next
604 var next-ah/edi: (addr handle word) <- copy _next
605 copy-object next-ah, dest
606 var next/eax: (addr word) <- lookup *next-ah
607 compare next, 0
608 break-if-=
609 dest <- get next, prev
610 copy-object self-ah, dest
611 }
612
613 fn emit-word _self: (addr word), out: (addr stream byte) {
614 var self/esi: (addr word) <- copy _self
615 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
616 var data/eax: (addr gap-buffer) <- lookup *data-ah
617 emit-gap-buffer data, out
618 }
619
620 fn word-is-decimal-integer? _self: (addr word) -> _/eax: boolean {
621 var self/eax: (addr word) <- copy _self
622 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
623 var data/eax: (addr gap-buffer) <- lookup *data-ah
624 var result/eax: boolean <- gap-buffer-is-decimal-integer? data
625 return result
626 }
627
628 fn word-exists? haystack: (addr word), needle: (addr word) -> _/eax: boolean {
629
630 compare haystack, 0
631 {
632 break-if-!=
633 return 0/false
634 }
635
636 var found?/eax: boolean <- words-equal? haystack, needle
637 compare found?, 0/false
638 {
639 break-if-=
640 return 1/true
641 }
642
643 var curr/eax: (addr word) <- copy haystack
644 var next-ah/eax: (addr handle word) <- get curr, next
645 var next/eax: (addr word) <- lookup *next-ah
646 var result/eax: boolean <- word-exists? next, needle
647 return result
648 }
649
650 fn test-word-exists? {
651 var needle-storage: word
652 var needle/esi: (addr word) <- address needle-storage
653 initialize-word-with needle, "abc"
654 var w-storage: (handle word)
655 var w-ah/edi: (addr handle word) <- address w-storage
656 allocate w-ah
657 var _w/eax: (addr word) <- lookup *w-ah
658 var w/ecx: (addr word) <- copy _w
659 initialize-word-with w, "aaa"
660
661 var result/eax: boolean <- word-exists? w, w
662 check result, "F - test-word-exists? reflexive"
663 result <- word-exists? w, needle
664 check-not result, "F - test-word-exists? 1"
665 append-word-at-end-with w-ah, "bbb"
666 result <- word-exists? w, needle
667 check-not result, "F - test-word-exists? 2"
668 append-word-at-end-with w-ah, "abc"
669 result <- word-exists? w, needle
670 check result, "F - test-word-exists? 3"
671 append-word-at-end-with w-ah, "ddd"
672 result <- word-exists? w, needle
673 check result, "F - test-word-exists? 4"
674 }
675
676 fn word-list-length words: (addr handle word) -> _/eax: int {
677 var curr-ah/esi: (addr handle word) <- copy words
678 var result/edi: int <- copy 0
679 {
680 var curr/eax: (addr word) <- lookup *curr-ah
681 compare curr, 0
682 break-if-=
683 {
684 var word-len/eax: int <- word-length curr
685 result <- add word-len
686 result <- add 1/inter-word-margin
687 }
688 curr-ah <- get curr, next
689 loop
690 }
691 return result
692 }
693
694
695 fn parse-words in: (addr array byte), out-ah: (addr handle word) {
696 var in-stream: (stream byte 0x100)
697 var in-stream-a/esi: (addr stream byte) <- address in-stream
698 write in-stream-a, in
699 var cursor-word-ah/ebx: (addr handle word) <- copy out-ah
700 $parse-words:loop: {
701 var done?/eax: boolean <- stream-empty? in-stream-a
702 compare done?, 0/false
703 break-if-!=
704 var _g/eax: grapheme <- read-grapheme in-stream-a
705 var g/ecx: grapheme <- copy _g
706
707 compare g, 0x20/space
708 {
709 break-if-=
710 var cursor-word/eax: (addr word) <- lookup *cursor-word-ah
711 add-grapheme-to-word cursor-word, g
712 loop $parse-words:loop
713 }
714
715 append-word cursor-word-ah
716 var cursor-word/eax: (addr word) <- lookup *cursor-word-ah
717 cursor-to-start cursor-word
718 cursor-word-ah <- get cursor-word, next
719 loop
720 }
721 }