aboutsummaryrefslogtreecommitdiffstats
path: root/forth.js
diff options
context:
space:
mode:
authordan <[email protected]>2023-05-30 18:23:54 -0400
committerdan <[email protected]>2023-05-30 18:23:54 -0400
commit24272d599e1886a8fb47e3e47d33a0aa7dd74e22 (patch)
tree3105c1638ff0bb909dff1023102a8e0fe809c83c /forth.js
parent66d61a5546e5e0173f92e941ab489a1c6474473e (diff)
downloadforth-24272d599e1886a8fb47e3e47d33a0aa7dd74e22.tar.gz
forth-24272d599e1886a8fb47e3e47d33a0aa7dd74e22.tar.bz2
forth-24272d599e1886a8fb47e3e47d33a0aa7dd74e22.zip
feat: web version also uses c code, compiled to wasm
Diffstat (limited to 'forth.js')
-rw-r--r--forth.js150
1 files changed, 25 insertions, 125 deletions
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 = `
<div id="forthouter">
<div id='forthresultsbox'>
<pre id="forthresults"></pre>
@@ -149,31 +63,17 @@ if (typeof window !== 'undefined') { // browser UI
<input id="forthline" type="text" value="" autocomplete="off">
</form>
</div>`
- 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;
}