https://github.com/akkartik/mu/blob/main/linux/tile/word.mu
1 fn initialize-word _self: (addr word) {
2 var self/esi: (addr word) <- copy _self
3 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
4 allocate data-ah
5 var data/eax: (addr gap-buffer) <- lookup *data-ah
6 initialize-gap-buffer data
7 }
8
9
10
11 fn initialize-word-with _self: (addr word), s: (addr array byte) {
12 var self/esi: (addr word) <- copy _self
13 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
14 allocate data-ah
15 var data/eax: (addr gap-buffer) <- lookup *data-ah
16 initialize-gap-buffer-with data, s
17 }
18
19 fn allocate-word-with _out: (addr handle word), s: (addr array byte) {
20 var out/eax: (addr handle word) <- copy _out
21 allocate out
22 var out-addr/eax: (addr word) <- lookup *out
23 initialize-word-with out-addr, s
24 }
25
26
27
28
29 fn append-word-with self-h: (handle word), s: (addr array byte) {
30 var self/eax: (addr word) <- lookup self-h
31 var next-ah/eax: (addr handle word) <- get self, next
32 allocate-word-with next-ah, s
33 var next/eax: (addr word) <- lookup *next-ah
34 var prev-ah/eax: (addr handle word) <- get next, prev
35 copy-handle self-h, prev-ah
36 }
37
38
39
40 fn prepend-word-with self-h: (handle word), s: (addr array byte) {
41 var self/eax: (addr word) <- lookup self-h
42 var prev-ah/eax: (addr handle word) <- get self, prev
43 allocate-word-with prev-ah, s
44 var prev/eax: (addr word) <- lookup *prev-ah
45 var next-ah/eax: (addr handle word) <- get prev, next
46 copy-handle self-h, next-ah
47 }
48
49
50
51 fn move-word-contents _src-ah: (addr handle word), _dest-ah: (addr handle word) {
52 var dest-ah/eax: (addr handle word) <- copy _dest-ah
53 var _dest/eax: (addr word) <- lookup *dest-ah
54 var dest/edi: (addr word) <- copy _dest
55 var src-ah/eax: (addr handle word) <- copy _src-ah
56 var _src/eax: (addr word) <- lookup *src-ah
57 var src/esi: (addr word) <- copy _src
58 cursor-to-start src
59 var src-data-ah/eax: (addr handle gap-buffer) <- get src, scalar-data
60 var src-data/eax: (addr gap-buffer) <- lookup *src-data-ah
61 var src-stack/ecx: (addr grapheme-stack) <- get src-data, right
62 {
63 var done?/eax: boolean <- grapheme-stack-empty? src-stack
64 compare done?, 0/false
65 break-if-!=
66 var g/eax: grapheme <- pop-grapheme-stack src-stack
67
68
69 add-grapheme-to-word dest, g
70 loop
71 }
72 }
73
74 fn copy-word-contents-before-cursor _src-ah: (addr handle word), _dest-ah: (addr handle word) {
75 var dest-ah/eax: (addr handle word) <- copy _dest-ah
76 var _dest/eax: (addr word) <- lookup *dest-ah
77 var dest/edi: (addr word) <- copy _dest
78 var src-ah/eax: (addr handle word) <- copy _src-ah
79 var src/eax: (addr word) <- lookup *src-ah
80 var src-data-ah/eax: (addr handle gap-buffer) <- get src, scalar-data
81 var src-data/eax: (addr gap-buffer) <- lookup *src-data-ah
82 var src-stack/ecx: (addr grapheme-stack) <- get src-data, left
83 var src-stack-data-ah/eax: (addr handle array grapheme) <- get src-stack, data
84 var _src-stack-data/eax: (addr array grapheme) <- lookup *src-stack-data-ah
85 var src-stack-data/edx: (addr array grapheme) <- copy _src-stack-data
86 var top-addr/ecx: (addr int) <- get src-stack, top
87 var i/eax: int <- copy 0
88 {
89 compare i, *top-addr
90 break-if->=
91 var g/edx: (addr grapheme) <- index src-stack-data, i
92 add-grapheme-to-word dest, *g
93 i <- increment
94 loop
95 }
96 }
97
98 fn word-equal? _self: (addr word), s: (addr array byte) -> _/eax: boolean {
99 var self/esi: (addr word) <- copy _self
100 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
101 var data/eax: (addr gap-buffer) <- lookup *data-ah
102 var result/eax: boolean <- gap-buffer-equal? data, s
103 return result
104 }
105
106 fn word-length _self: (addr word) -> _/eax: int {
107 var self/esi: (addr word) <- copy _self
108 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
109 var data/eax: (addr gap-buffer) <- lookup *data-ah
110 var result/eax: int <- gap-buffer-length data
111 return result
112 }
113
114 fn final-word _in: (addr handle word), out: (addr handle word) {
115 var curr-h: (handle word)
116 var curr-ah/esi: (addr handle word) <- address curr-h
117 copy-object _in, curr-ah
118 var curr/eax: (addr word) <- copy 0
119 var next/edi: (addr handle word) <- copy 0
120 {
121 curr <- lookup *curr-ah
122 next <- get curr, next
123 curr <- lookup *next
124 compare curr, 0
125 break-if-=
126 copy-object next, curr-ah
127 loop
128 }
129 copy-object curr-ah, out
130 }
131
132 fn first-grapheme _self: (addr word) -> _/eax: grapheme {
133 var self/esi: (addr word) <- copy _self
134 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
135 var data/eax: (addr gap-buffer) <- lookup *data-ah
136 var result/eax: grapheme <- first-grapheme-in-gap-buffer data
137 return result
138 }
139
140 fn grapheme-before-cursor _self: (addr word) -> _/eax: grapheme {
141 var self/esi: (addr word) <- copy _self
142 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
143 var data/eax: (addr gap-buffer) <- lookup *data-ah
144 var result/eax: grapheme <- grapheme-before-cursor-in-gap-buffer data
145 return result
146 }
147
148 fn add-grapheme-to-word _self: (addr word), c: grapheme {
149 var self/esi: (addr word) <- copy _self
150 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
151 var data/eax: (addr gap-buffer) <- lookup *data-ah
152 add-grapheme-at-gap data, c
153 }
154
155 fn cursor-at-start? _self: (addr word) -> _/eax: boolean {
156 var self/esi: (addr word) <- copy _self
157 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
158 var data/eax: (addr gap-buffer) <- lookup *data-ah
159 var result/eax: boolean <- gap-at-start? data
160 return result
161 }
162
163 fn cursor-at-end? _self: (addr word) -> _/eax: boolean {
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: boolean <- gap-at-end? data
168 return result
169 }
170
171 fn cursor-left _self: (addr word) {
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 dummy/eax: grapheme <- gap-left data
176 }
177
178 fn cursor-right _self: (addr word) {
179 var self/esi: (addr word) <- copy _self
180 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
181 var data/eax: (addr gap-buffer) <- lookup *data-ah
182 var dummy/eax: grapheme <- gap-right data
183 }
184
185 fn cursor-to-start _self: (addr word) {
186 var self/esi: (addr word) <- copy _self
187 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
188 var data/eax: (addr gap-buffer) <- lookup *data-ah
189 gap-to-start data
190 }
191
192 fn cursor-to-end _self: (addr word) {
193 var self/esi: (addr word) <- copy _self
194 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
195 var data/eax: (addr gap-buffer) <- lookup *data-ah
196 gap-to-end data
197 }
198
199 fn cursor-index _self: (addr word) -> _/eax: int {
200 var self/esi: (addr word) <- copy _self
201 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
202 var data/eax: (addr gap-buffer) <- lookup *data-ah
203 var result/eax: int <- gap-index data
204 return result
205 }
206
207 fn delete-before-cursor _self: (addr word) {
208 var self/esi: (addr word) <- copy _self
209 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
210 var data/eax: (addr gap-buffer) <- lookup *data-ah
211 delete-before-gap data
212 }
213
214 fn pop-after-cursor _self: (addr word) -> _/eax: grapheme {
215 var self/esi: (addr word) <- copy _self
216 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
217 var data/eax: (addr gap-buffer) <- lookup *data-ah
218 var result/eax: grapheme <- pop-after-gap data
219 return result
220 }
221
222 fn delete-next _self: (addr word) {
223 var self/esi: (addr word) <- copy _self
224 var next-ah/edi: (addr handle word) <- get self, next
225 var next/eax: (addr word) <- lookup *next-ah
226 compare next, 0
227 break-if-=
228 var next-next-ah/ecx: (addr handle word) <- get next, next
229 var self-ah/esi: (addr handle word) <- get next, prev
230 copy-object next-next-ah, next-ah
231 var new-next/eax: (addr word) <- lookup *next-next-ah
232 compare new-next, 0
233 break-if-=
234 var dest/eax: (addr handle word) <- get new-next, prev
235 copy-object self-ah, dest
236 }
237
238 fn print-word screen: (addr screen), _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 render-gap-buffer screen, data
243 }
244
245 fn print-words-in-reverse screen: (addr screen), _words-ah: (addr handle word) {
246 var words-ah/eax: (addr handle word) <- copy _words-ah
247 var words-a/eax: (addr word) <- lookup *words-ah
248 compare words-a, 0
249 break-if-=
250
251 var next-ah/ecx: (addr handle word) <- get words-a, next
252 print-words-in-reverse screen, next-ah
253
254 print-word screen, words-a
255 print-string screen, " "
256 }
257
258
259
260
261 fn copy-words _src-ah: (addr handle word), _dest-ah: (addr handle word) {
262 var src-ah/eax: (addr handle word) <- copy _src-ah
263 var src-a/eax: (addr word) <- lookup *src-ah
264 compare src-a, 0
265 break-if-=
266
267 var dest-ah/edi: (addr handle word) <- copy _dest-ah
268 copy-word src-a, dest-ah
269
270 var rest: (handle word)
271 var rest-ah/ecx: (addr handle word) <- address rest
272 var next-src-ah/esi: (addr handle word) <- get src-a, next
273 copy-words next-src-ah, rest-ah
274 chain-words dest-ah, rest-ah
275 }
276
277 fn copy-words-in-reverse _src-ah: (addr handle word), _dest-ah: (addr handle word) {
278 var src-ah/eax: (addr handle word) <- copy _src-ah
279 var _src-a/eax: (addr word) <- lookup *src-ah
280 var src-a/esi: (addr word) <- copy _src-a
281 compare src-a, 0
282 break-if-=
283
284 var next-src-ah/ecx: (addr handle word) <- get src-a, next
285 var dest-ah/edi: (addr handle word) <- copy _dest-ah
286 copy-words-in-reverse next-src-ah, dest-ah
287
288 copy-word-at-end src-a, dest-ah
289 }
290
291 fn copy-word-at-end src: (addr word), _dest-ah: (addr handle word) {
292 var dest-ah/edi: (addr handle word) <- copy _dest-ah
293
294 var dest-a/eax: (addr word) <- lookup *dest-ah
295 compare dest-a, 0
296 {
297 break-if-!=
298 copy-word src, dest-ah
299 return
300 }
301
302 var new: (handle word)
303 var new-ah/ecx: (addr handle word) <- address new
304 copy-word src, new-ah
305
306 var curr-ah/edi: (addr handle word) <- copy dest-ah
307 {
308 var curr-a/eax: (addr word) <- lookup *curr-ah
309 var next-ah/ecx: (addr handle word) <- get curr-a, next
310 var next-a/eax: (addr word) <- lookup *next-ah
311 compare next-a, 0
312 break-if-=
313 curr-ah <- copy next-ah
314 loop
315 }
316 chain-words curr-ah, new-ah
317 }
318
319 fn append-word-at-end-with _dest-ah: (addr handle word), s: (addr array byte) {
320 var dest-ah/edi: (addr handle word) <- copy _dest-ah
321
322 var dest-a/eax: (addr word) <- lookup *dest-ah
323 compare dest-a, 0
324 {
325 break-if-!=
326 allocate-word-with dest-ah, s
327 return
328 }
329
330 var curr-ah/edi: (addr handle word) <- copy dest-ah
331 {
332 var curr-a/eax: (addr word) <- lookup *curr-ah
333 var next-ah/ecx: (addr handle word) <- get curr-a, next
334 var next-a/eax: (addr word) <- lookup *next-ah
335 compare next-a, 0
336 break-if-=
337 curr-ah <- copy next-ah
338 loop
339 }
340 append-word-with *curr-ah, s
341 }
342
343 fn copy-word _src-a: (addr word), _dest-ah: (addr handle word) {
344 var dest-ah/eax: (addr handle word) <- copy _dest-ah
345 allocate dest-ah
346 var _dest-a/eax: (addr word) <- lookup *dest-ah
347 var dest-a/eax: (addr word) <- copy _dest-a
348 initialize-word dest-a
349 var dest/edi: (addr handle gap-buffer) <- get dest-a, scalar-data
350 var src-a/eax: (addr word) <- copy _src-a
351 var src/eax: (addr handle gap-buffer) <- get src-a, scalar-data
352 copy-gap-buffer src, dest
353 }
354
355
356 fn append-word _self-ah: (addr handle word) {
357 var saved-self-storage: (handle word)
358 var saved-self/eax: (addr handle word) <- address saved-self-storage
359 copy-object _self-ah, saved-self
360
361
362
363
364
365
366 var self-ah/esi: (addr handle word) <- copy _self-ah
367 var _self/eax: (addr word) <- lookup *self-ah
368 var self/ebx: (addr word) <- copy _self
369
370
371
372
373
374
375
376
377
378 var new: (handle word)
379 var new-ah/ecx: (addr handle word) <- address new
380 allocate new-ah
381 var new-addr/eax: (addr word) <- lookup new
382 initialize-word new-addr
383
384
385
386
387
388
389
390 var src/esi: (addr handle word) <- get self, next
391
392
393
394
395
396
397 var dest/edi: (addr handle word) <- get new-addr, next
398 copy-object src, dest
399
400 {
401 var next-addr/eax: (addr word) <- lookup *src
402 compare next-addr, 0
403 break-if-=
404
405
406
407
408
409
410 dest <- get next-addr, prev
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429 copy-object new-ah, dest
430
431
432
433
434
435
436
437
438 }
439
440 dest <- get new-addr, prev
441
442
443
444
445
446
447
448
449
450
451
452 var saved-self-ah/eax: (addr handle word) <- address saved-self-storage
453 copy-object saved-self-ah, dest
454
455 dest <- get self, next
456 copy-object new-ah, dest
457 }
458
459 fn chain-words _self-ah: (addr handle word), _next: (addr handle word) {
460 var self-ah/esi: (addr handle word) <- copy _self-ah
461 var _self/eax: (addr word) <- lookup *self-ah
462 var self/ecx: (addr word) <- copy _self
463 var dest/edx: (addr handle word) <- get self, next
464 var next-ah/edi: (addr handle word) <- copy _next
465 copy-object next-ah, dest
466 var next/eax: (addr word) <- lookup *next-ah
467 compare next, 0
468 break-if-=
469 dest <- get next, prev
470 copy-object self-ah, dest
471 }
472
473 fn emit-word _self: (addr word), out: (addr stream byte) {
474 var self/esi: (addr word) <- copy _self
475 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
476 var data/eax: (addr gap-buffer) <- lookup *data-ah
477 emit-gap-buffer data, out
478 }
479
480 fn word-to-string _self: (addr word), out: (addr handle array byte) {
481 var self/esi: (addr word) <- copy _self
482 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
483 var data/eax: (addr gap-buffer) <- lookup *data-ah
484 gap-buffer-to-string data, out
485 }
486
487 fn word-is-decimal-integer? _self: (addr word) -> _/eax: boolean {
488 var self/eax: (addr word) <- copy _self
489 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
490 var data/eax: (addr gap-buffer) <- lookup *data-ah
491 var result/eax: boolean <- gap-buffer-is-decimal-integer? data
492 return result
493 }
494
495
496 fn word-exists? _haystack-ah: (addr handle word), _needle: (addr word) -> _/ebx: boolean {
497 var needle-name-storage: (handle array byte)
498 var needle-name-ah/eax: (addr handle array byte) <- address needle-name-storage
499 word-to-string _needle, needle-name-ah
500 var _needle-name/eax: (addr array byte) <- lookup *needle-name-ah
501 var needle-name/edi: (addr array byte) <- copy _needle-name
502
503 var haystack-ah/esi: (addr handle word) <- copy _haystack-ah
504 var curr/eax: (addr word) <- lookup *haystack-ah
505 compare curr, 0
506 {
507 break-if-!=
508 return 0/false
509 }
510
511 var curr-name-storage: (handle array byte)
512 var curr-name-ah/ecx: (addr handle array byte) <- address curr-name-storage
513 word-to-string curr, curr-name-ah
514 var curr-name/eax: (addr array byte) <- lookup *curr-name-ah
515 var found?/eax: boolean <- string-equal? needle-name, curr-name
516 compare found?, 0
517 {
518 break-if-=
519 return 1/true
520 }
521
522 var curr/eax: (addr word) <- lookup *haystack-ah
523 var next-haystack-ah/eax: (addr handle word) <- get curr, next
524 var result/ebx: boolean <- word-exists? next-haystack-ah, _needle
525 return result
526 }
527
528 fn word-list-length words: (addr handle word) -> _/eax: int {
529 var curr-ah/esi: (addr handle word) <- copy words
530 var result/edi: int <- copy 0
531 {
532 var curr/eax: (addr word) <- lookup *curr-ah
533 compare curr, 0
534 break-if-=
535 {
536 var word-len/eax: int <- word-length curr
537 result <- add word-len
538 result <- add 1/inter-word-margin
539 }
540 curr-ah <- get curr, next
541 loop
542 }
543 return result
544 }
545
546
547 fn parse-words in: (addr array byte), out-ah: (addr handle word) {
548 var in-stream: (stream byte 0x100)
549 var in-stream-a/esi: (addr stream byte) <- address in-stream
550 write in-stream-a, in
551 var cursor-word-ah/ebx: (addr handle word) <- copy out-ah
552 $parse-words:loop: {
553 var done?/eax: boolean <- stream-empty? in-stream-a
554 compare done?, 0/false
555 break-if-!=
556 var _g/eax: grapheme <- read-grapheme in-stream-a
557 var g/ecx: grapheme <- copy _g
558
559 compare g, 0x20/space
560 {
561 break-if-=
562 var cursor-word/eax: (addr word) <- lookup *cursor-word-ah
563 add-grapheme-to-word cursor-word, g
564 loop $parse-words:loop
565 }
566
567 append-word cursor-word-ah
568 var cursor-word/eax: (addr word) <- lookup *cursor-word-ah
569 cursor-to-start cursor-word
570 cursor-word-ah <- get cursor-word, next
571 loop
572 }
573 }