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