mirror of
https://github.com/osmarks/website
synced 2025-02-04 05:09:11 +00:00
RPNCalc overhaul
This commit is contained in:
parent
b2bb51217d
commit
1902999735
@ -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)")
|
@ -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>
|
||||
|
@ -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
1639
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user