https://github.com/akkartik/mu/blob/master/apps/tile/data.mu
1 type sandbox {
2 setup: (handle line)
3 data: (handle line)
4
5 cursor-call-path: (handle call-path-element)
6 expanded-words: (handle call-path)
7 partial-name-for-cursor-word: (handle word)
8 partial-name-for-function: (handle word)
9
10 next: (handle sandbox)
11 prev: (handle sandbox)
12 }
13
14 type function {
15 name: (handle array byte)
16 args: (handle word)
17 body: (handle line)
18
19 next: (handle function)
20 }
21
22 type line {
23 name: (handle array byte)
24 data: (handle word)
25 result: (handle result)
26 next: (handle line)
27 prev: (handle line)
28 }
29
30 type word {
31 scalar-data: (handle gap-buffer)
32 next: (handle word)
33 prev: (handle word)
34 }
35
36 type value {
37 type: int
38 int-data: int
39 text-data: (handle array byte)
40 array-data: (handle array value)
41 file-data: (handle buffered-file)
42 }
43
44 type table {
45 data: (handle array bind)
46 next: (handle table)
47 }
48
49 type bind {
50 key: (handle array byte)
51 value: (handle value)
52 }
53
54
55
56 type call-path {
57 data: (handle call-path-element)
58 next: (handle call-path)
59 }
60
61
62 type call-path-element {
63 word: (handle word)
64 next: (handle call-path-element)
65 }
66
67 type result {
68 data: value-stack
69 error: (handle array byte)
70 }
71
72 fn initialize-sandbox _sandbox: (addr sandbox) {
73 var sandbox/esi: (addr sandbox) <- copy _sandbox
74 var line-ah/eax: (addr handle line) <- get sandbox, data
75 allocate line-ah
76 var line/eax: (addr line) <- lookup *line-ah
77 initialize-line line
78 var word-ah/ecx: (addr handle word) <- get line, data
79 var cursor-call-path-ah/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
80 allocate cursor-call-path-ah
81 var cursor-call-path/eax: (addr call-path-element) <- lookup *cursor-call-path-ah
82 var dest/eax: (addr handle word) <- get cursor-call-path, word
83 copy-object word-ah, dest
84 }
85
86
87 fn initialize-line _line: (addr line) {
88 var line/esi: (addr line) <- copy _line
89 var word-ah/eax: (addr handle word) <- get line, data
90 allocate word-ah
91 var word/eax: (addr word) <- lookup *word-ah
92 initialize-word word
93 }
94
95 fn create-primitive-functions _self: (addr handle function) {
96
97 var self/esi: (addr handle function) <- copy _self
98 allocate self
99 var _f/eax: (addr function) <- lookup *self
100 var f/esi: (addr function) <- copy _f
101 var name-ah/eax: (addr handle array byte) <- get f, name
102 populate-text-with name-ah, "2*"
103 var args-ah/eax: (addr handle word) <- get f, args
104 allocate args-ah
105 var args/eax: (addr word) <- lookup *args-ah
106 initialize-word-with args, "x"
107 var body-ah/eax: (addr handle line) <- get f, body
108 allocate body-ah
109 var body/eax: (addr line) <- lookup *body-ah
110 initialize-line body
111 var curr-word-ah/ecx: (addr handle word) <- get body, data
112
113 allocate curr-word-ah
114 var tmp/eax: (addr word) <- lookup *curr-word-ah
115 var curr-word/edx: (addr word) <- copy tmp
116 initialize-word-with curr-word, "x"
117
118 var next-word-ah/ebx: (addr handle word) <- get curr-word, next
119 allocate next-word-ah
120 tmp <- lookup *next-word-ah
121 initialize-word-with tmp, "2"
122
123 var prev-word-ah/edi: (addr handle word) <- get tmp, prev
124 copy-object curr-word-ah, prev-word-ah
125
126 curr-word-ah <- copy next-word-ah
127 curr-word <- copy tmp
128
129 next-word-ah <- get curr-word, next
130 allocate next-word-ah
131 tmp <- lookup *next-word-ah
132 initialize-word-with tmp, "*"
133
134 prev-word-ah <- get tmp, prev
135 copy-object curr-word-ah, prev-word-ah
136 tmp <- lookup *prev-word-ah
137
138 var next/esi: (addr handle function) <- get f, next
139 allocate next
140 var _f/eax: (addr function) <- lookup *next
141 var f/esi: (addr function) <- copy _f
142 var name-ah/eax: (addr handle array byte) <- get f, name
143 populate-text-with name-ah, "1+"
144 var args-ah/eax: (addr handle word) <- get f, args
145 allocate args-ah
146 var args/eax: (addr word) <- lookup *args-ah
147 initialize-word-with args, "x"
148 var body-ah/eax: (addr handle line) <- get f, body
149 allocate body-ah
150 var body/eax: (addr line) <- lookup *body-ah
151 initialize-line body
152 var curr-word-ah/ecx: (addr handle word) <- get body, data
153
154 allocate curr-word-ah
155 var tmp/eax: (addr word) <- lookup *curr-word-ah
156 curr-word <- copy tmp
157 initialize-word-with curr-word, "x"
158
159 next-word-ah <- get curr-word, next
160 allocate next-word-ah
161 tmp <- lookup *next-word-ah
162 initialize-word-with tmp, "1"
163
164 prev-word-ah <- get tmp, prev
165 copy-object curr-word-ah, prev-word-ah
166
167 curr-word-ah <- copy next-word-ah
168 curr-word <- copy tmp
169
170 next-word-ah <- get curr-word, next
171 allocate next-word-ah
172 tmp <- lookup *next-word-ah
173 initialize-word-with tmp, "+"
174
175 prev-word-ah <- get tmp, prev
176 copy-object curr-word-ah, prev-word-ah
177 tmp <- lookup *prev-word-ah
178
179 var next/esi: (addr handle function) <- get f, next
180 allocate next
181 var _f/eax: (addr function) <- lookup *next
182 var f/esi: (addr function) <- copy _f
183 var name-ah/eax: (addr handle array byte) <- get f, name
184 populate-text-with name-ah, "2+"
185 var args-ah/eax: (addr handle word) <- get f, args
186 allocate args-ah
187 var args/eax: (addr word) <- lookup *args-ah
188 initialize-word-with args, "x"
189 var body-ah/eax: (addr handle line) <- get f, body
190 allocate body-ah
191 var body/eax: (addr line) <- lookup *body-ah
192 initialize-line body
193 var curr-word-ah/ecx: (addr handle word) <- get body, data
194
195 allocate curr-word-ah
196 var tmp/eax: (addr word) <- lookup *curr-word-ah
197 curr-word <- copy tmp
198 initialize-word-with curr-word, "x"
199
200 next-word-ah <- get curr-word, next
201 allocate next-word-ah
202 tmp <- lookup *next-word-ah
203 initialize-word-with tmp, "1+"
204
205 prev-word-ah <- get tmp, prev
206 copy-object curr-word-ah, prev-word-ah
207
208 curr-word-ah <- copy next-word-ah
209 curr-word <- copy tmp
210
211 next-word-ah <- get curr-word, next
212 allocate next-word-ah
213 tmp <- lookup *next-word-ah
214 initialize-word-with tmp, "1+"
215
216 prev-word-ah <- get tmp, prev
217 copy-object curr-word-ah, prev-word-ah
218 tmp <- lookup *prev-word-ah
219
220 var next/esi: (addr handle function) <- get f, next
221 allocate next
222 var _f/eax: (addr function) <- lookup *next
223 var f/esi: (addr function) <- copy _f
224 var name-ah/eax: (addr handle array byte) <- get f, name
225 populate-text-with name-ah, "square"
226 var args-ah/eax: (addr handle word) <- get f, args
227 allocate args-ah
228 var args/eax: (addr word) <- lookup *args-ah
229 initialize-word-with args, "x"
230 var body-ah/eax: (addr handle line) <- get f, body
231 allocate body-ah
232 var body/eax: (addr line) <- lookup *body-ah
233 initialize-line body
234 var curr-word-ah/ecx: (addr handle word) <- get body, data
235
236 allocate curr-word-ah
237 var tmp/eax: (addr word) <- lookup *curr-word-ah
238 var curr-word/edx: (addr word) <- copy tmp
239 initialize-word-with curr-word, "x"
240
241 var next-word-ah/ebx: (addr handle word) <- get curr-word, next
242 allocate next-word-ah
243 tmp <- lookup *next-word-ah
244 initialize-word-with tmp, "x"
245
246 var prev-word-ah/edi: (addr handle word) <- get tmp, prev
247 copy-object curr-word-ah, prev-word-ah
248
249 curr-word-ah <- copy next-word-ah
250 curr-word <- copy tmp
251
252 next-word-ah <- get curr-word, next
253 allocate next-word-ah
254 tmp <- lookup *next-word-ah
255 initialize-word-with tmp, "*"
256
257 prev-word-ah <- get tmp, prev
258 copy-object curr-word-ah, prev-word-ah
259 tmp <- lookup *prev-word-ah
260
261 var next/esi: (addr handle function) <- get f, next
262 allocate next
263 var _f/eax: (addr function) <- lookup *next
264 var f/esi: (addr function) <- copy _f
265 var name-ah/eax: (addr handle array byte) <- get f, name
266 populate-text-with name-ah, "1-"
267 var args-ah/eax: (addr handle word) <- get f, args
268 allocate args-ah
269 var args/eax: (addr word) <- lookup *args-ah
270 initialize-word-with args, "x"
271 var body-ah/eax: (addr handle line) <- get f, body
272 allocate body-ah
273 var body/eax: (addr line) <- lookup *body-ah
274 initialize-line body
275 var curr-word-ah/ecx: (addr handle word) <- get body, data
276
277 allocate curr-word-ah
278 var tmp/eax: (addr word) <- lookup *curr-word-ah
279 curr-word <- copy tmp
280 initialize-word-with curr-word, "x"
281
282 next-word-ah <- get curr-word, next
283 allocate next-word-ah
284 tmp <- lookup *next-word-ah
285 initialize-word-with tmp, "1"
286
287 prev-word-ah <- get tmp, prev
288 copy-object curr-word-ah, prev-word-ah
289
290 curr-word-ah <- copy next-word-ah
291 curr-word <- copy tmp
292
293 next-word-ah <- get curr-word, next
294 allocate next-word-ah
295 tmp <- lookup *next-word-ah
296 initialize-word-with tmp, "-"
297
298 prev-word-ah <- get tmp, prev
299 copy-object curr-word-ah, prev-word-ah
300 tmp <- lookup *prev-word-ah
301
302 var next/esi: (addr handle function) <- get f, next
303 allocate next
304 var _f/eax: (addr function) <- lookup *next
305 var f/esi: (addr function) <- copy _f
306 var name-ah/eax: (addr handle array byte) <- get f, name
307 populate-text-with name-ah, "sub"
308
309 var args-ah/eax: (addr handle word) <- get f, args
310 allocate args-ah
311 var args/eax: (addr word) <- lookup *args-ah
312 initialize-word-with args, "y"
313 var next-arg-ah/eax: (addr handle word) <- get args, next
314 allocate next-arg-ah
315 var next-arg/eax: (addr word) <- lookup *next-arg-ah
316 initialize-word-with next-arg, "x"
317 var body-ah/eax: (addr handle line) <- get f, body
318 allocate body-ah
319 var body/eax: (addr line) <- lookup *body-ah
320 initialize-line body
321 var curr-word-ah/ecx: (addr handle word) <- get body, data
322
323 allocate curr-word-ah
324 var tmp/eax: (addr word) <- lookup *curr-word-ah
325 curr-word <- copy tmp
326 initialize-word-with curr-word, "x"
327
328 next-word-ah <- get curr-word, next
329 allocate next-word-ah
330 tmp <- lookup *next-word-ah
331 initialize-word-with tmp, "y"
332
333 prev-word-ah <- get tmp, prev
334 copy-object curr-word-ah, prev-word-ah
335
336 curr-word-ah <- copy next-word-ah
337 curr-word <- copy tmp
338
339 next-word-ah <- get curr-word, next
340 allocate next-word-ah
341 tmp <- lookup *next-word-ah
342 initialize-word-with tmp, "-"
343
344 prev-word-ah <- get tmp, prev
345 copy-object curr-word-ah, prev-word-ah
346 tmp <- lookup *prev-word-ah
347 }
348
349 fn function-body functions: (addr handle function), _word: (addr handle word), out: (addr handle line) {
350 var function-name-storage: (handle array byte)
351 var function-name-ah/ecx: (addr handle array byte) <- address function-name-storage
352 var word-ah/esi: (addr handle word) <- copy _word
353 var word/eax: (addr word) <- lookup *word-ah
354 var gap-ah/eax: (addr handle gap-buffer) <- get word, scalar-data
355 var gap/eax: (addr gap-buffer) <- lookup *gap-ah
356 gap-buffer-to-string gap, function-name-ah
357 var _function-name/eax: (addr array byte) <- lookup *function-name-ah
358 var function-name/esi: (addr array byte) <- copy _function-name
359 var curr-ah/ecx: (addr handle function) <- copy functions
360 $function-body:loop: {
361 var _curr/eax: (addr function) <- lookup *curr-ah
362 var curr/edx: (addr function) <- copy _curr
363 compare curr, 0
364 break-if-=
365 var curr-name-ah/eax: (addr handle array byte) <- get curr, name
366 var curr-name/eax: (addr array byte) <- lookup *curr-name-ah
367 var found?/eax: boolean <- string-equal? curr-name, function-name
368 compare found?, 0
369 {
370 break-if-=
371 var src/eax: (addr handle line) <- get curr, body
372 copy-object src, out
373 break $function-body:loop
374 }
375 curr-ah <- get curr, next
376 loop
377 }
378 }
379
380 fn body-length functions: (addr handle function), function-name: (addr handle word) -> _/eax: int {
381 var body-storage: (handle line)
382 var body-ah/edi: (addr handle line) <- address body-storage
383 function-body functions, function-name, body-ah
384 var body/eax: (addr line) <- lookup *body-ah
385 var result/eax: int <- line-length body
386 return result
387 }
388
389 fn line-length _in: (addr line) -> _/eax: int {
390 var in/esi: (addr line) <- copy _in
391 var curr-ah/ecx: (addr handle word) <- get in, data
392 var result/edi: int <- copy 0
393 {
394 var curr/eax: (addr word) <- lookup *curr-ah
395 compare curr, 0
396 break-if-=
397 curr-ah <- get curr, next
398 result <- increment
399 loop
400 }
401 return result
402 }
403
404 fn populate-text-with _out: (addr handle array byte), _in: (addr array byte) {
405 var in/esi: (addr array byte) <- copy _in
406 var n/ecx: int <- length in
407 var out/edx: (addr handle array byte) <- copy _out
408 populate out, n
409 var _out-addr/eax: (addr array byte) <- lookup *out
410 var out-addr/edx: (addr array byte) <- copy _out-addr
411 var i/eax: int <- copy 0
412 {
413 compare i, n
414 break-if->=
415 var src/esi: (addr byte) <- index in, i
416 var val/ecx: byte <- copy-byte *src
417 var dest/edi: (addr byte) <- index out-addr, i
418 copy-byte-to *dest, val
419 i <- increment
420 loop
421 }
422 }
423
424 fn initialize-path-from-sandbox _in: (addr sandbox), _out: (addr handle call-path-element) {
425 var sandbox/esi: (addr sandbox) <- copy _in
426 var line-ah/eax: (addr handle line) <- get sandbox, data
427 var line/eax: (addr line) <- lookup *line-ah
428 var src/esi: (addr handle word) <- get line, data
429 var out-ah/edi: (addr handle call-path-element) <- copy _out
430 var out/eax: (addr call-path-element) <- lookup *out-ah
431 var dest/edi: (addr handle word) <- get out, word
432 copy-object src, dest
433 }
434
435 fn initialize-path-from-line _line: (addr line), _out: (addr handle call-path-element) {
436 var line/eax: (addr line) <- copy _line
437 var src/esi: (addr handle word) <- get line, data
438 var out-ah/edi: (addr handle call-path-element) <- copy _out
439 var out/eax: (addr call-path-element) <- lookup *out-ah
440 var dest/edi: (addr handle word) <- get out, word
441 copy-object src, dest
442 }
443
444 fn find-in-call-paths call-paths: (addr handle call-path), needle: (addr handle call-path-element) -> _/eax: boolean {
445 var curr-ah/esi: (addr handle call-path) <- copy call-paths
446 $find-in-call-path:loop: {
447 var curr/eax: (addr call-path) <- lookup *curr-ah
448 compare curr, 0
449 break-if-=
450 {
451 var curr-data/eax: (addr handle call-path-element) <- get curr, data
452 var match?/eax: boolean <- call-path-element-match? curr-data, needle
453 compare match?, 0
454 {
455 break-if-=
456 return 1
457 }
458 }
459 curr-ah <- get curr, next
460 loop
461 }
462 return 0
463 }
464
465 fn call-path-element-match? _x: (addr handle call-path-element), _y: (addr handle call-path-element) -> _/eax: boolean {
466 var x-ah/eax: (addr handle call-path-element) <- copy _x
467 var x-a/eax: (addr call-path-element) <- lookup *x-ah
468 var x/esi: (addr call-path-element) <- copy x-a
469 var y-ah/eax: (addr handle call-path-element) <- copy _y
470 var y-a/eax: (addr call-path-element) <- lookup *y-ah
471 var y/edi: (addr call-path-element) <- copy y-a
472 compare x, y
473 {
474 break-if-!=
475 return 1
476 }
477 compare x, 0
478 {
479 break-if-!=
480 return 0
481 }
482 compare y, 0
483 {
484 break-if-!=
485 return 0
486 }
487
488 var x-data-ah/ecx: (addr handle word) <- get x, word
489 var x-data-a/eax: (addr word) <- lookup *x-data-ah
490 var x-data/ecx: int <- copy x-data-a
491 var y-data-ah/eax: (addr handle word) <- get y, word
492 var y-data-a/eax: (addr word) <- lookup *y-data-ah
493 var y-data/eax: int <- copy y-data-a
494
495
496
497
498
499 compare x-data, y-data
500 {
501 break-if-=
502 return 0
503 }
504 var x-next/ecx: (addr handle call-path-element) <- get x, next
505 var y-next/eax: (addr handle call-path-element) <- get y, next
506 var result/eax: boolean <- call-path-element-match? x-next, y-next
507 return result
508 }
509
510
511 fn insert-in-call-path list: (addr handle call-path), new: (addr handle call-path-element) {
512 var new-path-storage: (handle call-path)
513 var new-path-ah/edi: (addr handle call-path) <- address new-path-storage
514 allocate new-path-ah
515 var new-path/eax: (addr call-path) <- lookup *new-path-ah
516 var next/ecx: (addr handle call-path) <- get new-path, next
517 copy-object list, next
518 var dest/ecx: (addr handle call-path-element) <- get new-path, data
519 deep-copy-call-path-element new, dest
520 copy-object new-path-ah, list
521 }
522
523
524 fn deep-copy-call-path-element _src: (addr handle call-path-element), _dest: (addr handle call-path-element) {
525 var src/esi: (addr handle call-path-element) <- copy _src
526
527 var _src-addr/eax: (addr call-path-element) <- lookup *src
528 compare _src-addr, 0
529 break-if-=
530
531 var src-addr/esi: (addr call-path-element) <- copy _src-addr
532 var dest/eax: (addr handle call-path-element) <- copy _dest
533 allocate dest
534
535 var dest-addr/eax: (addr call-path-element) <- lookup *dest
536 {
537 var dest-data-addr/ecx: (addr handle word) <- get dest-addr, word
538 var src-data-addr/eax: (addr handle word) <- get src-addr, word
539 copy-object src-data-addr, dest-data-addr
540 }
541
542 var src-next/esi: (addr handle call-path-element) <- get src-addr, next
543 var dest-next/eax: (addr handle call-path-element) <- get dest-addr, next
544 deep-copy-call-path-element src-next, dest-next
545 }
546
547 fn delete-in-call-path list: (addr handle call-path), needle: (addr handle call-path-element) {
548 var curr-ah/esi: (addr handle call-path) <- copy list
549 $delete-in-call-path:loop: {
550 var _curr/eax: (addr call-path) <- lookup *curr-ah
551 var curr/ecx: (addr call-path) <- copy _curr
552 compare curr, 0
553 break-if-=
554 {
555 var curr-data/eax: (addr handle call-path-element) <- get curr, data
556 var match?/eax: boolean <- call-path-element-match? curr-data, needle
557 compare match?, 0
558 {
559 break-if-=
560 var next-ah/ecx: (addr handle call-path) <- get curr, next
561 copy-object next-ah, curr-ah
562 loop $delete-in-call-path:loop
563 }
564 }
565 curr-ah <- get curr, next
566 loop
567 }
568 }
569
570 fn increment-final-element list: (addr handle call-path-element) {
571 var final-ah/eax: (addr handle call-path-element) <- copy list
572 var final/eax: (addr call-path-element) <- lookup *final-ah
573 var val-ah/ecx: (addr handle word) <- get final, word
574 var val/eax: (addr word) <- lookup *val-ah
575 var new-ah/edx: (addr handle word) <- get val, next
576 var target/eax: (addr word) <- lookup *new-ah
577 compare target, 0
578 break-if-=
579 copy-object new-ah, val-ah
580 }
581
582 fn decrement-final-element list: (addr handle call-path-element) {
583 var final-ah/eax: (addr handle call-path-element) <- copy list
584 var final/eax: (addr call-path-element) <- lookup *final-ah
585 var val-ah/ecx: (addr handle word) <- get final, word
586 var val/eax: (addr word) <- lookup *val-ah
587
588
589
590
591
592 var new-ah/edx: (addr handle word) <- get val, prev
593 var target/eax: (addr word) <- lookup *new-ah
594 compare target, 0
595 break-if-=
596
597
598
599
600
601
602
603 copy-object new-ah, val-ah
604 }
605
606 fn move-final-element-to-start-of-line list: (addr handle call-path-element) {
607 var final-ah/eax: (addr handle call-path-element) <- copy list
608 var final/eax: (addr call-path-element) <- lookup *final-ah
609 var val-ah/ecx: (addr handle word) <- get final, word
610 var val/eax: (addr word) <- lookup *val-ah
611 var new-ah/edx: (addr handle word) <- get val, prev
612 var target/eax: (addr word) <- lookup *new-ah
613 compare target, 0
614 break-if-=
615 copy-object new-ah, val-ah
616 move-final-element-to-start-of-line list
617 }
618
619 fn push-to-call-path-element list: (addr handle call-path-element), new: (addr handle word) {
620 var new-element-storage: (handle call-path-element)
621 var new-element-ah/edi: (addr handle call-path-element) <- address new-element-storage
622 allocate new-element-ah
623 var new-element/eax: (addr call-path-element) <- lookup *new-element-ah
624
625 var dest/ecx: (addr handle word) <- get new-element, word
626 copy-object new, dest
627
628 var dest2/ecx: (addr handle call-path-element) <- get new-element, next
629 copy-object list, dest2
630
631 copy-object new-element-ah, list
632 }
633
634 fn drop-from-call-path-element _list: (addr handle call-path-element) {
635 var list-ah/esi: (addr handle call-path-element) <- copy _list
636 var list/eax: (addr call-path-element) <- lookup *list-ah
637 var next/eax: (addr handle call-path-element) <- get list, next
638 copy-object next, _list
639 }
640
641 fn drop-nested-calls _list: (addr handle call-path-element) {
642 var list-ah/esi: (addr handle call-path-element) <- copy _list
643 var list/eax: (addr call-path-element) <- lookup *list-ah
644 var next-ah/edi: (addr handle call-path-element) <- get list, next
645 var next/eax: (addr call-path-element) <- lookup *next-ah
646 compare next, 0
647 break-if-=
648 copy-object next-ah, _list
649 drop-nested-calls _list
650 }
651
652 fn dump-call-path-element screen: (addr screen), _x-ah: (addr handle call-path-element) {
653 var x-ah/ecx: (addr handle call-path-element) <- copy _x-ah
654 var _x/eax: (addr call-path-element) <- lookup *x-ah
655 var x/esi: (addr call-path-element) <- copy _x
656 var word-ah/eax: (addr handle word) <- get x, word
657 var word/eax: (addr word) <- lookup *word-ah
658 print-word screen, word
659 var next-ah/ecx: (addr handle call-path-element) <- get x, next
660 var next/eax: (addr call-path-element) <- lookup *next-ah
661 compare next, 0
662 {
663 break-if-=
664 print-string screen, " "
665 dump-call-path-element screen, next-ah
666 return
667 }
668 print-string screen, "\n"
669 }
670
671 fn dump-call-paths screen: (addr screen), _x-ah: (addr handle call-path) {
672 var x-ah/ecx: (addr handle call-path) <- copy _x-ah
673 var x/eax: (addr call-path) <- lookup *x-ah
674 compare x, 0
675 break-if-=
676 var src/ecx: (addr handle call-path-element) <- get x, data
677 dump-call-path-element screen, src
678 var next-ah/ecx: (addr handle call-path) <- get x, next
679 var next/eax: (addr call-path) <- lookup *next-ah
680 compare next, 0
681 {
682 break-if-=
683 dump-call-paths screen, next-ah
684 }
685 }