Emmy as JavaScript library (5)
(This post is part of a series, all with the same title)
(and needs lots more text to actually explain things)
<script src="https://kloimhardt.github.io/blog/js/emmy.js/build/emmy_bundle.js"></script>
<script> var loadEnv = (name) => { window[name] = emmy[name]; return name; } </script>
var mathfns =
[["div", /\//g],
["mul", /\*/g],
["sub", /\-/g],
["add", /\+/g],
["expt", /\^/g]]
mathfns.map(x=> x[0]).map(loadEnv);
var symbol = emmy.symbol;
var _replaceMath = (txt) =>
mathfns.reduce((s,r) => s.replace(r[1],r[0]),
txt.replace(/\'(\w+)/g,"symbol_$1"));
var replaceMath = _replaceMath;
var swapFirst = (j) =>
j.constructor == Array && mathfns.map(x=> x[0]).includes(j[1])
? [j[1], j[0]].concat(j.slice(2)).map(swapFirst)
: j.constructor == Array
? j.map(swapFirst)
: j;
var insertCommas = (txt) =>
txt.replace(/(\w+)/g,'"$1",')
.replace(/\,\s+\]/g," ]");
var makeBrackets = (txt) =>
txt.trim()
.replace(/\(/g,"[ ")
.replace(/\)/g," ],")
.replace(/,$/,"");
var textToJson = (txt) =>
JSON.parse(insertCommas(replaceMath(makeBrackets(txt))));
var drv = emmy.D;
var replaceD = (j) =>
j.constructor == Array
? j.map(replaceD)
: j == "D" ? "drv" : j;
["to_infix", "simplify"].map(loadEnv);
var _preAmble = (j) => ["to_infix", ["simplify", j]];
var preAmble = _preAmble;
var modifyJson = (j) => preAmble(replaceD(swapFirst(j)));
var _jsonToJs = (j) =>
j.constructor == String && j.substring(0, 7) == "symbol_"
? 'symbol("' + j.substring(7, j.length) + '")'
:j.constructor == Array
? jsonToJs(j[0]) + "(" + j.slice(1).map(jsonToJs) + ")"
: j;
var jsonToJs = _jsonToJs;
var expressionToJs = (expr) =>
jsonToJs(modifyJson(textToJson(expr)));
var expressionToJs = (expr) =>
expr[expr.length-1] === " "
? jsonToJs(modifyJson(textToJson(expr)))
: "'add blank'";
["sin", "cos"].map(loadEnv); null;
<script> var oldEval = window.eval; var newEval = (txt) => txt[0] === "(" ? oldEval(expressionToJs(txt)) : oldEval(txt); window.eval = newEval; </script>
old stuff still works
((cos (sin 0)) + (((2 / 3) - 4) * (5 ^ 2)))
((D (3 * (sin ^ 2))) 'x)
New stuff
[textToJson("(1 + 1)")," and " , textToJson("(1 - 1)")].toString()
var preAmble = (j) =>
j[0] != "define"
? _preAmble(j)
: j;
var __jsonToJs = (j) =>
j.constructor == Array && j[0] === "define"
&& j[1].constructor == String
? "var " + j[1] + " = " + jsonToJs(j[2]) + ";"
: _jsonToJs(j);
var jsonToJs = __jsonToJs;
(define value 6)
value
var jsonCode = textToJson("(define (funame x) (x + 1))")
var makeFun = (j, callBack) =>
"var " + j[1][0] + " = (" + j[1].slice(1) + ") => "
+ callBack(j[2]) +";";
makeFun(jsonCode, e=> "<" + e + ">")
var _3_jsonToJs = (j) =>
j.constructor == Array && j[0] === "define"
&& j[1].constructor == Array
? makeFun(j, jsonToJs)
: __jsonToJs(j);
var jsonToJs = _3_jsonToJs;
(define (funame x) (x + 1))
(funame 4)
var jsonCode = textToJson("(define ((ffuname x) y) (x + y))")
var makeFunFun = (j, callBack) =>
"var " + j[1][0][0] + " = (" + j[1][0].slice(1) + ") => "
+ "(" + j[1].slice(1) +") => " + callBack(j[2]) + ";";
makeFunFun(jsonCode, e=> "<" + e + ">")
var _4_jsonToJs = (j) =>
j.constructor == Array && j[0] === "define"
&& j[1].constructor == Array
&& j[1][0].constructor == Array
? makeFunFun(j, jsonToJs)
: _3_jsonToJs(j);
var jsonToJs = _4_jsonToJs;
(define ((ffuname x) y) (x + y))
((ffuname 4) 5)
var jsonCode = textToJson("(let ((x a) (y b)) (x + y))");
var smap = (f, v) =>
v.length === 1
? f(v[0]) +";"
: f(v[0]) +"; " + smap(f, v.slice(1));
var makeLet = (j, callBack) =>
"{" + smap((l) => "let " + l[0] + " = " + callBack(l[1]), j[1])
+ " return " + callBack(j[2]) + "; }"
makeLet(jsonCode, e=>"<"+ e +">");
var jsonToJs = (j) =>
j.constructor == Array && j[0] === "let"
? makeLet(j, jsonToJs)
: _4_jsonToJs(j);
expressionToJs("(define (fulet x) (let ((y 1)) (+ x y))) ")
(define (fulet x) (let ((y 1)) (+ x y)))
(fulet 4)
var replaceMath = (txt) =>
_replaceMath(txt.replace(/(\d+)\/(\d+)/g, "[ / $1 $2 ],"));
(1 + 1/2)
var __replaceMath = replaceMath
var replaceMath = (txt) =>
__replaceMath(txt.replace(/(\w+)\-(\w+)/g, "$1_$2"));
textToJson("(a - b)");
textToJson("(a-b)");
var L_free_particle = emmy.L_free_particle;
["velocity", "dot_product", "up"].map(loadEnv); null;
(define ((L-free-particle mass) local)
(let ((v (velocity local)))
(* 1/2 mass (dot-product v v))))
var literal_function = emmy.literal_function;
(define q
(up (literal-function 'x)
(literal-function 'y)
(literal-function 'z)))
In the next calculation, append a blank to see the result.
(q 't)
((D q) 't)
["Gamma", "compose"].map(loadEnv); null;
((Gamma q) 't)
((compose (L-free-particle 'm) (Gamma q)) 't)