DISABLE FDs (REMOVE ME).
[jackhill/mal.git] / wasm / step4_if_fn_do.wam
CommitLineData
3ea09886
JM
1(module $step4_if_fn_do
2
3 (global $repl_env (mut i32) (i32.const 0))
4
5 ;; READ
6 (func $READ (param $str i32) (result i32)
7 ($read_str $str)
8 )
9
10 ;; EVAL
11 (func $EVAL_AST (param $ast i32 $env i32) (result i32)
349faa83
JM
12 (LET $res 0 $val2 0 $val3 0 $type 0 $found 0
13 $ret 0 $empty 0 $current 0)
3ea09886 14
0a19c2f1
JM
15 (if (global.get $error_type) (return 0))
16 (local.set $type ($TYPE $ast))
3ea09886
JM
17
18 ;;($PR_VALUE ">>> EVAL_AST ast: '%s'\n" $ast)
19
20 ;;; switch(type)
21 (block $done
22 (block $default (block (block
23 (br_table 2 2 2 2 2 0 1 1 1 2 2 2 2 2 2 2 $type))
24 ;; symbol
25 ;; found/res returned as hi 32/lo 32 of i64
0a19c2f1 26 (local.set $res ($ENV_GET $env $ast))
3ea09886
JM
27 (br $done))
28 ;; list, vector, hashmap
29 ;; MAP_LOOP_START
0a19c2f1 30 (local.set $res ($MAP_LOOP_START $type))
3ea09886
JM
31 ;; push MAP_LOOP stack
32 ;;; empty = current = ret = res
0a19c2f1
JM
33 (local.set $ret $res)
34 (local.set $current $res)
35 (local.set $empty $res)
3ea09886
JM
36
37 (block $done
38 (loop $loop
39 ;; check if we are done evaluating the source sequence
349faa83 40 (br_if $done (i32.eq ($VAL0 $ast) 0))
3ea09886 41
0a19c2f1 42 (if (i32.eq $type (global.get $HASHMAP_T))
3ea09886 43 (then
0a19c2f1 44 (local.set $res ($EVAL ($MEM_VAL2_ptr $ast) $env)))
3ea09886 45 (else
0a19c2f1
JM
46 (local.set $res ($EVAL ($MEM_VAL1_ptr $ast) $env))))
47 (local.set $val2 $res)
3ea09886
JM
48
49 ;; if error, release the unattached element
0a19c2f1 50 (if (global.get $error_type)
3ea09886
JM
51 (then
52 ($RELEASE $res)
0a19c2f1 53 (local.set $res 0)
3ea09886
JM
54 (br $done)))
55
56 ;; for hash-maps, copy the key (inc ref since we are going
57 ;; to release it below)
0a19c2f1 58 (if (i32.eq $type (global.get $HASHMAP_T))
3ea09886 59 (then
0a19c2f1
JM
60 (local.set $val3 $val2)
61 (local.set $val2 ($MEM_VAL1_ptr $ast))
3ea09886
JM
62 (drop ($INC_REF $val2))))
63
64 ;; MAP_LOOP_UPDATE
0a19c2f1
JM
65 (local.set $res ($MAP_LOOP_UPDATE $type $empty $current $val2 $val3))
66 (if (i32.le_u $current (global.get $EMPTY_HASHMAP))
3ea09886 67 ;; if first element, set return to new element
0a19c2f1 68 (local.set $ret $res))
3ea09886 69 ;; update current to point to new element
0a19c2f1 70 (local.set $current $res)
3ea09886 71
0a19c2f1 72 (local.set $ast ($MEM_VAL0_ptr $ast))
3ea09886
JM
73
74 (br $loop)
75 )
76 )
77 ;; MAP_LOOP_DONE
0a19c2f1 78 (local.set $res $ret)
3ea09886
JM
79 ;; EVAL_AST_RETURN: nothing to do
80 (br $done))
81 ;; default
0a19c2f1 82 (local.set $res ($INC_REF $ast))
3ea09886
JM
83 )
84
85 $res
86 )
87
88 (func $MAL_GET_A1 (param $ast i32) (result i32)
89 ($MEM_VAL1_ptr ($MEM_VAL0_ptr $ast)))
90 (func $MAL_GET_A2 (param $ast i32) (result i32)
91 ($MEM_VAL1_ptr ($MEM_VAL0_ptr ($MEM_VAL0_ptr $ast))))
92 (func $MAL_GET_A3 (param $ast i32) (result i32)
93 ($MEM_VAL1_ptr ($MEM_VAL0_ptr ($MEM_VAL0_ptr ($MEM_VAL0_ptr $ast)))))
94
95 (func $EVAL (param $ast i32 $env i32) (result i32)
349faa83
JM
96 (LET $res 0 $el 0
97 $ftype 0 $f_args 0 $f 0 $args 0
98 $a0 0 $a0sym 0 $a1 0 $a2 0 $a3 0
99 $let_env 0 $fn_env 0 $a 0)
3ea09886 100
0a19c2f1
JM
101 (local.set $f_args 0)
102 (local.set $f 0)
103 (local.set $args 0)
3ea09886 104
0a19c2f1 105 (if (global.get $error_type) (return 0))
3ea09886 106
50eea9ad 107 ;;($PR_VALUE ">>> EVAL ast: '%s'\n" $ast)
3ea09886 108
0a19c2f1 109 (if (i32.ne ($TYPE $ast) (global.get $LIST_T))
3ea09886
JM
110 (return ($EVAL_AST $ast $env)))
111
112 ;; APPLY_LIST
113 (if ($EMPTY_Q $ast)
114 (return ($INC_REF $ast)))
115
0a19c2f1
JM
116 (local.set $a0 ($MEM_VAL1_ptr $ast))
117 (local.set $a0sym "")
118 (if (i32.eq ($TYPE $a0) (global.get $SYMBOL_T))
119 (local.set $a0sym ($to_String $a0)))
3ea09886
JM
120
121 (if (i32.eqz ($strcmp "def!" $a0sym))
122 (then
0a19c2f1
JM
123 (local.set $a1 ($MAL_GET_A1 $ast))
124 (local.set $a2 ($MAL_GET_A2 $ast))
125 (local.set $res ($EVAL $a2 $env))
126 (if (global.get $error_type) (return $res))
3ea09886
JM
127
128 ;; set a1 in env to a2
0a19c2f1 129 (local.set $res ($ENV_SET $env $a1 $res)))
3ea09886
JM
130 (else (if (i32.eqz ($strcmp "let*" $a0sym))
131 (then
0a19c2f1
JM
132 (local.set $a1 ($MAL_GET_A1 $ast))
133 (local.set $a2 ($MAL_GET_A2 $ast))
3ea09886
JM
134
135 ;; create new environment with outer as current environment
0a19c2f1 136 (local.set $let_env ($ENV_NEW $env))
3ea09886
JM
137
138 (block $done
139 (loop $loop
349faa83 140 (br_if $done (i32.eqz ($VAL0 $a1)))
3ea09886 141 ;; eval current A1 odd element
0a19c2f1 142 (local.set $res ($EVAL ($MEM_VAL1_ptr ($MEM_VAL0_ptr $a1))
3ea09886
JM
143 $let_env))
144
0a19c2f1 145 (br_if $done (global.get $error_type))
3ea09886
JM
146
147 ;; set key/value in the let environment
0a19c2f1 148 (local.set $res ($ENV_SET $let_env ($MEM_VAL1_ptr $a1) $res))
3ea09886
JM
149 ;; release our use, ENV_SET took ownership
150 ($RELEASE $res)
151
152 ;; skip to the next pair of a1 elements
0a19c2f1 153 (local.set $a1 ($MEM_VAL0_ptr ($MEM_VAL0_ptr $a1)))
3ea09886
JM
154 (br $loop)
155 )
156 )
0a19c2f1 157 (local.set $res ($EVAL $a2 $let_env))
3ea09886
JM
158 ;; EVAL_RETURN
159 ($RELEASE $let_env))
160 (else (if (i32.eqz ($strcmp "do" $a0sym))
161 (then
0a19c2f1
JM
162 (local.set $el ($EVAL_AST ($MEM_VAL0_ptr $ast) $env))
163 (local.set $res ($LAST $el))
3ea09886
JM
164 ($RELEASE $el))
165 (else (if (i32.eqz ($strcmp "if" $a0sym))
166 (then
0a19c2f1
JM
167 (local.set $a1 ($MAL_GET_A1 $ast))
168 (local.set $res ($EVAL $a1 $env))
3ea09886 169
0a19c2f1 170 (if (global.get $error_type)
3ea09886 171 (then (nop))
0a19c2f1
JM
172 (else (if (OR (i32.eq $res (global.get $NIL))
173 (i32.eq $res (global.get $FALSE)))
3ea09886
JM
174 (then
175 ($RELEASE $res)
176 ;; if no false case (A3), return nil
177 (if (i32.lt_u ($COUNT $ast) 4)
178 (then
0a19c2f1 179 (local.set $res ($INC_REF (global.get $NIL))))
3ea09886 180 (else
0a19c2f1
JM
181 (local.set $a3 ($MAL_GET_A3 $ast))
182 (local.set $res ($EVAL $a3 $env)))))
3ea09886
JM
183 (else
184 ($RELEASE $res)
0a19c2f1
JM
185 (local.set $a2 ($MAL_GET_A2 $ast))
186 (local.set $res ($EVAL $a2 $env)))))))
3ea09886
JM
187 (else (if (i32.eqz ($strcmp "fn*" $a0sym))
188 (then
0a19c2f1
JM
189 (local.set $a1 ($MAL_GET_A1 $ast))
190 (local.set $a2 ($MAL_GET_A2 $ast))
191 (local.set $res ($ALLOC (global.get $MALFUNC_T) $a2 $a1 $env)))
3ea09886
JM
192 (else
193 ;; EVAL_INVOKE
0a19c2f1
JM
194 (local.set $res ($EVAL_AST $ast $env))
195 (local.set $f_args $res)
3ea09886
JM
196
197 ;; if error, return f/args for release by caller
0a19c2f1 198 (if (global.get $error_type)
349faa83 199 (return $f_args))
3ea09886 200
0a19c2f1
JM
201 (local.set $args ($MEM_VAL0_ptr $f_args)) ;; rest
202 (local.set $f ($MEM_VAL1_ptr $f_args)) ;; value
3ea09886 203
0a19c2f1
JM
204 (local.set $ftype ($TYPE $f))
205 (if (i32.eq $ftype (global.get $FUNCTION_T))
3ea09886 206 (then
0a19c2f1 207 (local.set $res (call_indirect (type $fnT) $args ($VAL0 $f)))
3ea09886
JM
208 ;; release f/args
209 ($RELEASE $f_args))
0a19c2f1 210 (else (if (i32.eq $ftype (global.get $MALFUNC_T))
3ea09886 211 (then
0a19c2f1 212 (local.set $fn_env ($ENV_NEW_BINDS ($MEM_VAL2_ptr $f)
3ea09886
JM
213 ($MEM_VAL1_ptr $f) $args))
214
215 ;; claim the AST before releasing the list containing it
0a19c2f1 216 (local.set $a ($MEM_VAL0_ptr $f))
3ea09886
JM
217 (drop ($INC_REF $a))
218
219 ;; release f/args
220 ($RELEASE $f_args)
221
0a19c2f1 222 (local.set $res ($EVAL $a $fn_env))
3ea09886
JM
223 ;; EVAL_RETURN
224 ($RELEASE $fn_env)
225 ($RELEASE $a))
226 (else
227 ;; create new environment using env and params stored in function
50eea9ad 228 ($THROW_STR_1 "apply of non-function type: %d\n" $ftype)
0a19c2f1 229 (local.set $res 0)
3ea09886
JM
230 ($RELEASE $f_args)))))))))))))))
231
232 $res
233 )
234
235 ;; PRINT
236 (func $PRINT (param $ast i32) (result i32)
237 ($pr_str $ast 1)
238 )
239
240 ;; REPL
241 (func $RE (param $line i32 $env i32) (result i32)
349faa83
JM
242 (LET $mv1 0 $res 0)
243 (block $done
0a19c2f1
JM
244 (local.set $mv1 ($READ $line))
245 (br_if $done (global.get $error_type))
3ea09886 246
0a19c2f1 247 (local.set $res ($EVAL $mv1 $env))
3ea09886
JM
248 )
249
250 ;; release memory from MAL_READ
251 ($RELEASE $mv1)
252 $res
253 )
254
255 (func $REP (param $line i32 $env i32) (result i32)
349faa83
JM
256 (LET $mv2 0 $ms 0)
257 (block $done
0a19c2f1
JM
258 (local.set $mv2 ($RE $line $env))
259 (br_if $done (global.get $error_type))
3ea09886
JM
260
261;; ($PR_MEMORY -1 -1)
0a19c2f1 262 (local.set $ms ($PRINT $mv2))
3ea09886
JM
263 )
264
265 ;; release memory from RE
266 ($RELEASE $mv2)
267 $ms
268 )
269
ed13313d 270 (func $main (param $argc i32 $argv i32) (result i32)
349faa83 271 (LET $line (STATIC_ARRAY 201)
dd7a4f55 272 $res 0 $repl_env 0 $ms 0)
3ea09886
JM
273
274 ;; DEBUG
0a19c2f1
JM
275;; ($printf_1 "memoryBase: 0x%x\n" (global.get $memoryBase))
276;; ($printf_1 "heap_start: 0x%x\n" (global.get $heap_start))
277;; ($printf_1 "heap_end: 0x%x\n" (global.get $heap_end))
278;; ($printf_1 "mem: 0x%x\n" (global.get $mem))
279;; ($printf_1 "string_mem: %d\n" (global.get $string_mem))
3ea09886 280
0a19c2f1
JM
281 (global.set $repl_env ($ENV_NEW (global.get $NIL)))
282 (local.set $repl_env (global.get $repl_env))
3ea09886
JM
283
284 ;; core.EXT: defined in wasm
285 ($add_core_ns $repl_env)
286
349faa83
JM
287 ($checkpoint_user_memory)
288
3ea09886
JM
289 ;; core.mal: defined using the language itself
290 ($RELEASE ($RE "(def! not (fn* (a) (if a false true)))" $repl_env))
291
292 ;;($PR_MEMORY -1 -1)
293
294 ;; Start REPL
295 (block $repl_done
296 (loop $repl_loop
50eea9ad
JM
297 (br_if $repl_done (i32.eqz ($readline "user> " $line)))
298 (br_if $repl_loop (i32.eq (i32.load8_u $line) 0))
0a19c2f1
JM
299 (local.set $res ($REP $line $repl_env))
300 (if (global.get $error_type)
3ea09886 301 (then
0a19c2f1 302 (if (i32.eq 2 (global.get $error_type))
dd7a4f55 303 (then
0a19c2f1 304 (local.set $ms ($pr_str (global.get $error_val) 1))
dd7a4f55
JM
305 ($printf_1 "Error: %s\n" ($to_String $ms))
306 ($RELEASE $ms)
0a19c2f1 307 ($RELEASE (global.get $error_val)))
dd7a4f55 308 (else
0a19c2f1
JM
309 ($printf_1 "Error: %s\n" (global.get $error_str))))
310 (global.set $error_type 0))
3ea09886
JM
311 (else
312 ($printf_1 "%s\n" ($to_String $res))))
313 ($RELEASE $res)
50eea9ad
JM
314 ;;($PR_MEMORY_SUMMARY_SMALL)
315 (br $repl_loop)
316 )
317 )
3ea09886
JM
318
319 ($print "\n")
320 ;;($PR_MEMORY -1 -1)
321 0
322 )
323
3ea09886
JM
324)
325