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