https://github.com/akkartik/mu/blob/master/apps/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
10 compare curr, 0
11 break-if-=
12
13 emit-word curr, curr-stream
14
15
16 $evaluate:process-word: {
17
18 {
19 var is-add?/eax: boolean <- stream-data-equal? curr-stream, "+"
20 compare is-add?, 0
21 break-if-=
22 var _b/eax: int <- pop-int-from-value-stack out
23 var b/edx: int <- copy _b
24 var a/eax: int <- pop-int-from-value-stack out
25 a <- add b
26 push-int-to-value-stack out, a
27 break $evaluate:process-word
28 }
29 {
30 var is-sub?/eax: boolean <- stream-data-equal? curr-stream, "-"
31 compare is-sub?, 0
32 break-if-=
33 var _b/eax: int <- pop-int-from-value-stack out
34 var b/edx: int <- copy _b
35 var a/eax: int <- pop-int-from-value-stack out
36 a <- subtract b
37 push-int-to-value-stack out, a
38 break $evaluate:process-word
39 }
40 {
41 var is-mul?/eax: boolean <- stream-data-equal? curr-stream, "*"
42 compare is-mul?, 0
43 break-if-=
44 var _b/eax: int <- pop-int-from-value-stack out
45 var b/edx: int <- copy _b
46 var a/eax: int <- pop-int-from-value-stack out
47 a <- multiply b
48 push-int-to-value-stack out, a
49 break $evaluate:process-word
50 }
51
52 {
53 var done?/eax: boolean <- stream-empty? curr-stream
54 compare done?, 0
55 break-if-!=
56 var new-byte/eax: byte <- read-byte curr-stream
57 compare new-byte, 0x3d
58 break-if-!=
59 var key-h: (handle array byte)
60 var key/ecx: (addr handle array byte) <- address key-h
61 stream-to-string curr-stream, key
62 var foo/eax: (addr array byte) <- lookup *key
63 var val/eax: int <- pop-int-from-value-stack out
64 bind-int-in-table bindings, key, val
65 var line/eax: (addr line) <- copy scratch
66 var next-line-ah/eax: (addr handle line) <- get line, next
67 var next-line/eax: (addr line) <- lookup *next-line-ah
68 compare next-line, 0
69 break-if-= $evaluate:process-word
70 evaluate functions, bindings, next-line, end, out
71 break $evaluate:process-word
72 }
73 rewind-stream curr-stream
74
75 {
76 var callee-h: (handle function)
77 var callee-ah/eax: (addr handle function) <- address callee-h
78 find-function functions, curr-stream, callee-ah
79 var callee/eax: (addr function) <- lookup *callee-ah
80 compare callee, 0
81 break-if-=
82 perform-call callee, out, functions
83 break $evaluate:process-word
84 }
85
86 {
87 compare bindings, 0
88 break-if-=
89 var tmp: (handle array byte)
90 var curr-string-ah/edx: (addr handle array byte) <- address tmp
91 stream-to-string curr-stream, curr-string-ah
92 var curr-string/eax: (addr array byte) <- lookup *curr-string-ah
93 var val-storage: (handle value)
94 var val-ah/edi: (addr handle value) <- address val-storage
95 lookup-binding bindings, curr-string, val-ah
96 var val/eax: (addr value) <- lookup *val-ah
97 compare val, 0
98 break-if-=
99 push-value-stack out, val
100 break $evaluate:process-word
101 }
102
103 {
104 var n/eax: int <- parse-decimal-int-from-stream curr-stream
105 push-int-to-value-stack out, n
106 }
107 }
108
109 compare curr, end
110 break-if-=
111
112 var next-word-ah/edx: (addr handle word) <- get curr, next
113 curr <- lookup *next-word-ah
114
115 loop
116 }
117 }
118
119 fn test-evaluate {
120 var line-storage: line
121 var line/esi: (addr line) <- address line-storage
122 var first-word-ah/eax: (addr handle word) <- get line-storage, data
123 allocate-word-with first-word-ah, "3"
124 append-word-with *first-word-ah, "=a"
125 var next-line-ah/eax: (addr handle line) <- get line-storage, next
126 allocate next-line-ah
127 var next-line/eax: (addr line) <- lookup *next-line-ah
128 var first-word-ah/eax: (addr handle word) <- get next-line, data
129 allocate-word-with first-word-ah, "a"
130 var functions-storage: (handle function)
131 var functions/ecx: (addr handle function) <- address functions-storage
132 var table-storage: table
133 var table/ebx: (addr table) <- address table-storage
134 initialize-table table, 0x10
135 var stack-storage: value-stack
136 var stack/edi: (addr value-stack) <- address stack-storage
137 initialize-value-stack stack, 0x10
138 evaluate functions, table, line, 0, stack
139 var x/eax: int <- pop-int-from-value-stack stack
140 check-ints-equal x, 3, "F - test-evaluate"
141 }
142
143 fn find-function first: (addr handle function), name: (addr stream byte), out: (addr handle function) {
144 var curr/esi: (addr handle function) <- copy first
145 $find-function:loop: {
146 var _f/eax: (addr function) <- lookup *curr
147 var f/ecx: (addr function) <- copy _f
148 compare f, 0
149 break-if-=
150 var curr-name-ah/eax: (addr handle array byte) <- get f, name
151 var curr-name/eax: (addr array byte) <- lookup *curr-name-ah
152 var done?/eax: boolean <- stream-data-equal? name, curr-name
153 compare done?, 0
154 {
155 break-if-=
156 copy-handle *curr, out
157 break $find-function:loop
158 }
159 curr <- get f, next
160 loop
161 }
162 }
163
164 fn perform-call _callee: (addr function), caller-stack: (addr value-stack), functions: (addr handle function) {
165 var callee/ecx: (addr function) <- copy _callee
166
167 var table-storage: table
168 var table/esi: (addr table) <- address table-storage
169 initialize-table table, 0x10
170 bind-args callee, caller-stack, table
171
172 var body-ah/eax: (addr handle line) <- get callee, body
173 var body/eax: (addr line) <- lookup *body-ah
174
175 var stack-storage: value-stack
176 var stack/edi: (addr value-stack) <- address stack-storage
177 initialize-value-stack stack, 0x10
178
179 evaluate functions, table, body, 0, stack
180
181
182 var result/eax: int <- pop-int-from-value-stack stack
183 push-int-to-value-stack caller-stack, result
184 }
185
186
187
188 fn bind-args _callee: (addr function), caller-stack: (addr value-stack), table: (addr table) {
189 var callee/ecx: (addr function) <- copy _callee
190 var curr-arg-ah/eax: (addr handle word) <- get callee, args
191 var curr-arg/eax: (addr word) <- lookup *curr-arg-ah
192
193 var curr-key-storage: (handle array byte)
194 var curr-key/edx: (addr handle array byte) <- address curr-key-storage
195 {
196 compare curr-arg, 0
197 break-if-=
198
199 word-to-string curr-arg, curr-key
200 {
201
202
203
204
205 var curr-val/eax: int <- pop-int-from-value-stack caller-stack
206
207
208 bind-int-in-table table, curr-key, curr-val
209 }
210
211 var next-arg-ah/edx: (addr handle word) <- get curr-arg, next
212 curr-arg <- lookup *next-arg-ah
213 loop
214 }
215 }
216
217
218
219 fn max-stack-depth first-word: (addr word), final-word: (addr word) -> result/edi: int {
220 var curr-word/eax: (addr word) <- copy first-word
221 var curr-depth/ecx: int <- copy 0
222 result <- copy 0
223 $max-stack-depth:loop: {
224 $max-stack-depth:process-word: {
225
226 {
227 var is-add?/eax: boolean <- word-equal? curr-word, "+"
228 compare is-add?, 0
229 break-if-=
230 curr-depth <- decrement
231 break $max-stack-depth:process-word
232 }
233 {
234 var is-sub?/eax: boolean <- word-equal? curr-word, "-"
235 compare is-sub?, 0
236 break-if-=
237 curr-depth <- decrement
238 break $max-stack-depth:process-word
239 }
240 {
241 var is-mul?/eax: boolean <- word-equal? curr-word, "*"
242 compare is-mul?, 0
243 break-if-=
244 curr-depth <- decrement
245 break $max-stack-depth:process-word
246 }
247
248 curr-depth <- increment
249
250 {
251 compare curr-depth, result
252 break-if-<=
253 result <- copy curr-depth
254 }
255 }
256
257 compare curr-word, final-word
258 break-if-=
259
260 var next-word-ah/edx: (addr handle word) <- get curr-word, next
261 curr-word <- lookup *next-word-ah
262
263 loop
264 }
265 }