Permalink
Find file
aa16fca Jun 6, 2013
@fogus @flada-auxv
25 lines (22 sloc) 1.06 KB
class Lisp
def initialize(ext={})
@env = { :label => proc { |(name,val), _| @env[name] = eval(val, @env) },
:car => lambda { |(list), _| list[0] },
:cdr => lambda { |(list), _| list.drop 1 },
:cons => lambda { |(e,cell), _| [e] + cell },
:eq => lambda { |(l,r), ctx| eval(l, ctx) == eval(r, ctx) },
:if => proc { |(cond, thn, els), ctx| eval(cond, ctx) ? eval(thn, ctx) : eval(els, ctx) },
:atom => lambda { |(sexpr), _| (sexpr.is_a? Symbol) or (sexpr.is_a? Numeric) },
:quote => proc { |sexpr, _| sexpr[0] } }.merge(ext)
end
def apply fn, args, ctx=@env
return ctx[fn].call(args, ctx) if ctx[fn].respond_to? :call
self.eval ctx[fn][2], ctx.merge(Hash[*(ctx[fn][1].zip args).flatten(1)])
end
def eval sexpr, ctx=@env
return(ctx[sexpr] || sexpr) if ctx[:atom].call [sexpr], ctx
fn, *args = sexpr
args = args.map { |a| self.eval(a, ctx) } if ctx[fn].is_a?(Array) || (ctx[fn].respond_to?(:lambda?) && ctx[fn].lambda?)
apply(fn, args, ctx)
end
end