--- /dev/null
+c/switch_split.*
+!c/switch_split.c
+*~
+forth.wasm
--- /dev/null
+#! /bin/bash
+clang -emit-llvm --target=wasm32 -O3 -S $1
+FNAME=${1%.c}
+llc ${FNAME}.ll -march=wasm32
+s2wasm ${FNAME}.s > ${FNAME}.wast
+wat-desugar ${FNAME}.wast > ${FNAME}.wat
--- /dev/null
+extern int sys_read(int,int);
+extern int sys_request(int,int);
+extern int sys_write(int,int);
+extern int vocab_get(int);
+extern int vocab_set(int,int);
+extern void push(int);
+extern int pop(void);
+extern void rpush(int);
+extern int rpop(void);
+extern void rinit(void);
+static char memseg[1024] =
+ { 0, 0, 0, 9, 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 16, 0, 0, 0, 13, 0, 0, 0, 1
+ };
+static int interpret(int,int);
+int main(void) {
+ /* int start, here, eax, ebx, esi, mode;
+ here = (int) memseg + 512;
+ mode = here;
+ *(int*) mode = 11; //executing
+ here += 4;
+ //string "interpret"
+ eax = here;
+ *(int*)here++ = 9;
+ *(char*)here++ = 'i';
+ *(char*)here++ = 'n';
+ *(char*)here++ = 't';
+ *(char*)here++ = 'e';
+ *(char*)here++ = 'r';
+ *(char*)here++ = 'p';
+ *(char*)here++ = 'r';
+ *(char*)here++ = 'e';
+ *(char*)here++ = 't';
+ here += 3; //align
+ //initial definition of "interpret"
+ esi = here;
+ *(int*)here++ = 4; //WORD
+ *(int*)here++ = 2; //LIT
+ *(int*)here++ = mode; //addr of mode var
+ *(int*)here++ = 10; //FETCH
+ *(int*)here++ = 12; //EXECUTE
+ *(int*)here++ = 13; //NOOP
+ *(int*)here++ = 1; //RET
+ //insert into vocab
+ vocab_set(eax, esi);
+ //string "quit"
+ ebx = esi;
+ eax = here;
+ *(int*)here++ = 4;
+ *(char*)here++ = 'q';
+ *(char*)here++ = 'u';
+ *(char*)here++ = 'i';
+ *(char*)here++ = 't';
+ //initial definition of "quit"
+ esi = here;
+ *(int*)here++ = 3; //rinit
+ *(int*)here++ = ebx; //interpret
+ *(int*)here++ = 9; //JMP
+ *(int*)here++ = esi; //jmp addr 0 (interpret)
+ //insert into vocab
+ vocab_set(eax, esi); */
+ return interpret((int)memseg, (int)memseg);
+}
+static int interpret(int esi, int here) {
+ int eax = 0, ebx = 0, ecx = 0, edi = 0;
+ next:
+ eax = *(int*) esi;
+ esi += 4;
+ exec:
+ switch(eax) {
+ case 0: //interpret
+ esi = eax;
+ eax = *(int*)eax;
+ goto next;
+ case 1: // ret (exit)
+ esi = rpop();
+ goto next;
+ case 2: // pushnext (lit)
+ push(*(int*)esi);
+ esi += 4;
+ goto next;
+ case 3: // rinit
+ rinit();
+ goto next;
+ case 4: // word
+ esi += eax;
+ eax += esi;
+ goto next;
+ case 5: // sys_read
+ sys_read(pop(),pop());
+ goto next;
+ case 6: // sys_request
+ sys_request(pop(),pop());
+ goto next;
+ case 7: // sys_write
+ sys_write(pop(),pop());
+ goto next;
+ case 8: // bye
+ break;
+ case 9: // goto
+ esi = *(int*) esi;
+ goto next;
+ case 10: // @ fetch
+ push(*(int*)pop());
+ goto next;
+ case 11: // ! set
+ *(int*)pop() = pop();
+ goto next;
+ case 12: // EXECUTE
+ eax = pop();
+ goto exec;
+ case 13: // NOOP
+ push(1);
+ goto next;
+ default: // eax is an addr, jump to it and push esi
+ rpush(esi);
+ esi = eax;
+ goto next;
+ }
+ return 0;
+}
--- /dev/null
+(module
+ (type $FUNCSIG$i (func (result i32)))
+ (type $FUNCSIG$vi (func (param i32)))
+ (type $FUNCSIG$v (func))
+ (type $FUNCSIG$iii (func (param i32 i32) (result 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_request" (func $sys_request (param i32 i32) (result i32)))
+ (import "env" "sys_write" (func $sys_write (param i32 i32) (result i32)))
+ (table (;0;) 0 anyfunc)
+ (memory $0 1)
+ (data (i32.const 16) "\00\00\00\09interpret\00\00\00\00\00\00\00\00\00\00\04\00\00\00\02\00\00\00\10\00\00\00\0d\00\00\00\01\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00")
+ (export "memory" (memory $0))
+ (export "main" (func $main))
+ (func $main (result i32)
+ (local $0 i32) (local $1 i32)
+ i32.const 0
+ i32.load offset=4
+ i32.const 16
+ i32.sub
+ set_local $1
+ i32.const 0
+ get_local $1
+ i32.store offset=4
+ get_local $1
+ i32.const 0
+ i32.store offset=12
+ i32.const 16
+ i32.const 16
+ call $interpret
+ set_local $0
+ i32.const 0
+ get_local $1
+ i32.const 16
+ i32.add
+ i32.store offset=4
+ get_local $0)
+ (func $interpret (param $0 i32) (param $1 i32) (result i32)
+ (local $2 i32)
+ i32.const 0
+ i32.load offset=4
+ i32.const 32
+ i32.sub
+ set_local $2
+ i32.const 0
+ get_local $2
+ i32.store offset=4
+ get_local $2
+ get_local $0
+ i32.store offset=28
+ get_local $2
+ get_local $1
+ i32.store offset=24
+ get_local $2
+ i32.const 0
+ i32.store offset=20
+ get_local $2
+ i32.const 0
+ i32.store offset=16
+ get_local $2
+ i32.const 0
+ i32.store offset=12
+ get_local $2
+ i32.const 0
+ i32.store offset=8
+ loop $label$0 (result i32)
+ get_local $2
+ get_local $2
+ i32.load offset=28
+ i32.load
+ i32.store offset=20
+ get_local $2
+ get_local $2
+ i32.load offset=28
+ i32.const 4
+ i32.add
+ i32.store offset=28
+ block $label$1
+ block $label$2
+ block $label$3
+ loop $label$4
+ get_local $2
+ i32.load offset=20
+ set_local $1
+ get_local $1
+ i32.const 13
+ i32.gt_u
+ br_if $label$3
+ block $label$5
+ block $label$6
+ block $label$7
+ block $label$8
+ block $label$9
+ block $label$10
+ block $label$11
+ block $label$12
+ block $label$13
+ block $label$14
+ block $label$15
+ block $label$16
+ block $label$17
+ block $label$18
+ get_local $1
+ br_table $label$18 $label$17 $label$16 $label$15 $label$14 $label$13 $label$12 $label$11 $label$10 $label$9 $label$8 $label$7 $label$6 $label$5 $label$18
+ end
+ get_local $2
+ get_local $2
+ i32.load offset=20
+ i32.store offset=28
+ get_local $2
+ get_local $2
+ i32.load offset=20
+ i32.load
+ i32.store offset=20
+ br $label$1
+ end
+ get_local $2
+ call $rpop
+ i32.store offset=28
+ br $label$1
+ end
+ get_local $2
+ i32.load offset=28
+ i32.load
+ call $push
+ get_local $2
+ get_local $2
+ i32.load offset=28
+ i32.const 4
+ i32.add
+ i32.store offset=28
+ br $label$1
+ end
+ call $rinit
+ br $label$1
+ end
+ get_local $2
+ get_local $2
+ i32.load offset=28
+ get_local $2
+ i32.load offset=20
+ i32.add
+ i32.store offset=28
+ get_local $2
+ get_local $2
+ i32.load offset=20
+ get_local $2
+ i32.load offset=28
+ i32.add
+ i32.store offset=20
+ br $label$1
+ end
+ call $pop
+ call $pop
+ call $sys_read
+ drop
+ br $label$1
+ end
+ call $pop
+ call $pop
+ call $sys_request
+ drop
+ br $label$1
+ end
+ call $pop
+ call $pop
+ call $sys_write
+ drop
+ br $label$1
+ end
+ br $label$2
+ end
+ get_local $2
+ get_local $2
+ i32.load offset=28
+ i32.load
+ i32.store offset=28
+ br $label$1
+ end
+ call $pop
+ i32.load
+ call $push
+ br $label$1
+ end
+ call $pop
+ set_local $1
+ call $pop
+ get_local $1
+ i32.store
+ br $label$1
+ end
+ get_local $2
+ call $pop
+ i32.store offset=20
+ br $label$4
+ end
+ end
+ i32.const 1
+ call $push
+ br $label$1
+ end
+ get_local $2
+ i32.load offset=28
+ call $rpush
+ get_local $2
+ get_local $2
+ i32.load offset=20
+ i32.store offset=28
+ br $label$1
+ end
+ i32.const 0
+ get_local $2
+ i32.const 32
+ i32.add
+ i32.store offset=4
+ i32.const 0
+ return
+ end
+ br $label$0
+ end))
--- /dev/null
+: dothings ^C dup + ; ^E
+5 dothings .
--- /dev/null
+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>watForth</title>
+ </head>
+ <body>
+ <script src="forth.js"></script>
+ </body>
+</html>
--- /dev/null
+'use strict'
+let txtdiv = document.createElement("div")
+document.body.appendChild(txtdiv)
+const output = {
+ print: (string) => txtdiv.textContent += string
+}
+let wasmMem
+let forth
+
+/* Input capture */
+let stdin = ""
+document.addEventListener('keydown', (event) => {
+ console.log(`keydown: ${event.key}`)
+ if (event.key != "F5") {
+ event.preventDefault()
+ event.stopPropagation()
+ switch (event.key) {
+ case "Enter":
+ txtdiv = document.createElement("div")
+ document.body.appendChild(txtdiv)
+ forth()
+ output.print("__ok.")
+ txtdiv = document.createElement("div")
+ document.body.appendChild(txtdiv)
+ break
+ case "Backspace":
+ stdin = stdin.substring(0, stdin.length - 1)
+ txtdiv.textContent = txtdiv.textContent.substring(0, txtdiv.textContent.length - 1)
+ break
+ default:
+ if (event.key.length == 1) {
+ stdin += event.key
+ output.print(event.key)
+ }
+ break
+ }
+ }
+})
+
+const channels = [{
+ read: (writeAddr, maxBytes) => {
+ const maxChars = maxBytes >> 1
+ const bufView = new Uint16Array(wasmMem.buffer, writeAddr, maxChars)
+ let i
+ for (i = 0; i < maxChars && i < stdin.length; i++)
+ bufView[i] = stdin.charCodeAt(i)
+ stdin = stdin.substring(maxChars)
+ return i << 1
+ },
+ write: (readAddr, maxBytes) =>
+ output.print(String.fromCharCode.apply(
+ null,
+ new Uint16Array(wasmMem.buffer, readAddr, maxBytes)
+ ))
+}]
+const simstack = []
+const rstack = []
+const dictionary = {
+ ';': 1,
+ 'LIT': 2,
+ RINIT: 3,
+ WORD: 696,
+ KEY: 5,
+ DUP: 6,
+ '+': 7,
+ 'NOOP2': 8,
+ '.': 9,
+ '@': 10,
+ '!': 11,
+ EXECUTE: 12,
+ NOOP: 13,
+ 'JZ:': 14,
+ 'JNZ:': 15,
+ DROP: 16,
+ 'WS?': 17,
+ 'JMP:': 18,
+ 'WPUTC': 19,
+ 'WB0': 20,
+ 'FIND': 21,
+ 'NUMBER': 22,
+ 'W!LEN': 23,
+ 'J-1:': 24,
+ 'BYE': 25,
+ 'SWAP': 26,
+ 'WORDS': 27,
+ 'HERE': 28,
+ 'DEFINE': 29,
+ ':': 900,
+ 'MODE': 384,
+ 'WBUF': 256,
+ 'EXECUTE-MODE': 800,
+ 'QUIT': 600,
+ 'INTERPRET': 512
+}
+const wasmImport = {
+ env: {
+ pop: () => simstack.pop(),
+ push: (val) => simstack.push(val),
+ rinit: () => rstack.length = 0,
+ rpop: () => rstack.pop(),
+ rpush: (val) => rstack.push(val),
+ sys_write: (channel, fromBuffer) => {
+ if (channels[channel] === undefined)
+ return
+ const maxBytes = new DataView(
+ wasmMem.buffer,
+ fromBuffer,
+ 4
+ ).getUint32(0,true)
+ console.log(`write ch:${channel} addr:${fromBuffer} len:${maxBytes}`)
+ channels[channel].write(fromBuffer + 4, maxBytes)
+ },
+ sys_read: (channel, toBuffer) => {
+ console.log(`read ch:${channel} buf:${toBuffer} current: ${stdin}`)
+ const lenView = new DataView(wasmMem.buffer, toBuffer, 8)
+ const maxBytes = lenView.getUint32(0,true)
+ console.log(`read blen:${lenView.getUint32(0,true)} cstrlen:${lenView.getUint32(4,true)}`)
+ /* If the channel is undefined, or if there isn't enough room in
+ * toBuffer for even one character, then, if there is enough
+ * room for an int write a zero, exit */
+ if (channels[channel] === undefined || maxBytes < 6) {
+ if (maxBytes >= 4)
+ lenView.setUint32(4,0,true)
+ }
+ const numBytes = channels[channel].read(toBuffer + 8, maxBytes - 4)
+ lenView.setUint32(4,numBytes,true);
+ console.log(`read wrote ${lenView.getUint32(4,true)} bytes, remainder: ${stdin}`)
+ console.log(`read blen:${lenView.getUint32(0,true)} cstrlen:${lenView.getUint32(4,true)}`) },
+ sys_listen: (reqAddr, cbAddr) => {
+ //TODO: call into the module to wasm fn "event" to push an event
+ //to forth, which pushes esi to the return stack and queues the
+ //callback function provided from listen. reqaddr could be
+ //"fetch", in which case no channel is used. otherwise very
+ //similar to sys_fetch.
+ },
+ sys_fetch: (channel, reqAddr) => {
+ //TODO: map to fetch promise, write to channel buffer,
+ //javascript "fetch" as fallback, explicit handles for
+ //"textEntry" or any third party protocols like activitypub
+ console.log(`fetch ${channel} ${reqAddr}`)
+ },
+ sys_echo: (val) => output.print(`${val} `),
+ sys_echochar: (val) => output.print(String.fromCharCode(val)),
+ sys_reflect: (addr) => {
+ console.log(`reflect: ${addr}: ${
+ new DataView(wasmMem.buffer, addr, 4)
+ .getUint32(0,true)
+ }`)
+ },
+ vocab_get: (addr) => {
+ const bytes = new DataView(
+ wasmMem.buffer,
+ addr,
+ 4
+ ).getUint32(0,true)
+ const word = String.fromCharCode.apply(
+ null,
+ new Uint16Array(wasmMem.buffer, addr + 4, bytes >> 1)
+ )
+ const answer = dictionary[word.toUpperCase()]
+ console.log(`vocab_get ${word}: ${answer}`)
+ if (answer === undefined)
+ return 0
+ return answer
+ },
+ vocab_set: (addr, num) => {
+ const bytes = new DataView(
+ wasmMem.buffer,
+ addr,
+ 4
+ ).getUint32(0,true)
+ const word = String.fromCharCode.apply(
+ null,
+ new Uint16Array(wasmMem.buffer, addr + 4, bytes >> 1)
+ )
+ console.log(`vocab_set ${word}: ${num}`)
+ dictionary[word.toUpperCase()] = num
+ return 0
+ },
+ is_whitespace: (key) => /\s/.test(String.fromCharCode(key)),
+ sys_stack: () => console.log(`[${simstack}]`),
+ sys_parsenum: (addr, base) => {
+ const byteV = new DataView(
+ wasmMem.buffer,
+ addr,
+ 4
+ )
+ const word = String.fromCharCode.apply(
+ null,
+ new Uint16Array(wasmMem.buffer, addr + 4, byteV.getUint32(0,true) >> 1)
+ )
+ const answer = Number.parseInt(word, base)
+ byteV.setUint32(0,Number.isNaN(answer),true)
+ return answer
+ },
+ sys_words: () => {
+ output.print(Object.getOwnPropertyNames(dictionary).toString().split(',').join(' '))
+ }
+ }
+}
+
+fetch('forth.wasm')
+ .then(re => re.arrayBuffer())
+ .then(buf => WebAssembly.instantiate(buf, wasmImport))
+ .then(result => {
+ wasmMem = result.instance.exports.memory
+ forth = result.instance.exports.main
+ console.log('wasm loaded');
+ forth()
+ })
--- /dev/null
+(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)))
+ (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_echo" (func $sys_echo (param i32)))
+ (import "env" "sys_echochar" (func $sys_echochar (param 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" "is_whitespace" (func $is_whitespace (param i32) (result i32)))
+ (import "env" "sys_parsenum" (func $sys_parsenum (param 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
+ (; 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
+ (; 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
+ (; 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;)
+ (export "memory" (memory $0))
+ (export "main" (func $main))
+ (func $main (result i32)
+ call $interpret
+ )
+ (func $interpret (result i32)
+ (local $here i32)
+ (local $eax i32)
+ (local $esi i32)
+ (local $inbuf_head i32)
+ (local $wbuf_head i32)
+ i32.const 388
+ i32.load
+ set_local $here
+ i32.const 392
+ i32.load
+ set_local $esi
+ i32.const 16
+ set_local $inbuf_head
+ i32.const 260
+ set_local $wbuf_head
+ block $bye
+ loop $next
+ call $sys_stack
+ get_local $esi
+ call $sys_reflect
+ 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 $word 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
+ get_local $eax
+ br_table $op0 $ret (;2;)$lit $rinit (;4;)$word $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
+ call $pop
+ set_local $eax
+ call $pop
+ get_local $eax
+ call $vocab_set
+ drop
+ 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 ;; wbsetlen
+ get_global $wbuf
+ get_local $wbuf_head
+ get_global $wbuf_data
+ i32.sub
+ i32.store
+ get_global $wbuf
+ call $sys_reflect
+ br $next
+ end ;; parsenum
+ i32.const 396 (; load BASE ;)
+ i32.load
+ call $pop
+ tee_local $eax
+ call $sys_parsenum
+ call $push
+ get_local $eax
+ i32.load
+ call $push
+ br $next
+ end ;; dictget
+ call $pop
+ 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
+ br $next
+ end ;; wputc
+ get_local $wbuf_head
+ call $pop
+ i32.store16
+ get_local $wbuf_head
+ i32.const 2
+ i32.add
+ set_local $wbuf_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
+ call $sys_stack
+ 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
+ set_local $eax
+ call $pop
+ get_local $eax
+ 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_global $inbuf_size
+ i32.load
+ get_local $inbuf_head
+ get_global $inbuf_data
+ i32.sub
+ i32.le_u
+ br_if $key_read
+ 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
+ i32.const 0
+ get_global $inbuf
+ call $sys_read
+ block $nullread
+ get_global $inbuf_size
+ i32.load
+ i32.eqz
+ br_if $nullread
+ br $key_loop
+ end ;; nullread
+ i32.const -1 ;; <- keyval sent if sz == 0
+ call $push
+ br $next
+ end ;; key_loop
+ end ;; word
+ br $next
+ end ;; rinit
+ call $rinit
+ 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
+ get_local $esi
+ call $sys_reflect
+ br $next
+ end ;; default
+ get_local $esi
+ call $rpush
+ get_local $eax
+ set_local $esi
+ br $next
+ end ;; execloop
+ end ;; nextl
+ end ;; bye
+ get_local $here
+ )
+)
\ No newline at end of file