X-Git-Url: https://git.kengrimes.com/?p=watForth.git;a=blobdiff_plain;f=forth.wat;h=d5240604c57bf028b397437c4469e8dc47c8641d;hp=30bd82d82636fec66cff1f9d57b234885b1054ad;hb=refs%2Fheads%2Fmaster;hpb=0096f7eba3c6c1584234866ee3cbfe5b1df765c2 diff --git a/forth.wat b/forth.wat index 30bd82d..d524060 100644 --- a/forth.wat +++ b/forth.wat @@ -1,153 +1,440 @@ +(; 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 $FUNCSIG$v (func (param 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) (result i32))) - (import "env" "sys_fetch" (func $sys_fetch (param i32 i32) (result i32))) - (import "env" "sys_listen" (func $sys_listen (param i32) (result i32))) - (import "env" "sys_write" (func $sys_write (param i32 i32) (result 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_echochar" (func $sys_echochar (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) (result i32))) - (import "env" "vocab_set" (func $vocab_set (param i32) (param i32) (result 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) (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) - (global $inbuf i32 (i32.const 8)) - (global $inbuf_size i32 (i32.const 12)) - (global $inbuf_data i32 (i32.const 16)) - (global $wbuf i32 (i32.const 256)) - (global $wbuf_data i32 (i32.const 260)) - (data (i32.const 8) "\f4\00\00\00") ;; STDIN buf, 244 len - (data (i32.const 256) "\7c\00\00\00") ;; WBUF, 124 len - (data (i32.const 384) "\20\03\00\00") ;; MODE - (data (i32.const 388) "\18\04\00\00") ;; HERE - (data (i32.const 392) "\58\02\00\00") ;; START - (data (i32.const 396) "\0a\00\00\00") ;; BASE - (; Interpret ;) - (data (i32.const 512) "\b8\02\00\00") ;; WORD xt (696) - (data (i32.const 516) "\06\00\00\00") ;; DUP - (data (i32.const 520) "\0a\00\00\00") ;; @ - (data (i32.const 524) "\0e\00\00\00") ;; JZ: - (data (i32.const 528) "\2c\02\00\00") ;; INTERP-END addr (556) - (data (i32.const 532) "\02\00\00\00") ;; LIT xt - (data (i32.const 536) "\80\01\00\00") ;; MODE addr (384) - (data (i32.const 540) "\0a\00\00\00") ;; @ (fetch) xt - (data (i32.const 544) "\0c\00\00\00") ;; EXECUTE xt - (data (i32.const 548) "\0d\00\00\00") ;; NOOP xt - (data (i32.const 552) "\01\00\00\00") ;; RET - (data (i32.const 556) "\10\00\00\00") ;; DROP <-- INTERP-END - (data (i32.const 560) "\19\00\00\00") ;; BYE + (; 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 ;) - (data (i32.const 600) "\03\00\00\00") ;; RINIT xt - (data (i32.const 604) "\00\02\00\00") ;; INTERPRET xt (512) - (data (i32.const 608) "\12\00\00\00") ;; JMP xt - (data (i32.const 612) "\58\02\00\00") ;; quit location (600) - (; Test instructions ;) - (data (i32.const 640) "\02\00\00\00") ;; LIT - (data (i32.const 644) "\02\00\00\00") ;; 2 - (data (i32.const 648) "\06\00\00\00") ;; DUP - (data (i32.const 652) "\07\00\00\00") ;; + - (data (i32.const 656) "\09\00\00\00") ;; . - (data (i32.const 660) "\12\00\00\00") ;; JMP - (data (i32.const 664) "\58\02\00\00") ;; quit addr + (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 696) "\14\00\00\00") ;; WB0 - (data (i32.const 700) "\05\00\00\00") ;; KEY <-- KEYLOOP - (data (i32.const 704) "\06\00\00\00") ;; DUP - (data (i32.const 708) "\18\00\00\00") ;; J-1: 18 - (data (i32.const 712) "\0c\03\00\00") ;; addr of WORDEND - (data (i32.const 716) "\11\00\00\00") ;; WS? - (data (i32.const 720) "\0e\00\00\00") ;; JZ: - (data (i32.const 724) "\00\03\00\00") ;; addr of DOCHAR - (data (i32.const 728) "\10\00\00\00") ;; DROP - (data (i32.const 732) "\12\00\00\00") ;; JMP: - (data (i32.const 736) "\bc\02\00\00") ;; addr of KEYLOOP - (data (i32.const 740) "\05\00\00\00") ;; KEY <-- WORDLOOP - (data (i32.const 744) "\11\00\00\00") ;; WS? - (data (i32.const 748) "\0f\00\00\00") ;; JNZ: - (data (i32.const 752) "\0c\03\00\00") ;; addr of WORDEND - (data (i32.const 756) "\06\00\00\00") ;; DUP - (data (i32.const 760) "\18\00\00\00") ;; J-1: - (data (i32.const 764) "\0c\03\00\00") ;; addr of WORDEND - (data (i32.const 768) "\13\00\00\00") ;; WPUTC <-- DOCHAR - (data (i32.const 772) "\12\00\00\00") ;; JMP: - (data (i32.const 776) "\e4\02\00\00") ;; addr of WORDLOOP - (data (i32.const 780) "\10\00\00\00") ;; DROP <-- WORDEND - (data (i32.const 784) "\02\00\00\00") ;; LIT (push addr of wbuf, 256) - (data (i32.const 788) "\00\01\00\00") ;; wbuf addr (utf16 string) - (data (i32.const 792) "\17\00\00\00") ;; WB!LEN - (data (i32.const 796) "\01\00\00\00") ;; RET + (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 800) "\06\00\00\00") ;; DUP - (data (i32.const 804) "\15\00\00\00") ;; DICT_GET - (data (i32.const 808) "\06\00\00\00") ;; DUP - (data (i32.const 812) "\0e\00\00\00") ;; JZ: - (data (i32.const 816) "\44\03\00\00") ;; donum (832) - (data (i32.const 820) "\1a\00\00\00") ;; SWAP - (data (i32.const 824) "\10\00\00\00") ;; DROP - (data (i32.const 828) "\0c\00\00\00") ;; EXECUTE - (data (i32.const 832) "\01\00\00\00") ;; RET - (data (i32.const 836) "\10\00\00\00") ;; DROP (xt from dictionary) - (data (i32.const 840) "\16\00\00\00") ;; NUMBER <-- donum, pushes NUM, UNPARSED - (data (i32.const 844) "\06\00\00\00") ;; DUP - (data (i32.const 848) "\0f\00\00\00") ;; JNZ: - (data (i32.const 852) "\60\03\00\00") ;; donum_err (864) - (data (i32.const 856) "\10\00\00\00") ;; DROP - (data (i32.const 860) "\01\00\00\00") ;; RET - (data (i32.const 864) "\10\00\00\00") ;; PARSE_ERR <-- donum_err - (data (i32.const 868) "\10\00\00\00") ;; ( DROP DROP ) - (data (i32.const 872) "\19\00\00\00") ;; BYE - (; : definition ;) - (data (i32.const 900) "\b8\02\00\00") ;; WORD - (data (i32.const 904) "\1c\00\00\00") ;; HERE - (data (i32.const 908) "\1d\00\00\00") ;; VOCAB_SET - (data (i32.const 912) "\01\00\00\00") ;; RET - (data (i32.const 1000) "\08\00\00\00") ;; "word" size - (data (i32.const 1004) "w\00o\00r\00d\00") ;; utf16 - (data (i32.const 1012) "\12\00\00\00") ;; "interpret" size - (data (i32.const 1016) "i\00n\00t\00e\00r\00p\00r\00e\00t\00") ;; utf16 - (data (i32.const 1034) "\00\00") ;; align 32-bit - (data (i32.const 1036) "\08\00\00\00") ;; "quit" size - (data (i32.const 1040) "q\00u\00i\00t\00") ;; utf16 - (;HERE ---> 1048;) + (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 (result i32) + (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 (result i32) + (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 $wbuf_head i32) - i32.const 388 - i32.load - set_local $here - i32.const 392 + (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 - i32.const 260 - set_local $wbuf_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 - call $sys_stack - get_local $esi - call $sys_reflect get_local $esi get_local $esi i32.const 4 @@ -155,26 +442,368 @@ set_local $esi i32.load set_local $eax + loop $execloop block $default block $op0 block $ret block $lit block $rinit - block $word block $key block $dup block $plus block $noop2 block $emit + 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 $wputc block $wbzero - block $dictget block $parsenum block $wbsetlen block $jneg1 block $swap - block $words block $here block $dictset + 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;)$word $key (;6;)$dup $plus + 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 $wputc (;20;)$wbzero $dictget - (;22;)$parsenum $wbsetlen (;24;)$jneg1 $bye (;26;)$swap $words - (;28;)$here $dictset $default - end ;; dictset + (;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 - drop br $next end ;; here get_local $here @@ -207,46 +836,93 @@ i32.load set_local $esi br $next - end ;; wbsetlen - get_global $wbuf - get_local $wbuf_head - get_global $wbuf_data + end ;; wordfinish + get_local $wordbelt_head + get_local $wordbelt_tail i32.sub - i32.store - get_global $wbuf - call $sys_reflect + 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 - i32.const 396 (; load BASE ;) - i32.load + call $pop + call $rpush call $pop tee_local $eax + call $rpop call $sys_parsenum - call $push 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 ;; wbzero - get_global $wbuf_data - set_local $wbuf_head - get_global $wbuf - i32.const 0 - i32.store + 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 ;; wputc - get_local $wbuf_head + 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 $wbuf_head + get_local $wordbelt_head i32.const 2 i32.add - set_local $wbuf_head + set_local $wordbelt_head br $next end ;; jmp get_local $esi @@ -260,7 +936,6 @@ get_local $eax call $push call $push - call $sys_stack br $next end ;; drop call $pop @@ -311,9 +986,7 @@ br $next end ;; set call $pop - set_local $eax call $pop - get_local $eax i32.store br $next end ;; fetch @@ -343,13 +1016,32 @@ end ;; key loop $key_loop block $key_read - get_global $inbuf_size - i32.load get_local $inbuf_head - get_global $inbuf_data - i32.sub - i32.le_u + 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 @@ -359,24 +1051,46 @@ set_local $inbuf_head br $next end ;; key_read - i32.const 0 - get_global $inbuf + 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_global $inbuf_size - i32.load + get_local $eax i32.eqz br_if $nullread br $key_loop end ;; nullread - i32.const -1 ;; <- keyval sent if sz == 0 - call $push - br $next + 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 ;; word + end ;; logword + call $pop + tee_local $eax + call $pop + get_local $eax + call $sys_log br $next - end ;; rinit + end ;; rinit (unused) call $rinit + get_global $holy_bye + call $rpush br $next end ;; lit get_local $esi @@ -391,10 +1105,10 @@ call $rpop set_local $esi br $next - end ;; op0 + end ;; op0 (yield?) get_local $esi - call $sys_reflect - br $next + call $rpush + br $bye end ;; default get_local $esi call $rpush @@ -402,8 +1116,147 @@ set_local $esi br $next end ;; execloop - end ;; nextl + 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 ) -) \ No newline at end of file +)