A Lisp interpreter

# A 24 lines long minimal Lisp interpreter.
# Permits arithmetic and recursive functions.

use sys, string.syntax
ast = syntax.parser{
   scan = {symbols = list("()"), letter = "[~{_}()]"},
   transform = {atom = "", expr = "", list = |t| t[1..]},
   grammar = "atom = number | identifier; list = ('(' {expr}* ')');
              expr = atom | list; ast = expr;"}
dispatch = {
   "define": fn|t,env| env.(t[1]) = ev(t[2],env) end,
   "lambda": |t,env| |x| ev(t[2],table env(map(zip(t[1],x)))),
   "if": |t,env| (ev(t[2],env) if ev(t[1],env) else ev(t[3],env)),
   "let": |t,env| ev(t[2],
      table env(map(t[1].map(|[k,v]| [k,ev(v,env)]))))}
global_env = table{
   "+": |a| a.sum(),   "*": |a| a.prod(),  "#t": true,
   "-": |a| a[0]-a[1], "/": |a| a[0]/a[1], "#f": false,
   "=": |a| a[0]==a[1],"not": |a| not a[0],
   "<": |a| a[0]<a[1], "<=": |a| a[0]<=a[1],
   "block": |a| a[-1], "display": |a| print(*a)}
ev = |t,env| (t if t: Int else env.(t) if t: String
   else dispatch[t[0]](t,env) if t[0]: String and t[0] in dispatch
   else begin a = t.map(|x| ev(x,env)); a[0](a[1..]) end)
evals = |s| ev(ast(["(block ",s,")"].join()),global_env)
evals(read(sys.argv[1]))


(define fac
    (lambda (n)
        (if (= n 0) 1 (* n (fac (- n 1))))))

(display (fac 4))