channels working
[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) "\00\00\00\00") ;; 0
149 (data (i32.const 16756) "\02\00\00\00") ;; LIT
150 (data (i32.const 16760) "\04\30\00\00") ;; INBUFSIZE LOCATION
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 block $negrot
458 get_local $eax
459 br_table $op0 $ret (;2;)$lit $rinit (;4;)$logword $key (;6;)$dup $plus
460 (;8;)$jmp $emit (;10;)$fetch $set (;12;)$execute $noop (;14;)$jz $jnz
461 (;16;)$drop $wsbool (;18;)$jmp $wordputc (;20;)$wordstart $dictget
462 (;22;)$parsenum $wordfinish (;24;)$jneg1 $bye (;26;)$swap $words
463 (;28;)$here $dictset (;30;)$dup2 $rot (;32;)$drop2 $comma
464 (;34;)$subtract $inchan (;36;)$sethere $eqbool (;38;)$echostring $strstart
465 (;40;)$strput $strend (;42;)$fetchinc $setinc (;44;)$finddoes $definedoes
466 (;46;)$stacktrace $webfetch (;48;)$outchan $read (;50;)$awaiting $openchannel
467 (;52;)$rpush_op $fetch8_u (;54;)$negrot $default
468 end ;; negrot
469 call $pop
470 call $pop
471 set_local $eax
472 call $pop
473 get_local $eax
474 call $push
475 set_local $eax
476 call $push
477 get_local $eax
478 call $push
479 br $next
480 end ;; fetch8_u
481 call $pop
482 i32.load8_u
483 call $push
484 br $next
485 end ;; rpush_op
486 call $pop
487 call $rpush
488 br $next
489 end ;; openchannel
490 (; Get addr of channel block ;)
491 get_global $channel_table_p
492 get_global $channel_entry_size
493 call $sys_open
494 tee_local $eax
495 call $rpush ;;save to rstack
496 get_local $eax
497 i32.mul
498 i32.add
499 (; Set Out-Channel to 1 by default ;)
500 tee_local $eax
501 i32.const 3
502 i32.add ;; out channel
503 i32.const 1
504 i32.store8
505 (; leave a copy of channel_p on stack ;)
506 get_local $eax
507 (; Get addr of ch-start and ch-default-start ;)
508 get_local $eax
509 i32.const 4
510 i32.add ;; addr of channel start
511 tee_local $eax
512 get_local $eax
513 i32.const 4
514 i32.add ;; addr of channel default start
515 (; Store the user-provided address in both ;)
516 call $pop
517 tee_local $eax
518 i32.store
519 get_local $eax
520 i32.store
521 (; go bo buf-base (channel_p + 12), put HERE in it ;)
522 tee_local $eax
523 i32.const 12
524 i32.add
525 get_local $here
526 i32.store
527 (; set buf-tail ;)
528 get_local $eax
529 i32.const 16
530 i32.add
531 get_local $here
532 i32.store
533 (; set buf-head ;)
534 get_local $eax
535 i32.const 20
536 i32.add
537 get_local $here
538 i32.store
539 (; set buf-bound ;)
540 get_local $eax
541 i32.const 24
542 i32.add
543 (; set buf-bound = here += 512 ;)
544 get_local $here
545 i32.const 512
546 i32.add
547 tee_local $here
548 i32.store
549 (; return channel number ;)
550 call $rpop
551 call $push
552 br $next
553 end ;; read
554 get_local $channel_in
555 call $pop ;; location to write
556 set_local $eax
557 call $pop
558 get_local $eax
559 call $sys_read
560 br $next
561 end ;; outchan
562 call $pop
563 set_local $channel_out
564 br $next
565 end ;; webfetch
566 call $pop ;; u
567 call $rpush
568 call $pop ;; addr
569 set_local $eax
570 call $pop ;; callback
571 get_local $eax
572 call $rpop
573 call $sys_fetch
574 i32.const -1
575 i32.eq
576 br_if $bye
577 br $next
578 end ;; stacktrace
579 get_local $esi
580 call $rpush
581 call $sys_stack
582 call $rpop
583 drop
584 br $next
585 end ;; definedoes
586 call $pop
587 call $rpush
588 call $pop
589 set_local $eax
590 call $pop
591 get_local $eax
592 call $rpop
593 call $does_set
594 br $next
595 end ;; finddoes
596 call $pop
597 set_local $eax
598 call $pop
599 get_local $eax
600 call $does_get
601 call $push
602 br $next
603 end ;; setinc
604 call $pop
605 tee_local $eax
606 call $pop
607 i32.store
608 get_local $eax
609 i32.const 4
610 i32.add
611 call $push
612 br $next
613 end ;; fetchinc
614 call $pop
615 tee_local $eax
616 i32.const 4
617 i32.add
618 call $push
619 get_local $eax
620 i32.load
621 call $push
622 br $next
623 end ;; strend
624 get_local $stringbelt_tail
625 get_local $stringbelt_head
626 get_local $stringbelt_tail
627 i32.const 4
628 i32.add
629 i32.sub
630 tee_local $eax (; n bytes ;)
631 i32.store
632 (; align to 32-bit ;)
633 get_local $stringbelt_head
634 i32.const 3
635 i32.add
636 i32.const 8188
637 i32.and
638 set_local $stringbelt_head
639 (; /align ;)
640 get_local $stringbelt_tail
641 i32.const 4
642 i32.add
643 call $push
644 get_local $eax
645 call $push
646 br $next
647 end ;; strput
648 block $sbhasspace2
649 get_local $stringbelt_head
650 get_global $wordbelt_base
651 i32.lt_u
652 br_if $sbhasspace2
653 i32.const 0
654 tee_local $stringbelt_head
655 get_local $stringbelt_tail
656 i32.load
657 i32.store
658 get_local $stringbelt_head
659 i32.const 4
660 i32.add
661 set_local $stringbelt_head
662 get_local $stringbelt_tail
663 i32.const 4
664 i32.add
665 set_local $stringbelt_tail
666 loop $copystringtostart
667 get_local $stringbelt_head
668 get_local $stringbelt_tail
669 i32.load16_u
670 i32.store16
671 get_local $stringbelt_head
672 i32.const 2
673 i32.add
674 set_local $stringbelt_head
675 get_local $stringbelt_tail
676 i32.const 2
677 i32.add
678 tee_local $stringbelt_tail
679 get_global $wordbelt_base
680 i32.le_u
681 br_if $copystringtostart
682 end
683 i32.const 0
684 set_local $stringbelt_tail
685 end
686 get_local $stringbelt_head
687 call $pop
688 i32.store16
689 get_local $stringbelt_head
690 i32.const 2
691 i32.add
692 set_local $stringbelt_head
693 br $next
694 end ;; strstart
695 block $sbhasspace
696 get_local $stringbelt_head
697 get_global $wordbelt_base
698 i32.const 8
699 i32.sub
700 i32.le_u
701 br_if $sbhasspace
702 i32.const 0
703 set_local $stringbelt_head
704 end
705 get_local $stringbelt_head
706 get_local $stringbelt_head
707 tee_local $stringbelt_tail
708 i32.const 0
709 i32.store
710 i32.const 4
711 i32.add
712 set_local $stringbelt_head
713 br $next
714 end ;; echostring
715 get_local $channel_out
716 call $pop
717 set_local $eax
718 call $pop
719 get_local $eax
720 call $sys_send
721 br $next
722 end ;; eqbool
723 block $equiv
724 call $pop
725 call $pop
726 tee_local $eax
727 i32.eq
728 get_local $eax
729 call $push
730 br_if $equiv
731 i32.const 0
732 call $push
733 br $next
734 end
735 i32.const 1
736 call $push
737 br $next
738 end ;; sethere
739 call $pop
740 set_local $here
741 br $next
742 end ;; inchan
743 call $pop
744 set_local $channel_in
745 br $next
746 end ;; subtract
747 call $pop
748 set_local $eax
749 call $pop
750 get_local $eax
751 i32.sub
752 call $push
753 br $next
754 end ;; comma
755 get_local $here
756 call $pop
757 i32.store
758 get_local $here
759 i32.const 4
760 i32.add
761 set_local $here
762 br $next
763 end ;; drop2
764 call $pop
765 call $pop
766 drop
767 drop
768 br $next
769 end ;; rot
770 call $pop
771 call $pop
772 set_local $eax
773 call $pop
774 call $rpush
775 call $push
776 call $rpop
777 call $push
778 get_local $eax
779 call $push
780 br $next
781 end ;; dup2
782 get_local $esi
783 call $rpush
784 call $pop
785 set_local $eax
786 call $pop
787 tee_local $esi
788 call $push
789 get_local $eax
790 call $push
791 get_local $esi
792 call $push
793 get_local $eax
794 call $push
795 call $rpop
796 set_local $esi
797 br $next
798 end ;; dictset
799 call $pop
800 call $rpush
801 call $pop
802 set_local $eax
803 call $pop
804 get_local $eax
805 call $rpop
806 call $vocab_set
807 br $next
808 end ;; here
809 get_local $here
810 call $push
811 br $next
812 end ;; words
813 call $sys_words
814 br $next
815 end ;; swap
816 call $pop
817 call $pop
818 set_local $eax
819 call $push
820 get_local $eax
821 call $push
822 br $next
823 end ;; jneg1
824 block $jneg1if
825 call $pop
826 i32.const -1
827 i32.eq
828 br_if $jneg1if
829 get_local $esi
830 i32.const 4
831 i32.add
832 set_local $esi
833 br $next
834 end
835 get_local $esi
836 i32.load
837 set_local $esi
838 br $next
839 end ;; wordfinish
840 get_local $wordbelt_head
841 get_local $wordbelt_tail
842 i32.sub
843 set_local $eax (; n bytes ;)
844 (; align to 32-bit ;)
845 get_local $wordbelt_head
846 i32.const 3
847 i32.add
848 i32.const 12284
849 i32.and
850 set_local $wordbelt_head
851 (; /align ;)
852 get_local $wordbelt_tail
853 call $push
854 get_local $eax
855 call $push
856 br $next
857 end ;; parsenum
858 call $pop
859 call $rpush
860 call $pop
861 tee_local $eax
862 call $rpop
863 call $sys_parsenum
864 get_local $eax
865 i32.load
866 call $push
867 call $push
868 br $next
869 end ;; dictget
870 call $pop
871 set_local $eax
872 call $pop
873 get_local $eax
874 call $vocab_get
875 call $push
876 br $next
877 end ;; wordstart
878 block $wbhasspace
879 get_local $wordbelt_head
880 get_global $wordbelt_bound
881 i32.const 4
882 i32.sub
883 i32.le_u
884 br_if $wbhasspace
885 get_global $wordbelt_base
886 set_local $wordbelt_head
887 end
888 get_local $wordbelt_head
889 set_local $wordbelt_tail
890 br $next
891 end ;; wordputc
892 block $wbhasspace2
893 get_local $wordbelt_head
894 get_global $wordbelt_bound
895 i32.lt_u
896 br_if $wbhasspace2
897 get_global $wordbelt_base
898 set_local $wordbelt_head
899 loop $copywordtostart
900 get_local $wordbelt_head
901 get_local $wordbelt_tail
902 i32.load16_u
903 i32.store16
904 get_local $wordbelt_head
905 i32.const 2
906 i32.add
907 set_local $wordbelt_head
908 get_local $wordbelt_tail
909 i32.const 2
910 i32.add
911 tee_local $wordbelt_tail
912 get_global $wordbelt_bound
913 i32.lt_u
914 br_if $copywordtostart
915 end
916 get_global $wordbelt_base
917 set_local $wordbelt_tail
918 end
919 get_local $wordbelt_head
920 call $pop
921 i32.store16
922 get_local $wordbelt_head
923 i32.const 2
924 i32.add
925 set_local $wordbelt_head
926 br $next
927 end ;; jmp
928 get_local $esi
929 i32.load
930 set_local $esi
931 br $next
932 end ;; wsbool
933 call $pop
934 tee_local $eax
935 call $is_whitespace
936 get_local $eax
937 call $push
938 call $push
939 br $next
940 end ;; drop
941 call $pop
942 drop
943 br $next
944 end ;; jnz
945 block $jnzif
946 call $pop
947 i32.eqz
948 br_if $jnzif
949 get_local $esi
950 i32.load
951 set_local $esi
952 br $next
953 end
954 get_local $esi
955 i32.const 4
956 i32.add
957 set_local $esi
958 br $next
959 end ;; jz
960 block $jzif
961 call $pop
962 i32.eqz
963 br_if $jzif
964 get_local $esi
965 i32.const 4
966 i32.add
967 set_local $esi
968 br $next
969 end
970 get_local $esi
971 i32.load
972 set_local $esi
973 br $next
974 end ;; noop
975 br $next
976 end ;; execute
977 call $pop
978 tee_local $eax
979 i32.const 256
980 i32.lt_u
981 br_if $execloop
982 get_local $esi
983 call $rpush
984 get_local $eax
985 set_local $esi
986 br $next
987 end ;; set
988 call $pop
989 call $pop
990 i32.store
991 br $next
992 end ;; fetch
993 call $pop
994 i32.load
995 call $push
996 br $next
997 end ;; emit (.)
998 call $pop
999 call $sys_echo
1000 br $next
1001 end ;; noop2
1002 br $next
1003 end ;; plus
1004 call $pop
1005 call $pop
1006 i32.add
1007 call $push
1008 br $next
1009 end ;; dup
1010 call $pop
1011 tee_local $eax
1012 get_local $eax
1013 call $push
1014 call $push
1015 br $next
1016 end ;; key
1017 loop $key_loop
1018 block $key_read
1019 get_local $inbuf_head
1020 get_local $inbuf_tail
1021 i32.ge_u
1022 br_if $key_read
1023 block $key_echo
1024 get_local $channel_out
1025 i32.const -1
1026 i32.add
1027 br_if $key_echo
1028 (; if current channel's default start is QUIT ;)
1029 get_global $channel_table_p
1030 get_global $channel_entry_size
1031 get_local $channel_in
1032 i32.mul
1033 i32.add
1034 i32.const 8
1035 i32.add
1036 i32.load
1037 get_global $quit_p
1038 i32.ne
1039 br_if $key_echo
1040 i32.const 1
1041 get_local $inbuf_head
1042 i32.const 2
1043 call $sys_write
1044 end
1045 get_local $inbuf_head
1046 i32.load16_u
1047 call $push
1048 get_local $inbuf_head
1049 i32.const 2
1050 i32.add
1051 set_local $inbuf_head
1052 br $next
1053 end ;; key_read
1054 get_local $channel_in
1055 get_local $inbuf_base
1056 get_local $inbuf_bound
1057 get_local $inbuf_base
1058 i32.sub
1059 call $sys_read
1060 tee_local $eax
1061 get_local $inbuf_base
1062 i32.add
1063 set_local $inbuf_tail
1064 get_local $inbuf_base
1065 set_local $inbuf_head
1066 block $nullread
1067 get_local $eax
1068 i32.eqz
1069 br_if $nullread
1070 br $key_loop
1071 end ;; nullread
1072 block $pendingword
1073 get_local $wordbelt_head
1074 get_local $wordbelt_tail
1075 i32.eq
1076 br_if $pendingword
1077 i32.const 32
1078 call $push
1079 br $next
1080 end ;; pendingword
1081 br $bye
1082 end ;; key_loop
1083 end ;; logword
1084 call $pop
1085 tee_local $eax
1086 call $pop
1087 get_local $eax
1088 call $sys_log
1089 br $next
1090 end ;; rinit (unused)
1091 call $rinit
1092 get_global $holy_bye
1093 call $rpush
1094 br $next
1095 end ;; lit
1096 get_local $esi
1097 get_local $esi
1098 i32.const 4
1099 i32.add
1100 set_local $esi
1101 i32.load
1102 call $push
1103 br $next
1104 end ;; ret
1105 call $rpop
1106 set_local $esi
1107 br $next
1108 end ;; op0 (yield?)
1109 get_local $esi
1110 call $rpush
1111 br $bye
1112 end ;; default
1113 get_local $esi
1114 call $rpush
1115 get_local $eax
1116 set_local $esi
1117 br $next
1118 end ;; execloop
1119 end ;; next loop
1120 end ;; awaiting
1121
1122 (; set provided channel's waiter to this channel ;)
1123 get_global $channel_table_p
1124 get_global $channel_entry_size
1125 call $pop
1126 i32.mul
1127 i32.add
1128 tee_local $eax
1129 i32.const 2
1130 i32.add
1131 get_local $channel_in
1132 i32.store8
1133 (; set awaiter flag ;)
1134 get_local $eax
1135 get_local $eax
1136 i32.load8_u
1137 i32.const 2
1138 i32.or
1139 i32.store8
1140
1141 (; channel status save ;)
1142 get_global $channel_table_p
1143 get_global $channel_entry_size
1144 get_local $channel_in
1145 i32.mul
1146 i32.add
1147 tee_local $eax
1148 (; set buffer base ;)
1149 i32.const 12
1150 i32.add
1151 get_local $inbuf_base
1152 i32.store
1153 (; set buffer tail ;)
1154 get_local $eax
1155 i32.const 16
1156 i32.add
1157 get_local $inbuf_tail
1158 i32.store
1159 (; set buffer head ;)
1160 get_local $eax
1161 i32.const 20
1162 i32.add
1163 get_local $inbuf_head
1164 i32.store
1165 (; set buffer bound ;)
1166 get_local $eax
1167 i32.const 24
1168 i32.add
1169 get_local $inbuf_bound
1170 i32.store
1171
1172 (; set buffer buffer start ;)
1173 get_local $eax
1174 i32.const 4
1175 i32.add
1176 get_local $here
1177 i32.store
1178 (; backup return stack here, returning to esi ;)
1179 get_local $here
1180 get_local $esi
1181 get_local $eax
1182 i32.const 8
1183 i32.add
1184 i32.load
1185 call $lit_rstack
1186 set_local $here
1187
1188 i32.const -1
1189 set_local $inbuf_base ;; temporary bool "await-exit"
1190
1191 (; /awaiting ;)
1192 end ;; bye
1193
1194 get_global $channel_table_p
1195 get_global $channel_entry_size
1196 get_local $channel_in
1197 i32.mul
1198 i32.add
1199 tee_local $eax
1200 i32.const 3
1201 i32.add
1202 get_local $channel_out
1203 i32.store8
1204
1205 get_global $here_p
1206 get_local $here
1207 i32.store
1208 get_global $stringbelt_tail_p
1209 get_local $stringbelt_tail
1210 i32.store
1211 get_global $stringbelt_head_p
1212 get_local $stringbelt_head
1213 i32.store
1214 get_global $wordbelt_tail_p
1215 get_local $wordbelt_tail
1216 i32.store
1217 get_global $wordbelt_head_p
1218 get_local $wordbelt_head
1219 i32.store
1220
1221 block $await_exit
1222 get_local $inbuf_base
1223 i32.const -1
1224 i32.eq ;; halt if awaiting
1225 br_if $await_exit
1226 block $no_awaiter
1227 get_local $eax
1228 i32.load8_u
1229 i32.const 2
1230 i32.and
1231 i32.eqz ;; (FLAGS & 2) => awaiter, run it
1232 br_if $no_awaiter
1233 get_local $eax
1234 i32.const 2
1235 i32.add
1236 i32.load8_u
1237 tee_local $eax
1238 call $push
1239 get_global $channel_table_p
1240 get_global $channel_entry_size
1241 get_local $eax
1242 i32.mul
1243 i32.add
1244 tee_local $eax
1245 get_local $eax
1246 i32.load8_u
1247 i32.const 254
1248 i32.and
1249 i32.store8 ;; toggle off runflag
1250 call $pop
1251 call $main
1252 get_local $channel_in
1253 call $close_channel
1254 return
1255 end
1256 get_local $channel_in
1257 call $close_channel
1258 end
1259 i32.const 0
1260 return
1261 )
1262 )