SVRV

Lambda CalculuJS

I have made a lambda calculus to javascript converter and visualizer. The converter is finished, but the visualizer lacks the polish necessary for me to publish it.

Both λ and \ works as lambda and short-hand for multiple arguments must be separated with space (eg. \x y. y). Recursive function with an if-test must use lazy evaluation in order to work, made possible by wrapping the clauses in a function evaluated on the outside of the if (eq. if(\_.A)(\_.B)(_))

Because the code inludes a lot of pointless fluff, here's a small standalone evaluator. Beneath is an example. By running, it should evaluate to 120, the factorial of 5.

function λCalculus(calculus){
    var nextLambda = calculus.search(/[#λ\\]/)
    if(nextLambda == 0){
        var delim = calculus.search(/[.:]/);
        if(!~delim) throw Error("Missing body delimiter");
        var head = calculus.slice(1,delim)  
                           .split(/[^a-zA-Z0-9]+[0-9]*/);
        var body = λCalculus(calculus.slice(delim+1))
        var func = "#2#"
        for(var i in head){
            func = func.replace(/#2#/,
                   "function anonymous(#1#){ return #2#; }"
                   .replace(/#1#/,head[i]));
        }
        return func.replace(/#2#/,body);
    } else if(nextLambda > 0){
        var left = 1;
        var i = nextLambda;
        while(left>0&&++i<calculus.length){
            if(calculus[i] == "(") left++;
            else if(calculus[i] == ")") left--;
        }
        return calculus.slice(0,nextLambda)
             + λCalculus(calculus.slice(nextLambda,i))
             + λCalculus(calculus.slice(i));
    }
    return calculus;
}

// Some lambdas
var wrapper = "(λR cond zerop succ pred mult T F.@)(λx.x(x))(λc a b.c(a)(b))(λn.n(λx a b.b)(λa b.a))(λn f x. n(f)(f(x)))(λn f x. n(λg h.h(g(f)))(λu.x)(λu.u))(λa b c d.a(b(c))(d))(λx y.x)(λx y.y)"
var fac = wrapper.replace(/@/,"(λfac.fac)(R(λself n.cond(zerop(n))(λblank.succ(F))(λblank.mult(n)(R(self)(pred(n))))(0)))")
var three = "(λf x.f(f(f(x))))"
var five = "(λf x.f(f(f(f(f(x))))))"

// evaluation of (5!)
var js = λCalculus("("+fac+")"+"(λf x.f(f(f(f(f(x))))))")
function evalAsInteger(a){ return a(increment)(0); }
function increment(a){ return (a-0||0) + 1; }
console.log(js,evalAsInteger(eval(js)))