https://github.com/akkartik/mu/blob/master/apps/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
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 first-word _in: (addr handle word), out: (addr handle word) {
115 var curr-ah/esi: (addr handle word) <- copy _in
116 var curr/eax: (addr word) <- lookup *curr-ah
117 var prev/edi: (addr handle word) <- copy 0
118 {
119 prev <- get curr, prev
120 var curr/eax: (addr word) <- lookup *prev
121 compare curr, 0
122 break-if-=
123 copy-object prev, curr-ah
124 loop
125 }
126 copy-object curr-ah, out
127 }
128
129 fn final-word _in: (addr handle word), out: (addr handle word) {
130 var curr-h: (handle word)
131 var curr-ah/esi: (addr handle word) <- address curr-h
132 copy-object _in, curr-ah
133 var curr/eax: (addr word) <- copy 0
134 var next/edi: (addr handle word) <- copy 0
135 {
136 curr <- lookup *curr-ah
137 next <- get curr, next
138 curr <- lookup *next
139 compare curr, 0
140 break-if-=
141 copy-object next, curr-ah
142 loop
143 }
144 copy-object curr-ah, out
145 }
146
147 fn first-grapheme _self: (addr word) -> _/eax: grapheme {
148 var self/esi: (addr word) <- copy _self
149 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
150 var data/eax: (addr gap-buffer) <- lookup *data-ah
151 var result/eax: grapheme <- first-grapheme-in-gap-buffer data
152 return result
153 }
154
155 fn grapheme-before-cursor _self: (addr word) -> _/eax: grapheme {
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: grapheme <- grapheme-before-cursor-in-gap-buffer data
160 return result
161 }
162
163 fn add-grapheme-to-word _self: (addr word), c: 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 add-grapheme-at-gap data, c
168 }
169
170 fn cursor-at-start? _self: (addr word) -> _/eax: boolean {
171 var self/esi: (addr word) <- copy _self
172 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
173 var data/eax: (addr gap-buffer) <- lookup *data-ah
174 var result/eax: boolean <- gap-at-start? data
175 return result
176 }
177
178 fn cursor-at-end? _self: (addr word) -> _/eax: boolean {
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 result/eax: boolean <- gap-at-end? data
183 return result
184 }
185
186 fn cursor-left _self: (addr word) {
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 dummy/eax: grapheme <- gap-left data
191 }
192
193 fn cursor-right _self: (addr word) {
194 var self/esi: (addr word) <- copy _self
195 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
196 var data/eax: (addr gap-buffer) <- lookup *data-ah
197 var dummy/eax: grapheme <- gap-right data
198 }
199
200 fn cursor-to-start _self: (addr word) {
201 var self/esi: (addr word) <- copy _self
202 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
203 var data/eax: (addr gap-buffer) <- lookup *data-ah
204 gap-to-start data
205 }
206
207 fn cursor-to-end _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 gap-to-end data
212 }
213
214 fn cursor-index _self: (addr word) -> _/eax: int {
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: int <- gap-index data
219 return result
220 }
221
222 fn delete-before-cursor _self: (addr word) {
223 var self/esi: (addr word) <- copy _self
224 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
225 var data/eax: (addr gap-buffer) <- lookup *data-ah
226 delete-before-gap data
227 }
228
229 fn pop-after-cursor _self: (addr word) -> _/eax: grapheme {
230 var self/esi: (addr word) <- copy _self
231 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
232 var data/eax: (addr gap-buffer) <- lookup *data-ah
233 var result/eax: grapheme <- pop-after-gap data
234 return result
235 }
236
237 fn delete-next _self: (addr word) {
238 var self/esi: (addr word) <- copy _self
239 var next-ah/edi: (addr handle word) <- get self, next
240 var next/eax: (addr word) <- lookup *next-ah
241 compare next, 0
242 break-if-=
243 var next-next-ah/ecx: (addr handle word) <- get next, next
244 var self-ah/esi: (addr handle word) <- get next, prev
245 copy-object next-next-ah, next-ah
246 var new-next/eax: (addr word) <- lookup *next-next-ah
247 compare new-next, 0
248 break-if-=
249 var dest/eax: (addr handle word) <- get new-next, prev
250 copy-object self-ah, dest
251 }
252
253 fn print-word screen: (addr screen), _self: (addr word) {
254 var self/esi: (addr word) <- copy _self
255 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
256 var data/eax: (addr gap-buffer) <- lookup *data-ah
257 render-gap-buffer screen, data
258 }
259
260 fn print-words screen: (addr screen), _words-ah: (addr handle word) {
261 var words-ah/eax: (addr handle word) <- copy _words-ah
262 var words-a/eax: (addr word) <- lookup *words-ah
263 compare words-a, 0
264 break-if-=
265
266 print-word screen, words-a
267 print-string screen, " "
268
269 var next-ah/eax: (addr handle word) <- get words-a, next
270 print-words screen, next-ah
271 }
272
273 fn print-words-in-reverse screen: (addr screen), _words-ah: (addr handle word) {
274 var words-ah/eax: (addr handle word) <- copy _words-ah
275 var words-a/eax: (addr word) <- lookup *words-ah
276 compare words-a, 0
277 break-if-=
278
279 var next-ah/ecx: (addr handle word) <- get words-a, next
280 print-words-in-reverse screen, next-ah
281
282 print-word screen, words-a
283 print-string screen, " "
284 }
285
286
287
288
289 fn copy-words _src-ah: (addr handle word), _dest-ah: (addr handle word) {
290 var src-ah/eax: (addr handle word) <- copy _src-ah
291 var src-a/eax: (addr word) <- lookup *src-ah
292 compare src-a, 0
293 break-if-=
294
295 var dest-ah/edi: (addr handle word) <- copy _dest-ah
296 copy-word src-a, dest-ah
297
298 var rest: (handle word)
299 var rest-ah/ecx: (addr handle word) <- address rest
300 var next-src-ah/esi: (addr handle word) <- get src-a, next
301 copy-words next-src-ah, rest-ah
302 chain-words dest-ah, rest-ah
303 }
304
305 fn copy-words-in-reverse _src-ah: (addr handle word), _dest-ah: (addr handle word) {
306 var src-ah/eax: (addr handle word) <- copy _src-ah
307 var _src-a/eax: (addr word) <- lookup *src-ah
308 var src-a/esi: (addr word) <- copy _src-a
309 compare src-a, 0
310 break-if-=
311
312 var next-src-ah/ecx: (addr handle word) <- get src-a, next
313 var dest-ah/edi: (addr handle word) <- copy _dest-ah
314 copy-words-in-reverse next-src-ah, dest-ah
315
316 copy-word-at-end src-a, dest-ah
317 }
318
319 fn copy-word-at-end src: (addr word), _dest-ah: (addr handle word) {
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 copy-word src, dest-ah
327 return
328 }
329
330 var new: (handle word)
331 var new-ah/ecx: (addr handle word) <- address new
332 copy-word src, new-ah
333
334 var curr-ah/edi: (addr handle word) <- copy dest-ah
335 {
336 var curr-a/eax: (addr word) <- lookup *curr-ah
337 var next-ah/ecx: (addr handle word) <- get curr-a, next
338 var next-a/eax: (addr word) <- lookup *next-ah
339 compare next-a, 0
340 break-if-=
341 curr-ah <- copy next-ah
342 loop
343 }
344 chain-words curr-ah, new-ah
345 }
346
347 fn append-word-at-end-with _dest-ah: (addr handle word), s: (addr array byte) {
348 var dest-ah/edi: (addr handle word) <- copy _dest-ah
349
350 var dest-a/eax: (addr word) <- lookup *dest-ah
351 compare dest-a, 0
352 {
353 break-if-!=
354 allocate-word-with dest-ah, s
355 return
356 }
357
358 var curr-ah/edi: (addr handle word) <- copy dest-ah
359 {
360 var curr-a/eax: (addr word) <- lookup *curr-ah
361 var next-ah/ecx: (addr handle word) <- get curr-a, next
362 var next-a/eax: (addr word) <- lookup *next-ah
363 compare next-a, 0
364 break-if-=
365 curr-ah <- copy next-ah
366 loop
367 }
368 append-word-with *curr-ah, s
369 }
370
371 fn copy-word _src-a: (addr word), _dest-ah: (addr handle word) {
372 var dest-ah/eax: (addr handle word) <- copy _dest-ah
373 allocate dest-ah
374 var _dest-a/eax: (addr word) <- lookup *dest-ah
375 var dest-a/eax: (addr word) <- copy _dest-a
376 initialize-word dest-a
377 var dest/edi: (addr handle gap-buffer) <- get dest-a, scalar-data
378 var src-a/eax: (addr word) <- copy _src-a
379 var src/eax: (addr handle gap-buffer) <- get src-a, scalar-data
380 copy-gap-buffer src, dest
381 }
382
383
384 fn append-word _self-ah: (addr handle word) {
385 var saved-self-storage: (handle word)
386 var saved-self/eax: (addr handle word) <- address saved-self-storage
387 copy-object _self-ah, saved-self
388
389
390
391
392
393
394 var self-ah/esi: (addr handle word) <- copy _self-ah
395 var _self/eax: (addr word) <- lookup *self-ah
396 var self/ebx: (addr word) <- copy _self
397
398
399
400
401
402
403
404
405
406 var new: (handle word)
407 var new-ah/ecx: (addr handle word) <- address new
408 allocate new-ah
409 var new-addr/eax: (addr word) <- lookup new
410 initialize-word new-addr
411
412
413
414
415
416
417
418 var src/esi: (addr handle word) <- get self, next
419
420
421
422
423
424
425 var dest/edi: (addr handle word) <- get new-addr, next
426 copy-object src, dest
427
428 {
429 var next-addr/eax: (addr word) <- lookup *src
430 compare next-addr, 0
431 break-if-=
432
433
434
435
436
437
438 dest <- get next-addr, prev
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457 copy-object new-ah, dest
458
459
460
461
462
463
464
465
466 }
467
468 dest <- get new-addr, prev
469
470
471
472
473
474
475
476
477
478
479
480 var saved-self-ah/eax: (addr handle word) <- address saved-self-storage
481 copy-object saved-self-ah, dest
482
483 dest <- get self, next
484 copy-object new-ah, dest
485 }
486
487 fn chain-words _self-ah: (addr handle word), _next: (addr handle word) {
488 var self-ah/esi: (addr handle word) <- copy _self-ah
489 var _self/eax: (addr word) <- lookup *self-ah
490 var self/ecx: (addr word) <- copy _self
491 var dest/edx: (addr handle word) <- get self, next
492 var next-ah/edi: (addr handle word) <- copy _next
493 copy-object next-ah, dest
494 var next/eax: (addr word) <- lookup *next-ah
495 compare next, 0
496 break-if-=
497 dest <- get next, prev
498 copy-object self-ah, dest
499 }
500
501 fn emit-word _self: (addr word), out: (addr stream byte) {
502 var self/esi: (addr word) <- copy _self
503 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
504 var data/eax: (addr gap-buffer) <- lookup *data-ah
505 emit-gap-buffer data, out
506 }
507
508 fn word-to-string _self: (addr word), out: (addr handle array byte) {
509 var self/esi: (addr word) <- copy _self
510 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
511 var data/eax: (addr gap-buffer) <- lookup *data-ah
512 gap-buffer-to-string data, out
513 }
514
515 fn word-is-decimal-integer? _self: (addr word) -> _/eax: boolean {
516 var self/eax: (addr word) <- copy _self
517 var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
518 var data/eax: (addr gap-buffer) <- lookup *data-ah
519 var result/eax: boolean <- gap-buffer-is-decimal-integer? data
520 return result
521 }
522
523
524 fn word-exists? _haystack-ah: (addr handle word), _needle: (addr word) -> _/ebx: boolean {
525 var needle-name-storage: (handle array byte)
526 var needle-name-ah/eax: (addr handle array byte) <- address needle-name-storage
527 word-to-string _needle, needle-name-ah
528 var _needle-name/eax: (addr array byte) <- lookup *needle-name-ah
529 var needle-name/edi: (addr array byte) <- copy _needle-name
530
531 var haystack-ah/esi: (addr handle word) <- copy _haystack-ah
532 var curr/eax: (addr word) <- lookup *haystack-ah
533 compare curr, 0
534 {
535 break-if-!=
536 return 0
537 }
538
539 var curr-name-storage: (handle array byte)
540 var curr-name-ah/ecx: (addr handle array byte) <- address curr-name-storage
541 word-to-string curr, curr-name-ah
542 var curr-name/eax: (addr array byte) <- lookup *curr-name-ah
543 var found?/eax: boolean <- string-equal? needle-name, curr-name
544 compare found?, 0
545 {
546 break-if-=
547 return 1
548 }
549
550 var curr/eax: (addr word) <- lookup *haystack-ah
551 var next-haystack-ah/eax: (addr handle word) <- get curr, next
552 var result/ebx: boolean <- word-exists? next-haystack-ah, _needle
553 return result
554 }
555
556 fn word-list-length words: (addr handle word) -> _/eax: int {
557 var curr-ah/esi: (addr handle word) <- copy words
558 var result/edi: int <- copy 0
559 {
560 var curr/eax: (addr word) <- lookup *curr-ah
561 compare curr, 0
562 break-if-=
563 {
564 var word-len/eax: int <- word-length curr
565 result <- add word-len
566 result <- add 1
567 }
568 curr-ah <- get curr, next
569 loop
570 }
571 return result
572 }
573
574
575 fn parse-words in: (addr array byte), out-ah: (addr handle word) {
576 var in-stream: (stream byte 0x100)
577 var in-stream-a/esi: (addr stream byte) <- address in-stream
578 write in-stream-a, in
579 var cursor-word-ah/ebx: (addr handle word) <- copy out-ah
580 $parse-words:loop: {
581 var done?/eax: boolean <- stream-empty? in-stream-a
582 compare done?, 0
583 break-if-!=
584 var _g/eax: grapheme <- read-grapheme in-stream-a
585 var g/ecx: grapheme <- copy _g
586
587 compare g, 0x20
588 {
589 break-if-=
590 var cursor-word/eax: (addr word) <- lookup *cursor-word-ah
591 add-grapheme-to-word cursor-word, g
592 loop $parse-words:loop
593 }
594
595 append-word cursor-word-ah
596 var cursor-word/eax: (addr word) <- lookup *cursor-word-ah
597 cursor-word-ah <- get cursor-word, next
598 loop
599 }
600 }