json testing
[watForth.git] / forth.wat
1 (; This program is free software: you can redistribute it and/or modify
2 it under the terms of the GNU General Public License as published by
3 the Free Software Foundation, either version 3 of the License, or
4 (at your option) any later version.
5
6 This program is distributed in the hope that it will be useful,
7 but WITHOUT ANY WARRANTY; without even the implied warranty of
8 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 GNU General Public License for more details.
10
11 You should have received a copy of the GNU General Public License
12 along with this program. If not, see <http://www.gnu.org/licenses/>. ;)
13 (module
14 (type $FUNCSIGi (func (result i32)))
15 (type $FUNCSIGii (func (param i32)))
16 (type $FUNCSIGiii (func))
17 (type $FUNCSIGiv (func (param i32 i32) (result i32)))
18 (type $FUNCSIGv (func (param i32) (result i32)))
19 (type $FUNCSIGvi (func (param i32 i32 i32) (result i32)))
20 (type $FUNCSIGvii (func (param i32 i32)))
21 (type $FUNCSIGviii (func (param i32 i32 i32)))
22 (import "env" "pop" (func $pop (result i32)))
23 (import "env" "push" (func $push (param i32)))
24 (import "env" "rinit" (func $rinit))
25 (import "env" "rpop" (func $rpop (result i32)))
26 (import "env" "rpush" (func $rpush (param i32)))
27 (import "env" "sys_read" (func $sys_read (param i32 i32 i32) (result i32)))
28 (import "env" "sys_write" (func $sys_write (param i32 i32 i32)))
29 (import "env" "sys_send" (func $sys_send (param i32 i32 i32)))
30 (import "env" "sys_open" (func $sys_open (result i32)))
31 (import "env" "sys_close" (func $sys_close (param i32)))
32 (import "env" "sys_fetch" (func $sys_fetch (param i32 i32 i32) (result i32)))
33 (import "env" "sys_connect" (func $sys_connect (param i32 i32) (result i32)))
34 (import "env" "sys_echo" (func $sys_echo (param i32)))
35 (import "env" "sys_log" (func $sys_log (param i32 i32)))
36 (import "env" "sys_reflect" (func $sys_reflect (param i32)))
37 (import "env" "vocab_get" (func $vocab_get (param i32 i32) (result i32)))
38 (import "env" "vocab_set" (func $vocab_set (param i32 i32 i32)))
39 (import "env" "does_get" (func $does_get (param i32 i32) (result i32)))
40 (import "env" "does_set" (func $does_set (param i32 i32 i32)))
41 (import "env" "is_whitespace" (func $is_whitespace (param i32) (result i32)))
42 (import "env" "sys_parsenum" (func $sys_parsenum (param i32 i32) (result i32)))
43 (import "env" "sys_stack" (func $sys_stack))
44 (import "env" "sys_words" (func $sys_words))
45 (table (;0;) 0 anyfunc)
46 (memory $0 1)
47 (; String Belt ;) ;; 0x0000 Size: 8192
48 (global $wordbelt_base i32 (i32.const 8192) ) ;; 0x2000 Size: 4096
49 (global $wordbelt_bound i32 (i32.const 12288)) ;; 0x3000
50 (global $stdin_base i32 (i32.const 12288)) ;; 0x3000 Size: 2048
51 (global $kvars i32 (i32.const 14336)) ;; 0x3800 Size: 2048
52 (global $mode_p i32 (i32.const 14336))
53 (global $here_p i32 (i32.const 14340))
54 (global $start_p i32 (i32.const 14344))
55 (global $base_p i32 (i32.const 14348))
56 (global $stringbelt_tail_p i32 (i32.const 14352))
57 (global $stringbelt_head_p i32 (i32.const 14356))
58 (global $wordbelt_tail_p i32 (i32.const 14360))
59 (global $wordbelt_head_p i32 (i32.const 14364))
60 (data (i32.const 14336) "\28\41\00\00") ;; MODE
61 (data (i32.const 14340) "\04\5e\00\00") ;; HERE
62 (data (i32.const 14344) "\00\40\00\00") ;; START (16384) (Quit)
63 (data (i32.const 14348) "\0a\00\00\00") ;; BASE
64 (data (i32.const 14352) "\00\00\00\00") ;; STRINGBELT_TAIL
65 (data (i32.const 14356) "\00\00\00\00") ;; STRINGBELT_HEAD
66 (data (i32.const 14360) "\00\20\00\00") ;; WORDBELT_TAIL
67 (data (i32.const 14364) "\00\20\00\00") ;; WORDBELT_HEAD
68 (; Quit ;)
69 (global $quit_p i32 (i32.const 16384)) ;; 0x4000
70 (data (i32.const 16384) "\03\00\00\00") ;; RINIT xt
71 (global $quit_ret_p i32 (i32.const 16388))
72 (data (i32.const 16388) "\10\40\00\00") ;; INTERPRET xt
73 (data (i32.const 16392) "\12\00\00\00") ;; JMP xt
74 (data (i32.const 16396) "\00\40\00\00") ;; quit location (16384)
75 (; Interpret ;)
76 (data (i32.const 16400) "\74\40\00\00") ;; WORD xt (16500)
77 (data (i32.const 16404) "\0d\00\00\00") ;; (data (i32.const 16404) "\1e\00\00\00") ;; 2DUP
78 (data (i32.const 16408) "\0d\00\00\00") ;; (data (i32.const 16408) "\04\00\00\00") ;; SYS-LOG
79 (data (i32.const 16412) "\06\00\00\00") ;; DUP
80 (data (i32.const 16416) "\0e\00\00\00") ;; JZ:
81 (data (i32.const 16420) "\40\40\00\00") ;; INTERP-END addr (16444)
82 (data (i32.const 16424) "\02\00\00\00") ;; LIT xt
83 (data (i32.const 16428) "\00\38\00\00") ;; MODE addr (14336)
84 (data (i32.const 16432) "\0a\00\00\00") ;; @ (fetch) xt
85 (data (i32.const 16436) "\0c\00\00\00") ;; EXECUTE xt
86 (data (i32.const 16440) "\0d\00\00\00") ;; NOOP xt
87 (data (i32.const 16444) "\01\00\00\00") ;; RET
88 (data (i32.const 16448) "\10\00\00\00") ;; DROP <-- INTERP-END
89 (data (i32.const 16452) "\10\00\00\00") ;; DROP
90 (global $holy_bye i32 (i32.const 16456))
91 (data (i32.const 16456) "\19\00\00\00") ;; BYE <-- the Holy BYE
92 (; Word ;)
93 (data (i32.const 16500) "\14\00\00\00") ;; WORDSTART
94 (data (i32.const 16504) "\05\00\00\00") ;; KEY <-- KEYLOOP
95 (data (i32.const 16508) "\06\00\00\00") ;; DUP
96 (data (i32.const 16512) "\18\00\00\00") ;; J-1: 18
97 (data (i32.const 16516) "\f0\40\00\00") ;; addr of WORDEND
98 (data (i32.const 16520) "\11\00\00\00") ;; WS?
99 (data (i32.const 16524) "\0f\00\00\00") ;; JNZ:
100 (data (i32.const 16528) "\bc\40\00\00") ;; addr of KEYDROP
101 (data (i32.const 16532) "\02\00\00\00") ;; LIT
102 (data (i32.const 16536) "\5c\00\00\00") ;; 92 (\ character)
103 (data (i32.const 16540) "\25\00\00\00") ;; =?
104 (data (i32.const 16544) "\0e\00\00\00") ;; JZ:
105 (data (i32.const 16548) "\e4\40\00\00") ;; addr of DOCHAR
106 (data (i32.const 16552) "\10\00\00\00") ;; DROP
107 (data (i32.const 16556) "\94\41\00\00") ;; DO-BACKSLASH (continue using this wbuf we started)
108 (data (i32.const 16560) "\0d\00\00\00") ;; NOOP
109 (data (i32.const 16564) "\12\00\00\00") ;; JMP:
110 (data (i32.const 16568) "\74\40\00\00") ;; addr of KEYLOOP-1 (get a new wbuf, call to wbuf+1 ate ours)
111 (data (i32.const 16572) "\10\00\00\00") ;; DROP <-- KEYDROP
112 (data (i32.const 16576) "\12\00\00\00") ;; JMP:
113 (data (i32.const 16580) "\78\40\00\00") ;; addr of KEYLOOP
114 (data (i32.const 16584) "\05\00\00\00") ;; KEY <-- WORDLOOP
115 (data (i32.const 16588) "\11\00\00\00") ;; WS? <-- WORDLOOP_REENTRY
116 (data (i32.const 16592) "\0f\00\00\00") ;; JNZ:
117 (data (i32.const 16596) "\f0\40\00\00") ;; addr of WORDEND
118 (data (i32.const 16600) "\06\00\00\00") ;; DUP
119 (data (i32.const 16604) "\18\00\00\00") ;; J-1:
120 (data (i32.const 16608) "\f0\40\00\00") ;; addr of WORDEND
121 (data (i32.const 16612) "\13\00\00\00") ;; WORDPUTC <-- DOCHAR
122 (data (i32.const 16616) "\12\00\00\00") ;; JMP:
123 (data (i32.const 16620) "\c8\40\00\00") ;; addr of WORDLOOP
124 (data (i32.const 16624) "\10\00\00\00") ;; DROP <-- WORDEND
125 (data (i32.const 16628) "\17\00\00\00") ;; WORDFINISH
126 (data (i32.const 16632) "\01\00\00\00") ;; 2DUP //RET
127 (data (i32.const 16636) "\04\00\00\00") ;; .S
128 (data (i32.const 16640) "\01\00\00\00") ;; RET
129 (; Exec Mode ;)
130 (data (i32.const 16680) "\1e\00\00\00") ;; 2DUP
131 (data (i32.const 16684) "\15\00\00\00") ;; DICT_GET
132 (data (i32.const 16688) "\06\00\00\00") ;; DUP
133 (data (i32.const 16692) "\0e\00\00\00") ;; JZ:
134 (data (i32.const 16696) "\4c\41\00\00") ;; donum -1 (16716)
135 (data (i32.const 16700) "\1f\00\00\00") ;; ROT
136 (data (i32.const 16704) "\20\00\00\00") ;; 2DROP
137 (data (i32.const 16708) "\0c\00\00\00") ;; EXECUTE
138 (data (i32.const 16712) "\01\00\00\00") ;; RET
139 (data (i32.const 16716) "\10\00\00\00") ;; DROP (xt from dictionary)
140 (data (i32.const 16720) "\16\00\00\00") ;; NUMBER <-- donum, pushes NUM, UNPARSED
141 (data (i32.const 16724) "\06\00\00\00") ;; DUP
142 (data (i32.const 16728) "\0f\00\00\00") ;; JNZ:
143 (data (i32.const 16732) "\68\41\00\00") ;; donum_err (16744)
144 (data (i32.const 16736) "\10\00\00\00") ;; DROP
145 (data (i32.const 16740) "\01\00\00\00") ;; RET
146 (data (i32.const 16744) "\20\00\00\00") ;; 2DROP <-- donum_err
147 (data (i32.const 16748) "\02\00\00\00") ;; LIT
148 (data (i32.const 16752) "\04\30\00\00") ;; INBUFSIZE LOCATION
149 (data (i32.const 16756) "\02\00\00\00") ;; LIT
150 (data (i32.const 16760) "\00\00\00\00") ;; 0
151 (data (i32.const 16764) "\0b\00\00\00") ;; !
152 (data (i32.const 16768) "\19\00\00\00") ;; BYE
153 (data (i32.const 16772) "\00\00\00\00") ;;
154 (data (i32.const 16776) "\00\00\00\00") ;;
155 (data (i32.const 16780) "\00\00\00\00") ;;
156 (data (i32.const 16784) "\00\00\00\00") ;;
157 (; Do Backslash ;)
158 (data (i32.const 16788) "\05\00\00\00") ;; KEY
159 (data (i32.const 16792) "\11\00\00\00") ;; WS?
160 (data (i32.const 16796) "\0f\00\00\00") ;; JNZ:
161 (data (i32.const 16800) "\c8\41\00\00") ;; addr of DO_COMMENT_REENTRY
162 (data (i32.const 16804) "\cc\40\00\00") ;; WORDLOOP_REENTRY (call)
163 (data (i32.const 16808) "\28\41\00\00") ;; EXECUTE-MODE
164 (data (i32.const 16812) "\01\00\00\00") ;; RET
165 (; Do Comment ;)
166 (data (i32.const 16828) "\18\00\00\00") ;; j-1: <-- keypump
167 (data (i32.const 16832) "\e0\41\00\00") ;; addr of DC_END
168 (data (i32.const 16836) "\05\00\00\00") ;; KEY <-- DO_COMMENT
169 (data (i32.const 16840) "\02\00\00\00") ;; LIT <-- DO_COMMENT_REENTRY
170 (data (i32.const 16844) "\0a\00\00\00") ;; 10 (line feed)
171 (data (i32.const 16848) "\25\00\00\00") ;; =?
172 (data (i32.const 16852) "\0e\00\00\00") ;; JZ:
173 (data (i32.const 16856) "\bc\41\00\00") ;; addr of keypump
174 (data (i32.const 16860) "\10\00\00\00") ;; DROP
175 (data (i32.const 16864) "\01\00\00\00") ;; RET <-- DC_END
176 (; Channel Table ;)
177 (; 1 FLAGS: AWAITER | RUNNING ]LSB ;)
178 (; 1 reserved ;)
179 (; 1 AWAITER CHANNEL ;)
180 (; 1 OUT CHANNEL ;)
181 (; 8 START | START-DEFAULT ;)
182 (; 16 BUFFER ADDRESSES: BASE, TAIL, HEAD, BOUND ;)
183 (global $channel_table_p i32 (i32.const 16900))
184 (global $channel_entry_size i32 (i32.const 28))
185 (global $channel_max i32 (i32.const 255))
186 (data (i32.const 16900) "\00\00\00\01") ;; STDIN (COUT: 1)
187 (data (i32.const 16904) "\00\40\00\00") ;; STDIN-START (QUIT)
188 (data (i32.const 16908) "\00\40\00\00") ;; STDIN-START-DEFAULT
189 (data (i32.const 16912) "\00\30\00\00") ;; STDIN-BUFFER-BASE
190 (data (i32.const 16916) "\00\30\00\00") ;; STDIN-BUFFER-TAIL
191 (data (i32.const 16920) "\00\30\00\00") ;; STDIN-BUFFER-HEAD
192 (data (i32.const 16924) "\00\38\00\00") ;; STDIN-BUFFER-BOUND
193 (data (i32.const 16928) "\00\00\00\00") ;; STDOUT
194 (data (i32.const 16932) "\00\00\00\00") ;; STDOUT (TODO: error handler)
195 (data (i32.const 16936) "\00\00\00\00") ;; STDOUT
196 (data (i32.const 16940) "\00\00\00\00") ;; STDOUT
197 (data (i32.const 16944) "\00\00\00\00") ;; STDOUT
198 (data (i32.const 16948) "\00\00\00\00") ;; STDOUT
199 (data (i32.const 16952) "\00\00\00\00") ;; STDOUT
200 (data (i32.const 16956) "\00\00\00\00") ;; STDERR (null)
201 (data (i32.const 16960) "\00\00\00\00") ;; STDERR (TODO: error handler)
202 (; 16900 + ((4 * 7)=>28 * 256)=>7168 = 24068 | 0x5e04 === HERE ;)
203 (export "memory" (memory $0))
204 (func $lit_rstack (param $here i32) (param $start i32) (param $dstart i32) (result i32)
205 (local $eax i32) (local $ecx i32)
206 i32.const 0
207 set_local $ecx
208 block $backup_loop
209 call $rpop
210 tee_local $eax
211 get_global $holy_bye
212 i32.eq
213 br_if $backup_loop
214 get_local $eax
215 call $push
216 get_local $ecx
217 i32.const 1
218 i32.add
219 set_local $ecx
220 end
221 (; push channel default start ;)
222 get_local $here
223 get_local $dstart
224 i32.store
225 get_local $here
226 i32.const 4
227 i32.add
228 set_local $here
229 block $output_done
230 block $output_loop
231 get_local $ecx
232 i32.eqz
233 br_if $output_done
234 get_local $ecx
235 i32.const -1
236 i32.add
237 set_local $ecx
238 get_local $here
239 i32.const 2 ;; lit
240 i32.store
241 get_local $here
242 i32.const 4
243 i32.add
244 tee_local $here
245 call $pop
246 i32.store
247 get_local $here
248 i32.const 4
249 i32.add
250 tee_local $here
251 i32.const 52 ;; rpush_op
252 i32.store
253 get_local $here
254 i32.const 4
255 i32.add
256 set_local $here
257 br $output_loop
258 end
259 end
260 get_local $here
261 i32.const 46
262 i32.store
263 get_local $here
264 i32.const 4
265 i32.add
266 set_local $here
267
268 get_local $here
269 i32.const 18 ;; jmp
270 i32.store
271 get_local $here
272 i32.const 4
273 i32.add
274 tee_local $here
275 get_local $start
276 i32.store
277 get_local $here
278 i32.const 4
279 i32.add
280 return
281 )
282 (func $close_channel (param $channel_p i32)
283 (local $eax i32)
284 block $no_close
285 get_local $channel_p
286 i32.const 3
287 i32.le_u
288 br_if $no_close
289 get_local $channel_p
290 call $sys_close
291 end
292 get_global $channel_table_p
293 get_global $channel_entry_size
294 get_local $channel_p
295 i32.mul
296 i32.add
297 tee_local $channel_p
298 i32.const 4
299 i32.add
300 get_local $channel_p
301 i32.const 8
302 i32.add
303 i32.load
304 i32.store ;; restore awaiter's "start" to original
305 get_local $channel_p
306 i32.const 0
307 i32.store8 ;; clear target thread's flags
308 (; set stdin tail and head to base ;)
309 get_local $channel_p
310 i32.const 16
311 i32.add
312 get_local $channel_p
313 i32.const 20
314 i32.add
315 get_local $channel_p
316 i32.const 12
317 i32.add
318 i32.load
319 tee_local $eax
320 i32.store
321 get_local $eax
322 i32.store
323 )
324 (func $forth_min (param $i1 i32) (param $i2 i32) (result i32)
325 block $is_greater
326 get_local $i1
327 get_local $i2
328 i32.lt_u
329 br_if $is_greater
330 get_local $i2
331 return
332 end
333 get_local $i1
334 return
335 )
336 (export "main" (func $main))
337 (func $main (param $event_channel i32) (result i32)
338 call $rinit
339 get_global $holy_bye
340 call $rpush
341 get_local $event_channel
342 call $interpret
343 return
344 )
345 (func $interpret (param $channel_in i32) (result i32)
346 (local $here i32)
347 (local $eax i32)
348 (local $esi i32)
349 (local $inbuf_base i32)
350 (local $inbuf_tail i32)
351 (local $inbuf_head i32)
352 (local $inbuf_bound i32)
353 (local $stringbelt_tail i32)
354 (local $stringbelt_head i32)
355 (local $wordbelt_tail i32)
356 (local $wordbelt_head i32)
357 (local $channel_out i32)
358
359 (; channel in setup ;)
360 get_global $channel_table_p
361 get_global $channel_entry_size
362 get_global $channel_max
363 get_local $channel_in
364 call $forth_min
365 i32.mul
366 i32.add
367 set_local $eax
368
369 (; exit if the event is for a channel that is already running ;)
370 block $check_run
371 get_local $eax
372 i32.load8_u
373 i32.const 1
374 i32.and
375 i32.eqz ;; (FLAGS & 1) => running, return 0
376 br_if $check_run
377 i32.const 0
378 return
379 end
380
381 get_local $eax
382 get_local $eax
383 i32.load8_u
384 i32.const 1
385 i32.or
386 i32.store8 ;; set running flag
387 get_local $eax
388 i32.const 3
389 i32.add
390 i32.load8_u
391 set_local $channel_out
392
393 get_local $eax
394 i32.const 4
395 i32.add
396 i32.load
397 set_local $esi
398
399 get_local $eax
400 i32.const 12
401 i32.add
402 i32.load
403 set_local $inbuf_base
404 get_local $eax
405 i32.const 16
406 i32.add
407 i32.load
408 set_local $inbuf_tail
409 get_local $eax
410 i32.const 20
411 i32.add
412 i32.load
413 set_local $inbuf_head
414 get_local $eax
415 i32.const 24
416 i32.add
417 i32.load
418 set_local $inbuf_bound
419 (; /channel in setup ;)
420 get_global $here_p
421 i32.load
422 set_local $here
423 get_global $stringbelt_tail_p
424 i32.load
425 set_local $stringbelt_tail
426 get_global $stringbelt_head_p
427 i32.load
428 set_local $stringbelt_head
429 get_global $wordbelt_tail_p
430 i32.load
431 set_local $wordbelt_tail
432 get_global $wordbelt_head_p
433 i32.load
434 set_local $wordbelt_head
435 block $bye
436 block $awaiting
437 loop $next
438 get_local $esi
439 get_local $esi
440 i32.const 4
441 i32.add
442 set_local $esi
443 i32.load
444 set_local $eax
445
446 loop $execloop
447 block $default block $op0 block $ret block $lit block $rinit
448 block $logword block $key block $dup block $plus block $noop2 block $emit
449 block $fetch block $set block $execute block $noop block $jz block $jnz
450 block $drop block $wsbool block $jmp block $wordputc block $wordstart
451 block $dictget block $parsenum block $wordfinish block $jneg1 block $swap
452 block $words block $here block $dictset block $dup2 block $rot block $drop2
453 block $comma block $subtract block $inchan block $sethere block $eqbool
454 block $echostring block $strstart block $strput block $strend block $fetchinc
455 block $setinc block $finddoes block $definedoes block $stacktrace block $webfetch
456 block $outchan block $read block $openchannel block $rpush_op block $fetch8_u
457 get_local $eax
458 br_table $op0 $ret (;2;)$lit $rinit (;4;)$logword $key (;6;)$dup $plus
459 (;8;)$jmp $emit (;10;)$fetch $set (;12;)$execute $noop (;14;)$jz $jnz
460 (;16;)$drop $wsbool (;18;)$jmp $wordputc (;20;)$wordstart $dictget
461 (;22;)$parsenum $wordfinish (;24;)$jneg1 $bye (;26;)$swap $words
462 (;28;)$here $dictset (;30;)$dup2 $rot (;32;)$drop2 $comma
463 (;34;)$subtract $inchan (;36;)$sethere $eqbool (;38;)$echostring $strstart
464 (;40;)$strput $strend (;42;)$fetchinc $setinc (;44;)$finddoes $definedoes
465 (;46;)$stacktrace $webfetch (;48;)$outchan $read (;50;)$awaiting $openchannel
466 (;52;)$rpush_op $fetch8_u $default
467 end ;; fetch8_u
468 call $pop
469 i32.load8_u
470 call $push
471 br $next
472 end ;; rpush_op
473 call $pop
474 call $rpush
475 br $next
476 end ;; openchannel
477 (; Get addr of channel block ;)
478 get_global $channel_table_p
479 get_global $channel_entry_size
480 call $sys_open
481 tee_local $eax
482 call $rpush ;;save to rstack
483 get_local $eax
484 i32.mul
485 i32.add
486 (; Set Out-Channel to 1 by default ;)
487 tee_local $eax
488 i32.const 3
489 i32.add ;; out channel
490 i32.const 1
491 i32.store8
492 (; leave a copy of channel_p on stack ;)
493 get_local $eax
494 (; Get addr of ch-start and ch-default-start ;)
495 get_local $eax
496 i32.const 4
497 i32.add ;; addr of channel start
498 tee_local $eax
499 get_local $eax
500 i32.const 4
501 i32.add ;; addr of channel default start
502 (; Store the user-provided address in both ;)
503 call $pop
504 tee_local $eax
505 i32.store
506 get_local $eax
507 i32.store
508 (; go bo buf-base (channel_p + 12), put HERE in it ;)
509 tee_local $eax
510 i32.const 12
511 i32.add
512 get_local $here
513 i32.store
514 (; set buf-tail ;)
515 get_local $eax
516 i32.const 16
517 i32.add
518 get_local $here
519 i32.store
520 (; set buf-head ;)
521 get_local $eax
522 i32.const 20
523 i32.add
524 get_local $here
525 i32.store
526 (; set buf-bound ;)
527 get_local $eax
528 i32.const 24
529 i32.add
530 (; set buf-bound = here += 512 ;)
531 get_local $here
532 i32.const 512
533 i32.add
534 tee_local $here
535 i32.store
536 (; return channel number ;)
537 call $rpop
538 call $push
539 br $next
540 end ;; read
541 get_local $channel_in
542 call $pop ;; location to write
543 set_local $eax
544 call $pop
545 get_local $eax
546 call $sys_read
547 br $next
548 end ;; outchan
549 call $pop
550 set_local $channel_out
551 br $next
552 end ;; webfetch
553 call $pop ;; u
554 call $rpush
555 call $pop ;; addr
556 set_local $eax
557 call $pop ;; callback
558 get_local $eax
559 call $rpop
560 call $sys_fetch
561 i32.const -1
562 i32.eq
563 br_if $bye
564 br $next
565 end ;; stacktrace
566 get_local $esi
567 call $rpush
568 call $sys_stack
569 call $rpop
570 drop
571 br $next
572 end ;; definedoes
573 call $pop
574 call $rpush
575 call $pop
576 set_local $eax
577 call $pop
578 get_local $eax
579 call $rpop
580 call $does_set
581 br $next
582 end ;; finddoes
583 call $pop
584 set_local $eax
585 call $pop
586 get_local $eax
587 call $does_get
588 call $push
589 br $next
590 end ;; setinc
591 call $pop
592 call $rpush
593 call $pop
594 tee_local $eax
595 call $rpop
596 i32.store
597 get_local $eax
598 i32.const 4
599 i32.add
600 call $push
601 br $next
602 end ;; fetchinc
603 call $pop
604 tee_local $eax
605 i32.const 4
606 i32.add
607 call $push
608 get_local $eax
609 i32.load
610 call $push
611 br $next
612 end ;; strend
613 get_local $stringbelt_tail
614 get_local $stringbelt_head
615 get_local $stringbelt_tail
616 i32.const 4
617 i32.add
618 i32.sub
619 tee_local $eax (; n bytes ;)
620 i32.store
621 (; align to 32-bit ;)
622 get_local $stringbelt_head
623 i32.const 3
624 i32.add
625 i32.const 8188
626 i32.and
627 set_local $stringbelt_head
628 (; /align ;)
629 get_local $stringbelt_tail
630 i32.const 4
631 i32.add
632 call $push
633 get_local $eax
634 call $push
635 br $next
636 end ;; strput
637 block $sbhasspace2
638 get_local $stringbelt_head
639 get_global $wordbelt_base
640 i32.lt_u
641 br_if $sbhasspace2
642 i32.const 0
643 tee_local $stringbelt_head
644 get_local $stringbelt_tail
645 i32.load
646 i32.store
647 get_local $stringbelt_head
648 i32.const 4
649 i32.add
650 set_local $stringbelt_head
651 get_local $stringbelt_tail
652 i32.const 4
653 i32.add
654 set_local $stringbelt_tail
655 loop $copystringtostart
656 get_local $stringbelt_head
657 get_local $stringbelt_tail
658 i32.load16_u
659 i32.store16
660 get_local $stringbelt_head
661 i32.const 2
662 i32.add
663 set_local $stringbelt_head
664 get_local $stringbelt_tail
665 i32.const 2
666 i32.add
667 tee_local $stringbelt_tail
668 get_global $wordbelt_base
669 i32.le_u
670 br_if $copystringtostart
671 end
672 i32.const 0
673 set_local $stringbelt_tail
674 end
675 get_local $stringbelt_head
676 call $pop
677 i32.store16
678 get_local $stringbelt_head
679 i32.const 2
680 i32.add
681 set_local $stringbelt_head
682 br $next
683 end ;; strstart
684 block $sbhasspace
685 get_local $stringbelt_head
686 get_global $wordbelt_base
687 i32.const 8
688 i32.sub
689 i32.le_u
690 br_if $sbhasspace
691 i32.const 0
692 set_local $stringbelt_head
693 end
694 get_local $stringbelt_head
695 get_local $stringbelt_head
696 tee_local $stringbelt_tail
697 i32.const 0
698 i32.store
699 i32.const 4
700 i32.add
701 set_local $stringbelt_head
702 br $next
703 end ;; echostring
704 get_local $channel_out
705 call $pop
706 set_local $eax
707 call $pop
708 get_local $eax
709 call $sys_send
710 br $next
711 end ;; eqbool
712 block $equiv
713 call $pop
714 call $pop
715 tee_local $eax
716 i32.eq
717 get_local $eax
718 call $push
719 br_if $equiv
720 i32.const 0
721 call $push
722 br $next
723 end
724 i32.const 1
725 call $push
726 br $next
727 end ;; sethere
728 call $pop
729 set_local $here
730 br $next
731 end ;; inchan
732 call $pop
733 set_local $channel_in
734 br $next
735 end ;; subtract
736 call $pop
737 set_local $eax
738 call $pop
739 get_local $eax
740 i32.sub
741 call $push
742 br $next
743 end ;; comma
744 get_local $here
745 call $pop
746 i32.store
747 get_local $here
748 i32.const 4
749 i32.add
750 set_local $here
751 br $next
752 end ;; drop2
753 call $pop
754 call $pop
755 drop
756 drop
757 br $next
758 end ;; rot
759 call $pop
760 call $pop
761 set_local $eax
762 call $pop
763 call $rpush
764 call $push
765 call $rpop
766 call $push
767 get_local $eax
768 call $push
769 br $next
770 end ;; dup2
771 get_local $esi
772 call $rpush
773 call $pop
774 set_local $eax
775 call $pop
776 tee_local $esi
777 call $push
778 get_local $eax
779 call $push
780 get_local $esi
781 call $push
782 get_local $eax
783 call $push
784 call $rpop
785 set_local $esi
786 br $next
787 end ;; dictset
788 call $pop
789 call $rpush
790 call $pop
791 set_local $eax
792 call $pop
793 get_local $eax
794 call $rpop
795 call $vocab_set
796 br $next
797 end ;; here
798 get_local $here
799 call $push
800 br $next
801 end ;; words
802 call $sys_words
803 br $next
804 end ;; swap
805 call $pop
806 call $pop
807 set_local $eax
808 call $push
809 get_local $eax
810 call $push
811 br $next
812 end ;; jneg1
813 block $jneg1if
814 call $pop
815 i32.const -1
816 i32.eq
817 br_if $jneg1if
818 get_local $esi
819 i32.const 4
820 i32.add
821 set_local $esi
822 br $next
823 end
824 get_local $esi
825 i32.load
826 set_local $esi
827 br $next
828 end ;; wordfinish
829 get_local $wordbelt_head
830 get_local $wordbelt_tail
831 i32.sub
832 set_local $eax (; n bytes ;)
833 (; align to 32-bit ;)
834 get_local $wordbelt_head
835 i32.const 3
836 i32.add
837 i32.const 12284
838 i32.and
839 set_local $wordbelt_head
840 (; /align ;)
841 get_local $wordbelt_tail
842 call $push
843 get_local $eax
844 call $push
845 br $next
846 end ;; parsenum
847 call $pop
848 call $rpush
849 call $pop
850 tee_local $eax
851 call $rpop
852 call $sys_parsenum
853 get_local $eax
854 i32.load
855 call $push
856 call $push
857 br $next
858 end ;; dictget
859 call $pop
860 set_local $eax
861 call $pop
862 get_local $eax
863 call $vocab_get
864 call $push
865 br $next
866 end ;; wordstart
867 block $wbhasspace
868 get_local $wordbelt_head
869 get_global $wordbelt_bound
870 i32.const 4
871 i32.sub
872 i32.le_u
873 br_if $wbhasspace
874 get_global $wordbelt_base
875 set_local $wordbelt_head
876 end
877 get_local $wordbelt_head
878 set_local $wordbelt_tail
879 br $next
880 end ;; wordputc
881 block $wbhasspace2
882 get_local $wordbelt_head
883 get_global $wordbelt_bound
884 i32.lt_u
885 br_if $wbhasspace2
886 get_global $wordbelt_base
887 set_local $wordbelt_head
888 loop $copywordtostart
889 get_local $wordbelt_head
890 get_local $wordbelt_tail
891 i32.load16_u
892 i32.store16
893 get_local $wordbelt_head
894 i32.const 2
895 i32.add
896 set_local $wordbelt_head
897 get_local $wordbelt_tail
898 i32.const 2
899 i32.add
900 tee_local $wordbelt_tail
901 get_global $wordbelt_bound
902 i32.lt_u
903 br_if $copywordtostart
904 end
905 get_global $wordbelt_base
906 set_local $wordbelt_tail
907 end
908 get_local $wordbelt_head
909 call $pop
910 i32.store16
911 get_local $wordbelt_head
912 i32.const 2
913 i32.add
914 set_local $wordbelt_head
915 br $next
916 end ;; jmp
917 get_local $esi
918 i32.load
919 set_local $esi
920 br $next
921 end ;; wsbool
922 call $pop
923 tee_local $eax
924 call $is_whitespace
925 get_local $eax
926 call $push
927 call $push
928 br $next
929 end ;; drop
930 call $pop
931 drop
932 br $next
933 end ;; jnz
934 block $jnzif
935 call $pop
936 i32.eqz
937 br_if $jnzif
938 get_local $esi
939 i32.load
940 set_local $esi
941 br $next
942 end
943 get_local $esi
944 i32.const 4
945 i32.add
946 set_local $esi
947 br $next
948 end ;; jz
949 block $jzif
950 call $pop
951 i32.eqz
952 br_if $jzif
953 get_local $esi
954 i32.const 4
955 i32.add
956 set_local $esi
957 br $next
958 end
959 get_local $esi
960 i32.load
961 set_local $esi
962 br $next
963 end ;; noop
964 br $next
965 end ;; execute
966 call $pop
967 tee_local $eax
968 i32.const 256
969 i32.lt_u
970 br_if $execloop
971 get_local $esi
972 call $rpush
973 get_local $eax
974 set_local $esi
975 br $next
976 end ;; set
977 call $pop
978 set_local $eax
979 call $pop
980 get_local $eax
981 i32.store
982 br $next
983 end ;; fetch
984 call $pop
985 i32.load
986 call $push
987 br $next
988 end ;; emit (.)
989 call $pop
990 call $sys_echo
991 br $next
992 end ;; noop2
993 br $next
994 end ;; plus
995 call $pop
996 call $pop
997 i32.add
998 call $push
999 br $next
1000 end ;; dup
1001 call $pop
1002 tee_local $eax
1003 get_local $eax
1004 call $push
1005 call $push
1006 br $next
1007 end ;; key
1008 loop $key_loop
1009 block $key_read
1010 get_local $inbuf_head
1011 get_local $inbuf_tail
1012 i32.ge_u
1013 br_if $key_read
1014 block $key_echo
1015 get_local $channel_out
1016 i32.const -1
1017 i32.add
1018 br_if $key_echo
1019 (; if current channel's default start is QUIT ;)
1020 get_global $channel_table_p
1021 get_global $channel_entry_size
1022 get_local $channel_in
1023 i32.mul
1024 i32.add
1025 i32.const 8
1026 i32.add
1027 i32.load
1028 get_global $quit_p
1029 i32.ne
1030 br_if $key_echo
1031 i32.const 1
1032 get_local $inbuf_head
1033 i32.const 2
1034 call $sys_write
1035 end
1036 get_local $inbuf_head
1037 i32.load16_u
1038 call $push
1039 get_local $inbuf_head
1040 i32.const 2
1041 i32.add
1042 set_local $inbuf_head
1043 br $next
1044 end ;; key_read
1045 get_local $channel_in
1046 get_local $inbuf_base
1047 get_local $inbuf_bound
1048 get_local $inbuf_base
1049 i32.sub
1050 call $sys_read
1051 tee_local $eax
1052 get_local $inbuf_base
1053 i32.add
1054 set_local $inbuf_tail
1055 get_local $inbuf_base
1056 set_local $inbuf_head
1057 block $nullread
1058 get_local $eax
1059 i32.eqz
1060 br_if $nullread
1061 br $key_loop
1062 end ;; nullread
1063 block $pendingword
1064 get_local $wordbelt_head
1065 get_local $wordbelt_tail
1066 i32.eq
1067 br_if $pendingword
1068 i32.const 32
1069 call $push
1070 br $next
1071 end ;; pendingword
1072 br $bye
1073 end ;; key_loop
1074 end ;; logword
1075 call $pop
1076 tee_local $eax
1077 call $pop
1078 get_local $eax
1079 call $sys_log
1080 br $next
1081 end ;; rinit (unused)
1082 call $rinit
1083 get_global $holy_bye
1084 call $rpush
1085 br $next
1086 end ;; lit
1087 get_local $esi
1088 get_local $esi
1089 i32.const 4
1090 i32.add
1091 set_local $esi
1092 i32.load
1093 call $push
1094 br $next
1095 end ;; ret
1096 call $rpop
1097 set_local $esi
1098 br $next
1099 end ;; op0 (yield?)
1100 get_local $esi
1101 call $rpush
1102 br $bye
1103 end ;; default
1104 get_local $esi
1105 call $rpush
1106 get_local $eax
1107 set_local $esi
1108 br $next
1109 end ;; execloop
1110 end ;; next loop
1111 end ;; awaiting
1112
1113 (; set provided channel's waiter to this channel ;)
1114 get_global $channel_table_p
1115 get_global $channel_entry_size
1116 call $pop
1117 i32.mul
1118 i32.add
1119 tee_local $eax
1120 i32.const 2
1121 i32.add
1122 get_local $channel_in
1123 i32.store8
1124 (; set awaiter flag ;)
1125 get_local $eax
1126 get_local $eax
1127 i32.load8_u
1128 i32.const 2
1129 i32.or
1130 i32.store8
1131
1132 (; channel status save ;)
1133 get_global $channel_table_p
1134 get_global $channel_entry_size
1135 get_local $channel_in
1136 i32.mul
1137 i32.add
1138 tee_local $eax
1139 (; set buffer base ;)
1140 i32.const 12
1141 i32.add
1142 get_local $inbuf_base
1143 i32.store
1144 (; set buffer tail ;)
1145 get_local $eax
1146 i32.const 16
1147 i32.add
1148 get_local $inbuf_tail
1149 i32.store
1150 (; set buffer head ;)
1151 get_local $eax
1152 i32.const 20
1153 i32.add
1154 get_local $inbuf_head
1155 i32.store
1156 (; set buffer bound ;)
1157 get_local $eax
1158 i32.const 24
1159 i32.add
1160 get_local $inbuf_bound
1161 i32.store
1162
1163 (; set buffer buffer start ;)
1164 get_local $eax
1165 i32.const 4
1166 i32.add
1167 get_local $here
1168 i32.store
1169 (; backup return stack here, returning to esi ;)
1170 get_local $here
1171 get_local $esi
1172 get_local $eax
1173 i32.const 8
1174 i32.add
1175 i32.load
1176 call $lit_rstack
1177 set_local $here
1178
1179 i32.const -1
1180 set_local $inbuf_base ;; temporary bool "await-exit"
1181
1182 (; /awaiting ;)
1183 end ;; bye
1184
1185 get_global $channel_table_p
1186 get_global $channel_entry_size
1187 get_local $channel_in
1188 i32.mul
1189 i32.add
1190 tee_local $eax
1191 i32.const 3
1192 i32.add
1193 get_local $channel_out
1194 i32.store8
1195
1196 get_global $here_p
1197 get_local $here
1198 i32.store
1199 get_global $stringbelt_tail_p
1200 get_local $stringbelt_tail
1201 i32.store
1202 get_global $stringbelt_head_p
1203 get_local $stringbelt_head
1204 i32.store
1205 get_global $wordbelt_tail_p
1206 get_local $wordbelt_tail
1207 i32.store
1208 get_global $wordbelt_head_p
1209 get_local $wordbelt_head
1210 i32.store
1211
1212 block $await_exit
1213 get_local $inbuf_base
1214 i32.const -1
1215 i32.eq ;; halt if awaiting
1216 br_if $await_exit
1217 block $no_awaiter
1218 get_local $eax
1219 i32.load8_u
1220 i32.const 2
1221 i32.and
1222 i32.eqz ;; (FLAGS & 2) => awaiter, run it
1223 br_if $no_awaiter
1224 get_local $eax
1225 i32.const 2
1226 i32.add
1227 i32.load8_u
1228 tee_local $eax
1229 call $push
1230 get_global $channel_table_p
1231 get_global $channel_entry_size
1232 get_local $eax
1233 i32.mul
1234 i32.add
1235 tee_local $eax
1236 get_local $eax
1237 i32.load8_u
1238 i32.const 254
1239 i32.and
1240 i32.store8 ;; toggle off runflag
1241 call $pop
1242 call $main
1243 get_local $channel_in
1244 call $close_channel
1245 return
1246 end
1247 get_local $channel_in
1248 call $close_channel
1249 end
1250 i32.const 0
1251 return
1252 )
1253 )