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