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