(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>

Refactor symbol and 1/2 into specialchars. Move JSON.parse from textToJson to expressionToJs. Move the "blank" out of code into newEval


var symbol = emmy.symbol;

var specialchars =
[["symbol_$1", /\'(\w+)/g],
["[ / $1 $2 ],", /(\d+)\/(\d+)/g]];

var mathfns =
[["div", /\//g],
["mul", /\*/g],
["sub", /\-/g],
["add", /\+/g],
["expt", /\^/g]]

mathfns.map(x=> x[0]).map(loadEnv);

var replaceMath = (txt) =>
specialchars.concat(mathfns)
.reduce((s,r) => s.replace(r[1],r[0]), txt);

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) =>
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) =>
j[0] != "define"
? ["to_infix", ["simplify", j]]
: j;

var modifyJson = (j) => preAmble(replaceD(swapFirst(j)));

var makeFun = (j, callBack) =>
"var " + j[1][0] + " = (" + j[1].slice(1) + ") => "
+ callBack(j[2]) +";";

var makeFunFun = (j, callBack) =>
"var " + j[1][0][0] + " = (" + j[1][0].slice(1) + ") => "
+ "(" + j[1].slice(1) +") => " + callBack(j[2]) + ";";

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]) + "; }"

var jsonToJs = (j) =>
j.constructor == Array && j[0] === "let"
? makeLet(j, jsonToJs)
:j.constructor == Array && j[0] === "define"
&& j[1].constructor == Array
&& j[1][0].constructor == Array
? makeFunFun(j, jsonToJs)
:j.constructor == Array && j[0] === "define"
&& j[1].constructor == Array
? makeFun(j, jsonToJs)
:j.constructor == Array && j[0] === "define"
&& j[1].constructor == String
? "var " + j[1] + " = " + jsonToJs(j[2]) + ";"
: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 expressionToJs = (expr) =>
jsonToJs(modifyJson(JSON.parse(textToJson(expr))));

var literal_function = emmy.literal_function;

["sin", "cos", "velocity", "dot_product",
"up", "Gamma", "compose"].map(loadEnv); null;
    
<script>
     var oldEval = window.eval;
     var newEval = (txt) =>
         txt.substr(0, 2) === ";("
         ? expressionToJs(txt.substr(1))
         : txt[0] === "(" && txt[txt.length - 1] != " "
         ? textToJson(txt)
         : txt[0] === "("
         ? oldEval(expressionToJs(txt))
         : txt[txt.length - 1] != ";"
         ? "Add ; to JS: " + txt
         : oldEval(txt);
     window.eval = newEval;
</script>

What we have up to now


((1 / 2) / 2) 
    

(3 * (1 / 2)) 
    

(1 + (((2 / 3) - 4) * 5)) 
    

(2 ^ 3) 
    

(1 + (cos 0)) 
    

(+ 1 (cos 0)) 
    

((sin ^ 2) (314 / 100)) 
    

((cos (sin 0)) + (((2 / 3) - 4) * (5 ^ 2))) 
    

(+ (cos (sin 0)) (* (- (/ 2 3) 4) (expt 5 2))) 
    

(3 * (cos 0)) 
    

((3 * cos) 0) 
    

(cos 'x) 
    

((3 * (sin ^ 2)) 'x) 
    

((D (3 * (sin ^ 2))) 'x) 
    

(define value 6) 
    

(1 + value) 
    

(define (funame x) (x + 1)) 
    

(funame 4) 
    

(define ((ffuname x) y) (x + y)) 
    


((ffuname 4) 5) 
    

(define (fulet x) (let ((y 1)) (+ x y))) 
    

(fulet 4) 
    

(1 + 1/2) 
    

Implementation of new functionality

Make floating point and negative numbers possible.


;(define (f-1-2 x) x)
    

var _specialchars =
[["", /\:/g],
 ["symbol_$1", /\'(\w+)/g],
 ["$1_dot_$2", /(\d+)\.(\d+)/g],
 [" minus_$2", /(\s+)\-(\w+)/g],
 ["$1_", /(\w+)\-/g],
 ["[ / $1 $2 ],", /(\w+)\/(\d+)/g]];

var specialchars = _specialchars;

var post_specialchars =
[["$1.$2", /(\d+)_dot_(\d+)/],
["-$1", /minus_(\w+)/]]

var _replaceD = replaceD;

var replaceD = (j) =>
j.constructor == String && j == "D"
? "drv"
: j.constructor == String
? post_specialchars.reduce((s,r) => s.replace(r[1],r[0]), j)
: _replaceD(j);

    

;(define (f-1-2 x) x)
    

(-1.7 + 2.9) 
    

loadEnv("pi");
    

(* -:pi/2) 
    

var identity = x => x;

var edgeCases = (j) =>
j[0] === "define"
&& j[2].constructor == Array && j[2][0] === "let"
&& j[1].constructor == String
? ["identity", "'let not allowed in variable definition'"]
: j;

var letFlat2 = (j) =>
j[0] === "let"
? j[1].concat(letFlat2(j[2]))
: [j];

var constructLet = (j) =>
["let", j.slice(0, j.length - 1), j[j.length - 1]]

var letFlat = (j) =>
j.constructor == Array && j[0] === "let"
? constructLet(letFlat2(j))
: j.constructor == Array
? j.map(letFlat)
: j;

var _modifyJson = modifyJson
var modifyJson = (j) => _modifyJson(letFlat(edgeCases(j)));
    

(identity 1/2) 
    

(define (fu z) (let ((x 1)) (let ((y 2)) (+ x y z)))) 
    

(fu 7) 
    

(define value1 (let ...)) is excluded explicitely.


(define value1 (let ((x 1)) (+ x 1))) 
    

var __specialchars =
[["__gt_", /->/g]].concat(specialchars);

var specialchars = __specialchars;
    

(define F->G 3) 
    

(identity F->G) 
    

loadEnv("nth");
var time = x => nth(x, 0);
    

(time (up 't (up 'r 'phi) (up 'rdot 'phidot))) 
    

var jsonCode = textToJson("(lambda (x y) (+ x y))");

var makeLambda = (j, callBack) =>
"(" + j[1] + ") => " + callBack(j[2]) +";";

makeLambda(jsonCode, e => "<" + e + ">");
    

var _jsonToJs = jsonToJs;

var jsonToJs = (j) =>
j.constructor == Array && j[0] === "lambda"
? makeLambda(j, jsonToJs)
: _jsonToJs(j);
    

(define funame (lambda (x y) (+ x y))) 
    

(funame 1 2) 
    

(define (fu x)
  (let ((ffu (lambda (y)
               (let ((r 1))
                 (+ y x r)))))
    ffu)) 
    

((fu 3) 4) 
    

var _post_specialchars =
    [["symbol_$1^$2", /symbol_(\w+)expt(\w+)/],
     ["$1e-$2", /(\d+)e_(\d+)/]].concat(post_specialchars);

var post_specialchars = _post_specialchars;
    

('v_r^x ^ 4) 
    

(3 * 1.0e-11) 
    

Take a look at all 109 examples of the SICMechanics book part one

The compiler now is in a state to run all 109 examples of the first part of the SICMechanics book.