RPNCalc overhaul

This commit is contained in:
osmarks 2021-03-06 21:15:16 +00:00
parent b2bb51217d
commit 1902999735
5 changed files with 1288 additions and 417 deletions

View File

@ -81,12 +81,10 @@ const addDefn = (name, args, fn) => {
}
}
const add = (args) => [{type:"num", val:args[0] + args[1]}];
const sub = (args) => [{type:"num", val:args[0] - args[1]}];
const div = (args) => [{type:"num", val:args[0] / args[1]}];
const mult = (args) => [{type:"num", val:args[0] * args[1]}];
const pow = (args) => [{type:"num", val:Math.pow(args[0], args[1])}];
const root = (args) => [{type:"num", val:Math.sqrt(args[0])}];
const addBinopDefn = (name, op) => addDefn(name, ["num", "num"], args => [{ type: "num", val: op(args[0], args[1]) }])
const addUnopDefn = (name, op) => addDefn(name, ["num"], args => [{ type: "num", val: op(args[0]) }])
const addConstDefn = (name, val) => addDefn(name, [], args => [{ type: "num", val }])
const type = (args) => [{type:"type", val:args[0].type}];
const pair = (args) => [{type:"pair", val:{fst:args[0], snd:args[1]}}];
const fst = (args) => [args[0].fst];
@ -103,12 +101,19 @@ const eq = (args) => {
}
}
addDefn("+", ["num", "num"], add);
addDefn("-", ["num", "num"], sub);
addDefn("/", ["num", "num"], div);
addDefn("*", ["num", "num"], mult);
addDefn("^", ["num", "num"], pow);
addDefn("sqrt", ["num"], root);
addBinopDefn("+", (x, y) => x + y)
addBinopDefn("-", (x, y) => x - y)
addBinopDefn("/", (x, y) => x / y)
addBinopDefn("*", (x, y) => x * y)
addBinopDefn("%", (x, y) => x % y)
addBinopDefn("^", Math.pow)
addBinopDefn("atan2", Math.atan2)
for (const func of ["abs", "floor", "log", "asin", "acos", "atan", "sin", "cos", "tan", "exp", "cbrt", "ceil", "sqrt"]) {
addUnopDefn(func, Math[func])
}
addConstDefn("e", Math.E)
addConstDefn("pi", Math.PI)
addDefn("==", 4, eq);
addDefn("pair", 2, pair);
addDefn("fst", ["pair"], fst);
@ -125,4 +130,6 @@ addRPNDefn("listthen", "(fn -> (internal; x acc -> '(->acc fn) '(->x acc pair in
addRPNDefn("list", "'(a -> a) listthen");
addRPNDefn("lmap", "(list fn -> list '(->list fst fn list snd 'fn lmap pair) list 0 tuple ==)");
addRPNDefn("unlist", "(l -> (internal; list -> '(->) '(->list fst list snd internal) list 0 tuple ==) stop l internal)");
addRPNDefn("map", "fn -> '(l->l 'fn lmap unlist) listthen");
addRPNDefn("map", "fn -> '(l->l 'fn lmap unlist) listthen");
addRPNDefn("hypot", "(a b -> a a * b b * + sqrt)")
addRPNDefn("swap", "(a b -> b a)")

View File

@ -12,8 +12,13 @@ code {
background-color:rgb(230, 230, 230);
padding: 0 0.125rem;
}
button {
border: 1px solid gray;
padding: 0.3em;
}
</style>
<textarea id="inbox"></textarea>
<textarea id="inbox" rows=10></textarea>
<button id="step">step</button>
<button id="play">play</button>
<button id="load">load</button>
@ -26,7 +31,7 @@ code {
<p>use <code>(name; value)</code> to define something. the definition can be recursive. <code>value</code> is executed and <code>name</code> is set to the final state of the stack, i.e. <code>(name; 1 3)</code> is possible</p>
<p>use <code>'</code> to push instead of apply to the stack, e.g. <code>'(a -> a)</code>. This is useful for lazyness, i.e. <code>'(->lazy evaluated thing)</code></p>
<ul>
<li><code>+, -, *, /, ^, sqrt</code>: mathematical operations</li>
<li><code>+, -, *, /, ^, sqrt, cbrt, exp, log, (a)cos/sin/tan, abs, floor</code>: mathematical operations</li>
<li><code>==</code>: equality (automatically derived for all types); returns <code>a b -> a</code> if true, <code>a b -> b</code> if false</li>
<li><code>typeof</code>: returns the type of the object</li>
<li><code>pair, fst, snd</code>: pairs two objects, gets first or second item of pair</li>

View File

@ -81,6 +81,8 @@ play.onclick = _ => {
input = null;
}
// TODO: Actually deal with horrible XSS problems. It seems to be safe for now due to string literals being bad, at least.
// It may be possible to do JSF[REDACTED]k-style things to get around this, though.
stepb.onclick = _ => {
if (state === null) {
return;
@ -98,11 +100,23 @@ stepb.onclick = _ => {
if (!(pos.start === 0 && pos.end === 0)) {
insbox.innerHTML = highlight(input, pos.start, pos.end, "green");
}
if (state.stacks.length > 1) {
outbox.innerHTML = "... " + prettyprint(state.stacks[state.stacks.length-1]);
} else {
outbox.innerHTML = prettyprint(state.stacks[0]);
let out = []
let emptyCounter = 0
for (const stack of state.stacks) {
if (stack.length === 0) {
emptyCounter += 1
} else {
if (emptyCounter !== 0) {
out.push(`[empty x${emptyCounter}]`)
emptyCounter = 0
}
out.push(prettyprint(stack))
}
}
if (emptyCounter !== 0) {
out.push(`[empty x${emptyCounter}]`)
}
outbox.innerHTML = out.join("<br>")
}
}

1639
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@
"markdown-it": "^10.0.0",
"mustache": "^4.0.1",
"nanoid": "^2.1.11",
"pug": "^2.0.4",
"pug": "^3.0.2",
"ramda": "^0.26.1",
"sass": "^1.26.8",
"terser": "^4.8.0"