https://github.com/akkartik/mu/blob/master/apps/tile/rpn.mu
1 fn evaluate defs: (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 callee-h: (handle function)
54 var callee-ah/eax: (addr handle function) <- address callee-h
55 find-function defs, curr-stream, callee-ah
56 var callee/eax: (addr function) <- lookup *callee-ah
57 compare callee, 0
58 break-if-=
59 perform-call callee, out, defs
60 break $evaluate:process-word
61 }
62
63 {
64 compare bindings, 0
65 break-if-=
66 var tmp: (handle array byte)
67 var curr-string-ah/edx: (addr handle array byte) <- address tmp
68 stream-to-string curr-stream, curr-string-ah
69 var curr-string/eax: (addr array byte) <- lookup *curr-string-ah
70 var val-storage: (handle value)
71 var val-ah/edi: (addr handle value) <- address val-storage
72 lookup-binding bindings, curr-string, val-ah
73 var val/eax: (addr value) <- lookup *val-ah
74 compare val, 0
75 break-if-=
76
77
78
79
80
81 push-value-stack out, val
82 break $evaluate:process-word
83 }
84
85 {
86 var n/eax: int <- parse-decimal-int-from-stream curr-stream
87 push-int-to-value-stack out, n
88 }
89 }
90
91 compare curr, end
92 break-if-=
93
94 var next-word-ah/edx: (addr handle word) <- get curr, next
95 curr <- lookup *next-word-ah
96
97 loop
98 }
99 }
100
101 fn find-function first: (addr handle function), name: (addr stream byte), out: (addr handle function) {
102 var curr/esi: (addr handle function) <- copy first
103 $find-function:loop: {
104 var _f/eax: (addr function) <- lookup *curr
105 var f/ecx: (addr function) <- copy _f
106 compare f, 0
107 break-if-=
108 var curr-name-ah/eax: (addr handle array byte) <- get f, name
109 var curr-name/eax: (addr array byte) <- lookup *curr-name-ah
110 var done?/eax: boolean <- stream-data-equal? name, curr-name
111 compare done?, 0
112 {
113 break-if-=
114 copy-handle *curr, out
115 break $find-function:loop
116 }
117 curr <- get f, next
118 loop
119 }
120 }
121
122 fn perform-call _callee: (addr function), caller-stack: (addr value-stack), defs: (addr handle function) {
123 var callee/ecx: (addr function) <- copy _callee
124
125 var table-storage: table
126 var table/esi: (addr table) <- address table-storage
127 initialize-table table, 0x10
128 bind-args callee, caller-stack, table
129
130 var body-ah/eax: (addr handle line) <- get callee, body
131 var body/eax: (addr line) <- lookup *body-ah
132
133 var stack-storage: value-stack
134 var stack/edi: (addr value-stack) <- address stack-storage
135 initialize-value-stack stack, 0x10
136
137 evaluate defs, table, body, 0, stack
138
139
140 var result/eax: int <- pop-int-from-value-stack stack
141 push-int-to-value-stack caller-stack, result
142 }
143
144 fn bind-args _callee: (addr function), caller-stack: (addr value-stack), table: (addr table) {
145 var callee/ecx: (addr function) <- copy _callee
146 var curr-arg-ah/eax: (addr handle word) <- get callee, args
147 var curr-arg/eax: (addr word) <- lookup *curr-arg-ah
148
149 var curr-key-storage: (handle array byte)
150 var curr-key/edx: (addr handle array byte) <- address curr-key-storage
151 {
152 compare curr-arg, 0
153 break-if-=
154
155 word-to-string curr-arg, curr-key
156 {
157
158
159
160
161 var curr-val/eax: int <- pop-int-from-value-stack caller-stack
162
163
164 bind-int-in-table table, curr-key, curr-val
165 }
166
167 var next-arg-ah/edx: (addr handle word) <- get curr-arg, next
168 curr-arg <- lookup *next-arg-ah
169 loop
170 }
171 }
172
173
174
175 fn max-stack-depth first-word: (addr word), final-word: (addr word) -> result/edi: int {
176 var curr-word/eax: (addr word) <- copy first-word
177 var curr-depth/ecx: int <- copy 0
178 result <- copy 0
179 $max-stack-depth:loop: {
180 $max-stack-depth:process-word: {
181
182 {
183 var is-add?/eax: boolean <- word-equal? curr-word, "+"
184 compare is-add?, 0
185 break-if-=
186 curr-depth <- decrement
187 break $max-stack-depth:process-word
188 }
189 {
190 var is-sub?/eax: boolean <- word-equal? curr-word, "-"
191 compare is-sub?, 0
192 break-if-=
193 curr-depth <- decrement
194 break $max-stack-depth:process-word
195 }
196 {
197 var is-mul?/eax: boolean <- word-equal? curr-word, "*"
198 compare is-mul?, 0
199 break-if-=
200 curr-depth <- decrement
201 break $max-stack-depth:process-word
202 }
203
204 curr-depth <- increment
205
206 {
207 compare curr-depth, result
208 break-if-<=
209 result <- copy curr-depth
210 }
211 }
212
213 compare curr-word, final-word
214 break-if-=
215
216 var next-word-ah/edx: (addr handle word) <- get curr-word, next
217 curr-word <- lookup *next-word-ah
218
219 loop
220 }
221 }