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