https://github.com/akkartik/mu/blob/main/shell/sandbox.mu
1 type sandbox {
2 data: (handle gap-buffer)
3 value: (handle stream byte)
4 screen-var: (handle cell)
5 keyboard-var: (handle cell)
6 trace: (handle trace)
7 cursor-in-data?: boolean
8 cursor-in-keyboard?: boolean
9 cursor-in-trace?: boolean
10 }
11
12 fn initialize-sandbox _self: (addr sandbox), fake-screen-and-keyboard?: boolean {
13 var self/esi: (addr sandbox) <- copy _self
14 var data-ah/eax: (addr handle gap-buffer) <- get self, data
15 allocate data-ah
16 var data/eax: (addr gap-buffer) <- lookup *data-ah
17 initialize-gap-buffer data, 0x1000/4KB
18
19 var value-ah/eax: (addr handle stream byte) <- get self, value
20 populate-stream value-ah, 0x1000/4KB
21
22 {
23 compare fake-screen-and-keyboard?, 0/false
24 break-if-=
25 var screen-ah/eax: (addr handle cell) <- get self, screen-var
26 new-fake-screen screen-ah, 5/width, 4/height, 1/enable-pixel-graphics
27 var keyboard-ah/eax: (addr handle cell) <- get self, keyboard-var
28 new-fake-keyboard keyboard-ah, 0x10/keyboard-capacity
29 }
30
31 var trace-ah/eax: (addr handle trace) <- get self, trace
32 allocate trace-ah
33 var trace/eax: (addr trace) <- lookup *trace-ah
34 initialize-trace trace, 0x8000/lines, 0x80/visible-lines
35 var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data?
36 copy-to *cursor-in-data?, 1/true
37 }
38
39
40
41 fn initialize-sandbox-with _self: (addr sandbox), s: (addr array byte) {
42 var self/esi: (addr sandbox) <- copy _self
43 var data-ah/eax: (addr handle gap-buffer) <- get self, data
44 allocate data-ah
45 var data/eax: (addr gap-buffer) <- lookup *data-ah
46 initialize-gap-buffer-with data, s
47 }
48
49 fn allocate-sandbox-with _out: (addr handle sandbox), s: (addr array byte) {
50 var out/eax: (addr handle sandbox) <- copy _out
51 allocate out
52 var out-addr/eax: (addr sandbox) <- lookup *out
53 initialize-sandbox-with out-addr, s
54 }
55
56 fn write-sandbox out: (addr stream byte), _self: (addr sandbox) {
57 var self/eax: (addr sandbox) <- copy _self
58 var data-ah/eax: (addr handle gap-buffer) <- get self, data
59 var data/eax: (addr gap-buffer) <- lookup *data-ah
60 {
61 var len/eax: int <- gap-buffer-length data
62 compare len, 0
63 break-if-!=
64 return
65 }
66 write out, " (sandbox . "
67 append-gap-buffer data, out
68 write out, ")\n"
69 }
70
71
72
73 fn render-sandbox screen: (addr screen), _self: (addr sandbox), xmin: int, ymin: int, xmax: int, ymax: int {
74 clear-rect screen, xmin, ymin, xmax, ymax, 0/bg=black
75 var self/esi: (addr sandbox) <- copy _self
76
77 var data-ah/eax: (addr handle gap-buffer) <- get self, data
78 var _data/eax: (addr gap-buffer) <- lookup *data-ah
79 var data/edx: (addr gap-buffer) <- copy _data
80 var x/eax: int <- copy xmin
81 var y/ecx: int <- copy ymin
82 y <- maybe-render-empty-screen screen, self, xmin, y
83 y <- maybe-render-keyboard screen, self, xmin, y
84 var cursor-in-sandbox?/ebx: (addr boolean) <- get self, cursor-in-data?
85 x, y <- render-gap-buffer-wrapping-right-then-down screen, data, x, y, xmax, ymax, *cursor-in-sandbox?
86 y <- increment
87
88 var trace-ah/eax: (addr handle trace) <- get self, trace
89 var _trace/eax: (addr trace) <- lookup *trace-ah
90 var trace/edx: (addr trace) <- copy _trace
91 var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace?
92 y <- render-trace screen, trace, xmin, y, xmax, ymax, *cursor-in-trace?
93
94 $render-sandbox:value: {
95 var value-ah/eax: (addr handle stream byte) <- get self, value
96 var _value/eax: (addr stream byte) <- lookup *value-ah
97 var value/esi: (addr stream byte) <- copy _value
98 rewind-stream value
99 var done?/eax: boolean <- stream-empty? value
100 compare done?, 0/false
101 break-if-!=
102 var x/eax: int <- copy 0
103 x, y <- draw-text-wrapping-right-then-down screen, "=> ", xmin, y, xmax, ymax, xmin, y, 7/fg, 0/bg
104 var x2/edx: int <- copy x
105 var dummy/eax: int <- draw-stream-rightward screen, value, x2, xmax, y, 7/fg=grey, 0/bg
106 }
107 y <- add 2
108 y <- maybe-render-screen screen, self, xmin, y
109
110 var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data?
111 compare *cursor-in-data?, 0/false
112 {
113 break-if-=
114 render-sandbox-menu screen, self
115 return
116 }
117 var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace?
118 compare *cursor-in-trace?, 0/false
119 {
120 break-if-=
121 render-trace-menu screen
122 return
123 }
124 var cursor-in-keyboard?/eax: (addr boolean) <- get self, cursor-in-keyboard?
125 compare *cursor-in-keyboard?, 0/false
126 {
127 break-if-=
128 render-keyboard-menu screen
129 return
130 }
131 }
132
133 fn clear-sandbox-output screen: (addr screen), _self: (addr sandbox), xmin: int, ymin: int, xmax: int, ymax: int {
134
135 var self/esi: (addr sandbox) <- copy _self
136 var data-ah/eax: (addr handle gap-buffer) <- get self, data
137 var _data/eax: (addr gap-buffer) <- lookup *data-ah
138 var data/edx: (addr gap-buffer) <- copy _data
139 var x/eax: int <- copy xmin
140 var y/ecx: int <- copy ymin
141 y <- maybe-render-empty-screen screen, self, xmin, y
142 y <- maybe-render-keyboard screen, self, xmin, y
143 var cursor-in-sandbox?/ebx: (addr boolean) <- get self, cursor-in-data?
144 x, y <- render-gap-buffer-wrapping-right-then-down screen, data, x, y, xmax, ymax, *cursor-in-sandbox?
145 y <- increment
146 clear-rect screen, xmin, y, xmax, ymax, 0/bg=black
147 }
148
149 fn maybe-render-empty-screen screen: (addr screen), _self: (addr sandbox), xmin: int, ymin: int -> _/ecx: int {
150 var self/esi: (addr sandbox) <- copy _self
151 var screen-obj-cell-ah/eax: (addr handle cell) <- get self, screen-var
152 var screen-obj-cell/eax: (addr cell) <- lookup *screen-obj-cell-ah
153 compare screen-obj-cell, 0
154 {
155 break-if-!=
156 return ymin
157 }
158 var screen-obj-cell-type/ecx: (addr int) <- get screen-obj-cell, type
159 compare *screen-obj-cell-type, 5/screen
160 {
161 break-if-=
162 return ymin
163 }
164 var y/ecx: int <- copy ymin
165 var screen-obj-ah/eax: (addr handle screen) <- get screen-obj-cell, screen-data
166 var _screen-obj/eax: (addr screen) <- lookup *screen-obj-ah
167 var screen-obj/edx: (addr screen) <- copy _screen-obj
168 var x/eax: int <- draw-text-rightward screen, "screen: ", xmin, 0x99/xmax, y, 7/fg, 0/bg
169 y <- render-empty-screen screen, screen-obj, x, y
170 return y
171 }
172
173 fn maybe-render-screen screen: (addr screen), _self: (addr sandbox), xmin: int, ymin: int -> _/ecx: int {
174 var self/esi: (addr sandbox) <- copy _self
175 var screen-obj-cell-ah/eax: (addr handle cell) <- get self, screen-var
176 var screen-obj-cell/eax: (addr cell) <- lookup *screen-obj-cell-ah
177 compare screen-obj-cell, 0
178 {
179 break-if-!=
180 return ymin
181 }
182 var screen-obj-cell-type/ecx: (addr int) <- get screen-obj-cell, type
183 compare *screen-obj-cell-type, 5/screen
184 {
185 break-if-=
186 return ymin
187 }
188 var screen-obj-ah/eax: (addr handle screen) <- get screen-obj-cell, screen-data
189 var _screen-obj/eax: (addr screen) <- lookup *screen-obj-ah
190 var screen-obj/edx: (addr screen) <- copy _screen-obj
191 {
192 var screen-empty?/eax: boolean <- fake-screen-empty? screen-obj
193 compare screen-empty?, 0/false
194 break-if-=
195 return ymin
196 }
197 var x/eax: int <- draw-text-rightward screen, "screen: ", xmin, 0x99/xmax, ymin, 7/fg, 0/bg
198 var y/ecx: int <- copy ymin
199 y <- render-screen screen, screen-obj, x, y
200 return y
201 }
202
203 fn render-empty-screen screen: (addr screen), _target-screen: (addr screen), xmin: int, ymin: int -> _/ecx: int {
204 var target-screen/esi: (addr screen) <- copy _target-screen
205 var screen-y/edi: int <- copy ymin
206
207 {
208 set-cursor-position screen, xmin, screen-y
209 move-cursor-right screen
210 var width/edx: (addr int) <- get target-screen, width
211 var x/ebx: int <- copy 0
212 {
213 compare x, *width
214 break-if->=
215 draw-code-point-at-cursor screen, 0x2d/horizontal-bar, 0x18/fg, 0/bg
216 move-cursor-right screen
217 x <- increment
218 loop
219 }
220 screen-y <- increment
221 }
222
223 var height/edx: (addr int) <- get target-screen, height
224 var y/ecx: int <- copy 0
225 {
226 compare y, *height
227 break-if->=
228 set-cursor-position screen, xmin, screen-y
229 draw-code-point-at-cursor screen, 0x7c/vertical-bar, 0x18/fg, 0/bg
230 move-cursor-right screen
231 var width/edx: (addr int) <- get target-screen, width
232 var x/ebx: int <- copy 0
233 {
234 compare x, *width
235 break-if->=
236 draw-code-point-at-cursor screen, 0x20/space, 0x18/fg, 0/bg
237 move-cursor-right screen
238 x <- increment
239 loop
240 }
241 draw-code-point-at-cursor screen, 0x7c/vertical-bar, 0x18/fg, 0/bg
242 y <- increment
243 screen-y <- increment
244 loop
245 }
246
247 {
248 set-cursor-position screen, xmin, screen-y
249 move-cursor-right screen
250 var width/edx: (addr int) <- get target-screen, width
251 var x/ebx: int <- copy 0
252 {
253 compare x, *width
254 break-if->=
255 draw-code-point-at-cursor screen, 0x2d/horizontal-bar, 0x18/fg, 0/bg
256 move-cursor-right screen
257 x <- increment
258 loop
259 }
260 screen-y <- increment
261 }
262 return screen-y
263 }
264
265 fn render-screen screen: (addr screen), _target-screen: (addr screen), xmin: int, ymin: int -> _/ecx: int {
266 var target-screen/esi: (addr screen) <- copy _target-screen
267 var screen-y/edi: int <- copy ymin
268
269 {
270 set-cursor-position screen, xmin, screen-y
271 move-cursor-right screen
272 var width/edx: (addr int) <- get target-screen, width
273 var x/ebx: int <- copy 0
274 {
275 compare x, *width
276 break-if->=
277 draw-code-point-at-cursor screen, 0x2d/horizontal-bar, 0x18/fg, 0/bg
278 move-cursor-right screen
279 x <- increment
280 loop
281 }
282 screen-y <- increment
283 }
284
285 {
286 var height/edx: (addr int) <- get target-screen, height
287 var y/ecx: int <- copy 0
288 {
289 compare y, *height
290 break-if->=
291 set-cursor-position screen, xmin, screen-y
292 draw-code-point-at-cursor screen, 0x7c/vertical-bar, 0x18/fg, 0/bg
293 move-cursor-right screen
294 var width/edx: (addr int) <- get target-screen, width
295 var x/ebx: int <- copy 0
296 {
297 compare x, *width
298 break-if->=
299 print-screen-cell-of-fake-screen screen, target-screen, x, y
300 move-cursor-right screen
301 x <- increment
302 loop
303 }
304 draw-code-point-at-cursor screen, 0x7c/vertical-bar, 0x18/fg, 0/bg
305 y <- increment
306 screen-y <- increment
307 loop
308 }
309 }
310
311 {
312
313 var tmp/eax: int <- copy xmin
314 tmp <- add 1/margin-left
315 tmp <- shift-left 3/log2-font-width
316 var left: int
317 copy-to left, tmp
318 tmp <- copy ymin
319 tmp <- add 1/margin-top
320 tmp <- shift-left 4/log2-font-height
321 var top: int
322 copy-to top, tmp
323 var pixels-ah/eax: (addr handle array byte) <- get target-screen, pixels
324 var _pixels/eax: (addr array byte) <- lookup *pixels-ah
325 var pixels/edi: (addr array byte) <- copy _pixels
326 compare pixels, 0
327 break-if-=
328 var y/ebx: int <- copy 0
329 var height-addr/edx: (addr int) <- get target-screen, height
330 var height/edx: int <- copy *height-addr
331 height <- shift-left 4/log2-font-height
332 {
333 compare y, height
334 break-if->=
335 var width-addr/edx: (addr int) <- get target-screen, width
336 var width/edx: int <- copy *width-addr
337 width <- shift-left 3/log2-font-width
338 var x/eax: int <- copy 0
339 {
340 compare x, width
341 break-if->=
342 {
343 var idx/ecx: int <- pixel-index target-screen, x, y
344 var color-addr/ecx: (addr byte) <- index pixels, idx
345 var color/ecx: byte <- copy-byte *color-addr
346 var color2/ecx: int <- copy color
347 compare color2, 0
348 break-if-=
349 var x2/eax: int <- copy x
350 x2 <- add left
351 var y2/ebx: int <- copy y
352 y2 <- add top
353 pixel screen, x2, y2, color2
354 }
355 x <- increment
356 loop
357 }
358 y <- increment
359 loop
360 }
361 }
362
363 {
364 set-cursor-position screen, xmin, screen-y
365 move-cursor-right screen
366 var width/edx: (addr int) <- get target-screen, width
367 var x/ebx: int <- copy 0
368 {
369 compare x, *width
370 break-if->=
371 draw-code-point-at-cursor screen, 0x2d/horizontal-bar, 0x18/fg, 0/bg
372 move-cursor-right screen
373 x <- increment
374 loop
375 }
376 screen-y <- increment
377 }
378 return screen-y
379 }
380
381 fn has-keyboard? _self: (addr sandbox) -> _/eax: boolean {
382 var self/esi: (addr sandbox) <- copy _self
383 var keyboard-obj-cell-ah/eax: (addr handle cell) <- get self, keyboard-var
384 var keyboard-obj-cell/eax: (addr cell) <- lookup *keyboard-obj-cell-ah
385 compare keyboard-obj-cell, 0
386 {
387 break-if-!=
388 return 0/false
389 }
390 var keyboard-obj-cell-type/ecx: (addr int) <- get keyboard-obj-cell, type
391 compare *keyboard-obj-cell-type, 6/keyboard
392 {
393 break-if-=
394 return 0/false
395 }
396 var keyboard-obj-ah/eax: (addr handle gap-buffer) <- get keyboard-obj-cell, keyboard-data
397 var _keyboard-obj/eax: (addr gap-buffer) <- lookup *keyboard-obj-ah
398 var keyboard-obj/edx: (addr gap-buffer) <- copy _keyboard-obj
399 compare keyboard-obj, 0
400 {
401 break-if-!=
402 return 0/false
403 }
404 return 1/true
405 }
406
407 fn maybe-render-keyboard screen: (addr screen), _self: (addr sandbox), xmin: int, ymin: int -> _/ecx: int {
408 var self/esi: (addr sandbox) <- copy _self
409 var keyboard-obj-cell-ah/eax: (addr handle cell) <- get self, keyboard-var
410 var keyboard-obj-cell/eax: (addr cell) <- lookup *keyboard-obj-cell-ah
411 compare keyboard-obj-cell, 0
412 {
413 break-if-!=
414 return ymin
415 }
416 var keyboard-obj-cell-type/ecx: (addr int) <- get keyboard-obj-cell, type
417 compare *keyboard-obj-cell-type, 6/keyboard
418 {
419 break-if-=
420 return ymin
421 }
422 var keyboard-obj-ah/eax: (addr handle gap-buffer) <- get keyboard-obj-cell, keyboard-data
423 var _keyboard-obj/eax: (addr gap-buffer) <- lookup *keyboard-obj-ah
424 var keyboard-obj/edx: (addr gap-buffer) <- copy _keyboard-obj
425 var x/eax: int <- draw-text-rightward screen, "keyboard: ", xmin, 0x99/xmax, ymin, 7/fg, 0/bg
426 var y/ecx: int <- copy ymin
427 var cursor-in-keyboard?/esi: (addr boolean) <- get self, cursor-in-keyboard?
428 y <- render-keyboard screen, keyboard-obj, x, y, *cursor-in-keyboard?
429 y <- increment
430 return y
431 }
432
433
434 fn render-keyboard screen: (addr screen), _keyboard: (addr gap-buffer), xmin: int, ymin: int, render-cursor?: boolean -> _/ecx: int {
435 var keyboard/esi: (addr gap-buffer) <- copy _keyboard
436 var width/edx: int <- copy 0x10/keyboard-capacity
437 var y/edi: int <- copy ymin
438
439 {
440 set-cursor-position screen, xmin, y
441 move-cursor-right screen
442 var x/ebx: int <- copy 0
443 {
444 compare x, width
445 break-if->=
446 draw-code-point-at-cursor screen, 0x2d/horizontal-bar, 0x18/fg, 0/bg
447 move-cursor-right screen
448 x <- increment
449 loop
450 }
451 y <- increment
452 }
453
454 var x/eax: int <- copy xmin
455 draw-code-point screen, 0x7c/vertical-bar, x, y, 0x18/fg, 0/bg
456 x <- increment
457 x <- render-gap-buffer screen, keyboard, x, y, render-cursor?
458 x <- copy xmin
459 x <- add 1
460 x <- add 0x10/keyboard-capacity
461 draw-code-point screen, 0x7c/vertical-bar, x, y, 0x18/fg, 0/bg
462 y <- increment
463
464 {
465 set-cursor-position screen, xmin, y
466 move-cursor-right screen
467 var x/ebx: int <- copy 0
468 {
469 compare x, width
470 break-if->=
471 draw-code-point-at-cursor screen, 0x2d/horizontal-bar, 0x18/fg, 0/bg
472 move-cursor-right screen
473 x <- increment
474 loop
475 }
476 y <- increment
477 }
478 return y
479 }
480
481 fn print-screen-cell-of-fake-screen screen: (addr screen), _target: (addr screen), x: int, y: int {
482 var target/ecx: (addr screen) <- copy _target
483 var data-ah/eax: (addr handle array screen-cell) <- get target, data
484 var data/eax: (addr array screen-cell) <- lookup *data-ah
485 var index/ecx: int <- screen-cell-index target, x, y
486 var offset/ecx: (offset screen-cell) <- compute-offset data, index
487 var src-cell/esi: (addr screen-cell) <- index data, offset
488 var src-grapheme/eax: (addr grapheme) <- get src-cell, data
489 var src-color/ecx: (addr int) <- get src-cell, color
490 var src-background-color/edx: (addr int) <- get src-cell, background-color
491 draw-grapheme-at-cursor screen, *src-grapheme, *src-color, *src-background-color
492 }
493
494 fn render-sandbox-menu screen: (addr screen), _self: (addr sandbox) {
495 var _width/eax: int <- copy 0
496 var height/ecx: int <- copy 0
497 _width, height <- screen-size screen
498 var width/edx: int <- copy _width
499 var y/ecx: int <- copy height
500 y <- decrement
501 var height/ebx: int <- copy y
502 height <- increment
503 clear-rect screen, 0/x, y, width, height, 0/bg=black
504 set-cursor-position screen, 0/x, y
505 draw-text-rightward-from-cursor screen, " ctrl-r ", width, 0/fg, 7/bg=grey
506 draw-text-rightward-from-cursor screen, " run main ", width, 7/fg, 0/bg
507 draw-text-rightward-from-cursor screen, " ctrl-s ", width, 0/fg, 7/bg=grey
508 draw-text-rightward-from-cursor screen, " run sandbox ", width, 7/fg, 0/bg
509 $render-sandbox-menu:render-tab: {
510 var self/eax: (addr sandbox) <- copy _self
511 var has-trace?/eax: boolean <- has-trace? self
512 compare has-trace?, 0/false
513 {
514 break-if-=
515 draw-text-rightward-from-cursor screen, " tab ", width, 0/fg, 9/bg=blue
516 draw-text-rightward-from-cursor screen, " to trace ", width, 7/fg, 0/bg
517 break $render-sandbox-menu:render-tab
518 }
519 draw-text-rightward-from-cursor screen, " tab ", width, 0/fg, 0x18/bg=keyboard
520 draw-text-rightward-from-cursor screen, " to keyboard ", width, 7/fg, 0/bg
521 }
522 draw-text-rightward-from-cursor screen, " ctrl-a ", width, 0/fg, 7/bg=grey
523 draw-text-rightward-from-cursor screen, " << ", width, 7/fg, 0/bg
524 draw-text-rightward-from-cursor screen, " ctrl-b ", width, 0/fg, 7/bg=grey
525 draw-text-rightward-from-cursor screen, " <word ", width, 7/fg, 0/bg
526 draw-text-rightward-from-cursor screen, " ctrl-f ", width, 0/fg, 7/bg=grey
527 draw-text-rightward-from-cursor screen, " word> ", width, 7/fg, 0/bg
528 draw-text-rightward-from-cursor screen, " ctrl-e ", width, 0/fg, 7/bg=grey
529 draw-text-rightward-from-cursor screen, " >> ", width, 7/fg, 0/bg
530 }
531
532 fn render-keyboard-menu screen: (addr screen) {
533 var width/eax: int <- copy 0
534 var height/ecx: int <- copy 0
535 width, height <- screen-size screen
536 var y/ecx: int <- copy height
537 y <- decrement
538 var height/edx: int <- copy y
539 height <- increment
540 clear-rect screen, 0/x, y, width, height, 0/bg=black
541 set-cursor-position screen, 0/x, y
542 draw-text-rightward-from-cursor screen, " ctrl-r ", width, 0/fg, 7/bg=grey
543 draw-text-rightward-from-cursor screen, " run main ", width, 7/fg, 0/bg
544 draw-text-rightward-from-cursor screen, " ctrl-s ", width, 0/fg, 7/bg=grey
545 draw-text-rightward-from-cursor screen, " run sandbox ", width, 7/fg, 0/bg
546 draw-text-rightward-from-cursor screen, " tab ", width, 0/fg, 3/bg=cyan
547 draw-text-rightward-from-cursor screen, " to sandbox ", width, 7/fg, 0/bg
548 }
549
550 fn edit-sandbox _self: (addr sandbox), key: byte, globals: (addr global-table), data-disk: (addr disk), real-screen: (addr screen), tweak-real-screen?: boolean {
551 var self/esi: (addr sandbox) <- copy _self
552 var g/edx: grapheme <- copy key
553
554 {
555 compare g, 0x13/ctrl-s
556 break-if-!=
557
558
559
560
561 store-state data-disk, self, globals
562
563 var data-ah/eax: (addr handle gap-buffer) <- get self, data
564 var _data/eax: (addr gap-buffer) <- lookup *data-ah
565 var data/ecx: (addr gap-buffer) <- copy _data
566 var value-ah/eax: (addr handle stream byte) <- get self, value
567 var _value/eax: (addr stream byte) <- lookup *value-ah
568 var value/edx: (addr stream byte) <- copy _value
569 var trace-ah/eax: (addr handle trace) <- get self, trace
570 var _trace/eax: (addr trace) <- lookup *trace-ah
571 var trace/ebx: (addr trace) <- copy _trace
572 clear-trace trace
573 {
574 compare tweak-real-screen?, 0/false
575 break-if-=
576 clear-sandbox-output real-screen, self, 0x40/sandbox-left-margin, 0/y, 0x80/screen-width, 0x2f/screen-height-without-menu
577 }
578 var screen-cell/eax: (addr handle cell) <- get self, screen-var
579 clear-screen-cell screen-cell
580 var keyboard-cell/esi: (addr handle cell) <- get self, keyboard-var
581 rewind-keyboard-cell keyboard-cell
582 {
583 compare tweak-real-screen?, 0/false
584 break-if-=
585 set-cursor-position real-screen, 0/x, 0/y
586 }
587 run data, value, globals, trace, screen-cell, keyboard-cell
588 return
589 }
590
591 {
592 compare g, 9/tab
593 break-if-!=
594
595 {
596 var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data?
597 compare *cursor-in-data?, 0/false
598 break-if-=
599 var has-trace?/eax: boolean <- has-trace? self
600 compare has-trace?, 0/false
601 {
602 break-if-=
603 var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data?
604 copy-to *cursor-in-data?, 0/false
605 var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace?
606 copy-to *cursor-in-trace?, 1/false
607 return
608 }
609 var has-keyboard?/eax: boolean <- has-keyboard? self
610 compare has-keyboard?, 0/false
611 {
612 break-if-=
613 var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data?
614 copy-to *cursor-in-data?, 0/false
615 var cursor-in-keyboard?/eax: (addr boolean) <- get self, cursor-in-keyboard?
616 copy-to *cursor-in-keyboard?, 1/false
617 return
618 }
619 return
620 }
621
622 {
623 var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace?
624 compare *cursor-in-trace?, 0/false
625 break-if-=
626 copy-to *cursor-in-trace?, 0/false
627 var cursor-target/ecx: (addr boolean) <- get self, cursor-in-keyboard?
628 var has-keyboard?/eax: boolean <- has-keyboard? self
629 compare has-keyboard?, 0/false
630 {
631 break-if-!=
632 cursor-target <- get self, cursor-in-data?
633 }
634 copy-to *cursor-target, 1/true
635 return
636 }
637
638 {
639 var cursor-in-keyboard?/eax: (addr boolean) <- get self, cursor-in-keyboard?
640 compare *cursor-in-keyboard?, 0/false
641 break-if-=
642 copy-to *cursor-in-keyboard?, 0/false
643 var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data?
644 copy-to *cursor-in-data?, 1/true
645 return
646 }
647 return
648 }
649
650 {
651 var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data?
652 compare *cursor-in-data?, 0/false
653 break-if-=
654 var data-ah/eax: (addr handle gap-buffer) <- get self, data
655 var data/eax: (addr gap-buffer) <- lookup *data-ah
656 edit-gap-buffer data, g
657 return
658 }
659
660 {
661 var cursor-in-keyboard?/eax: (addr boolean) <- get self, cursor-in-keyboard?
662 compare *cursor-in-keyboard?, 0/false
663 break-if-=
664 var keyboard-cell-ah/eax: (addr handle cell) <- get self, keyboard-var
665 var keyboard-cell/eax: (addr cell) <- lookup *keyboard-cell-ah
666 compare keyboard-cell, 0
667 {
668 break-if-!=
669 return
670 }
671 var keyboard-cell-type/ecx: (addr int) <- get keyboard-cell, type
672 compare *keyboard-cell-type, 6/keyboard
673 {
674 break-if-=
675 return
676 }
677 var keyboard-ah/eax: (addr handle gap-buffer) <- get keyboard-cell, keyboard-data
678 var keyboard/eax: (addr gap-buffer) <- lookup *keyboard-ah
679 edit-gap-buffer keyboard, g
680 return
681 }
682
683 {
684 var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace?
685 compare *cursor-in-trace?, 0/false
686 break-if-=
687 var trace-ah/eax: (addr handle trace) <- get self, trace
688 var trace/eax: (addr trace) <- lookup *trace-ah
689 edit-trace trace, g
690 return
691 }
692 }
693
694 fn run in: (addr gap-buffer), out: (addr stream byte), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell) {
695 var read-result-storage: (handle cell)
696 var read-result/esi: (addr handle cell) <- address read-result-storage
697 read-cell in, read-result, trace
698 var error?/eax: boolean <- has-errors? trace
699 {
700 compare error?, 0/false
701 break-if-=
702 return
703 }
704 var nil-storage: (handle cell)
705 var nil-ah/eax: (addr handle cell) <- address nil-storage
706 allocate-pair nil-ah
707 var eval-result-storage: (handle cell)
708 var eval-result/edi: (addr handle cell) <- address eval-result-storage
709 debug-print "^", 4/fg, 0/bg
710 evaluate read-result, eval-result, *nil-ah, globals, trace, screen-cell, keyboard-cell, 1/call-number
711 debug-print "$", 4/fg, 0/bg
712 var error?/eax: boolean <- has-errors? trace
713 {
714 compare error?, 0/false
715 break-if-=
716 return
717 }
718 clear-stream out
719 print-cell eval-result, out, trace
720 mark-lines-dirty trace
721 }
722
723 fn test-run-integer {
724 var sandbox-storage: sandbox
725 var sandbox/esi: (addr sandbox) <- address sandbox-storage
726 initialize-sandbox sandbox, 0/no-screen-or-keyboard
727
728 edit-sandbox sandbox, 0x31/1, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
729
730 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
731
732 var screen-on-stack: screen
733 var screen/edi: (addr screen) <- address screen-on-stack
734 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
735
736 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
737 check-screen-row screen, 0/y, "1 ", "F - test-run-integer/0"
738 check-screen-row screen, 1/y, "... ", "F - test-run-integer/1"
739 check-screen-row screen, 2/y, "=> 1 ", "F - test-run-integer/2"
740 }
741
742 fn test-run-with-spaces {
743 var sandbox-storage: sandbox
744 var sandbox/esi: (addr sandbox) <- address sandbox-storage
745 initialize-sandbox sandbox, 0/no-screen-or-keyboard
746
747 edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
748 edit-sandbox sandbox, 0x31/1, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
749 edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
750 edit-sandbox sandbox, 0xa/newline, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
751
752 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
753
754 var screen-on-stack: screen
755 var screen/edi: (addr screen) <- address screen-on-stack
756 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
757
758 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
759 check-screen-row screen, 0/y, " 1 ", "F - test-run-with-spaces/0"
760 check-screen-row screen, 1/y, " ", "F - test-run-with-spaces/1"
761 check-screen-row screen, 2/y, "... ", "F - test-run-with-spaces/2"
762 check-screen-row screen, 3/y, "=> 1 ", "F - test-run-with-spaces/3"
763 }
764
765 fn test-run-quote {
766 var sandbox-storage: sandbox
767 var sandbox/esi: (addr sandbox) <- address sandbox-storage
768 initialize-sandbox sandbox, 0/no-screen-or-keyboard
769
770 edit-sandbox sandbox, 0x27/quote, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
771 edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
772
773 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
774
775 var screen-on-stack: screen
776 var screen/edi: (addr screen) <- address screen-on-stack
777 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
778
779 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
780 check-screen-row screen, 0/y, "'a ", "F - test-run-quote/0"
781 check-screen-row screen, 1/y, "... ", "F - test-run-quote/1"
782 check-screen-row screen, 2/y, "=> a ", "F - test-run-quote/2"
783 }
784
785 fn test-run-dotted-list {
786 var sandbox-storage: sandbox
787 var sandbox/esi: (addr sandbox) <- address sandbox-storage
788 initialize-sandbox sandbox, 0/no-screen-or-keyboard
789
790 edit-sandbox sandbox, 0x27/quote, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
791 edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
792 edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
793 edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
794 edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
795 edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
796 edit-sandbox sandbox, 0x62/b, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
797 edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
798
799 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
800
801 var screen-on-stack: screen
802 var screen/edi: (addr screen) <- address screen-on-stack
803 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
804
805 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
806 check-screen-row screen, 0/y, "'(a . b) ", "F - test-run-dotted-list/0"
807 check-screen-row screen, 1/y, "... ", "F - test-run-dotted-list/1"
808 check-screen-row screen, 2/y, "=> (a . b) ", "F - test-run-dotted-list/2"
809 }
810
811 fn test-run-dot-and-list {
812 var sandbox-storage: sandbox
813 var sandbox/esi: (addr sandbox) <- address sandbox-storage
814 initialize-sandbox sandbox, 0/no-screen-or-keyboard
815
816 edit-sandbox sandbox, 0x27/quote, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
817 edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
818 edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
819 edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
820 edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
821 edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
822 edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
823 edit-sandbox sandbox, 0x62/b, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
824 edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
825 edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
826
827 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
828
829 var screen-on-stack: screen
830 var screen/edi: (addr screen) <- address screen-on-stack
831 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
832
833 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
834 check-screen-row screen, 0/y, "'(a . (b)) ", "F - test-run-dot-and-list/0"
835 check-screen-row screen, 1/y, "... ", "F - test-run-dot-and-list/1"
836 check-screen-row screen, 2/y, "=> (a b) ", "F - test-run-dot-and-list/2"
837 }
838
839 fn test-run-final-dot {
840 var sandbox-storage: sandbox
841 var sandbox/esi: (addr sandbox) <- address sandbox-storage
842 initialize-sandbox sandbox, 0/no-screen-or-keyboard
843
844 edit-sandbox sandbox, 0x27/quote, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
845 edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
846 edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
847 edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
848 edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
849 edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
850
851 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
852
853 var screen-on-stack: screen
854 var screen/edi: (addr screen) <- address screen-on-stack
855 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
856
857 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
858 check-screen-row screen, 0/y, "'(a .) ", "F - test-run-final-dot/0"
859 check-screen-row screen, 1/y, "... ", "F - test-run-final-dot/1"
860 check-screen-row screen, 2/y, "'. )' makes no sense ", "F - test-run-final-dot/2"
861
862 }
863
864 fn test-run-double-dot {
865 var sandbox-storage: sandbox
866 var sandbox/esi: (addr sandbox) <- address sandbox-storage
867 initialize-sandbox sandbox, 0/no-screen-or-keyboard
868
869 edit-sandbox sandbox, 0x27/quote, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
870 edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
871 edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
872 edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
873 edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
874 edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
875 edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
876 edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
877
878 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
879
880 var screen-on-stack: screen
881 var screen/edi: (addr screen) <- address screen-on-stack
882 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
883
884 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
885 check-screen-row screen, 0/y, "'(a . .) ", "F - test-run-double-dot/0"
886 check-screen-row screen, 1/y, "... ", "F - test-run-double-dot/1"
887 check-screen-row screen, 2/y, "'. .' makes no sense ", "F - test-run-double-dot/2"
888
889 }
890
891 fn test-run-multiple-expressions-after-dot {
892 var sandbox-storage: sandbox
893 var sandbox/esi: (addr sandbox) <- address sandbox-storage
894 initialize-sandbox sandbox, 0/no-screen-or-keyboard
895
896 edit-sandbox sandbox, 0x27/quote, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
897 edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
898 edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
899 edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
900 edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
901 edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
902 edit-sandbox sandbox, 0x62/b, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
903 edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
904 edit-sandbox sandbox, 0x63/c, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
905 edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
906
907 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
908
909 var screen-on-stack: screen
910 var screen/edi: (addr screen) <- address screen-on-stack
911 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
912
913 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
914 check-screen-row screen, 0/y, "'(a . b c) ", "F - test-run-multiple-expressions-after-dot/0"
915 check-screen-row screen, 1/y, "... ", "F - test-run-multiple-expressions-after-dot/1"
916 check-screen-row screen, 2/y, "cannot have multiple expressions between '.' and ')' ", "F - test-run-multiple-expressions-after-dot/2"
917
918 }
919
920 fn test-run-error-invalid-integer {
921 var sandbox-storage: sandbox
922 var sandbox/esi: (addr sandbox) <- address sandbox-storage
923 initialize-sandbox sandbox, 0/no-screen-or-keyboard
924
925 edit-sandbox sandbox, 0x31/1, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
926 edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
927
928 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
929
930 var screen-on-stack: screen
931 var screen/edi: (addr screen) <- address screen-on-stack
932 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
933
934 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
935 check-screen-row screen, 0/y, "1a ", "F - test-run-error-invalid-integer/0"
936 check-screen-row screen, 1/y, "... ", "F - test-run-error-invalid-integer/0"
937 check-screen-row screen, 2/y, "invalid number ", "F - test-run-error-invalid-integer/2"
938 }
939
940 fn test-run-move-cursor-into-trace {
941 var sandbox-storage: sandbox
942 var sandbox/esi: (addr sandbox) <- address sandbox-storage
943 initialize-sandbox sandbox, 0/no-screen-or-keyboard
944
945 edit-sandbox sandbox, 0x31/1, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
946 edit-sandbox sandbox, 0x32/2, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
947
948 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
949
950 var screen-on-stack: screen
951 var screen/edi: (addr screen) <- address screen-on-stack
952 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
953
954 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
955 check-screen-row screen, 0/y, "12 ", "F - test-run-move-cursor-into-trace/pre-0"
956 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-run-move-cursor-into-trace/pre-0/cursor"
957 check-screen-row screen, 1/y, "... ", "F - test-run-move-cursor-into-trace/pre-1"
958 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-run-move-cursor-into-trace/pre-1/cursor"
959 check-screen-row screen, 2/y, "=> 12 ", "F - test-run-move-cursor-into-trace/pre-2"
960 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-run-move-cursor-into-trace/pre-2/cursor"
961
962 edit-sandbox sandbox, 9/tab, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
963
964 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
965 check-screen-row screen, 0/y, "12 ", "F - test-run-move-cursor-into-trace/trace-0"
966 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-run-move-cursor-into-trace/trace-0/cursor"
967 check-screen-row screen, 1/y, "... ", "F - test-run-move-cursor-into-trace/trace-1"
968 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "||| ", "F - test-run-move-cursor-into-trace/trace-1/cursor"
969 check-screen-row screen, 2/y, "=> 12 ", "F - test-run-move-cursor-into-trace/trace-2"
970 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-run-move-cursor-into-trace/trace-2/cursor"
971
972 edit-sandbox sandbox, 9/tab, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
973
974 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
975 check-screen-row screen, 0/y, "12 ", "F - test-run-move-cursor-into-trace/input-0"
976 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-run-move-cursor-into-trace/input-0/cursor"
977 check-screen-row screen, 1/y, "... ", "F - test-run-move-cursor-into-trace/input-1"
978 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-run-move-cursor-into-trace/input-1/cursor"
979 check-screen-row screen, 2/y, "=> 12 ", "F - test-run-move-cursor-into-trace/input-2"
980 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-run-move-cursor-into-trace/input-2/cursor"
981 }
982
983 fn has-trace? _self: (addr sandbox) -> _/eax: boolean {
984 var self/esi: (addr sandbox) <- copy _self
985 var trace-ah/eax: (addr handle trace) <- get self, trace
986 var _trace/eax: (addr trace) <- lookup *trace-ah
987 var trace/edx: (addr trace) <- copy _trace
988 compare trace, 0
989 {
990 break-if-!=
991 return 0/false
992 }
993 var first-free/ebx: (addr int) <- get trace, first-free
994 compare *first-free, 0
995 {
996 break-if->
997 return 0/false
998 }
999 return 1/true
1000 }