From: ken Date: Fri, 16 Feb 2018 22:50:46 +0000 (-0800) Subject: Initial X-Git-Url: https://git.kengrimes.com/?p=watForth.git;a=commitdiff_plain;h=0096f7eba3c6c1584234866ee3cbfe5b1df765c2 Initial --- 0096f7eba3c6c1584234866ee3cbfe5b1df765c2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0fb9098 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +c/switch_split.* +!c/switch_split.c +*~ +forth.wasm diff --git a/c/c2wat b/c/c2wat new file mode 100755 index 0000000..d2bec09 --- /dev/null +++ b/c/c2wat @@ -0,0 +1,6 @@ +#! /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 diff --git a/c/switch_split.c b/c/switch_split.c new file mode 100644 index 0000000..ba9b2af --- /dev/null +++ b/c/switch_split.c @@ -0,0 +1,121 @@ +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; +} diff --git a/c/switch_split_0.wat b/c/switch_split_0.wat new file mode 100644 index 0000000..140b820 --- /dev/null +++ b/c/switch_split_0.wat @@ -0,0 +1,224 @@ +(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)) diff --git a/forth.forth b/forth.forth new file mode 100644 index 0000000..2facfc9 --- /dev/null +++ b/forth.forth @@ -0,0 +1,2 @@ +: dothings ^C dup + ; ^E +5 dothings . diff --git a/forth.html b/forth.html new file mode 100644 index 0000000..b35238f --- /dev/null +++ b/forth.html @@ -0,0 +1,10 @@ + + + + + watForth + + + + + diff --git a/forth.js b/forth.js new file mode 100644 index 0000000..486a50c --- /dev/null +++ b/forth.js @@ -0,0 +1,210 @@ +'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() + }) diff --git a/forth.wat b/forth.wat new file mode 100644 index 0000000..30bd82d --- /dev/null +++ b/forth.wat @@ -0,0 +1,409 @@ +(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