https://github.com/akkartik/mu/blob/master/apps/tile/environment.mu
1 type environment {
2 screen: (handle screen)
3 functions: (handle function)
4 sandboxes: (handle sandbox)
5 nrows: int
6 ncols: int
7 code-separator-col: int
8 }
9
10 fn initialize-environment _env: (addr environment) {
11 var env/esi: (addr environment) <- copy _env
12
13 var functions/eax: (addr handle function) <- get env, functions
14 create-primitive-functions functions
15
16 var sandbox-ah/eax: (addr handle sandbox) <- get env, sandboxes
17 allocate sandbox-ah
18 var sandbox/eax: (addr sandbox) <- lookup *sandbox-ah
19 initialize-sandbox sandbox
20
21 var screen-ah/eax: (addr handle screen) <- get env, screen
22 var _screen/eax: (addr screen) <- lookup *screen-ah
23 var screen/edi: (addr screen) <- copy _screen
24 var nrows/eax: int <- copy 0
25 var ncols/ecx: int <- copy 0
26 nrows, ncols <- screen-size screen
27 var dest/edx: (addr int) <- get env, nrows
28 copy-to *dest, nrows
29 dest <- get env, ncols
30 copy-to *dest, ncols
31 var repl-col/ecx: int <- copy ncols
32 repl-col <- shift-right 1
33 dest <- get env, code-separator-col
34 copy-to *dest, repl-col
35 }
36
37 fn draw-screen _env: (addr environment) {
38 var env/esi: (addr environment) <- copy _env
39 var screen-ah/eax: (addr handle screen) <- get env, screen
40 var _screen/eax: (addr screen) <- lookup *screen-ah
41 var screen/edi: (addr screen) <- copy _screen
42 var dest/edx: (addr int) <- get env, code-separator-col
43 var tmp/eax: int <- copy *dest
44 clear-canvas env
45 tmp <- add 2
46 move-cursor screen, 3, tmp
47 }
48
49 fn initialize-environment-with-fake-screen _self: (addr environment), nrows: int, ncols: int {
50 var self/esi: (addr environment) <- copy _self
51 var screen-ah/eax: (addr handle screen) <- get self, screen
52 allocate screen-ah
53 var screen-addr/eax: (addr screen) <- lookup *screen-ah
54 initialize-screen screen-addr, nrows, ncols
55 initialize-environment self
56 }
57
58
59
60
61
62 fn process _self: (addr environment), key: grapheme {
63 $process:body: {
64 var self/esi: (addr environment) <- copy _self
65 var sandbox-ah/eax: (addr handle sandbox) <- get self, sandboxes
66 var _sandbox/eax: (addr sandbox) <- lookup *sandbox-ah
67 var sandbox/edi: (addr sandbox) <- copy _sandbox
68 var rename-word-mode-ah?/ecx: (addr handle word) <- get sandbox, partial-name-for-cursor-word
69 var rename-word-mode?/eax: (addr word) <- lookup *rename-word-mode-ah?
70 compare rename-word-mode?, 0
71 {
72 break-if-=
73
74 process-sandbox-rename sandbox, key
75 break $process:body
76 }
77 var define-function-mode-ah?/ecx: (addr handle word) <- get sandbox, partial-name-for-function
78 var define-function-mode?/eax: (addr word) <- lookup *define-function-mode-ah?
79 compare define-function-mode?, 0
80 {
81 break-if-=
82
83 var functions/ecx: (addr handle function) <- get self, functions
84 process-sandbox-define sandbox, functions, key
85 break $process:body
86 }
87
88 process-sandbox self, sandbox, key
89 }
90 }
91
92 fn process-sandbox _self: (addr environment), _sandbox: (addr sandbox), key: grapheme {
93 $process-sandbox:body: {
94 var self/esi: (addr environment) <- copy _self
95 var sandbox/edi: (addr sandbox) <- copy _sandbox
96 var cursor-call-path-ah/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
97 var cursor-call-path/eax: (addr call-path-element) <- lookup *cursor-call-path-ah
98 var cursor-word-ah/ebx: (addr handle word) <- get cursor-call-path, word
99 var _cursor-word/eax: (addr word) <- lookup *cursor-word-ah
100 var cursor-word/ecx: (addr word) <- copy _cursor-word
101 compare key, 0x445b1b
102 $process-sandbox:key-left-arrow: {
103 break-if-!=
104
105
106 var at-start?/eax: boolean <- cursor-at-start? cursor-word
107 compare at-start?, 0
108 {
109 break-if-!=
110
111 cursor-left cursor-word
112 break $process-sandbox:body
113 }
114
115 {
116 var cursor-call-path/esi: (addr handle call-path-element) <- get sandbox, cursor-call-path
117 var expanded-words/edx: (addr handle call-path) <- get sandbox, expanded-words
118 var curr-word-is-expanded?/eax: boolean <- find-in-call-paths expanded-words, cursor-call-path
119 compare curr-word-is-expanded?, 0
120 break-if-=
121
122
123 var self/ecx: (addr environment) <- copy _self
124 var functions/ecx: (addr handle function) <- get self, functions
125 var body: (handle line)
126 var body-ah/eax: (addr handle line) <- address body
127 function-body functions, cursor-word-ah, body-ah
128 var body-addr/eax: (addr line) <- lookup *body-ah
129 var first-word-ah/edx: (addr handle word) <- get body-addr, data
130 var final-word-h: (handle word)
131 var final-word-ah/eax: (addr handle word) <- address final-word-h
132 final-word first-word-ah, final-word-ah
133 push-to-call-path-element cursor-call-path, final-word-ah
134
135 var cursor-call-path-ah/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
136 var cursor-call-path/eax: (addr call-path-element) <- lookup *cursor-call-path-ah
137 var cursor-word-ah/eax: (addr handle word) <- get cursor-call-path, word
138 var cursor-word/eax: (addr word) <- lookup *cursor-word-ah
139 cursor-to-end cursor-word
140 break $process-sandbox:body
141 }
142
143 $process-sandbox:key-left-arrow-first-word: {
144 var prev-word-ah/edx: (addr handle word) <- get cursor-word, prev
145 var prev-word/eax: (addr word) <- lookup *prev-word-ah
146 compare prev-word, 0
147 break-if-!=
148 $process-sandbox:key-left-arrow-first-word-and-caller: {
149
150 {
151 var cursor-call-path-ah/edi: (addr handle call-path-element) <- get sandbox, cursor-call-path
152 var cursor-call-path/eax: (addr call-path-element) <- lookup *cursor-call-path-ah
153 var next-cursor-element-ah/edx: (addr handle call-path-element) <- get cursor-call-path, next
154 var next-cursor-element/eax: (addr call-path-element) <- lookup *next-cursor-element-ah
155 compare next-cursor-element, 0
156 break-if-= $process-sandbox:key-left-arrow-first-word-and-caller
157 copy-object next-cursor-element-ah, cursor-call-path-ah
158 }
159 var cursor-call-path-ah/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
160 var cursor-call-path/eax: (addr call-path-element) <- lookup *cursor-call-path-ah
161 var cursor-word-ah/eax: (addr handle word) <- get cursor-call-path, word
162 var _cursor-word/eax: (addr word) <- lookup *cursor-word-ah
163 cursor-word <- copy _cursor-word
164 }
165 }
166
167 var prev-word-ah/edx: (addr handle word) <- get cursor-word, prev
168 var prev-word/eax: (addr word) <- lookup *prev-word-ah
169 {
170 compare prev-word, 0
171 break-if-=
172
173 cursor-to-end prev-word
174
175
176
177
178
179
180
181
182
183
184 var cursor-call-path/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
185 decrement-final-element cursor-call-path
186
187
188
189
190
191
192
193
194
195
196 }
197 break $process-sandbox:body
198 }
199 compare key, 0x435b1b
200 $process-sandbox:key-right-arrow: {
201 break-if-!=
202
203 var at-end?/eax: boolean <- cursor-at-end? cursor-word
204 compare at-end?, 0
205 {
206 break-if-!=
207
208 cursor-right cursor-word
209 break $process-sandbox:body
210 }
211
212 {
213 var next-word-ah/edx: (addr handle word) <- get cursor-word, next
214 var next-word/eax: (addr word) <- lookup *next-word-ah
215 compare next-word, 0
216 break-if-!=
217 var cursor-call-path-ah/edi: (addr handle call-path-element) <- get sandbox, cursor-call-path
218 var cursor-call-path/eax: (addr call-path-element) <- lookup *cursor-call-path-ah
219 var next-cursor-element-ah/ecx: (addr handle call-path-element) <- get cursor-call-path, next
220 var next-cursor-element/eax: (addr call-path-element) <- lookup *next-cursor-element-ah
221 compare next-cursor-element, 0
222 break-if-=
223 copy-object next-cursor-element-ah, cursor-call-path-ah
224 break $process-sandbox:body
225 }
226
227 var next-word-ah/edx: (addr handle word) <- get cursor-word, next
228 var next-word/eax: (addr word) <- lookup *next-word-ah
229 {
230 compare next-word, 0
231 break-if-=
232
233 cursor-to-start next-word
234
235 var cursor-call-path/ecx: (addr handle call-path-element) <- get sandbox, cursor-call-path
236 increment-final-element cursor-call-path
237
238
239 $process-sandbox:key-right-arrow-next-word-is-call-expanded: {
240
241 {
242 var expanded-words/eax: (addr handle call-path) <- get sandbox, expanded-words
243 var curr-word-is-expanded?/eax: boolean <- find-in-call-paths expanded-words, cursor-call-path
244 compare curr-word-is-expanded?, 0
245 break-if-= $process-sandbox:key-right-arrow-next-word-is-call-expanded
246 }
247 var callee-h: (handle function)
248 var callee-ah/edx: (addr handle function) <- address callee-h
249 var functions/ebx: (addr handle function) <- get self, functions
250 callee functions, next-word, callee-ah
251 var callee/eax: (addr function) <- lookup *callee-ah
252 var callee-body-ah/eax: (addr handle line) <- get callee, body
253 var callee-body/eax: (addr line) <- lookup *callee-body-ah
254 var callee-body-first-word/edx: (addr handle word) <- get callee-body, data
255 push-to-call-path-element cursor-call-path, callee-body-first-word
256
257 var cursor-call-path-ah/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
258 var cursor-call-path/eax: (addr call-path-element) <- lookup *cursor-call-path-ah
259 var cursor-word-ah/eax: (addr handle word) <- get cursor-call-path, word
260 var cursor-word/eax: (addr word) <- lookup *cursor-word-ah
261 cursor-to-start cursor-word
262
263 break $process-sandbox:body
264 }
265 }
266 break $process-sandbox:body
267 }
268 compare key, 0xa
269 {
270 break-if-!=
271
272 toggle-cursor-word sandbox
273 break $process-sandbox:body
274 }
275
276 compare key, 2
277 $process-sandbox:prev-word: {
278 break-if-!=
279
280 var prev-word-ah/edx: (addr handle word) <- get cursor-word, prev
281 var prev-word/eax: (addr word) <- lookup *prev-word-ah
282 {
283 compare prev-word, 0
284 break-if-=
285 cursor-to-end prev-word
286 var cursor-call-path/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
287 decrement-final-element cursor-call-path
288 break $process-sandbox:body
289 }
290
291 {
292 var cursor-call-path-ah/edi: (addr handle call-path-element) <- get sandbox, cursor-call-path
293 var cursor-call-path/eax: (addr call-path-element) <- lookup *cursor-call-path-ah
294 var caller-cursor-element-ah/ecx: (addr handle call-path-element) <- get cursor-call-path, next
295 var caller-cursor-element/eax: (addr call-path-element) <- lookup *caller-cursor-element-ah
296 compare caller-cursor-element, 0
297 break-if-=
298
299 var caller-word-ah/eax: (addr handle word) <- get caller-cursor-element, word
300 var caller-word/eax: (addr word) <- lookup *caller-word-ah
301 var word-before-caller-ah/eax: (addr handle word) <- get caller-word, prev
302 var word-before-caller/eax: (addr word) <- lookup *word-before-caller-ah
303 compare word-before-caller, 0
304 break-if-=
305
306 drop-from-call-path-element cursor-call-path-ah
307 decrement-final-element cursor-call-path-ah
308 break $process-sandbox:body
309 }
310 }
311 compare key, 6
312 $process-sandbox:next-word: {
313 break-if-!=
314
315
316 var next-word-ah/edx: (addr handle word) <- get cursor-word, next
317 var next-word/eax: (addr word) <- lookup *next-word-ah
318 {
319 compare next-word, 0
320 break-if-=
321
322 cursor-to-end next-word
323 var cursor-call-path/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
324 increment-final-element cursor-call-path
325 break $process-sandbox:body
326 }
327
328
329 var cursor-call-path-ah/edi: (addr handle call-path-element) <- get sandbox, cursor-call-path
330 var cursor-call-path/eax: (addr call-path-element) <- lookup *cursor-call-path-ah
331 var caller-cursor-element-ah/ecx: (addr handle call-path-element) <- get cursor-call-path, next
332 var caller-cursor-element/eax: (addr call-path-element) <- lookup *caller-cursor-element-ah
333 compare caller-cursor-element, 0
334 break-if-=
335
336 copy-object caller-cursor-element-ah, cursor-call-path-ah
337 break $process-sandbox:body
338 }
339
340 compare key, 1
341 $process-sandbox:start-of-line: {
342 break-if-!=
343
344 var cursor-call-path-ah/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
345 drop-nested-calls cursor-call-path-ah
346 move-final-element-to-start-of-line cursor-call-path-ah
347
348 var cursor-call-path/eax: (addr call-path-element) <- lookup *cursor-call-path-ah
349 var cursor-word-ah/eax: (addr handle word) <- get cursor-call-path, word
350 var cursor-word/eax: (addr word) <- lookup *cursor-word-ah
351 cursor-to-start cursor-word
352
353
354 break $process-sandbox:body
355 }
356 compare key, 5
357 $process-sandbox:end-of-line: {
358 break-if-!=
359
360 var cursor-call-path-ah/ecx: (addr handle call-path-element) <- get sandbox, cursor-call-path
361 initialize-path-from-sandbox sandbox, cursor-call-path-ah
362 var cursor-call-path/eax: (addr call-path-element) <- lookup *cursor-call-path-ah
363 var dest/eax: (addr handle word) <- get cursor-call-path, word
364 final-word dest, dest
365
366 var cursor-word/eax: (addr word) <- lookup *cursor-word-ah
367 cursor-to-end cursor-word
368
369
370 break $process-sandbox:body
371 }
372 compare key, 0x15
373 $process-sandbox:clear-line: {
374 break-if-!=
375
376 initialize-sandbox sandbox
377 break $process-sandbox:body
378 }
379
380 var cursor-call-path-ah/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
381 var cursor-call-path/eax: (addr call-path-element) <- lookup *cursor-call-path-ah
382 var next-cursor-element-ah/eax: (addr handle call-path-element) <- get cursor-call-path, next
383 var next-cursor-element/eax: (addr call-path-element) <- lookup *next-cursor-element-ah
384 compare next-cursor-element, 0
385 break-if-!= $process-sandbox:body
386
387 compare key, 0x7f
388 $process-sandbox:backspace: {
389 break-if-!=
390
391 var at-start?/eax: boolean <- cursor-at-start? cursor-word
392 compare at-start?, 0
393 {
394 break-if-!=
395 delete-before-cursor cursor-word
396 break $process-sandbox:body
397 }
398
399 var prev-word-ah/eax: (addr handle word) <- get cursor-word, prev
400 var prev-word/eax: (addr word) <- lookup *prev-word-ah
401 {
402 compare prev-word, 0
403 break-if-=
404 cursor-to-end prev-word
405 delete-next prev-word
406 var cursor-call-path/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
407 decrement-final-element cursor-call-path
408 }
409 break $process-sandbox:body
410 }
411 compare key, 0x20
412 $process-sandbox:space: {
413 break-if-!=
414
415
416 {
417 var at-start?/eax: boolean <- cursor-at-start? cursor-word
418 compare at-start?, 0
419 break-if-=
420 var prev-word-ah/eax: (addr handle word) <- get cursor-word, prev
421 append-word prev-word-ah
422 var cursor-call-path/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
423 decrement-final-element cursor-call-path
424 break $process-sandbox:body
425 }
426
427
428 {
429 var first-grapheme/eax: grapheme <- first-grapheme cursor-word
430 compare first-grapheme, 0x22
431 break-if-!=
432 var final-grapheme/eax: grapheme <- grapheme-before-cursor cursor-word
433 compare final-grapheme, 0x22
434 break-if-=
435 break $process-sandbox:space
436 }
437
438
439 {
440 var first-grapheme/eax: grapheme <- first-grapheme cursor-word
441 compare first-grapheme, 0x5b
442 break-if-!=
443 var final-grapheme/eax: grapheme <- grapheme-before-cursor cursor-word
444 compare final-grapheme, 0x5d
445 break-if-=
446 break $process-sandbox:space
447 }
448
449
450 append-word cursor-word-ah
451 var cursor-call-path/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
452 increment-final-element cursor-call-path
453
454 var at-end?/eax: boolean <- cursor-at-end? cursor-word
455 compare at-end?, 0
456 break-if-!= $process-sandbox:body
457
458
459 var next-word-ah/eax: (addr handle word) <- get cursor-word, next
460 var _next-word/eax: (addr word) <- lookup *next-word-ah
461 var next-word/ebx: (addr word) <- copy _next-word
462 {
463 var at-end?/eax: boolean <- cursor-at-end? cursor-word
464 compare at-end?, 0
465 break-if-!=
466 var g/eax: grapheme <- pop-after-cursor cursor-word
467 add-grapheme-to-word next-word, g
468 loop
469 }
470 cursor-to-start next-word
471 break $process-sandbox:body
472 }
473 compare key, 0xe
474 $process:rename-word: {
475 break-if-!=
476
477
478 var new-name-ah/eax: (addr handle word) <- get sandbox, partial-name-for-cursor-word
479 allocate new-name-ah
480 var new-name/eax: (addr word) <- lookup *new-name-ah
481 initialize-word new-name
482 break $process-sandbox:body
483 }
484 compare key, 4
485 $process:define-function: {
486 break-if-!=
487
488 var new-name-ah/eax: (addr handle word) <- get sandbox, partial-name-for-function
489 allocate new-name-ah
490 var new-name/eax: (addr word) <- lookup *new-name-ah
491 initialize-word new-name
492 break $process-sandbox:body
493 }
494
495 var g/edx: grapheme <- copy key
496 var print?/eax: boolean <- real-grapheme? key
497 $process-sandbox:real-grapheme: {
498 compare print?, 0
499 break-if-=
500 add-grapheme-to-word cursor-word, g
501 break $process-sandbox:body
502 }
503
504 }
505 }
506
507
508
509
510 fn process-sandbox-rename _sandbox: (addr sandbox), key: grapheme {
511 $process-sandbox-rename:body: {
512 var sandbox/esi: (addr sandbox) <- copy _sandbox
513 var new-name-ah/edi: (addr handle word) <- get sandbox, partial-name-for-cursor-word
514
515 compare key, 0x1b
516 $process-sandbox-rename:cancel: {
517 break-if-!=
518 var empty: (handle word)
519 copy-handle empty, new-name-ah
520 break $process-sandbox-rename:body
521 }
522
523 compare key, 0xa
524 $process-sandbox-rename:commit: {
525 break-if-!=
526
527
528 var new-line-h: (handle line)
529 var new-line-ah/eax: (addr handle line) <- address new-line-h
530 allocate new-line-ah
531 var new-line/eax: (addr line) <- lookup *new-line-ah
532 initialize-line new-line
533 var new-line-word-ah/ecx: (addr handle word) <- get new-line, data
534 {
535
536 var cursor-ah/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
537 var cursor/eax: (addr call-path-element) <- lookup *cursor-ah
538 var word-at-cursor-ah/eax: (addr handle word) <- get cursor, word
539
540
541
542
543
544
545 move-word-contents word-at-cursor-ah, new-line-word-ah
546
547 copy-word-contents-before-cursor new-name-ah, word-at-cursor-ah
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566 }
567
568 {
569 var new-name/eax: (addr word) <- lookup *new-name-ah
570 cursor-to-start new-name
571 add-grapheme-to-word new-name, 0x3d
572 }
573
574 chain-words new-line-word-ah, new-name-ah
575
576 var new-line-next/ecx: (addr handle line) <- get new-line, next
577 var sandbox-slot/edx: (addr handle line) <- get sandbox, data
578 copy-object sandbox-slot, new-line-next
579
580 copy-handle new-line-h, sandbox-slot
581
582 var empty: (handle word)
583 copy-handle empty, new-name-ah
584
585
586
587
588
589
590
591
592
593
594
595
596
597 break $process-sandbox-rename:body
598 }
599
600 compare key, 0x7f
601 $process-sandbox-rename:backspace: {
602 break-if-!=
603
604 var new-name/eax: (addr word) <- lookup *new-name-ah
605 var at-start?/eax: boolean <- cursor-at-start? new-name
606 compare at-start?, 0
607 {
608 break-if-!=
609 var new-name/eax: (addr word) <- lookup *new-name-ah
610 delete-before-cursor new-name
611 }
612 break $process-sandbox-rename:body
613 }
614
615 var print?/eax: boolean <- real-grapheme? key
616 $process-sandbox-rename:real-grapheme: {
617 compare print?, 0
618 break-if-=
619 var new-name/eax: (addr word) <- lookup *new-name-ah
620 add-grapheme-to-word new-name, key
621 break $process-sandbox-rename:body
622 }
623
624 }
625 }
626
627
628
629
630
631 fn process-sandbox-define _sandbox: (addr sandbox), functions: (addr handle function), key: grapheme {
632 $process-sandbox-define:body: {
633 var sandbox/esi: (addr sandbox) <- copy _sandbox
634 var new-name-ah/edi: (addr handle word) <- get sandbox, partial-name-for-function
635
636 compare key, 0x1b
637 $process-sandbox-define:cancel: {
638 break-if-!=
639 var empty: (handle word)
640 copy-handle empty, new-name-ah
641 break $process-sandbox-define:body
642 }
643
644 compare key, 0xa
645 $process-sandbox-define:commit: {
646 break-if-!=
647
648
649 var new-function: (handle function)
650 var new-function-ah/ecx: (addr handle function) <- address new-function
651 allocate new-function-ah
652 var _new-function/eax: (addr function) <- lookup *new-function-ah
653 var new-function/ebx: (addr function) <- copy _new-function
654 var dest/edx: (addr handle function) <- get new-function, next
655 copy-object functions, dest
656 copy-object new-function-ah, functions
657
658 var new-name/eax: (addr word) <- lookup *new-name-ah
659 var dest/edx: (addr handle array byte) <- get new-function, name
660 word-to-string new-name, dest
661
662 var body-ah/eax: (addr handle line) <- get new-function, body
663 allocate body-ah
664 var body/eax: (addr line) <- lookup *body-ah
665 var body-contents/ecx: (addr handle word) <- get body, data
666 var final-line-storage: (handle line)
667 var final-line-ah/eax: (addr handle line) <- address final-line-storage
668 final-line sandbox, final-line-ah
669 var final-line/eax: (addr line) <- lookup *final-line-ah
670 var final-line-contents/eax: (addr handle word) <- get final-line, data
671 copy-object final-line-contents, body-contents
672
673 copy-unbound-words-to-args functions
674
675 var empty-word: (handle word)
676 copy-handle empty-word, final-line-contents
677 construct-call functions, final-line-contents
678
679 var empty-word: (handle word)
680 copy-handle empty-word, new-name-ah
681
682 var final-line/eax: (addr line) <- lookup final-line-storage
683 var cursor-call-path-ah/ecx: (addr handle call-path-element) <- get sandbox, cursor-call-path
684 allocate cursor-call-path-ah
685 initialize-path-from-line final-line, cursor-call-path-ah
686 break $process-sandbox-define:body
687 }
688
689 compare key, 0x7f
690 $process-sandbox-define:backspace: {
691 break-if-!=
692
693 var new-name/eax: (addr word) <- lookup *new-name-ah
694 var at-start?/eax: boolean <- cursor-at-start? new-name
695 compare at-start?, 0
696 {
697 break-if-!=
698 var new-name/eax: (addr word) <- lookup *new-name-ah
699 delete-before-cursor new-name
700 }
701 break $process-sandbox-define:body
702 }
703
704 var print?/eax: boolean <- real-grapheme? key
705 $process-sandbox-define:real-grapheme: {
706 compare print?, 0
707 break-if-=
708 var new-name/eax: (addr word) <- lookup *new-name-ah
709 add-grapheme-to-word new-name, key
710 break $process-sandbox-define:body
711 }
712
713 }
714 }
715
716
717
718
719 fn copy-unbound-words-to-args _functions: (addr handle function) {
720
721 var target-ah/eax: (addr handle function) <- copy _functions
722 var _target/eax: (addr function) <- lookup *target-ah
723 var target/esi: (addr function) <- copy _target
724 var dest-ah/edi: (addr handle word) <- get target, args
725
726 var functions-ah/edx: (addr handle function) <- get target, next
727
728 var line-ah/eax: (addr handle line) <- get target, body
729 var line/eax: (addr line) <- lookup *line-ah
730 var curr-ah/eax: (addr handle word) <- get line, data
731 var curr/eax: (addr word) <- lookup *curr-ah
732 {
733 compare curr, 0
734 break-if-=
735 $copy-unbound-words-to-args:loop-iter: {
736
737 {
738 var is-int?/eax: boolean <- word-is-decimal-integer? curr
739 compare is-int?, 0
740 break-if-!= $copy-unbound-words-to-args:loop-iter
741 }
742
743 var bound?/ebx: boolean <- bound-function? curr, functions-ah
744 compare bound?, 0
745 break-if-!=
746
747 var dup?/ebx: boolean <- arg-exists? _functions, curr
748 compare dup?, 0
749 break-if-!= $copy-unbound-words-to-args:loop-iter
750
751 var rest-h: (handle word)
752 var rest-ah/ecx: (addr handle word) <- address rest-h
753 copy-object dest-ah, rest-ah
754 copy-word curr, dest-ah
755 chain-words dest-ah, rest-ah
756 }
757 var next-ah/ecx: (addr handle word) <- get curr, next
758 curr <- lookup *next-ah
759 loop
760 }
761 }
762
763 fn bound-function? w: (addr word), functions-ah: (addr handle function) -> _/ebx: boolean {
764 var result/ebx: boolean <- copy 1
765 {
766
767 var subresult/eax: boolean <- word-equal? w, "+"
768 compare subresult, 0
769 break-if-!=
770
771 subresult <- word-equal? w, "-"
772 compare subresult, 0
773 break-if-!=
774
775 subresult <- word-equal? w, "*"
776 compare subresult, 0
777 break-if-!=
778
779 subresult <- word-equal? w, "len"
780 compare subresult, 0
781 break-if-!=
782
783 subresult <- word-equal? w, "open"
784 compare subresult, 0
785 break-if-!=
786
787 subresult <- word-equal? w, "read"
788 compare subresult, 0
789 break-if-!=
790
791 subresult <- word-equal? w, "slurp"
792 compare subresult, 0
793 break-if-!=
794
795 subresult <- word-equal? w, "lines"
796 compare subresult, 0
797 break-if-!=
798
799 subresult <- word-equal? w, "dup"
800 compare subresult, 0
801 break-if-!=
802
803 subresult <- word-equal? w, "swap"
804 compare subresult, 0
805 break-if-!=
806
807 var out-h: (handle function)
808 var out/eax: (addr handle function) <- address out-h
809 callee functions-ah, w, out
810 var found?/eax: (addr function) <- lookup *out
811 result <- copy found?
812 }
813 return result
814 }
815
816 fn arg-exists? _f-ah: (addr handle function), arg: (addr word) -> _/ebx: boolean {
817 var f-ah/eax: (addr handle function) <- copy _f-ah
818 var f/eax: (addr function) <- lookup *f-ah
819 var args-ah/eax: (addr handle word) <- get f, args
820 var result/ebx: boolean <- word-exists? args-ah, arg
821 return result
822 }
823
824
825 fn construct-call _f-ah: (addr handle function), _dest-ah: (addr handle word) {
826 var f-ah/eax: (addr handle function) <- copy _f-ah
827 var _f/eax: (addr function) <- lookup *f-ah
828 var f/esi: (addr function) <- copy _f
829
830 var args-ah/eax: (addr handle word) <- get f, args
831 var dest-ah/edi: (addr handle word) <- copy _dest-ah
832 copy-words-in-reverse args-ah, dest-ah
833
834 var name-ah/eax: (addr handle array byte) <- get f, name
835 var name/eax: (addr array byte) <- lookup *name-ah
836 append-word-at-end-with dest-ah, name
837 }
838
839 fn word-index _words: (addr handle word), _n: int, out: (addr handle word) {
840 $word-index:body: {
841 var n/ecx: int <- copy _n
842 {
843 compare n, 0
844 break-if-!=
845 copy-object _words, out
846 break $word-index:body
847 }
848 var words-ah/eax: (addr handle word) <- copy _words
849 var words/eax: (addr word) <- lookup *words-ah
850 var next/eax: (addr handle word) <- get words, next
851 n <- decrement
852 word-index next, n, out
853 }
854 }
855
856 fn toggle-cursor-word _sandbox: (addr sandbox) {
857 $toggle-cursor-word:body: {
858 var sandbox/esi: (addr sandbox) <- copy _sandbox
859 var expanded-words/edi: (addr handle call-path) <- get sandbox, expanded-words
860 var cursor-call-path/ecx: (addr handle call-path-element) <- get sandbox, cursor-call-path
861
862
863
864
865 var already-expanded?/eax: boolean <- find-in-call-paths expanded-words, cursor-call-path
866 compare already-expanded?, 0
867 {
868 break-if-!=
869
870
871 insert-in-call-path expanded-words cursor-call-path
872
873
874 break $toggle-cursor-word:body
875 }
876 {
877 break-if-=
878
879 delete-in-call-path expanded-words cursor-call-path
880 }
881 }
882 }
883
884
885
886
887
888 fn evaluate-environment _env: (addr environment), stack: (addr value-stack) {
889 var env/esi: (addr environment) <- copy _env
890
891 var functions/edx: (addr handle function) <- get env, functions
892
893 var sandbox-ah/esi: (addr handle sandbox) <- get env, sandboxes
894 var sandbox/eax: (addr sandbox) <- lookup *sandbox-ah
895 var line-ah/eax: (addr handle line) <- get sandbox, data
896 var _line/eax: (addr line) <- lookup *line-ah
897 var line/esi: (addr line) <- copy _line
898 evaluate functions, 0, line, 0, stack
899 }
900
901 fn render _env: (addr environment) {
902
903 var env/esi: (addr environment) <- copy _env
904 clear-canvas env
905
906 var screen-ah/eax: (addr handle screen) <- get env, screen
907 var _screen/eax: (addr screen) <- lookup *screen-ah
908 var screen/edi: (addr screen) <- copy _screen
909
910 var _repl-col/eax: (addr int) <- get env, code-separator-col
911 var repl-col/ecx: int <- copy *_repl-col
912 repl-col <- add 2
913
914 var functions/edx: (addr handle function) <- get env, functions
915
916 var sandbox-ah/eax: (addr handle sandbox) <- get env, sandboxes
917 var sandbox/eax: (addr sandbox) <- lookup *sandbox-ah
918
919
920
921
922
923
924
925
926
927 var bindings-storage: table
928 var bindings/ebx: (addr table) <- address bindings-storage
929 initialize-table bindings, 0x10
930 render-sandbox screen, functions, bindings, sandbox, 3, repl-col
931 }
932
933 fn render-sandbox screen: (addr screen), functions: (addr handle function), bindings: (addr table), _sandbox: (addr sandbox), top-row: int, left-col: int {
934 var sandbox/esi: (addr sandbox) <- copy _sandbox
935
936 var curr-line-ah/eax: (addr handle line) <- get sandbox, data
937 var _curr-line/eax: (addr line) <- lookup *curr-line-ah
938 var curr-line/ecx: (addr line) <- copy _curr-line
939
940 var curr-row/edx: int <- copy top-row
941
942 var cursor-row: int
943 var cursor-row-addr: (addr int)
944 var tmp/eax: (addr int) <- address cursor-row
945 copy-to cursor-row-addr, tmp
946 var cursor-col: int
947 var cursor-col-addr: (addr int)
948 tmp <- address cursor-col
949 copy-to cursor-col-addr, tmp
950
951
952 {
953 var next-line-ah/eax: (addr handle line) <- get curr-line, next
954 var next-line/eax: (addr line) <- lookup *next-line-ah
955 compare next-line, 0
956 break-if-=
957 {
958 var cursor-call-path-ah/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
959 var cursor-call-path/eax: (addr call-path-element) <- lookup *cursor-call-path-ah
960 var cursor-word-ah/eax: (addr handle word) <- get cursor-call-path, word
961 var cursor-word/eax: (addr word) <- lookup *cursor-word-ah
962
963
964
965
966
967
968
969
970
971 render-line-without-stack screen, curr-line, curr-row, left-col, cursor-word, cursor-row-addr, cursor-col-addr
972 }
973 curr-line <- copy next-line
974 curr-row <- add 2
975 loop
976 }
977
978
979 render-final-line-with-stack screen, functions, bindings, sandbox, curr-row, left-col, cursor-row-addr, cursor-col-addr
980
981 render-rename-dialog screen, sandbox, cursor-row, cursor-col
982 render-define-dialog screen, sandbox, cursor-row, cursor-col
983 move-cursor screen, cursor-row, cursor-col
984 }
985
986 fn render-final-line-with-stack screen: (addr screen), functions: (addr handle function), bindings: (addr table), _sandbox: (addr sandbox), top-row: int, left-col: int, cursor-row-addr: (addr int), cursor-col-addr: (addr int) {
987 var sandbox/esi: (addr sandbox) <- copy _sandbox
988
989 var expanded-words/edi: (addr handle call-path) <- get sandbox, expanded-words
990
991 var cursor-call-path-ah/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
992 var cursor-call-path/eax: (addr call-path-element) <- lookup *cursor-call-path-ah
993 var cursor-word-ah/eax: (addr handle word) <- get cursor-call-path, word
994 var _cursor-word/eax: (addr word) <- lookup *cursor-word-ah
995 var cursor-word/ebx: (addr word) <- copy _cursor-word
996
997
998
999
1000 var cursor-call-path: (addr handle call-path-element)
1001 {
1002 var src/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
1003 copy-to cursor-call-path, src
1004 }
1005
1006 var first-line-ah/eax: (addr handle line) <- get sandbox, data
1007 var _first-line/eax: (addr line) <- lookup *first-line-ah
1008 var first-line/edx: (addr line) <- copy _first-line
1009
1010 var final-line-storage: (handle line)
1011 var final-line-ah/eax: (addr handle line) <- address final-line-storage
1012 final-line sandbox, final-line-ah
1013 var final-line/eax: (addr line) <- lookup *final-line-ah
1014
1015 var curr-path-storage: (handle call-path-element)
1016 var curr-path/ecx: (addr handle call-path-element) <- address curr-path-storage
1017 allocate curr-path
1018 initialize-path-from-line final-line, curr-path
1019
1020 var dummy/ecx: int <- render-line screen, functions, bindings, first-line, final-line, expanded-words, top-row, left-col, curr-path, cursor-word, cursor-call-path, cursor-row-addr, cursor-col-addr
1021 }
1022
1023 fn final-line _sandbox: (addr sandbox), out: (addr handle line) {
1024 var sandbox/esi: (addr sandbox) <- copy _sandbox
1025 var curr-line-ah/ecx: (addr handle line) <- get sandbox, data
1026 {
1027 var curr-line/eax: (addr line) <- lookup *curr-line-ah
1028 var next-line-ah/edx: (addr handle line) <- get curr-line, next
1029 var next-line/eax: (addr line) <- lookup *next-line-ah
1030 compare next-line, 0
1031 break-if-=
1032 curr-line-ah <- copy next-line-ah
1033 loop
1034 }
1035 copy-object curr-line-ah, out
1036 }
1037
1038 fn render-rename-dialog screen: (addr screen), _sandbox: (addr sandbox), cursor-row: int, cursor-col: int {
1039 var sandbox/edi: (addr sandbox) <- copy _sandbox
1040 var rename-word-mode-ah?/ecx: (addr handle word) <- get sandbox, partial-name-for-cursor-word
1041 var rename-word-mode?/eax: (addr word) <- lookup *rename-word-mode-ah?
1042 compare rename-word-mode?, 0
1043 break-if-=
1044
1045 var top-row/eax: int <- copy cursor-row
1046 top-row <- subtract 3
1047 var bottom-row/ecx: int <- copy cursor-row
1048 bottom-row <- add 3
1049 var left-col/edx: int <- copy cursor-col
1050 left-col <- subtract 0x10
1051 var right-col/ebx: int <- copy cursor-col
1052 right-col <- add 0x10
1053 clear-rect screen, top-row, left-col, bottom-row, right-col
1054 draw-box screen, top-row, left-col, bottom-row, right-col
1055
1056 var menu-row/ecx: int <- copy bottom-row
1057 menu-row <- decrement
1058 var menu-col/edx: int <- copy left-col
1059 menu-col <- add 2
1060 move-cursor screen, menu-row, menu-col
1061 start-reverse-video screen
1062 print-string screen, " esc "
1063 reset-formatting screen
1064 print-string screen, " cancel "
1065 start-reverse-video screen
1066 print-string screen, " enter "
1067 reset-formatting screen
1068 print-string screen, " rename "
1069
1070 var start-col/ecx: int <- copy cursor-col
1071 var word-ah?/edx: (addr handle word) <- get sandbox, partial-name-for-cursor-word
1072 var word/eax: (addr word) <- lookup *word-ah?
1073 var cursor-index/eax: int <- cursor-index word
1074 start-col <- subtract cursor-index
1075 move-cursor screen, cursor-row, start-col
1076 var word/eax: (addr word) <- lookup *word-ah?
1077 print-word screen, word
1078 }
1079
1080 fn render-define-dialog screen: (addr screen), _sandbox: (addr sandbox), cursor-row: int, cursor-col: int {
1081 var sandbox/edi: (addr sandbox) <- copy _sandbox
1082 var define-function-mode-ah?/ecx: (addr handle word) <- get sandbox, partial-name-for-function
1083 var define-function-mode?/eax: (addr word) <- lookup *define-function-mode-ah?
1084 compare define-function-mode?, 0
1085 break-if-=
1086
1087 var top-row/eax: int <- copy cursor-row
1088 top-row <- subtract 3
1089 var bottom-row/ecx: int <- copy cursor-row
1090 bottom-row <- add 3
1091 var left-col/edx: int <- copy cursor-col
1092 left-col <- subtract 0x10
1093 var right-col/ebx: int <- copy cursor-col
1094 right-col <- add 0x10
1095 clear-rect screen, top-row, left-col, bottom-row, right-col
1096 draw-box screen, top-row, left-col, bottom-row, right-col
1097
1098 var menu-row/ecx: int <- copy bottom-row
1099 menu-row <- decrement
1100 var menu-col/edx: int <- copy left-col
1101 menu-col <- add 2
1102 move-cursor screen, menu-row, menu-col
1103 start-reverse-video screen
1104 print-string screen, " esc "
1105 reset-formatting screen
1106 print-string screen, " cancel "
1107 start-reverse-video screen
1108 print-string screen, " enter "
1109 reset-formatting screen
1110 print-string screen, " define "
1111
1112 var start-col/ecx: int <- copy cursor-col
1113 var word-ah?/edx: (addr handle word) <- get sandbox, partial-name-for-function
1114 var word/eax: (addr word) <- lookup *word-ah?
1115 var cursor-index/eax: int <- cursor-index word
1116 start-col <- subtract cursor-index
1117 move-cursor screen, cursor-row, start-col
1118 var word/eax: (addr word) <- lookup *word-ah?
1119 print-word screen, word
1120 }
1121
1122
1123 fn render-line-without-stack screen: (addr screen), _line: (addr line), curr-row: int, left-col: int, cursor-word: (addr word), cursor-row-addr: (addr int), cursor-col-addr: (addr int) {
1124
1125 var line/eax: (addr line) <- copy _line
1126 var first-word-ah/eax: (addr handle word) <- get line, data
1127 var _curr-word/eax: (addr word) <- lookup *first-word-ah
1128 var curr-word/esi: (addr word) <- copy _curr-word
1129
1130
1131 var curr-col/ecx: int <- copy left-col
1132
1133 {
1134 compare curr-word, 0
1135 break-if-=
1136
1137
1138
1139
1140
1141
1142 var old-col/edx: int <- copy curr-col
1143 reset-formatting screen
1144 move-cursor screen, curr-row, curr-col
1145 print-word screen, curr-word
1146 {
1147 var max-width/eax: int <- word-length curr-word
1148 curr-col <- add max-width
1149 curr-col <- add 1
1150 }
1151
1152 {
1153 compare curr-word, cursor-word
1154 break-if-!=
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168 var dest/ecx: (addr int) <- copy cursor-row-addr
1169 var src/eax: int <- copy curr-row
1170 copy-to *dest, src
1171 dest <- copy cursor-col-addr
1172 copy-to *dest, old-col
1173 var cursor-index-in-word/eax: int <- cursor-index curr-word
1174 add-to *dest, cursor-index-in-word
1175 }
1176
1177 var next-word-ah/edx: (addr handle word) <- get curr-word, next
1178 var _curr-word/eax: (addr word) <- lookup *next-word-ah
1179 curr-word <- copy _curr-word
1180 loop
1181 }
1182 }
1183
1184 fn call-depth-at-cursor _sandbox: (addr sandbox) -> _/eax: int {
1185 var sandbox/esi: (addr sandbox) <- copy _sandbox
1186 var cursor-call-path/edi: (addr handle call-path-element) <- get sandbox, cursor-call-path
1187 var result/eax: int <- call-path-element-length cursor-call-path
1188 result <- add 2
1189 return result
1190 }
1191
1192 fn call-path-element-length _x: (addr handle call-path-element) -> _/eax: int {
1193 var curr-ah/ecx: (addr handle call-path-element) <- copy _x
1194 var result/edi: int <- copy 0
1195 {
1196 var curr/eax: (addr call-path-element) <- lookup *curr-ah
1197 compare curr, 0
1198 break-if-=
1199 curr-ah <- get curr, next
1200 result <- increment
1201 loop
1202 }
1203 return result
1204 }
1205
1206
1207
1208
1209
1210 fn render-line screen: (addr screen), functions: (addr handle function), bindings: (addr table), first-line: (addr line), _line: (addr line), expanded-words: (addr handle call-path), top-row: int, left-col: int, curr-path: (addr handle call-path-element), cursor-word: (addr word), cursor-call-path: (addr handle call-path-element), cursor-row-addr: (addr int), cursor-col-addr: (addr int) -> _/ecx: int {
1211
1212
1213 var line/esi: (addr line) <- copy _line
1214 var first-word-ah/eax: (addr handle word) <- get line, data
1215 var curr-word/eax: (addr word) <- lookup *first-word-ah
1216 var debug-row: int
1217 copy-to debug-row, 0x20
1218
1219
1220 var curr-col/ecx: int <- copy left-col
1221
1222 {
1223 compare curr-word, 0
1224 break-if-=
1225
1226
1227
1228
1229
1230
1231
1232 $render-line:subsidiary: {
1233 {
1234
1235 var display-subsidiary-stack?/eax: boolean <- find-in-call-paths expanded-words, curr-path
1236 compare display-subsidiary-stack?, 0
1237 break-if-= $render-line:subsidiary
1238 }
1239
1240
1241 var callee/edi: (addr function) <- copy 0
1242 {
1243 var callee-h: (handle function)
1244 var callee-ah/ecx: (addr handle function) <- address callee-h
1245 callee functions, curr-word, callee-ah
1246 var _callee/eax: (addr function) <- lookup *callee-ah
1247 callee <- copy _callee
1248 compare callee, 0
1249 break-if-= $render-line:subsidiary
1250 }
1251 move-cursor screen, top-row, curr-col
1252 start-color screen, 8, 7
1253 print-word screen, curr-word
1254 {
1255 var word-len/eax: int <- word-length curr-word
1256 curr-col <- add word-len
1257 curr-col <- add 2
1258 increment top-row
1259 }
1260
1261 var stack-storage: value-stack
1262 var stack/edx: (addr value-stack) <- address stack-storage
1263 initialize-value-stack stack, 0x10
1264 {
1265 var prev-word-ah/eax: (addr handle word) <- get curr-word, prev
1266 var prev-word/eax: (addr word) <- lookup *prev-word-ah
1267 compare prev-word, 0
1268 break-if-=
1269 evaluate functions, bindings, line, prev-word, stack
1270 }
1271
1272 var callee-bindings-storage: table
1273 var callee-bindings/esi: (addr table) <- address callee-bindings-storage
1274 initialize-table callee-bindings, 0x10
1275 bind-args callee, stack, callee-bindings
1276
1277 var callee-body-ah/eax: (addr handle line) <- get callee, body
1278 var callee-body/eax: (addr line) <- lookup *callee-body-ah
1279 var callee-body-first-word/edx: (addr handle word) <- get callee-body, data
1280
1281 push-to-call-path-element curr-path, callee-body-first-word
1282 curr-col <- render-line screen, functions, callee-bindings, callee-body, callee-body, expanded-words, top-row, curr-col, curr-path, cursor-word, cursor-call-path, cursor-row-addr, cursor-col-addr
1283 drop-from-call-path-element curr-path
1284
1285 move-cursor screen, top-row, curr-col
1286 print-code-point screen, 0x21d7
1287
1288 curr-col <- add 2
1289 decrement top-row
1290 }
1291
1292 var old-col/edx: int <- copy curr-col
1293
1294
1295
1296
1297
1298 curr-col <- render-column screen, functions, bindings, first-line, line, curr-word, top-row, curr-col
1299
1300 $render-line:cache-cursor-column: {
1301
1302
1303
1304
1305
1306
1307 {
1308 var found?/eax: boolean <- call-path-element-match? curr-path, cursor-call-path
1309 compare found?, 0
1310 break-if-= $render-line:cache-cursor-column
1311 }
1312
1313
1314
1315
1316
1317 var dest/edi: (addr int) <- copy cursor-row-addr
1318 {
1319 var src/eax: int <- copy top-row
1320 copy-to *dest, src
1321 }
1322 dest <- copy cursor-col-addr
1323 copy-to *dest, old-col
1324 var cursor-index-in-word/eax: int <- cursor-index curr-word
1325 add-to *dest, cursor-index-in-word
1326 }
1327
1328
1329 var next-word-ah/edx: (addr handle word) <- get curr-word, next
1330 curr-word <- lookup *next-word-ah
1331
1332
1333
1334
1335
1336 increment-final-element curr-path
1337 loop
1338 }
1339 return curr-col
1340 }
1341
1342 fn callee functions: (addr handle function), word: (addr word), out: (addr handle function) {
1343 var stream-storage: (stream byte 0x10)
1344 var stream/esi: (addr stream byte) <- address stream-storage
1345 emit-word word, stream
1346 find-function functions, stream, out
1347 }
1348
1349
1350
1351
1352
1353
1354 fn render-column screen: (addr screen), functions: (addr handle function), bindings: (addr table), first-line: (addr line), line: (addr line), final-word: (addr word), top-row: int, left-col: int -> _/ecx: int {
1355
1356 var max-width/esi: int <- copy 0
1357 {
1358
1359 var indented-col/ebx: int <- copy left-col
1360 indented-col <- add 1
1361
1362 var stack: value-stack
1363 var stack-addr/edi: (addr value-stack) <- address stack
1364 initialize-value-stack stack-addr, 0x10
1365 evaluate functions, bindings, first-line, final-word, stack-addr
1366
1367 var curr-row/edx: int <- copy top-row
1368 curr-row <- add 2
1369 var _max-width/eax: int <- value-stack-max-width stack-addr
1370 max-width <- copy _max-width
1371 {
1372 var top-addr/ecx: (addr int) <- get stack-addr, top
1373 compare *top-addr, 0
1374 break-if-<=
1375 decrement *top-addr
1376 move-cursor screen, curr-row, indented-col
1377 {
1378 var data-ah/eax: (addr handle array value) <- get stack-addr, data
1379 var data/eax: (addr array value) <- lookup *data-ah
1380 var top/edx: int <- copy *top-addr
1381 var dest-offset/edx: (offset value) <- compute-offset data, top
1382 var val/eax: (addr value) <- index data, dest-offset
1383 render-value screen, val, max-width
1384 }
1385 curr-row <- increment
1386 loop
1387 }
1388 }
1389
1390 max-width <- add 2
1391
1392
1393 reset-formatting screen
1394 move-cursor screen, top-row, left-col
1395 print-word screen, final-word
1396 {
1397 var size/eax: int <- word-length final-word
1398 compare size, max-width
1399 break-if-<=
1400 max-width <- copy size
1401 }
1402
1403
1404 var right-col/ecx: int <- copy left-col
1405 right-col <- add max-width
1406 right-col <- add 1
1407
1408
1409
1410
1411 return right-col
1412 }
1413
1414 fn render-value screen: (addr screen), _val: (addr value), max-width: int {
1415 $render-value:body: {
1416 var val/esi: (addr value) <- copy _val
1417 var val-type/ecx: (addr int) <- get val, type
1418
1419 compare *val-type, 1
1420 {
1421 break-if-!=
1422 var val-ah/eax: (addr handle array byte) <- get val, text-data
1423 var val-string/eax: (addr array byte) <- lookup *val-ah
1424 compare val-string, 0
1425 break-if-=
1426 var orig-len/ecx: int <- length val-string
1427 var truncated: (handle array byte)
1428 var truncated-ah/esi: (addr handle array byte) <- address truncated
1429 substring val-string, 0, 0xc, truncated-ah
1430 var truncated-string/eax: (addr array byte) <- lookup *truncated-ah
1431
1432
1433
1434
1435
1436 var len/edx: int <- length truncated-string
1437 start-color screen, 0xf2, 7
1438 print-code-point screen, 0x275d
1439 print-string screen, truncated-string
1440 compare len, orig-len
1441 {
1442 break-if-=
1443 print-code-point screen, 0x2026
1444 }
1445 print-code-point screen, 0x275e
1446 reset-formatting screen
1447 break $render-value:body
1448 }
1449 compare *val-type, 2
1450 {
1451 break-if-!=
1452 var val-ah/eax: (addr handle array value) <- get val, array-data
1453 var val-array/eax: (addr array value) <- lookup *val-ah
1454 render-array screen, val-array
1455 break $render-value:body
1456 }
1457 compare *val-type, 3
1458 {
1459 break-if-!=
1460 var val-ah/eax: (addr handle buffered-file) <- get val, file-data
1461 var val-file/eax: (addr buffered-file) <- lookup *val-ah
1462 start-color screen, 0, 7
1463
1464 print-string screen, " FILE "
1465 break $render-value:body
1466 }
1467
1468 var val-int/eax: (addr int) <- get val, int-data
1469 render-integer screen, *val-int, max-width
1470 }
1471 }
1472
1473
1474 fn render-integer screen: (addr screen), val: int, max-width: int {
1475 $render-integer:body: {
1476
1477 compare max-width, 0
1478 {
1479 break-if-!=
1480 print-int32-decimal screen, val
1481 break $render-integer:body
1482 }
1483 var bg/eax: int <- hash-color val
1484 var fg/ecx: int <- copy 7
1485 {
1486 compare bg, 2
1487 break-if-!=
1488 fg <- copy 0
1489 }
1490 {
1491 compare bg, 3
1492 break-if-!=
1493 fg <- copy 0
1494 }
1495 {
1496 compare bg, 6
1497 break-if-!=
1498 fg <- copy 0
1499 }
1500 start-color screen, fg, bg
1501 print-grapheme screen, 0x20
1502 print-int32-decimal-right-justified screen, val, max-width
1503 print-grapheme screen, 0x20
1504 }
1505 }
1506
1507 fn render-array screen: (addr screen), _a: (addr array value) {
1508 start-color screen, 0xf2, 7
1509
1510 print-grapheme screen, 0x5b
1511 var a/esi: (addr array value) <- copy _a
1512 var max/ecx: int <- length a
1513 var i/eax: int <- copy 0
1514 {
1515 compare i, max
1516 break-if->=
1517 {
1518 compare i, 0
1519 break-if-=
1520 print-string screen, " "
1521 }
1522 var off/ecx: (offset value) <- compute-offset a, i
1523 var x/ecx: (addr value) <- index a, off
1524 render-value screen, x, 0
1525 i <- increment
1526 loop
1527 }
1528 print-grapheme screen, 0x5d
1529 }
1530
1531 fn hash-color val: int -> _/eax: int {
1532 var result/eax: int <- try-modulo val, 7
1533 return result
1534 }
1535
1536 fn clear-canvas _env: (addr environment) {
1537 var env/esi: (addr environment) <- copy _env
1538 var screen-ah/edi: (addr handle screen) <- get env, screen
1539 var _screen/eax: (addr screen) <- lookup *screen-ah
1540 var screen/edi: (addr screen) <- copy _screen
1541 clear-screen screen
1542 var nrows/eax: (addr int) <- get env, nrows
1543 var _repl-col/ecx: (addr int) <- get env, code-separator-col
1544 var repl-col/ecx: int <- copy *_repl-col
1545 draw-vertical-line screen, 1, *nrows, repl-col
1546
1547 move-cursor screen, *nrows, 0
1548 start-reverse-video screen
1549 print-string screen, " ctrl-q "
1550 reset-formatting screen
1551 print-string screen, " quit "
1552 var menu-start/ebx: int <- copy repl-col
1553 menu-start <- subtract 0x40
1554 move-cursor screen, *nrows, menu-start
1555 start-reverse-video screen
1556 print-string screen, " ctrl-a "
1557 reset-formatting screen
1558 print-string screen, " ⏮ "
1559 start-reverse-video screen
1560 print-string screen, " ctrl-b "
1561 reset-formatting screen
1562 print-string screen, " ◀ word "
1563 start-reverse-video screen
1564 print-string screen, " ctrl-f "
1565 reset-formatting screen
1566 print-string screen, " word ▶ "
1567 start-reverse-video screen
1568 print-string screen, " ctrl-e "
1569 reset-formatting screen
1570 print-string screen, " ⏭ "
1571 start-reverse-video screen
1572 print-string screen, " ctrl-u "
1573 reset-formatting screen
1574 print-string screen, " clear line "
1575 start-reverse-video screen
1576 print-string screen, " ctrl-n "
1577 reset-formatting screen
1578 print-string screen, " name value "
1579 start-reverse-video screen
1580 print-string screen, " ctrl-d "
1581 reset-formatting screen
1582 print-string screen, " define function "
1583
1584 var start-col/ecx: int <- copy repl-col
1585 start-col <- subtract 0x20
1586 move-cursor screen, 1, start-col
1587 print-string screen, "primitives:"
1588 start-col <- add 2
1589 move-cursor screen, 2, start-col
1590 print-string screen, "+ - * len"
1591 move-cursor screen, 3, start-col
1592 print-string screen, "open read slurp lines"
1593 move-cursor screen, 4, start-col
1594 print-string screen, "dup swap"
1595
1596 start-col <- subtract 2
1597 move-cursor screen, 6, start-col
1598 print-string screen, "functions:"
1599 start-col <- add 2
1600 var row/ebx: int <- copy 7
1601 var functions/esi: (addr handle function) <- get env, functions
1602 {
1603 var curr/eax: (addr function) <- lookup *functions
1604 compare curr, 0
1605 break-if-=
1606 row <- render-function screen, row, start-col, curr
1607 functions <- get curr, next
1608 row <- increment
1609 loop
1610 }
1611 }
1612
1613
1614 fn render-function screen: (addr screen), row: int, col: int, _f: (addr function) -> _/ebx: int {
1615 var f/esi: (addr function) <- copy _f
1616 var args/ecx: (addr handle word) <- get f, args
1617 move-cursor screen, row, col
1618 print-words-in-reverse screen, args
1619 var name-ah/eax: (addr handle array byte) <- get f, name
1620 var name/eax: (addr array byte) <- lookup *name-ah
1621 start-bold screen
1622 print-string screen, name
1623 reset-formatting screen
1624 increment row
1625 add-to col, 2
1626 move-cursor screen, row, col
1627 print-string screen, "= "
1628 var body-ah/eax: (addr handle line) <- get f, body
1629 var body/eax: (addr line) <- lookup *body-ah
1630 var body-words-ah/eax: (addr handle word) <- get body, data
1631 print-words screen, body-words-ah
1632 return row
1633 }
1634
1635 fn real-grapheme? g: grapheme -> _/eax: boolean {
1636
1637 compare g, 0xa
1638 {
1639 break-if-!=
1640 return 1
1641 }
1642
1643 compare g, 9
1644 {
1645 break-if-!=
1646 return 1
1647 }
1648
1649 compare g, 0x20
1650 {
1651 break-if->=
1652 return 0
1653 }
1654
1655 compare g, 0xff
1656 {
1657 break-if->
1658 return 1
1659 }
1660
1661 and-with g, 0xff
1662 compare g, 0x1b
1663 {
1664 break-if-!=
1665 return 0
1666 }
1667
1668 return 1
1669 }