From 24272d599e1886a8fb47e3e47d33a0aa7dd74e22 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 30 May 2023 18:23:54 -0400 Subject: feat: web version also uses c code, compiled to wasm --- forth.js | 150 +++++++++++---------------------------------------------------- 1 file changed, 25 insertions(+), 125 deletions(-) (limited to 'forth.js') diff --git a/forth.js b/forth.js index 5cea76f..c7ff27d 100644 --- a/forth.js +++ b/forth.js @@ -1,96 +1,11 @@ -function forth(print = console.log) { - const s = []; // the stack - const popNum = () => Number(s.pop()); - const fs = { - '/' : () => { - const a2 = popNum(); - const a1 = popNum(); - s.push(a1 / a2); - }, - '-' : () => { - const a2 = popNum(); - const a1 = popNum(); - s.push(a1 - a2); - }, - '+' : () => { s.push(popNum() + popNum()) }, - '*' : () => { s.push(popNum() * popNum()) }, - '=' : () => { s.push(popNum() === popNum()) }, - 'swap' : () => { - const a1 = s.pop(); - const a2 = s.pop(); - s.push(a1); - s.push(a2); - }, - 'drop' : () => { - s.pop(); - }, - 'over' : () => { - const a1 = s.pop(); - const a2 = s.pop(); - s.push(a2); - s.push(a1); - s.push(a2); - }, - 'rot' : () => { - const a1 = s.pop(); - const a2 = s.pop(); - const a3 = s.pop(); - s.push(a2); - s.push(a1); - s.push(a3); - }, - 'then' : () => {/*Doing nothing skips the token*/}, - 'if' : (initialIdx, tokens) => { - if (!popNum()) { - let localIdx = initialIdx; - while (tokens[localIdx] && tokens[localIdx] !== 'then') {localIdx++} - return localIdx - initialIdx; - } - }, - 'not' : () => { s.push(!popNum()) }, - '.' : () => { print(s.pop()) }, - 'peek' : () => { print(s[s.length - 1]) }, - 'dup' : () => { - const a = s.pop(); - s.push(a); - s.push(a); - }, - ':' : (initialIdx, tokens) => { - let localIdx = initialIdx + 1; - const fname = tokens[localIdx++]; - const fnContent = []; - for (;tokens[localIdx] !== ';'; localIdx++) { - fnContent.push(tokens[localIdx]); - } - fs[fname] = () => { - exec(fnContent); - } - return localIdx - initialIdx; // numItemsSkipped - }, - } - - function exec(tokens) { - for (let tokenIdx = 0; tokenIdx < tokens.length; tokenIdx++) { - const token = tokens[tokenIdx]; - if (fs[token]) { - const numItemsSkipped = fs[token](tokenIdx, tokens); - if (Number.isInteger(numItemsSkipped)) { - tokenIdx += numItemsSkipped; - } - } - else { - s.push(token); - } - } - } - return t => - new Promise( - resolve => { - exec(t.split(/[ \n\t]+/).filter(x => x !== '')); - resolve(); - } - ); +function exec(x) { + return Module.ccall( + "extern_eval", // name of C function + "string", // return type + ["string"], // argument types + [x] // arguments + ); } /* @@ -99,14 +14,13 @@ root tag to add to page: * */ -if (typeof window !== 'undefined') { // browser UI - const style = document.createElement('style') - style.innerHTML = ` +const style = document.createElement('style') +style.innerHTML = ` #forthroot * { background-color: #42456f; color: white; - font-family: monospace; - font-size: 1.2rem; + font-family: monospace; + font-size: 1.2rem; box-sizing: border-box; } #forthouter { @@ -138,8 +52,8 @@ if (typeof window !== 'undefined') { // browser UI margin-bottom: 0px; } `; - document.head.appendChild(style); - forthroot.innerHTML = ` +document.head.appendChild(style); +forthroot.innerHTML = `

@@ -149,31 +63,17 @@ if (typeof window !== 'undefined') { // browser UI
         
       
     
` - forthouter.onclick = () => forthline.focus(); - const print = x => { - forthresults.innerHTML = forthresults.innerHTML + x + '\n' ; - forthouter.scrollTo(0, forthouter.scrollHeight); - }; - const m = forth(print); - forthform.onsubmit = () => { - const input = forthline.value; - if (input !== '') { - print(`> ${input}`); - m(input); - forthline.value = ''; - } - return false; +forthouter.onclick = () => forthline.focus(); +const print = x => { + forthresults.innerHTML = forthresults.innerHTML + x ; + forthouter.scrollTo(0, forthouter.scrollHeight); +}; +forthform.onsubmit = () => { + const input = forthline.value; + if (input !== '') { + print(`> ${input}\n`); + print(exec(input)); + forthline.value = ''; } - -} else { // UI if NodeJS - const readline = require('readline'); - const rl = readline.createInterface({ input: process.stdin, output: process.stderr }); - const prompt = (query) => new Promise((resolve) => rl.question(query, resolve)); - const m = forth(); - (async () => { - while (true) { - const input = await prompt("> "); - m(input) - } - })(); + return false; } -- cgit v1.2.3