Skip to content

Instantly share code, notes, and snippets.

@billhails
Last active June 30, 2018 09:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save billhails/a60523cfb0eac708bf90c9b65a74d21a to your computer and use it in GitHub Desktop.
Save billhails/a60523cfb0eac708bf90c9b65a74d21a to your computer and use it in GitHub Desktop.
Example lambda interpreter written in F-natural
{
// very simple environment, one binding per frame
typedef environment { frame(string, expression, environment) | root }
// lookup access to the environment
fn lookup {
(str, frame(str, value, _)) { value }
(str, frame(_, _, parent)) { lookup(str, parent) }
(str, root) { error("mce symbol not defined " @@ str) }
}
// very simple AST
typedef expression {
addition(expression, expression) |
subtraction(expression, expression) |
multiplication(expression, expression) |
division(expression, expression) |
number(int) |
symbol(string) |
conditional(expression, expression, expression) |
lambda(expression, expression) |
closure(expression, environment) |
application(expression, expression)
}
// an interpreter
fn eval {
(addition(l, r), env) { add(eval(l, env), eval(r, env)) }
(subtraction(l, r), env) { sub(eval(l, env), eval(r, env)) }
(multiplication(l, r), env) { mul(eval(l, env), eval(r, env)) }
(division(l, r), env) { div(eval(l, env), eval(r, env)) }
(i = number(_), env) { i }
(symbol(str), env) { lookup(str, env) }
(conditional(test, pro, con), env) { cond(test, pro, con, env) }
(l = lambda(symbol(_), _), env) { closure(l, env) }
(application(function, arg), env) { apply(eval(function, env), eval(arg, env)) }
}
// function application
fn apply (closure(lambda(symbol(str), body), env), arg) {
eval(body, frame(str, arg, env))
}
// built-ins
fn add (number(a), number(b)) { number(a + b) }
fn sub (number(a), number(b)) { number(a - b) }
fn mul (number(a), number(b)) { number(a * b) }
fn div (number(a), number(b)) { number(a / b) }
fn cond(test, pro, con, env) {
switch (eval(test, env)) {
(number(0)) { eval(con, env) } // 0 is false
(number(_)) { eval(pro, env) }
}
}
// try it out: [((lambda (x) (if x (+ x 2) x)) a) |- a: 3] = 5
eval(
application(
lambda(
symbol("x"),
conditional(
symbol("x"),
addition(symbol("x"), number(2)),
symbol("x")
)
),
symbol("a")
),
frame("a", number(3), root)
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment