https://github.com/akkartik/mu/blob/main/linux/tile/rpn.mu
  1 fn evaluate functions: (addr handle function), bindings: (addr table), scratch: (addr line), end: (addr word), out: (addr value-stack) {
  2   var line/eax: (addr line) <- copy scratch
  3   var word-ah/eax: (addr handle word) <- get line, data
  4   var curr/eax: (addr word) <- lookup *word-ah
  5   var curr-stream-storage: (stream byte 0x10)
  6   var curr-stream/edi: (addr stream byte) <- address curr-stream-storage
  7   clear-value-stack out
  8   $evaluate:loop: {
  9     # precondition (should never hit)
 10     compare curr, 0
 11     break-if-=
 12     # update curr-stream
 13     emit-word curr, curr-stream
 14 #?     print-string-to-real-screen "eval: "
 15 #?     print-stream-to-real-screen curr-stream
 16 #?     print-string-to-real-screen "\n"
 17     $evaluate:process-word: {
 18       ### if curr-stream is an operator, perform it
 19       ## numbers
 20       {
 21         var add?/eax: boolean <- stream-data-equal? curr-stream, "+"
 22         compare add?, 0
 23         break-if-=
 24         var _b/xmm0: float <- pop-number-from-value-stack out
 25         var b/xmm1: float <- copy _b
 26         var a/xmm0: float <- pop-number-from-value-stack out
 27         a <- add b
 28         push-number-to-value-stack out, a
 29         break $evaluate:process-word
 30       }
 31       {
 32         var sub?/eax: boolean <- stream-data-equal? curr-stream, "-"
 33         compare sub?, 0
 34         break-if-=
 35         var _b/xmm0: float <- pop-number-from-value-stack out
 36         var b/xmm1: float <- copy _b
 37         var a/xmm0: float <- pop-number-from-value-stack out
 38         a <- subtract b
 39         push-number-to-value-stack out, a
 40         break $evaluate:process-word
 41       }
 42       {
 43         var mul?/eax: boolean <- stream-data-equal? curr-stream, "*"
 44         compare mul?, 0
 45         break-if-=
 46         var _b/xmm0: float <- pop-number-from-value-stack out
 47         var b/xmm1: float <- copy _b
 48         var a/xmm0: float <- pop-number-from-value-stack out
 49         a <- multiply b
 50         push-number-to-value-stack out, a
 51         break $evaluate:process-word
 52       }
 53       {
 54         var div?/eax: boolean <- stream-data-equal? curr-stream, "/"
 55         compare div?, 0
 56         break-if-=
 57         var _b/xmm0: float <- pop-number-from-value-stack out
 58         var b/xmm1: float <- copy _b
 59         var a/xmm0: float <- pop-number-from-value-stack out
 60         a <- divide b
 61         push-number-to-value-stack out, a
 62         break $evaluate:process-word
 63       }
 64       {
 65         var sqrt?/eax: boolean <- stream-data-equal? curr-stream, "sqrt"
 66         compare sqrt?, 0
 67         break-if-=
 68         var a/xmm0: float <- pop-number-from-value-stack out
 69         a <- square-root a
 70         push-number-to-value-stack out, a
 71         break $evaluate:process-word
 72       }
 73       ## strings/arrays
 74       {
 75         var len?/eax: boolean <- stream-data-equal? curr-stream, "len"
 76         compare len?, 0
 77         break-if-=
 78 #?         print-string 0, "is len\n"
 79         # pop target-val from out
 80         var out2/esi: (addr value-stack) <- copy out
 81         var top-addr/ecx: (addr int) <- get out2, top
 82         compare *top-addr, 0
 83         break-if-<=
 84 #?         print-string 0, "stack has stuff\n"
 85         var data-ah/eax: (addr handle array value) <- get out2, data
 86         var data/eax: (addr array value) <- lookup *data-ah
 87         var top/edx: int <- copy *top-addr
 88         top <- decrement
 89         var dest-offset/edx: (offset value) <- compute-offset data, top
 90         var target-val/edx: (addr value) <- index data, dest-offset
 91         # check target-val is a string or array
 92         var target-type-addr/eax: (addr int) <- get target-val, type
 93         compare *target-type-addr, 1/string
 94         {
 95           break-if-!=
 96           # compute length
 97           var src-ah/eax: (addr handle array byte) <- get target-val, text-data
 98           var src/eax: (addr array byte) <- lookup *src-ah
 99           var result/ebx: int <- length src
100           var result-f/xmm0: float <- convert result
101           # save result into target-val
102           var type-addr/eax: (addr int) <- get target-val, type
103           copy-to *type-addr, 0/int
104           var target-string-ah/eax: (addr handle array byte) <- get target-val, text-data
105           clear-object target-string-ah
106           var target/eax: (addr float) <- get target-val, number-data
107           copy-to *target, result-f
108           break $evaluate:process-word
109         }
110         compare *target-type-addr, 2/array
111         {
112           break-if-!=
113           # compute length
114           var src-ah/eax: (addr handle array value) <- get target-val, array-data
115           var src/eax: (addr array value) <- lookup *src-ah
116           var result/ebx: int <- length src
117           var result-f/xmm0: float <- convert result
118           # save result into target-val
119           var type-addr/eax: (addr int) <- get target-val, type
120           copy-to *type-addr, 0/int
121           var target-array-ah/eax: (addr handle array value) <- get target-val, array-data
122           clear-object target-array-ah
123           var target/eax: (addr float) <- get target-val, number-data
124           copy-to *target, result-f
125           break $evaluate:process-word
126         }
127       }
128       ## files
129       {
130         var open?/eax: boolean <- stream-data-equal? curr-stream, "open"
131         compare open?, 0
132         break-if-=
133         # pop target-val from out
134         var out2/esi: (addr value-stack) <- copy out
135         var top-addr/ecx: (addr int) <- get out2, top
136         compare *top-addr, 0
137         break-if-<=
c{0: 0 (((1 string-address)) <- ((new)) hello, _) -- nil
c{0: 1 (((2 string-address)) <- ((new)) abc) -- nil
c{0: 2 (((3 string-address)) <- ((interpolate)) ((1 string-address)) ((2 string-address))) -- nil
c{1: 0 ✓ (((1 string-address)) <- ((new)) hello, _)
c{1: 1 ✓ (((2 string-address)) <- ((new)) abc)
c{1: 2 ✓ (((3 string-address)) <- ((interpolate)) ((1 string-address)) ((2 string-address)))
cn0: convert-names in main
cn0: (((1 string-address)) <- ((new)) hello, _) nil nil
cn0: checking arg hello, _
cn0: checking oarg ((1 string-address))
maybe-add: ((1 string-address))
cn0: (((2 string-address)) <- ((new)) abc) nil nil
cn0: checking arg abc
cn0: checking oarg ((2 string-address))
maybe-add: ((2 string-address))
cn0: (((3 string-address)) <- ((interpolate)) ((1 string-address)) ((2 string-address))) nil nil
cn0: checking arg ((1 string-address))
maybe-add: ((1 string-address))
cn0: checking arg ((2 string-address))
maybe-add: ((2 string-address))
cn0: checking oarg ((3 string-address))
maybe-add: ((3 string-address))
cn1: (((1 string-address)) <- ((new)) hello, _)
cn1: (((2 string-address)) <- ((new)) abc)
cn1: (((3 string-address)) <- ((interpolate)) ((1 string-address)) ((2 string-address)))
schedule: main
run: main 0: (((1 string-address)) <- ((new)) hello, _)
run: main 0: 1000 => ((1 string-address))
mem: ((1 string-address)): 1 <= 1000
run: main 1: (((2 string-address)) <- ((new)) abc)
run: main 1: 1009 => ((2 string-address))
mem: ((2 string-address)): 2 <= 1009
run: main 2: (((3 string-address)) <- ((interpolate)) ((1 string-address)) ((2 string-address)))
mem: ((1 string-address)) => 1000
mem: ((2 string-address)) => 1009
run: interpolate/main 0: (((default-space space-address)) <- ((new)) ((space literal)) ((60 literal)))
run: interpolate/main 0: 1013 => ((default-space space-address))
run: interpolate/main 1: (((1 string-address)) <- ((next-input)))
arg: nil 0 (1000 1009)
run: interpolate/main 1: 1000 => ((1 string-address))
mem: ((1 string-address)): 1015 <= 1000
run: interpolate/main 2: (((2 integer)) <- ((length)) ((1 string-address) (deref)))
array-len: ((1 string-address) (deref))
mem: ((1000 integer) (raw)) => 8
run: interpolate/main 2: 8 => ((2 integer))
mem: ((2 integer)): 1016 <= 8
run: interpolate/main 3: (((3 integer)) <- ((copy)) ((2 integer)))
mem: ((2 integer)) => 8
run: interpolate/main 3: 8 => ((3 integer))
mem: ((3 integer)): 1017 <= 8
run: interpolate/main 4: (((4 string-address)) ((5 boolean)) <- ((next-input)))
arg: nil 1 (1000 1009)
run: interpolate/main 4: 1009 => ((4 string-address))
mem: ((4 string-address)): 1018 <= 1009
run: interpolate/main 4: t => ((5 boolean))
mem: ((5 boolean)): 1019 <= t
run: interpolate/main 5: (((jump-unless)) ((5 boolean)) ((4 offset)))
mem: ((5 boolean)) => t
run: interpolate/main 6: (((6 integer)) <- ((length)) ((4 string-address) (deref)))
array-len: ((4 string-address) (deref))
mem: ((1009 integer) (raw)) => 3
run: interpolate/main 6: 3 => ((6 integer))
mem: ((6 integer)): 1020 <= 3
run: interpolate/main 7: (((3 integer)) <- ((add)) ((3 integer)) ((6 integer)))
mem: ((3 integer)) => 8
mem: ((6 integer)) => 3
run: interpolate/main 7: 11 => ((3 integer))
mem: ((3 integer)): 1017 <= 11
run: interpolate/main 8: (((3 integer)) <- ((subtract)) ((3 integer)) ((1 literal)))
mem: ((3 integer)) => 11
run: interpolate/main 8: 10 => ((3 integer))
mem: ((3 integer)): 1017 <= 10
run: interpolate/main 9: (((jump)) ((-6 offset)))
run: interpolate/main 4: (((4 string-address)) ((5 boolean)) <- ((next-input)))
arg: nil 2 (1000 1009)
run: interpolate/main 4: nil => ((4 string-address))
mem: ((4 string-address)): 1018 <= nil
run: interpolate/main 4: nil => ((5 boolean))
mem: ((5 boolean)): 1019 <= nil
run: interpolate/main 5: (((jump-unless)) ((5 boolean)) ((4 offset)))
mem: ((5 boolean)) => nil
run: interpolate/main 10: (_ <- ((input)) ((0 literal)))
arg: (((0 literal))) 0 (1000 1009)
run: interpolate/main 11: (((7 string-address)) <- ((new)) ((string literal)) ((3 integer)))
mem: ((3 integer)) => 10
run: interpolate/main 11: 1074 => ((7 string-address))
mem: ((7 string-address)): 1021 <= 1074
run: interpolate/main 12: (((8 integer)) <- ((copy)) ((0 literal)))
run: interpolate/main 12: 0 => ((8 integer))
mem: ((8 integer)): 1022 <= 0
run: interpolate/main 13: (((9 integer)) <- ((copy)) ((0 literal)))
run: interpolate/main 13: 0 => ((9 integer))
mem: ((9 integer)): 1023 <= 0
run: interpolate/main 14: (((4 string-address)) ((5 boolean)) <- ((next-input)))
arg: nil 1 (1000 1009)
run: interpolate/main 14: 1009 => ((4 string-address))
mem: ((4 string-address)): 1018 <= 1009
run: interpolate/main 14: t => ((5 boolean))
mem: ((5 boolean)): 1019 <= t
run: interpolate/main 15: (((jump-unless)) ((5 boolean)) ((21 offset)))
mem: ((5 boolean)) => t
run: interpolate/main 16: (((10 boolean)) <- ((greater-or-equal)) ((9 integer)) ((2 integer)))
mem: ((9 integer)) => 0
mem: ((2 integer)) => 8
run: interpolate/main 16: nil => ((10 boolean))
mem: ((10 boolean)): 1024 <= nil
run: interpolate/main 17: (((jump-if)) ((10 boolean)) ((19 offset)))
mem: ((10 boolean)) => nil
run: interpolate/main 18: (((11 byte)) <- ((index)) ((1 string-address) (deref)) ((9 integer)))
mem: ((9 integer)) => 0
array-len: ((1000 string) (raw))
mem: ((1000 integer) (raw)) => 8
mem: ((1001 byte) (raw)) => h
run: interpolate/main 18: #\h => ((11 byte))
mem: ((11 byte)): 1025 <= #\h
run: interpolate/main 19: (((12 boolean)) <- ((equal)) ((11 byte)) ((_ literal)))
mem: ((11 byte)) => h
run: interpolate/main 19: nil => ((12 boolean))
mem: ((12 boolean)): 1026 <= nil
run: interpolate/main 20: (((jump-if)) ((12 boolean)) ((5 offset)))
mem: ((12 boolean)) => nil
run: interpolate/main 21: (((13 byte-address)) <- ((index-address)) ((7 string-address) (deref)) ((8 integer)))
mem: ((8 integer)) => 0
array-len: ((1074 string) (raw))
mem: ((1074 integer) (raw)) => 10
run: interpolate/main 21: 1075 => ((13 byte-address))
mem: ((13 byte-address)): 1027 <= 1075
run: interpolate/main 22: (((13 byte-address) (deref)) <- ((copy)) ((11 byte)))
mem: ((11 byte)) => h
run: interpolate/main 22: #\h => ((13 byte-address) (deref))
mem: ((13 byte-address) (deref)): 1075 <= #\h
run: interpolate/main 23: (((9 integer)) <- ((add)) ((9 integer)) ((1 literal)))
mem: ((9 integer)) => 0
run: interpolate/main 23: 1 => ((9 integer))
mem: ((9 integer)): 1023 <= 1
run: interpolate/main 24: (((8 integer)) <- ((add)) ((8 integer)) ((1 literal)))
mem: ((8 integer)) => 0
run: interpolate/main 24: 1 => ((8 integer))
mem: ((8 integer)): 1022 <= 1
run: interpolate/main 25: (((jump)) ((-10 offset)))
run: interpolate/main 16: (((10 boolean)) <- ((greater-or-equal)) ((9 integer)) ((2 integer)))
mem: ((9 integer)) => 1
mem: ((2 integer)) => 8
run: interpolate/main 16: nil => ((10 boolean))
mem: ((10 boolean)): 1024 <= nil
run: interpolate/main 17: (((jump-if)) ((10 boolean)) ((19 offset)))
mem: ((10 boolean)) => nil
run: interpolate/main 18: (((11 byte)) <- ((index)) ((1 string-address) (deref)) ((9 integer)))
mem: ((9 integer)) => 1
array-len: ((1000 string) (raw))
mem: ((1000 integer) (raw)) => 8
mem: ((1002 byte) (raw)) => e
run: interpolate/main 18: #\e => ((11 byte))
mem: ((11 byte)): 1025 <= #\e
run: interpolate/main 19: (((12 boolean)) <- ((equal)) ((11 byte)) ((_ literal)))
mem: ((11 byte)) => e
run: interpolate/main 19: nil => ((12 boolean))
mem: ((12 boolean)): 1026 <= nil
run: interpolate/main 20: (((jump-if)) ((12 boolean)) ((5 offset)))
mem: ((12 boolean)) => nil
run: interpolate/main 21: (((13 byte-address)) <- ((index-address)) ((7 string-address) (deref)) ((8 integer)))
mem: ((8 integer)) => 1
array-len: ((1074 string) (raw))
mem: ((1074 integer) (raw)) => 10
run: interpolate/main 21: 1076 => ((13 byte-address))
mem: ((13 byte-address)): 1027 <= 1076
run: interpolate/main 22: (((13 byte-address) (deref)) <- ((copy)) ((11 byte)))
mem: ((11 byte)) => e
run: interpolate/main 22: #\e => ((13 byte-address) (deref))
mem: ((13 byte-address) (deref)): 1076 <= #\e
run: interpolate/main 23: (((9 integer)) <- ((add)) ((9 integer)) ((1 literal)))
mem: ((9 integer)) => 1
run: interpolate/main 23: 2 => ((9 integer))
mem: ((9 integer)): 1023 <= 2
run: interpolate/main 24: (((8 integer)) <- ((add)) ((8 integer)) ((1 literal)))
mem: ((8 integer)) => 1
run: interpolate/main 24: 2 => ((8 integer))
mem: ((8 integer)): 1022 <= 2
run: interpolate/main 25: (((jump)) ((-10 offset)))
run: interpolate/main 16: (((10 boolean)) <- ((greater-or-equal)) ((9 integer)) ((2 integer)))
mem: ((9 integer)) => 2
mem: ((2 integer)) => 8
run: interpolate/main 16: nil => ((10 boolean))
mem: ((10 boolean)): 1024 <= nil
run: interpolate/main 17: (((jump-if)) ((10 boolean)) ((19 offset)))
mem: ((10 boolean)) => nil
run: interpolate/main 18: (((11 byte)) <- ((index)) ((1 string-address) (deref)) ((9 integer)))
mem: ((9 integer)) => 2
array-len: ((1000 string) (raw))
mem: ((1000 integer) (raw)) => 8
mem: ((1003 byte) (raw)) => l
run: interpolate/main 18: #\l => ((11 byte))
mem: ((11 byte)): 1025 <= #\l
run: interpolate/main 19: (((12 boolean)) <- ((equal)) ((11 byte)) ((_ literal)))
mem: ((11 byte)) => l
run: interpolate/main 19: nil => ((12 boolean))
mem: ((12 boolean)): 1026 <= nil
run: interpolate/main 20: (((jump-if)) ((12 boolean)) ((5 offset)))
mem: ((12 boolean)) => nil
run: interpolate/main 21: (((13 byte-address)) <- ((index-address)) ((7 string-address) (deref)) ((8 integer)))
mem: ((8 integer)) => 2
array-len: ((1074 string) (raw))
mem: ((1074 integer) (raw)) => 10
run: interpolate/main 21: 1077 => ((13 byte-address))
mem: ((13 byte-address)): 1027 <= 1077
run: interpolate/main 22: (((13 byte-address) (deref)) <- ((copy)) ((11 byte)))
mem: ((11 byte)) => l
run: interpolate/main 22: #\l => ((13 byte-address) (deref))
mem: ((13 byte-address) (deref)): 1077 <= #\l
run: interpolate/main 23: (((9 integer)) <- ((add)) ((9 integer)) ((1 literal)))
mem: ((9 integer)) => 2
run: interpolate/main 23: 3 => ((9 integer))
mem: ((9 integer)): 1023 <= 3
run: interpolate/main 24: (((8 integer)) <- ((add)) ((8 integer)) ((1 literal)))
mem: ((8 integer)) => 2
run: interpolate/main 24: 3 => ((8 integer))
mem: ((8 integer)): 1022 <= 3
run: interpolate/main 25: (((jump)) ((-10 offset)))
run: interpolate/main 16: (((10 boolean)) <- ((greater-or-equal)) ((9 integer)) ((2 integer)))
mem: ((9 integer)) => 3
mem: ((2 integer)) => 8
run: interpolate/main 16: nil => ((10 boolean))
mem: ((10 boolean)): 1024 <= nil
run: interpolate/main 17: (((jump-if)) ((10 boolean)) ((19 offset)))
mem: ((10 boolean)) => nil
run: interpolate/main 18: (((11 byte)) <- ((index)) ((1 string-address) (deref)) ((9 integer)))
mem: ((9 integer)) => 3
array-len: ((1000 string) (raw))
mem: ((1000 integer) (raw)) => 8
mem: ((1004 byte) (raw)) => l
run: interpolate/main 18: #\l => ((11 byte))
mem: ((11 byte)): 1025 <= #\l
run: interpolate/main 19: (((12 boolean)) <- ((equal)) ((11 byte)) ((_ literal)))
mem: ((11 byte)) => l
run: interpolate/main 19: nil => ((12 boolean))
mem: ((12 boolean)): 1026 <= nil
run: interpolate/main 20: (((jump-if)) ((12 boolean)) ((5 offset)))
mem: ((12 boolean)) => nil
run: interpolate/main 21: (((13 byte-address)) <- ((index-address)) ((7 string-address) (deref)) ((8 integer)))
mem: ((8 integer)) => 3
array-len: ((1074 string) (raw))
mem: ((1074 integer) (raw)) => 10
run: interpolate/main 21: 1078 => ((13 byte-address))
mem: ((13 byte-address)): 1027 <= 1078
run: interpolate/main 22: (((13 byte-address) (deref)) <- ((copy)) ((11 byte)))
mem: ((11 byte)) => l
run: interpolate/main 22: #\l => ((13 byte-address) (deref))
mem: ((13 byte-address) (deref)): 1078 <= #\l
run: interpolate/main 23: (((9 integer)) <- ((add)) ((9 integer)) ((1 literal)))
mem: ((9 integer)) => 3
run: interpolate/main 23: 4 => ((9 integer))
mem: ((9 integer)): 1023 <= 4
run: interpolate/main 24: (((8 integer)) <- ((add)) ((8 integer)) ((1 literal)))
mem: ((8 integer)) => 3
run: interpolate/main 24: 4 => ((8 integer))
mem: ((8 integer)): 1022 <= 4
run: interpolate/main 25: (((jump)) ((-10 offset)))
run: interpolate/main 16: (((10 boolean)) <- ((greater-or-equal)) ((9 integer)) ((2 integer)))
mem: ((9 integer)) => 4
mem: ((2 integer)) => 8
run: interpolate/main 16: nil => ((10 boolean))
mem: ((10 boolean)): 1024 <= nil
run: interpolate/main 17: (((jump-if)) ((10 boolean)) ((19 offset)))
mem: ((10 boolean)) => nil
run: interpolate/main 18: (((11 byte)) <- ((index)) ((1 string-address) (deref)) ((9 integer)))
mem: ((9 integer)) => 4
array-len: ((1000 string) (raw))
mem: ((1000 integer) (raw)) => 8
mem: ((1005 byte) (raw)) => o
run: interpolate/main 18: #\o => ((11 byte))
mem: ((11 byte)): 1025 <= #\o
run: interpolate/main 19: (((12 boolean)) <- ((equal)) ((11 byte)) ((_ literal)))
mem: ((11 byte)) => o
run: interpolate/main 19: nil => ((12 boolean))
mem: ((12 boolean)): 1026 <= nil
run: interpolate/main 20: (((jump-if)) ((12 boolean)) ((5 offset)))
mem: ((12 boolean)) => nil
run: interpolate/main 21: (((13 byte-address)) <- ((index-address)) ((7 string-address) (deref)) ((8 integer)))
mem: ((8 integer)) => 4
array-len: ((1074 string) (raw))
mem: ((1074 integer) (raw)) => 10
run: interpolate/main 21: 1079 => ((13 byte-address))
mem: ((13 byte-address)): 1027 <= 1079
run: interpolate/main 22: (((13 byte-address) (deref)) <- ((copy)) ((11 byte)))
mem: ((11 byte)) => o
run: interpolate/main 22: #\o => ((13 byte-address) (deref))
mem: ((13 byte-address) (deref)): 1079 <= #\o
run: interpolate/main 23: (((9 integer)) <- ((add)) ((9 integer)) ((1 literal)))
mem: ((9 integer)) => 4
run: interpolate/main 23: 5 => ((9 integer))
mem: ((9 integer)): 1023 <= 5
run: interpolate/main 24: (((8 integer)) <- ((add)) ((8 integer)) ((1 literal)))
mem: ((8 integer)) => 4
run: interpolate/main 24: 5 => ((8 integer))
mem: ((8 integer)): 1022 <= 5
run: interpolate/main 25: (((jump)) ((-10 offset)))
run: interpolate/main 16: (((10 boolean)) <- ((greater-or-equal)) ((9 integer)) ((2 integer)))
mem: ((9 integer)) => 5
mem: ((2 integer)) => 8
run: interpolate/main 16: nil => ((10 boolean))
mem: ((10 boolean)): 1024 <= nil
run: interpolate/main 17: (((jump-if)) ((10 boolean)) ((19 offset)))
mem: ((10 boolean)) => nil
run: interpolate/main 18: (((11 byte)) <- ((index)) ((1 string-address) (deref)) ((9 integer)))
mem: ((9 integer)) => 5
array-len: ((1000 string) (raw))
mem: ((1000 integer) (raw)) => 8
mem: ((1006 byte) (raw)) => ,
run: interpolate/main 18: #\, => ((11 byte))
mem: ((11 byte)): 1025 <= #\,
run: interpolate/main 19: (((12 boolean)) <- ((equal)) ((11 byte)) ((_ literal)))
mem: ((11 byte)) => ,
run: interpolate/main 19: nil => ((12 boolean))
mem: ((12 boolean)): 1026 <= nil
run: interpolate/main 20: (((jump-if)) ((12 boolean)) ((5 offset)))
mem: ((12 boolean)) => nil
run: interpolate/main 21: (((13 byte-address)) <- ((index-address)) ((7 string-address) (deref)) ((8 integer)))
mem: ((8 integer)) => 5
array-len: ((1074 string) (raw))
mem: ((1074 integer) (raw)) => 10
run: interpolate/main 21: 1080 => ((13 byte-address))
mem: ((13 byte-address)): 1027 <= 1080
run: interpolate/main 22: (((13 byte-address) (deref)) <- ((copy)) ((11 byte)))
mem: ((11 byte)) => ,
run: interpolate/main 22: #\, => ((13 byte-address) (deref))
mem: ((13 byte-address) (deref)): 1080 <= #\,
run: interpolate/main 23: (((9 integer)) <- ((add)) ((9 integer)) ((1 literal)))
mem: ((9 integer)) => 5
run: interpolate/main 23: 6 => ((9 integer))
mem: ((9 integer)): 1023 <= 6
run: interpolate/main 24: (((8 integer)) <- ((add)) ((8 integer)) ((1 literal)))
mem: ((8 integer)) => 5
run: interpolate/main 24: 6 => ((8 integer))
mem: ((8 integer)): 1022 <= 6
run: interpolate/main 25: (((jump)) ((-10 offset)))
run: interpolate/main 16: (((10 boolean)) <- ((greater-or-equal)) ((9 integer)) ((2 integer)))
mem: ((9 integer)) => 6
mem: ((2 integer)) => 8
run: interpolate/main 16: nil => ((10 boolean))
mem: ((10 boolean)): 1024 <= nil
run: interpolate/main 17: (((jump-if)) ((10 boolean)) ((19 offset)))
mem: ((10 boolean)) => nil
run: interpolate/main 18: (((11 byte)) <- ((index)) ((1 string-address) (deref)) ((9 integer)))
mem: ((9 integer)) => 6
array-len: ((1000 string) (raw))
mem: ((1000 integer) (raw)) => 8
mem: ((1007 byte) (raw)) =>  
run: interpolate/main 18: #\space => ((11 byte))
mem: ((11 byte)): 1025 <= #\space
run: interpolate/main 19: (((12 boolean)) <- ((equal)) ((11 byte)) ((_ literal)))
mem: ((11 byte)) =>  
run: interpolate/main 19: nil => ((12 boolean))
mem: ((12 boolean)): 1026 <= nil
run: interpolate/main 20: (((jump-if)) ((12 boolean)) ((5 offset)))
mem: ((12 boolean)) => nil
run: interpolate/main 21: (((13 byte-address)) <- ((index-address)) ((7 string-address) (deref)) ((8 integer)))
mem: ((8 integer)) => 6
array-len: ((1074 string) (raw))
mem: ((1074 integer) (raw)) => 10
run: interpolate/main 21: 1081 => ((13 byte-address))
mem: ((13 byte-address)): 1027 <= 1081
run: interpolate/main 22: (((13 byte-address) (deref)) <- ((copy)) ((11 byte)))
mem: ((11 byte)) =>  
run: interpolate/main 22: #\space => ((13 byte-address) (deref))
mem: ((13 byte-address) (deref)): 1081 <= #\space
run: interpolate/main 23: (((9 integer)) <- ((add)) ((9 integer)) ((1 literal)))
mem: ((9 integer)) => 6
run: interpolate/main 23: 7 => ((9 integer))
mem: ((9 integer)): 1023 <= 7
run: interpolate/main 24: (((8 integer)) <- ((add)) ((8 integer)) ((1 literal)))
mem: ((8 integer)) => 6
run: interpolate/main 24: 7 => ((8 integer))
mem: ((8 integer)): 1022 <= 7
run: interpolate/main 25: (((jump)) ((-10 offset)))
run: interpolate/main 16: (((10 boolean)) <- ((greater-or-equal)) ((9 integer)) ((2 integer)))
mem: ((9 integer)) => 7
mem: ((2 integer)) => 8
run: interpolate/main 16: nil => ((10 boolean))
mem: ((10 boolean)): 1024 <= nil
run: interpolate/main 17: (((jump-if)) ((10 boolean)) ((19 offset)))
mem: ((10 boolean)) => nil
run: interpolate/main 18: (((11 byte)) <- ((index)) ((1 string-address) (deref)) ((9 integer)))
mem: ((9 integer)) => 7
array-len: ((1000 string) (raw))
mem: ((1000 integer) (raw)) => 8
mem: ((1008 byte) (raw)) => _
run: interpolate/main 18: #\_ => ((11 byte))
mem: ((11 byte)): 1025 <= #\_
run: interpolate/main 19: (((12 boolean)) <- ((equal)) ((11 byte)) ((_ literal)))
mem: ((11 byte)) => _
run: interpolate/main 19: t => ((12 boolean))
mem: ((12 boolean)): 1026 <= t
run: interpolate/main 20: (((jump-if)) ((12 boolean)) ((5 offset)))
mem: ((12 boolean)) => t
run: interpolate/main 26: (((14 integer)) <- ((copy)) ((0 literal)))
run: interpolate/main 26: 0 => ((14 integer))
mem: ((14 integer)): 1028 <= 0
run: interpolate/main 27: (((15 boolean)) <- ((greater-or-equal)) ((14 integer)) ((6 integer)))
mem: ((14 integer)) => 0
mem: ((6 integer)) => 3
run: interpolate/main 27: nil => ((15 boolean))
mem: ((15 boolean)): 1029 <= nil
run: interpolate/main 28: (((jump-if)) ((15 boolean)) ((6 offset)))
mem: ((15 boolean)) => nil
run: interpolate/main 29: (((11 byte)) <- ((index)) ((4 string-address) (deref)) ((14 integer)))
mem: ((14 integer)) => 0
array-len: ((1009 string) (raw))
mem: ((1009 integer) (raw)) => 3
mem: ((1010 byte) (raw)) => a
run: interpolate/main 29: #\a => ((11 byte))
mem: ((11 byte)): 1025 <= #\a
run: interpolate/main 30: (((13 byte-address)) <- ((index-address)) ((7 string-address) (deref)) ((8 integer)))
mem: ((8 integer)) => 7
array-len: ((1074 string) (raw))
mem: ((1074 integer) (raw)) => 10
run: interpolate/main 30: 1082 => ((13 byte-address))
mem: ((13 byte-address)): 1027 <= 1082
run: interpolate/main 31: (((13 byte-address) (deref)) <- ((copy)) ((11 byte)))
mem: ((11 byte)) => a
run: interpolate/main 31: #\a => ((13 byte-address) (deref))
mem: ((13 byte-address) (deref)): 1082 <= #\a
run: interpolate/main 32: (((14 integer)) <- ((add)) ((14 integer)) ((1 literal)))
mem: ((14 integer)) => 0
run: interpolate/main 32: 1 => ((14 integer))
mem: ((14 integer)): 1028 <= 1
run: interpolate/main 33: (((8 integer)) <- ((add)) ((8 integer)) ((1 literal)))
mem: ((8 integer)) => 7
run: interpolate/main 33: 8 => ((8 integer))
mem: ((8 integer)): 1022 <= 8
run: interpolate/main 34: (((jump)) ((-8 offset)))
run: interpolate/main 27: (((15 boolean)) <- ((greater-or-equal)) ((14 integer)) ((6 integer)))
mem: ((14 integer)) => 1
mem: ((6 integer)) => 3
run: interpolate/main 27: nil => ((15 boolean))
mem: ((15 boolean)): 1029 <= nil
run: interpolate/main 28: (((jump-if)) ((15 boolean)) ((6 offset)))
mem: ((15 boolean)) => nil
run: interpolate/main 29: (((11 byte)) <- ((index)) ((4 string-address) (deref)) ((14 integer)))
mem: ((14 integer)) => 1
array-len: ((1009 string) (raw))
mem: ((1009 integer) (raw)) => 3
mem: ((1011 byte) (raw)) => b
run: interpolate/main 29: #\b => ((11 byte))
mem: ((11 byte)): 1025 <= #\b
run: interpolate/main 30: (((13 byte-address)) <- ((index-address)) ((7 string-address) (deref)) ((8 integer)))
mem: ((8 integer)) => 8
array-len: ((1074 string) (raw))
mem: ((1074 integer) (raw)) => 10
run: interpolate/main 30: 1083 => ((13 byte-address))
mem: ((13 byte-address)): 1027 <= 1083
run: interpolate/main 31: (((13 byte-address) (deref)) <- ((copy)) ((11 byte)))
mem: ((11 byte)) => b
run: interpolate/main 31: #\b => ((13 byte-address) (deref))
mem: ((13 byte-address) (deref)): 1083 <= #\b
run: interpolate/main 32: (((14 integer)) <- ((add)) ((14 integer)) ((1 literal)))
mem: ((14 integer)) => 1
run: interpolate/main 32: 2 => ((14 integer))
mem: ((14 integer)): 1028 <= 2
run: interpolate/main 33: (((8 integer)) <- ((add)) ((8 integer)) ((1 literal)))
mem: ((8 integer)) => 8
run: interpolate/main 33: 9 => ((8 integer))
mem: ((8 integer)): 1022 <= 9
run: interpolate/main 34: (((jump)) ((-8 offset)))
run: interpolate/main 27: (((15 boolean)) <- ((greater-or-equal)) ((14 integer)) ((6 integer)))
mem: ((14 integer)) => 2
mem: ((6 integer)) => 3
run: interpolate/main 27: nil => ((15 boolean))
mem: ((15 boolean)): 1029 <= nil
run: interpolate/main 28: (((jump-if)) ((15 boolean)) ((6 offset)))
mem: ((15 boolean)) => nil
run: interpolate/main 29: (((11 byte)) <- ((index)) ((4 string-address) (deref)) ((14 integer)))
mem: ((14 integer)) => 2
array-len: ((1009 string) (raw))
mem: ((1009 integer) (raw)) => 3
mem: ((1012 byte) (raw)) => c
run: interpolate/main 29: #\c => ((11 byte))
mem: ((11 byte)): 1025 <= #\c
run: interpolate/main 30: (((13 byte-address)) <- ((index-address)) ((7 string-address) (deref)) ((8 integer)))
mem: ((8 integer)) => 9
array-len: ((1074 string) (raw))
mem: ((1074 integer) (raw)) => 10
run: interpolate/main 30: 1084 => ((13 byte-address))
mem: ((13 byte-address)): 1027 <= 1084
run: interpolate/main 31: (((13 byte-address) (deref)) <- ((copy)) ((11 byte)))
mem: ((11 byte)) => c
run: interpolate/main 31: #\c => ((13 byte-address) (deref))
mem: ((13 byte-address) (deref)): 1084 <= #\c
run: interpolate/main 32: (((14 integer)) <- ((add)) ((14 integer)) ((1 literal)))
mem: ((14 integer)) => 2
run: interpolate/main 32: 3 => ((14 integer))
mem: ((14 integer)): 1028 <= 3
run: interpolate/main 33: (((8 integer)) <- ((add)) ((8 integer)) ((1 literal)))
mem: ((8 integer)) => 9
run: interpolate/main 33: 10 => ((8 integer))
mem: ((8 integer)): 1022 <= 10
run: interpolate/main 34: (((jump)) ((-8 offset)))
run: interpolate/main 27: (((15 boolean)) <- ((greater-or-equal)) ((14 integer)) ((6 integer)))
mem: ((14 integer)) => 3
mem: ((6 integer)) => 3
run: interpolate/main 27: t => ((15 boolean))
mem: ((15 boolean)): 1029 <= t
run: interpolate/main 28: (((jump-if)) ((15 boolean)) ((6 offset)))
mem: ((15 boolean)) => t
run: interpolate/main 35: (((9 integer)) <- ((add)) ((9 integer)) ((1 literal)))
mem: ((9 integer)) => 7
run: interpolate/main 35: 8 => ((9 integer))
mem: ((9 integer)): 1023 <= 8
run: interpolate/main 36: (((jump)) ((-23 offset)))
run: interpolate/main 14: (((4 string-address)) ((5 boolean)) <- ((next-input)))
arg: nil 2 (1000 1009)
run: interpolate/main 14: nil => ((4 string-address))
mem: ((4 string-address)): 1018 <= nil
run: interpolate/main 14: nil => ((5 boolean))
mem: ((5 boolean)): 1019 <= nil
run: interpolate/main 15: (((jump-unless)) ((5 boolean)) ((21 offset)))
mem: ((5 boolean)) => nil
run: interpolate/main 37: (((10 boolean)) <- ((greater-or-equal)) ((9 integer)) ((2 integer)))
mem: ((9 integer)) => 8
mem: ((2 integer)) => 8
run: interpolate/main 37: t => ((10 boolean))
mem: ((10 boolean)): 1024 <= t
run: interpolate/main 38: (((jump-if)) ((10 boolean)) ((6 offset)))
mem: ((10 boolean)) => t
run: interpolate/main 45: (((reply)) ((7 string-address)))
mem: ((7 string-address)) => 1074
run: main 2: 1074 => ((3 string-address))
mem: ((3 string-address)): 3 <= 1074
schedule: done with routine nil
322 # pop string from out 323 var top-addr/ecx: (addr int) <- get out2, top 324 compare *top-addr, 0 325 break-if-<= 326 decrement *top-addr 327 var data-ah/eax: (addr handle array value) <- get out2, data 328 var _data/eax: (addr array value) <- lookup *data-ah 329 var data/edi: (addr array value) <- copy _data 330 var top/eax: int <- copy *top-addr 331 var dest-offset/edx: (offset value) <- compute-offset data, top 332 var s/esi: (addr value) <- index data, dest-offset 333 # select target screen from top of out (but don't pop it) 334 compare *top-addr, 0 335 break-if-<= 336 var top/eax: int <- copy *top-addr 337 top <- decrement 338 var dest-offset/edx: (offset value) <- compute-offset data, top 339 var target-val/edx: (addr value) <- index data, dest-offset 340 var type/eax: (addr int) <- get target-val, type 341 compare *type, 4/screen 342 break-if-!= 343 # print string to target screen 344 var dest-ah/eax: (addr handle screen) <- get target-val, screen-data 345 var dest/eax: (addr screen) <- lookup *dest-ah 346 var r/ecx: (addr int) <- get dest, cursor-row 347 var c/edx: (addr int) <- get dest, cursor-col 348 render-value-at dest, *r, *c, s, 0 349 break $evaluate:process-word 350 } 351 { 352 var move?/eax: boolean <- stream-data-equal? curr-stream, "move" 353 compare move?, 0 354 break-if-= 355 var out2/esi: (addr value-stack) <- copy out 356 # pop args 357 var r-f/xmm0: float <- pop-number-from-value-stack out2 358 var r/ecx: int <- convert r-f 359 var c-f/xmm0: float <- pop-number-from-value-stack out2 360 var c/edx: int <- convert c-f 361 # select screen from top of out (but don't pop it) 362 var top-addr/ebx: (addr int) <- get out2, top 363 compare *top-addr, 0 364 break-if-<= 365 var data-ah/eax: (addr handle array value) <- get out2, data 366 var _data/eax: (addr array value) <- lookup *data-ah 367 var data/edi: (addr array value) <- copy _data 368 var top/eax: int <- copy *top-addr 369 top <- decrement 370 var target-offset/eax: (offset value) <- compute-offset data, top 371 var target-val/ebx: (addr value) <- index data, target-offset 372 var type/eax: (addr int) <- get target-val, type 373 compare *type, 4/screen 374 break-if-!= 375 var target-ah/eax: (addr handle screen) <- get target-val, screen-data 376 var target/eax: (addr screen) <- lookup *target-ah 377 move-cursor target, r, c 378 break $evaluate:process-word 379 } 380 { 381 var up?/eax: boolean <- stream-data-equal? curr-stream, "up" 382 compare up?, 0 383 break-if-= 384 var out2/esi: (addr value-stack) <- copy out 385 var top-addr/ebx: (addr int) <- get out2, top 386 compare *top-addr, 0 387 break-if-<= 388 # pop args 389 var d-f/xmm0: float <- pop-number-from-value-stack out2 390 var d/ecx: int <- convert d-f 391 # select screen from top of out (but don't pop it) 392 compare *top-addr, 0 393 break-if-<= 394 var data-ah/eax: (addr handle array value) <- get out2, data 395 var _data/eax: (addr array value) <- lookup *data-ah 396 var data/edi: (addr array value) <- copy _data 397 var top/eax: int <- copy *top-addr 398 top <- decrement 399 var target-offset/eax: (offset value) <- compute-offset data, top 400 var target-val/ebx: (addr value) <- index data, target-offset 401 var type/eax: (addr int) <- get target-val, type 402 compare *type, 4/screen 403 break-if-!= 404 var target-ah/eax: (addr handle screen) <- get target-val, screen-data 405 var _target/eax: (addr screen) <- lookup *target-ah 406 var target/edi: (addr screen) <- copy _target 407 var r/edx: (addr int) <- get target, cursor-row 408 var c/eax: (addr int) <- get target, cursor-col 409 var col/eax: int <- copy *c 410 { 411 compare d, 0 412 break-if-<= 413 compare *r, 1 414 break-if-<= 415 print-string target "│" 416 decrement *r 417 move-cursor target, *r, col 418 d <- decrement 419 loop 420 } 421 break $evaluate:process-word 422 } 423 { 424 var down?/eax: boolean <- stream-data-equal? curr-stream, "down" 425 compare down?, 0 426 break-if-= 427 var out2/esi: (addr value-stack) <- copy out 428 var top-addr/ebx: (addr int) <- get out2, top 429 compare *top-addr, 0 430 break-if-<= 431 # pop args 432 var d-f/xmm0: float <- pop-number-from-value-stack out2 433 var d/ecx: int <- convert d-f 434 # select screen from top of out (but don't pop it) 435 compare *top-addr, 0 436 break-if-<= 437 var data-ah/eax: (addr handle array value) <- get out2, data 438 var _data/eax: (addr array value) <- lookup *data-ah 439 var data/edi: (addr array value) <- copy _data 440 var top/eax: int <- copy *top-addr 441 top <- decrement 442 var target-offset/eax: (offset value) <- compute-offset data, top 443 var target-val/ebx: (addr value) <- index data, target-offset 444 var type/eax: (addr int) <- get target-val, type 445 compare *type, 4/screen 446 break-if-!= 447 var target-ah/eax: (addr handle screen) <- get target-val, screen-data 448 var _target/eax: (addr screen) <- lookup *target-ah 449 var target/edi: (addr screen) <- copy _target 450 var bound-a/ebx: (addr int) <- get target, num-rows 451 var bound/ebx: int <- copy *bound-a 452 var r/edx: (addr int) <- get target, cursor-row 453 var c/eax: (addr int) <- get target, cursor-col 454 var col/eax: int <- copy *c 455 { 456 compare d, 0 457 break-if-<= 458 compare *r, bound 459 break-if->= 460 print-string target "│" 461 increment *r 462 move-cursor target, *r, col 463 d <- decrement 464 loop 465 } 466 break $evaluate:process-word 467 } 468 { 469 var left?/eax: boolean <- stream-data-equal? curr-stream, "left" 470 compare left?, 0 471 break-if-= 472 var out2/esi: (addr value-stack) <- copy out 473 var top-addr/ebx: (addr int) <- get out2, top 474 compare *top-addr, 0 475 break-if-<= 476 # pop args 477 var d-f/xmm0: float <- pop-number-from-value-stack out2 478 var d/ecx: int <- convert d-f 479 # select screen from top of out (but don't pop it) 480 compare *top-addr, 0 481 break-if-<= 482 var data-ah/eax: (addr handle array value) <- get out2, data 483 var _data/eax: (addr array value) <- lookup *data-ah 484 var data/edi: (addr array value) <- copy _data 485 var top/eax: int <- copy *top-addr 486 top <- decrement 487 var target-offset/eax: (offset value) <- compute-offset data, top 488 var target-val/ebx: (addr value) <- index data, target-offset 489 var type/eax: (addr int) <- get target-val, type 490 compare *type, 4/screen 491 break-if-!= 492 var target-ah/eax: (addr handle screen) <- get target-val, screen-data 493 var _target/eax: (addr screen) <- lookup *target-ah 494 var target/edi: (addr screen) <- copy _target 495 var c/edx: (addr int) <- get target, cursor-col 496 var r/eax: (addr int) <- get target, cursor-row 497 var row/eax: int <- copy *r 498 { 499 compare d, 0 500 break-if-<= 501 compare *c, 1 502 break-if-<= 503 print-string target "─" 504 decrement *c 505 decrement *c # second one to undo the print above 506 move-cursor target, row, *c 507 d <- decrement 508 loop 509 } 510 break $evaluate:process-word 511 } 512 { 513 var right?/eax: boolean <- stream-data-equal? curr-stream, "right" 514 compare right?, 0 515 break-if-= 516 var out2/esi: (addr value-stack) <- copy out 517 var top-addr/ebx: (addr int) <- get out2, top 518 compare *top-addr, 0 519 break-if-<= 520 # pop args 521 var _d/xmm0: float <- pop-number-from-value-stack out2 522 var d/ecx: int <- convert _d 523 # select screen from top of out (but don't pop it) 524 compare *top-addr, 0 525 break-if-<= 526 var data-ah/eax: (addr handle array value) <- get out2, data 527 var _data/eax: (addr array value) <- lookup *data-ah 528 var data/edi: (addr array value) <- copy _data 529 var top/eax: int <- copy *top-addr 530 top <- decrement 531 var target-offset/eax: (offset value) <- compute-offset data, top 532 var target-val/ebx: (addr value) <- index data, target-offset 533 var type/eax: (addr int) <- get target-val, type 534 compare *type, 4/screen 535 break-if-!= 536 var target-ah/eax: (addr handle screen) <- get target-val, screen-data 537 var _target/eax: (addr screen) <- lookup *target-ah 538 var target/edi: (addr screen) <- copy _target 539 var bound-a/ebx: (addr int) <- get target, num-rows 540 var bound/ebx: int <- copy *bound-a 541 var c/edx: (addr int) <- get target, cursor-col 542 var r/eax: (addr int) <- get target, cursor-row 543 var row/eax: int <- copy *r 544 { 545 compare d, 0 546 break-if-<= 547 compare *c, bound 548 break-if->= 549 print-string target "─" 550 # no increment; the print took care of it 551 move-cursor target, row, *c 552 d <- decrement 553 loop 554 } 555 break $evaluate:process-word 556 } 557 ## HACKS: we're trying to avoid turning this into Forth 558 { 559 var dup?/eax: boolean <- stream-data-equal? curr-stream, "dup" 560 compare dup?, 0 561 break-if-= 562 # read src-val from out 563 var out2/esi: (addr value-stack) <- copy out 564 var top-addr/ecx: (addr int) <- get out2, top 565 compare *top-addr, 0 566 break-if-<= 567 var data-ah/eax: (addr handle array value) <- get out2, data 568 var data/eax: (addr array value) <- lookup *data-ah 569 var top/ecx: int <- copy *top-addr 570 top <- decrement 571 var offset/edx: (offset value) <- compute-offset data, top 572 var src-val/edx: (addr value) <- index data, offset 573 # push a copy of it 574 top <- increment 575 var offset/ebx: (offset value) <- compute-offset data, top 576 var target-val/ebx: (addr value) <- index data, offset 577 copy-object src-val, target-val 578 # commit 579 var top-addr/ecx: (addr int) <- get out2, top 580 increment *top-addr 581 break $evaluate:process-word 582 } 583 { 584 var swap?/eax: boolean <- stream-data-equal? curr-stream, "swap" 585 compare swap?, 0 586 break-if-= 587 # read top-val from out 588 var out2/esi: (addr value-stack) <- copy out 589 var top-addr/ecx: (addr int) <- get out2, top 590 compare *top-addr, 0 591 break-if-<= 592 var data-ah/eax: (addr handle array value) <- get out2, data 593 var data/eax: (addr array value) <- lookup *data-ah 594 var top/ecx: int <- copy *top-addr 595 top <- decrement 596 var offset/edx: (offset value) <- compute-offset data, top 597 var top-val/edx: (addr value) <- index data, offset 598 # read next val from out 599 top <- decrement 600 var offset/ebx: (offset value) <- compute-offset data, top 601 var pen-top-val/ebx: (addr value) <- index data, offset 602 # swap 603 var tmp: value 604 var tmp-a/eax: (addr value) <- address tmp 605 copy-object top-val, tmp-a 606 copy-object pen-top-val, top-val 607 copy-object tmp-a, pen-top-val 608 break $evaluate:process-word 609 } 610 ### if curr-stream defines a binding, save top of stack to bindings 611 { 612 var done?/eax: boolean <- stream-empty? curr-stream 613 compare done?, 0/false 614 break-if-!= 615 var new-byte/eax: byte <- read-byte curr-stream 616 compare new-byte, 0x3d/= 617 break-if-!= 618 # pop target-val from out 619 var out2/esi: (addr value-stack) <- copy out 620 var top-addr/ecx: (addr int) <- get out2, top 621 compare *top-addr, 0 622 break-if-<= 623 var data-ah/eax: (addr handle array value) <- get out2, data 624 var data/eax: (addr array value) <- lookup *data-ah 625 var top/edx: int <- copy *top-addr 626 top <- decrement 627 var dest-offset/edx: (offset value) <- compute-offset data, top 628 var target-val/edx: (addr value) <- index data, dest-offset 629 # create binding from curr-stream to target-val 630 var key-h: (handle array byte) 631 var key/ecx: (addr handle array byte) <- address key-h 632 stream-to-array curr-stream, key 633 bind-in-table bindings, key, target-val 634 break $evaluate:process-word 635 } 636 rewind-stream curr-stream 637 ### if curr-stream is a known function name, call it appropriately 638 { 639 var callee-h: (handle function) 640 var callee-ah/eax: (addr handle function) <- address callee-h 641 find-function functions, curr-stream, callee-ah 642 var callee/eax: (addr function) <- lookup *callee-ah 643 compare callee, 0 644 break-if-= 645 perform-call callee, out, functions 646 break $evaluate:process-word 647 } 648 ### if it's a name, push its value 649 { 650 compare bindings, 0 651 break-if-= 652 var tmp: (handle array byte) 653 var curr-string-ah/edx: (addr handle array byte) <- address tmp 654 stream-to-array curr-stream, curr-string-ah # unfortunate leak 655 var curr-string/eax: (addr array byte) <- lookup *curr-string-ah 656 var val-storage: (handle value) 657 var val-ah/edi: (addr handle value) <- address val-storage 658 lookup-binding bindings, curr-string, val-ah 659 var val/eax: (addr value) <- lookup *val-ah 660 compare val, 0 661 break-if-= 662 push-value-stack out, val 663 break $evaluate:process-word 664 } 665 ### if the word starts with a quote and ends with a quote, turn it into a string 666 { 667 var start/eax: byte <- stream-first curr-stream 668 compare start, 0x22/double-quote 669 break-if-!= 670 var end/eax: byte <- stream-final curr-stream 671 compare end, 0x22/double-quote 672 break-if-!= 673 var h: (handle array byte) 674 var s/eax: (addr handle array byte) <- address h 675 unquote-stream-to-array curr-stream, s # leak 676 push-string-to-value-stack out, *s 677 break $evaluate:process-word 678 } 679 ### if the word starts with a '[' and ends with a ']', turn it into an array 680 { 681 var start/eax: byte <- stream-first curr-stream 682 compare start, 0x5b/[ 683 break-if-!= 684 var end/eax: byte <- stream-final curr-stream 685 compare end, 0x5d/] 686 break-if-!= 687 # wastefully create a new input string to strip quotes 688 var h: (handle array value) 689 var input-ah/eax: (addr handle array byte) <- address h 690 unquote-stream-to-array curr-stream, input-ah # leak 691 # wastefully parse input into int-array 692 # TODO: support parsing arrays of other types 693 var input/eax: (addr array byte) <- lookup *input-ah 694 var h2: (handle array int) 695 var int-array-ah/esi: (addr handle array int) <- address h2 696 parse-array-of-decimal-ints input, int-array-ah # leak 697 var _int-array/eax: (addr array int) <- lookup *int-array-ah 698 var int-array/esi: (addr array int) <- copy _int-array 699 var len/ebx: int <- length int-array 700 # push value-array of same size as int-array 701 var h3: (handle array value) 702 var value-array-ah/eax: (addr handle array value) <- address h3 703 populate value-array-ah, len 704 push-array-to-value-stack out, *value-array-ah 705 # copy int-array into value-array 706 var _value-array/eax: (addr array value) <- lookup *value-array-ah 707 var value-array/edi: (addr array value) <- copy _value-array 708 var i/eax: int <- copy 0 709 { 710 compare i, len 711 break-if->= 712 var src-addr/ecx: (addr int) <- index int-array, i 713 var src/ecx: int <- copy *src-addr 714 var src-f/xmm0: float <- convert src 715 var dest-offset/edx: (offset value) <- compute-offset value-array, i 716 var dest-val/edx: (addr value) <- index value-array, dest-offset 717 var dest/edx: (addr float) <- get dest-val, number-data 718 copy-to *dest, src-f 719 i <- increment 720 loop 721 } 722 break $evaluate:process-word 723 } 724 ### otherwise assume it's a literal number and push it 725 { 726 var n/eax: int <- parse-decimal-int-from-stream curr-stream 727 var n-f/xmm0: float <- convert n 728 push-number-to-value-stack out, n-f 729 } 730 } 731 # termination check 732 compare curr, end 733 break-if-= 734 # update 735 var next-word-ah/edx: (addr handle word) <- get curr, next 736 curr <- lookup *next-word-ah 737 # 738 loop 739 } 740 # process next line if necessary 741 var line/eax: (addr line) <- copy scratch 742 var next-line-ah/eax: (addr handle line) <- get line, next 743 var next-line/eax: (addr line) <- lookup *next-line-ah 744 compare next-line, 0 745 break-if-= 746 evaluate functions, bindings, next-line, end, out 747 } 748 749 fn test-evaluate { 750 var line-storage: line 751 var line/esi: (addr line) <- address line-storage 752 var first-word-ah/eax: (addr handle word) <- get line-storage, data 753 allocate-word-with first-word-ah, "3" 754 append-word-with *first-word-ah, "=a" 755 var next-line-ah/eax: (addr handle line) <- get line-storage, next 756 allocate next-line-ah 757 var next-line/eax: (addr line) <- lookup *next-line-ah 758 var first-word-ah/eax: (addr handle word) <- get next-line, data 759 allocate-word-with first-word-ah, "a" 760 var functions-storage: (handle function) 761 var functions/ecx: (addr handle function) <- address functions-storage 762 var table-storage: table 763 var table/ebx: (addr table) <- address table-storage 764 initialize-table table, 0x10 765 var stack-storage: value-stack 766 var stack/edi: (addr value-stack) <- address stack-storage 767 initialize-value-stack stack, 0x10 768 evaluate functions, table, line, 0, stack 769 var x-f/xmm0: float <- pop-number-from-value-stack stack 770 var x/eax: int <- convert x-f 771 check-ints-equal x, 3, "F - test-evaluate" 772 } 773 774 fn find-function first: (addr handle function), name: (addr stream byte), out: (addr handle function) { 775 var curr/esi: (addr handle function) <- copy first 776 $find-function:loop: { 777 var _f/eax: (addr function) <- lookup *curr 778 var f/ecx: (addr function) <- copy _f 779 compare f, 0 780 break-if-= 781 var curr-name-ah/eax: (addr handle array byte) <- get f, name 782 var curr-name/eax: (addr array byte) <- lookup *curr-name-ah 783 var done?/eax: boolean <- stream-data-equal? name, curr-name 784 compare done?, 0/false 785 { 786 break-if-= 787 copy-handle *curr, out 788 break $find-function:loop 789 } 790 curr <- get f, next 791 loop 792 } 793 } 794 795 fn perform-call _callee: (addr function), caller-stack: (addr value-stack), functions: (addr handle function) { 796 var callee/ecx: (addr function) <- copy _callee 797 # create bindings for args 798 var table-storage: table 799 var table/esi: (addr table) <- address table-storage 800 initialize-table table, 0x10 801 bind-args callee, caller-stack, table 802 # obtain body 803 var body-ah/eax: (addr handle line) <- get callee, body 804 var body/eax: (addr line) <- lookup *body-ah 805 # perform call 806 var stack-storage: value-stack 807 var stack/edi: (addr value-stack) <- address stack-storage 808 initialize-value-stack stack, 0x10 809 #? print-string-to-real-screen "about to enter recursive eval\n" 810 evaluate functions, table, body, 0, stack 811 #? print-string-to-real-screen "exited recursive eval\n" 812 # pop target-val from out 813 var top-addr/ecx: (addr int) <- get stack, top 814 compare *top-addr, 0 815 break-if-<= 816 var data-ah/eax: (addr handle array value) <- get stack, data 817 var data/eax: (addr array value) <- lookup *data-ah 818 var top/edx: int <- copy *top-addr 819 top <- decrement 820 var dest-offset/edx: (offset value) <- compute-offset data, top 821 var target-val/edx: (addr value) <- index data, dest-offset 822 # stitch target-val into caller-stack 823 push-value-stack caller-stack, target-val 824 } 825 826 # pop args from the caller-stack and bind them to successive args 827 # implies: function args are stored in reverse order 828 fn bind-args _callee: (addr function), _caller-stack: (addr value-stack), table: (addr table) { 829 var callee/ecx: (addr function) <- copy _callee 830 var curr-arg-ah/eax: (addr handle word) <- get callee, args 831 var curr-arg/eax: (addr word) <- lookup *curr-arg-ah 832 # 833 var curr-key-storage: (handle array byte) 834 var curr-key/edx: (addr handle array byte) <- address curr-key-storage 835 { 836 compare curr-arg, 0 837 break-if-= 838 # create binding 839 word-to-string curr-arg, curr-key 840 { 841 # pop target-val from caller-stack 842 var caller-stack/esi: (addr value-stack) <- copy _caller-stack 843 var top-addr/ecx: (addr int) <- get caller-stack, top 844 compare *top-addr, 0 845 break-if-<= 846 decrement *top-addr 847 var data-ah/eax: (addr handle array value) <- get caller-stack, data 848 var data/eax: (addr array value) <- lookup *data-ah 849 var top/ebx: int <- copy *top-addr 850 var dest-offset/ebx: (offset value) <- compute-offset data, top 851 var target-val/ebx: (addr value) <- index data, dest-offset 852 # create binding from curr-key to target-val 853 bind-in-table table, curr-key, target-val 854 } 855 # 856 var next-arg-ah/edx: (addr handle word) <- get curr-arg, next 857 curr-arg <- lookup *next-arg-ah 858 loop 859 } 860 } 861 862 # Copy of 'simplify' that just tracks the maximum stack depth needed 863 # Doesn't actually need to simulate the stack, since every word has a predictable effect. 864 fn max-stack-depth first-word: (addr word), final-word: (addr word) -> _/edi: int { 865 var curr-word/eax: (addr word) <- copy first-word 866 var curr-depth/ecx: int <- copy 0 867 var result/edi: int <- copy 0 868 $max-stack-depth:loop: { 869 $max-stack-depth:process-word: { 870 # handle operators 871 { 872 var add?/eax: boolean <- word-equal? curr-word, "+" 873 compare add?, 0 874 break-if-= 875 curr-depth <- decrement 876 break $max-stack-depth:process-word 877 } 878 { 879 var sub?/eax: boolean <- word-equal? curr-word, "-" 880 compare sub?, 0 881 break-if-= 882 curr-depth <- decrement 883 break $max-stack-depth:process-word 884 } 885 { 886 var mul?/eax: boolean <- word-equal? curr-word, "*" 887 compare mul?, 0 888 break-if-= 889 curr-depth <- decrement 890 break $max-stack-depth:process-word 891 } 892 # otherwise it's an int (do we need error-checking?) 893 curr-depth <- increment 894 # update max depth if necessary 895 { 896 compare curr-depth, result 897 break-if-<= 898 result <- copy curr-depth 899 } 900 } 901 # if curr-word == final-word break 902 compare curr-word, final-word 903 break-if-= 904 # curr-word = curr-word->next 905 var next-word-ah/edx: (addr handle word) <- get curr-word, next 906 curr-word <- lookup *next-word-ah 907 # 908 loop 909 } 910 return result 911 }