(; This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ;) (module (type $FUNCSIGi (func (result i32))) (type $FUNCSIGii (func (param i32))) (type $FUNCSIGiii (func)) (type $FUNCSIGiv (func (param i32 i32) (result i32))) (type $FUNCSIGv (func (param i32) (result i32))) (type $FUNCSIGvi (func (param i32 i32 i32) (result i32))) (type $FUNCSIGvii (func (param i32 i32))) (type $FUNCSIGviii (func (param i32 i32 i32))) (import "env" "pop" (func $pop (result i32))) (import "env" "push" (func $push (param i32))) (import "env" "rinit" (func $rinit)) (import "env" "rpop" (func $rpop (result i32))) (import "env" "rpush" (func $rpush (param i32))) (import "env" "sys_read" (func $sys_read (param i32 i32 i32) (result i32))) (import "env" "sys_write" (func $sys_write (param i32 i32 i32))) (import "env" "sys_send" (func $sys_send (param i32 i32 i32))) (import "env" "sys_open" (func $sys_open (result i32))) (import "env" "sys_close" (func $sys_close (param i32))) (import "env" "sys_fetch" (func $sys_fetch (param i32 i32 i32) (result i32))) (import "env" "sys_connect" (func $sys_connect (param i32 i32) (result i32))) (import "env" "sys_echo" (func $sys_echo (param i32))) (import "env" "sys_log" (func $sys_log (param i32 i32))) (import "env" "sys_reflect" (func $sys_reflect (param i32))) (import "env" "vocab_get" (func $vocab_get (param i32 i32) (result i32))) (import "env" "vocab_set" (func $vocab_set (param i32 i32 i32))) (import "env" "does_get" (func $does_get (param i32 i32) (result i32))) (import "env" "does_set" (func $does_set (param i32 i32 i32))) (import "env" "is_whitespace" (func $is_whitespace (param i32) (result i32))) (import "env" "sys_parsenum" (func $sys_parsenum (param i32 i32) (result i32))) (import "env" "sys_stack" (func $sys_stack)) (import "env" "sys_words" (func $sys_words)) (table (;0;) 0 anyfunc) (memory $0 1) (; String Belt ;) ;; 0x0000 Size: 8192 (global $wordbelt_base i32 (i32.const 8192) ) ;; 0x2000 Size: 4096 (global $wordbelt_bound i32 (i32.const 12288)) ;; 0x3000 (global $stdin_base i32 (i32.const 12288)) ;; 0x3000 Size: 2048 (global $kvars i32 (i32.const 14336)) ;; 0x3800 Size: 2048 (global $mode_p i32 (i32.const 14336)) (global $here_p i32 (i32.const 14340)) (global $start_p i32 (i32.const 14344)) (global $base_p i32 (i32.const 14348)) (global $stringbelt_tail_p i32 (i32.const 14352)) (global $stringbelt_head_p i32 (i32.const 14356)) (global $wordbelt_tail_p i32 (i32.const 14360)) (global $wordbelt_head_p i32 (i32.const 14364)) (data (i32.const 14336) "\28\41\00\00") ;; MODE (data (i32.const 14340) "\04\5e\00\00") ;; HERE (data (i32.const 14344) "\00\40\00\00") ;; START (16384) (Quit) (data (i32.const 14348) "\0a\00\00\00") ;; BASE (data (i32.const 14352) "\00\00\00\00") ;; STRINGBELT_TAIL (data (i32.const 14356) "\00\00\00\00") ;; STRINGBELT_HEAD (data (i32.const 14360) "\00\20\00\00") ;; WORDBELT_TAIL (data (i32.const 14364) "\00\20\00\00") ;; WORDBELT_HEAD (; Quit ;) (global $quit_p i32 (i32.const 16384)) ;; 0x4000 (data (i32.const 16384) "\03\00\00\00") ;; RINIT xt (global $quit_ret_p i32 (i32.const 16388)) (data (i32.const 16388) "\10\40\00\00") ;; INTERPRET xt (data (i32.const 16392) "\12\00\00\00") ;; JMP xt (data (i32.const 16396) "\00\40\00\00") ;; quit location (16384) (; Interpret ;) (data (i32.const 16400) "\74\40\00\00") ;; WORD xt (16500) (data (i32.const 16404) "\0d\00\00\00") ;; (data (i32.const 16404) "\1e\00\00\00") ;; 2DUP (data (i32.const 16408) "\0d\00\00\00") ;; (data (i32.const 16408) "\04\00\00\00") ;; SYS-LOG (data (i32.const 16412) "\06\00\00\00") ;; DUP (data (i32.const 16416) "\0e\00\00\00") ;; JZ: (data (i32.const 16420) "\40\40\00\00") ;; INTERP-END addr (16444) (data (i32.const 16424) "\02\00\00\00") ;; LIT xt (data (i32.const 16428) "\00\38\00\00") ;; MODE addr (14336) (data (i32.const 16432) "\0a\00\00\00") ;; @ (fetch) xt (data (i32.const 16436) "\0c\00\00\00") ;; EXECUTE xt (data (i32.const 16440) "\0d\00\00\00") ;; NOOP xt (data (i32.const 16444) "\01\00\00\00") ;; RET (data (i32.const 16448) "\10\00\00\00") ;; DROP <-- INTERP-END (data (i32.const 16452) "\10\00\00\00") ;; DROP (global $holy_bye i32 (i32.const 16456)) (data (i32.const 16456) "\19\00\00\00") ;; BYE <-- the Holy BYE (; Word ;) (data (i32.const 16500) "\14\00\00\00") ;; WORDSTART (data (i32.const 16504) "\05\00\00\00") ;; KEY <-- KEYLOOP (data (i32.const 16508) "\06\00\00\00") ;; DUP (data (i32.const 16512) "\18\00\00\00") ;; J-1: 18 (data (i32.const 16516) "\f0\40\00\00") ;; addr of WORDEND (data (i32.const 16520) "\11\00\00\00") ;; WS? (data (i32.const 16524) "\0f\00\00\00") ;; JNZ: (data (i32.const 16528) "\bc\40\00\00") ;; addr of KEYDROP (data (i32.const 16532) "\02\00\00\00") ;; LIT (data (i32.const 16536) "\5c\00\00\00") ;; 92 (\ character) (data (i32.const 16540) "\25\00\00\00") ;; =? (data (i32.const 16544) "\0e\00\00\00") ;; JZ: (data (i32.const 16548) "\e4\40\00\00") ;; addr of DOCHAR (data (i32.const 16552) "\10\00\00\00") ;; DROP (data (i32.const 16556) "\94\41\00\00") ;; DO-BACKSLASH (continue using this wbuf we started) (data (i32.const 16560) "\0d\00\00\00") ;; NOOP (data (i32.const 16564) "\12\00\00\00") ;; JMP: (data (i32.const 16568) "\74\40\00\00") ;; addr of KEYLOOP-1 (get a new wbuf, call to wbuf+1 ate ours) (data (i32.const 16572) "\10\00\00\00") ;; DROP <-- KEYDROP (data (i32.const 16576) "\12\00\00\00") ;; JMP: (data (i32.const 16580) "\78\40\00\00") ;; addr of KEYLOOP (data (i32.const 16584) "\05\00\00\00") ;; KEY <-- WORDLOOP (data (i32.const 16588) "\11\00\00\00") ;; WS? <-- WORDLOOP_REENTRY (data (i32.const 16592) "\0f\00\00\00") ;; JNZ: (data (i32.const 16596) "\f0\40\00\00") ;; addr of WORDEND (data (i32.const 16600) "\06\00\00\00") ;; DUP (data (i32.const 16604) "\18\00\00\00") ;; J-1: (data (i32.const 16608) "\f0\40\00\00") ;; addr of WORDEND (data (i32.const 16612) "\13\00\00\00") ;; WORDPUTC <-- DOCHAR (data (i32.const 16616) "\12\00\00\00") ;; JMP: (data (i32.const 16620) "\c8\40\00\00") ;; addr of WORDLOOP (data (i32.const 16624) "\10\00\00\00") ;; DROP <-- WORDEND (data (i32.const 16628) "\17\00\00\00") ;; WORDFINISH (data (i32.const 16632) "\01\00\00\00") ;; 2DUP //RET (data (i32.const 16636) "\04\00\00\00") ;; .S (data (i32.const 16640) "\01\00\00\00") ;; RET (; Exec Mode ;) (data (i32.const 16680) "\1e\00\00\00") ;; 2DUP (data (i32.const 16684) "\15\00\00\00") ;; DICT_GET (data (i32.const 16688) "\06\00\00\00") ;; DUP (data (i32.const 16692) "\0e\00\00\00") ;; JZ: (data (i32.const 16696) "\4c\41\00\00") ;; donum -1 (16716) (data (i32.const 16700) "\1f\00\00\00") ;; ROT (data (i32.const 16704) "\20\00\00\00") ;; 2DROP (data (i32.const 16708) "\0c\00\00\00") ;; EXECUTE (data (i32.const 16712) "\01\00\00\00") ;; RET (data (i32.const 16716) "\10\00\00\00") ;; DROP (xt from dictionary) (data (i32.const 16720) "\16\00\00\00") ;; NUMBER <-- donum, pushes NUM, UNPARSED (data (i32.const 16724) "\06\00\00\00") ;; DUP (data (i32.const 16728) "\0f\00\00\00") ;; JNZ: (data (i32.const 16732) "\68\41\00\00") ;; donum_err (16744) (data (i32.const 16736) "\10\00\00\00") ;; DROP (data (i32.const 16740) "\01\00\00\00") ;; RET (data (i32.const 16744) "\20\00\00\00") ;; 2DROP <-- donum_err (data (i32.const 16748) "\02\00\00\00") ;; LIT (data (i32.const 16752) "\00\00\00\00") ;; 0 (data (i32.const 16756) "\02\00\00\00") ;; LIT (data (i32.const 16760) "\04\30\00\00") ;; INBUFSIZE LOCATION (data (i32.const 16764) "\0b\00\00\00") ;; ! (data (i32.const 16768) "\19\00\00\00") ;; BYE (data (i32.const 16772) "\00\00\00\00") ;; (data (i32.const 16776) "\00\00\00\00") ;; (data (i32.const 16780) "\00\00\00\00") ;; (data (i32.const 16784) "\00\00\00\00") ;; (; Do Backslash ;) (data (i32.const 16788) "\05\00\00\00") ;; KEY (data (i32.const 16792) "\11\00\00\00") ;; WS? (data (i32.const 16796) "\0f\00\00\00") ;; JNZ: (data (i32.const 16800) "\c8\41\00\00") ;; addr of DO_COMMENT_REENTRY (data (i32.const 16804) "\cc\40\00\00") ;; WORDLOOP_REENTRY (call) (data (i32.const 16808) "\28\41\00\00") ;; EXECUTE-MODE (data (i32.const 16812) "\01\00\00\00") ;; RET (; Do Comment ;) (data (i32.const 16828) "\18\00\00\00") ;; j-1: <-- keypump (data (i32.const 16832) "\e0\41\00\00") ;; addr of DC_END (data (i32.const 16836) "\05\00\00\00") ;; KEY <-- DO_COMMENT (data (i32.const 16840) "\02\00\00\00") ;; LIT <-- DO_COMMENT_REENTRY (data (i32.const 16844) "\0a\00\00\00") ;; 10 (line feed) (data (i32.const 16848) "\25\00\00\00") ;; =? (data (i32.const 16852) "\0e\00\00\00") ;; JZ: (data (i32.const 16856) "\bc\41\00\00") ;; addr of keypump (data (i32.const 16860) "\10\00\00\00") ;; DROP (data (i32.const 16864) "\01\00\00\00") ;; RET <-- DC_END (; Channel Table ;) (; 1 FLAGS: AWAITER | RUNNING ]LSB ;) (; 1 reserved ;) (; 1 AWAITER CHANNEL ;) (; 1 OUT CHANNEL ;) (; 8 START | START-DEFAULT ;) (; 16 BUFFER ADDRESSES: BASE, TAIL, HEAD, BOUND ;) (global $channel_table_p i32 (i32.const 16900)) (global $channel_entry_size i32 (i32.const 28)) (global $channel_max i32 (i32.const 255)) (data (i32.const 16900) "\00\00\00\01") ;; STDIN (COUT: 1) (data (i32.const 16904) "\00\40\00\00") ;; STDIN-START (QUIT) (data (i32.const 16908) "\00\40\00\00") ;; STDIN-START-DEFAULT (data (i32.const 16912) "\00\30\00\00") ;; STDIN-BUFFER-BASE (data (i32.const 16916) "\00\30\00\00") ;; STDIN-BUFFER-TAIL (data (i32.const 16920) "\00\30\00\00") ;; STDIN-BUFFER-HEAD (data (i32.const 16924) "\00\38\00\00") ;; STDIN-BUFFER-BOUND (data (i32.const 16928) "\00\00\00\00") ;; STDOUT (data (i32.const 16932) "\00\00\00\00") ;; STDOUT (TODO: error handler) (data (i32.const 16936) "\00\00\00\00") ;; STDOUT (data (i32.const 16940) "\00\00\00\00") ;; STDOUT (data (i32.const 16944) "\00\00\00\00") ;; STDOUT (data (i32.const 16948) "\00\00\00\00") ;; STDOUT (data (i32.const 16952) "\00\00\00\00") ;; STDOUT (data (i32.const 16956) "\00\00\00\00") ;; STDERR (null) (data (i32.const 16960) "\00\00\00\00") ;; STDERR (TODO: error handler) (; 16900 + ((4 * 7)=>28 * 256)=>7168 = 24068 | 0x5e04 === HERE ;) (export "memory" (memory $0)) (func $lit_rstack (param $here i32) (param $start i32) (param $dstart i32) (result i32) (local $eax i32) (local $ecx i32) i32.const 0 set_local $ecx block $backup_loop call $rpop tee_local $eax get_global $holy_bye i32.eq br_if $backup_loop get_local $eax call $push get_local $ecx i32.const 1 i32.add set_local $ecx end (; push channel default start ;) get_local $here get_local $dstart i32.store get_local $here i32.const 4 i32.add set_local $here block $output_done block $output_loop get_local $ecx i32.eqz br_if $output_done get_local $ecx i32.const -1 i32.add set_local $ecx get_local $here i32.const 2 ;; lit i32.store get_local $here i32.const 4 i32.add tee_local $here call $pop i32.store get_local $here i32.const 4 i32.add tee_local $here i32.const 52 ;; rpush_op i32.store get_local $here i32.const 4 i32.add set_local $here br $output_loop end end get_local $here i32.const 46 i32.store get_local $here i32.const 4 i32.add set_local $here get_local $here i32.const 18 ;; jmp i32.store get_local $here i32.const 4 i32.add tee_local $here get_local $start i32.store get_local $here i32.const 4 i32.add return ) (func $close_channel (param $channel_p i32) (local $eax i32) block $no_close get_local $channel_p i32.const 3 i32.le_u br_if $no_close get_local $channel_p call $sys_close end get_global $channel_table_p get_global $channel_entry_size get_local $channel_p i32.mul i32.add tee_local $channel_p i32.const 4 i32.add get_local $channel_p i32.const 8 i32.add i32.load i32.store ;; restore awaiter's "start" to original get_local $channel_p i32.const 0 i32.store8 ;; clear target thread's flags (; set stdin tail and head to base ;) get_local $channel_p i32.const 16 i32.add get_local $channel_p i32.const 20 i32.add get_local $channel_p i32.const 12 i32.add i32.load tee_local $eax i32.store get_local $eax i32.store ) (func $forth_min (param $i1 i32) (param $i2 i32) (result i32) block $is_greater get_local $i1 get_local $i2 i32.lt_u br_if $is_greater get_local $i2 return end get_local $i1 return ) (export "main" (func $main)) (func $main (param $event_channel i32) (result i32) call $rinit get_global $holy_bye call $rpush get_local $event_channel call $interpret return ) (func $interpret (param $channel_in i32) (result i32) (local $here i32) (local $eax i32) (local $esi i32) (local $inbuf_base i32) (local $inbuf_tail i32) (local $inbuf_head i32) (local $inbuf_bound i32) (local $stringbelt_tail i32) (local $stringbelt_head i32) (local $wordbelt_tail i32) (local $wordbelt_head i32) (local $channel_out i32) (; channel in setup ;) get_global $channel_table_p get_global $channel_entry_size get_global $channel_max get_local $channel_in call $forth_min i32.mul i32.add set_local $eax (; exit if the event is for a channel that is already running ;) block $check_run get_local $eax i32.load8_u i32.const 1 i32.and i32.eqz ;; (FLAGS & 1) => running, return 0 br_if $check_run i32.const 0 return end get_local $eax get_local $eax i32.load8_u i32.const 1 i32.or i32.store8 ;; set running flag get_local $eax i32.const 3 i32.add i32.load8_u set_local $channel_out get_local $eax i32.const 4 i32.add i32.load set_local $esi get_local $eax i32.const 12 i32.add i32.load set_local $inbuf_base get_local $eax i32.const 16 i32.add i32.load set_local $inbuf_tail get_local $eax i32.const 20 i32.add i32.load set_local $inbuf_head get_local $eax i32.const 24 i32.add i32.load set_local $inbuf_bound (; /channel in setup ;) get_global $here_p i32.load set_local $here get_global $stringbelt_tail_p i32.load set_local $stringbelt_tail get_global $stringbelt_head_p i32.load set_local $stringbelt_head get_global $wordbelt_tail_p i32.load set_local $wordbelt_tail get_global $wordbelt_head_p i32.load set_local $wordbelt_head block $bye block $awaiting loop $next get_local $esi get_local $esi i32.const 4 i32.add set_local $esi i32.load set_local $eax loop $execloop block $default block $op0 block $ret block $lit block $rinit block $logword block $key block $dup block $plus block $noop2 block $emit block $fetch block $set block $execute block $noop block $jz block $jnz block $drop block $wsbool block $jmp block $wordputc block $wordstart block $dictget block $parsenum block $wordfinish block $jneg1 block $swap block $words block $here block $dictset block $dup2 block $rot block $drop2 block $comma block $subtract block $inchan block $sethere block $eqbool block $echostring block $strstart block $strput block $strend block $fetchinc block $setinc block $finddoes block $definedoes block $stacktrace block $webfetch block $outchan block $read block $openchannel block $rpush_op block $fetch8_u block $negrot get_local $eax br_table $op0 $ret (;2;)$lit $rinit (;4;)$logword $key (;6;)$dup $plus (;8;)$jmp $emit (;10;)$fetch $set (;12;)$execute $noop (;14;)$jz $jnz (;16;)$drop $wsbool (;18;)$jmp $wordputc (;20;)$wordstart $dictget (;22;)$parsenum $wordfinish (;24;)$jneg1 $bye (;26;)$swap $words (;28;)$here $dictset (;30;)$dup2 $rot (;32;)$drop2 $comma (;34;)$subtract $inchan (;36;)$sethere $eqbool (;38;)$echostring $strstart (;40;)$strput $strend (;42;)$fetchinc $setinc (;44;)$finddoes $definedoes (;46;)$stacktrace $webfetch (;48;)$outchan $read (;50;)$awaiting $openchannel (;52;)$rpush_op $fetch8_u (;54;)$negrot $default end ;; negrot call $pop call $pop set_local $eax call $pop get_local $eax call $push set_local $eax call $push get_local $eax call $push br $next end ;; fetch8_u call $pop i32.load8_u call $push br $next end ;; rpush_op call $pop call $rpush br $next end ;; openchannel (; Get addr of channel block ;) get_global $channel_table_p get_global $channel_entry_size call $sys_open tee_local $eax call $rpush ;;save to rstack get_local $eax i32.mul i32.add (; Set Out-Channel to 1 by default ;) tee_local $eax i32.const 3 i32.add ;; out channel i32.const 1 i32.store8 (; leave a copy of channel_p on stack ;) get_local $eax (; Get addr of ch-start and ch-default-start ;) get_local $eax i32.const 4 i32.add ;; addr of channel start tee_local $eax get_local $eax i32.const 4 i32.add ;; addr of channel default start (; Store the user-provided address in both ;) call $pop tee_local $eax i32.store get_local $eax i32.store (; go bo buf-base (channel_p + 12), put HERE in it ;) tee_local $eax i32.const 12 i32.add get_local $here i32.store (; set buf-tail ;) get_local $eax i32.const 16 i32.add get_local $here i32.store (; set buf-head ;) get_local $eax i32.const 20 i32.add get_local $here i32.store (; set buf-bound ;) get_local $eax i32.const 24 i32.add (; set buf-bound = here += 512 ;) get_local $here i32.const 512 i32.add tee_local $here i32.store (; return channel number ;) call $rpop call $push br $next end ;; read get_local $channel_in call $pop ;; location to write set_local $eax call $pop get_local $eax call $sys_read br $next end ;; outchan call $pop set_local $channel_out br $next end ;; webfetch call $pop ;; u call $rpush call $pop ;; addr set_local $eax call $pop ;; callback get_local $eax call $rpop call $sys_fetch i32.const -1 i32.eq br_if $bye br $next end ;; stacktrace get_local $esi call $rpush call $sys_stack call $rpop drop br $next end ;; definedoes call $pop call $rpush call $pop set_local $eax call $pop get_local $eax call $rpop call $does_set br $next end ;; finddoes call $pop set_local $eax call $pop get_local $eax call $does_get call $push br $next end ;; setinc call $pop tee_local $eax call $pop i32.store get_local $eax i32.const 4 i32.add call $push br $next end ;; fetchinc call $pop tee_local $eax i32.const 4 i32.add call $push get_local $eax i32.load call $push br $next end ;; strend get_local $stringbelt_tail get_local $stringbelt_head get_local $stringbelt_tail i32.const 4 i32.add i32.sub tee_local $eax (; n bytes ;) i32.store (; align to 32-bit ;) get_local $stringbelt_head i32.const 3 i32.add i32.const 8188 i32.and set_local $stringbelt_head (; /align ;) get_local $stringbelt_tail i32.const 4 i32.add call $push get_local $eax call $push br $next end ;; strput block $sbhasspace2 get_local $stringbelt_head get_global $wordbelt_base i32.lt_u br_if $sbhasspace2 i32.const 0 tee_local $stringbelt_head get_local $stringbelt_tail i32.load i32.store get_local $stringbelt_head i32.const 4 i32.add set_local $stringbelt_head get_local $stringbelt_tail i32.const 4 i32.add set_local $stringbelt_tail loop $copystringtostart get_local $stringbelt_head get_local $stringbelt_tail i32.load16_u i32.store16 get_local $stringbelt_head i32.const 2 i32.add set_local $stringbelt_head get_local $stringbelt_tail i32.const 2 i32.add tee_local $stringbelt_tail get_global $wordbelt_base i32.le_u br_if $copystringtostart end i32.const 0 set_local $stringbelt_tail end get_local $stringbelt_head call $pop i32.store16 get_local $stringbelt_head i32.const 2 i32.add set_local $stringbelt_head br $next end ;; strstart block $sbhasspace get_local $stringbelt_head get_global $wordbelt_base i32.const 8 i32.sub i32.le_u br_if $sbhasspace i32.const 0 set_local $stringbelt_head end get_local $stringbelt_head get_local $stringbelt_head tee_local $stringbelt_tail i32.const 0 i32.store i32.const 4 i32.add set_local $stringbelt_head br $next end ;; echostring get_local $channel_out call $pop set_local $eax call $pop get_local $eax call $sys_send br $next end ;; eqbool block $equiv call $pop call $pop tee_local $eax i32.eq get_local $eax call $push br_if $equiv i32.const 0 call $push br $next end i32.const 1 call $push br $next end ;; sethere call $pop set_local $here br $next end ;; inchan call $pop set_local $channel_in br $next end ;; subtract call $pop set_local $eax call $pop get_local $eax i32.sub call $push br $next end ;; comma get_local $here call $pop i32.store get_local $here i32.const 4 i32.add set_local $here br $next end ;; drop2 call $pop call $pop drop drop br $next end ;; rot call $pop call $pop set_local $eax call $pop call $rpush call $push call $rpop call $push get_local $eax call $push br $next end ;; dup2 get_local $esi call $rpush call $pop set_local $eax call $pop tee_local $esi call $push get_local $eax call $push get_local $esi call $push get_local $eax call $push call $rpop set_local $esi br $next end ;; dictset call $pop call $rpush call $pop set_local $eax call $pop get_local $eax call $rpop call $vocab_set br $next end ;; here get_local $here call $push br $next end ;; words call $sys_words br $next end ;; swap call $pop call $pop set_local $eax call $push get_local $eax call $push br $next end ;; jneg1 block $jneg1if call $pop i32.const -1 i32.eq br_if $jneg1if get_local $esi i32.const 4 i32.add set_local $esi br $next end get_local $esi i32.load set_local $esi br $next end ;; wordfinish get_local $wordbelt_head get_local $wordbelt_tail i32.sub set_local $eax (; n bytes ;) (; align to 32-bit ;) get_local $wordbelt_head i32.const 3 i32.add i32.const 12284 i32.and set_local $wordbelt_head (; /align ;) get_local $wordbelt_tail call $push get_local $eax call $push br $next end ;; parsenum call $pop call $rpush call $pop tee_local $eax call $rpop call $sys_parsenum get_local $eax i32.load call $push call $push br $next end ;; dictget call $pop set_local $eax call $pop get_local $eax call $vocab_get call $push br $next end ;; wordstart block $wbhasspace get_local $wordbelt_head get_global $wordbelt_bound i32.const 4 i32.sub i32.le_u br_if $wbhasspace get_global $wordbelt_base set_local $wordbelt_head end get_local $wordbelt_head set_local $wordbelt_tail br $next end ;; wordputc block $wbhasspace2 get_local $wordbelt_head get_global $wordbelt_bound i32.lt_u br_if $wbhasspace2 get_global $wordbelt_base set_local $wordbelt_head loop $copywordtostart get_local $wordbelt_head get_local $wordbelt_tail i32.load16_u i32.store16 get_local $wordbelt_head i32.const 2 i32.add set_local $wordbelt_head get_local $wordbelt_tail i32.const 2 i32.add tee_local $wordbelt_tail get_global $wordbelt_bound i32.lt_u br_if $copywordtostart end get_global $wordbelt_base set_local $wordbelt_tail end get_local $wordbelt_head call $pop i32.store16 get_local $wordbelt_head i32.const 2 i32.add set_local $wordbelt_head br $next end ;; jmp get_local $esi i32.load set_local $esi br $next end ;; wsbool call $pop tee_local $eax call $is_whitespace get_local $eax call $push call $push br $next end ;; drop call $pop drop br $next end ;; jnz block $jnzif call $pop i32.eqz br_if $jnzif get_local $esi i32.load set_local $esi br $next end get_local $esi i32.const 4 i32.add set_local $esi br $next end ;; jz block $jzif call $pop i32.eqz br_if $jzif get_local $esi i32.const 4 i32.add set_local $esi br $next end get_local $esi i32.load set_local $esi br $next end ;; noop br $next end ;; execute call $pop tee_local $eax i32.const 256 i32.lt_u br_if $execloop get_local $esi call $rpush get_local $eax set_local $esi br $next end ;; set call $pop call $pop i32.store br $next end ;; fetch call $pop i32.load call $push br $next end ;; emit (.) call $pop call $sys_echo br $next end ;; noop2 br $next end ;; plus call $pop call $pop i32.add call $push br $next end ;; dup call $pop tee_local $eax get_local $eax call $push call $push br $next end ;; key loop $key_loop block $key_read get_local $inbuf_head get_local $inbuf_tail i32.ge_u br_if $key_read block $key_echo get_local $channel_out i32.const -1 i32.add br_if $key_echo (; if current channel's default start is QUIT ;) get_global $channel_table_p get_global $channel_entry_size get_local $channel_in i32.mul i32.add i32.const 8 i32.add i32.load get_global $quit_p i32.ne br_if $key_echo i32.const 1 get_local $inbuf_head i32.const 2 call $sys_write end get_local $inbuf_head i32.load16_u call $push get_local $inbuf_head i32.const 2 i32.add set_local $inbuf_head br $next end ;; key_read get_local $channel_in get_local $inbuf_base get_local $inbuf_bound get_local $inbuf_base i32.sub call $sys_read tee_local $eax get_local $inbuf_base i32.add set_local $inbuf_tail get_local $inbuf_base set_local $inbuf_head block $nullread get_local $eax i32.eqz br_if $nullread br $key_loop end ;; nullread block $pendingword get_local $wordbelt_head get_local $wordbelt_tail i32.eq br_if $pendingword i32.const 32 call $push br $next end ;; pendingword br $bye end ;; key_loop end ;; logword call $pop tee_local $eax call $pop get_local $eax call $sys_log br $next end ;; rinit (unused) call $rinit get_global $holy_bye call $rpush br $next end ;; lit get_local $esi get_local $esi i32.const 4 i32.add set_local $esi i32.load call $push br $next end ;; ret call $rpop set_local $esi br $next end ;; op0 (yield?) get_local $esi call $rpush br $bye end ;; default get_local $esi call $rpush get_local $eax set_local $esi br $next end ;; execloop end ;; next loop end ;; awaiting (; set provided channel's waiter to this channel ;) get_global $channel_table_p get_global $channel_entry_size call $pop i32.mul i32.add tee_local $eax i32.const 2 i32.add get_local $channel_in i32.store8 (; set awaiter flag ;) get_local $eax get_local $eax i32.load8_u i32.const 2 i32.or i32.store8 (; channel status save ;) get_global $channel_table_p get_global $channel_entry_size get_local $channel_in i32.mul i32.add tee_local $eax (; set buffer base ;) i32.const 12 i32.add get_local $inbuf_base i32.store (; set buffer tail ;) get_local $eax i32.const 16 i32.add get_local $inbuf_tail i32.store (; set buffer head ;) get_local $eax i32.const 20 i32.add get_local $inbuf_head i32.store (; set buffer bound ;) get_local $eax i32.const 24 i32.add get_local $inbuf_bound i32.store (; set buffer buffer start ;) get_local $eax i32.const 4 i32.add get_local $here i32.store (; backup return stack here, returning to esi ;) get_local $here get_local $esi get_local $eax i32.const 8 i32.add i32.load call $lit_rstack set_local $here i32.const -1 set_local $inbuf_base ;; temporary bool "await-exit" (; /awaiting ;) end ;; bye get_global $channel_table_p get_global $channel_entry_size get_local $channel_in i32.mul i32.add tee_local $eax i32.const 3 i32.add get_local $channel_out i32.store8 get_global $here_p get_local $here i32.store get_global $stringbelt_tail_p get_local $stringbelt_tail i32.store get_global $stringbelt_head_p get_local $stringbelt_head i32.store get_global $wordbelt_tail_p get_local $wordbelt_tail i32.store get_global $wordbelt_head_p get_local $wordbelt_head i32.store block $await_exit get_local $inbuf_base i32.const -1 i32.eq ;; halt if awaiting br_if $await_exit block $no_awaiter get_local $eax i32.load8_u i32.const 2 i32.and i32.eqz ;; (FLAGS & 2) => awaiter, run it br_if $no_awaiter get_local $eax i32.const 2 i32.add i32.load8_u tee_local $eax call $push get_global $channel_table_p get_global $channel_entry_size get_local $eax i32.mul i32.add tee_local $eax get_local $eax i32.load8_u i32.const 254 i32.and i32.store8 ;; toggle off runflag call $pop call $main get_local $channel_in call $close_channel return end get_local $channel_in call $close_channel end i32.const 0 return ) )