Skip to content

Instantly share code, notes, and snippets.

@jvoorhis
Created March 16, 2009 17:12
Show Gist options
  • Save jvoorhis/79963 to your computer and use it in GitHub Desktop.
Save jvoorhis/79963 to your computer and use it in GitHub Desktop.
class Val < Struct.new(:val)
def fold(rules)
rules[self.class].(val)
end
end
class Var < Struct.new(:lbl)
def fold(rules)
rules[self.class].(lbl)
end
end
class Add < Struct.new(:x, :y)
def fold(rules)
rules[self.class].(x.fold(rules), y.fold(rules))
end
end
class Seq < Struct.new(:left, :right)
def fold(rules)
rules[self.class].(left.fold(rules), right.fold(rules))
end
end
class Asgn < Struct.new(:lbl, :expr)
def fold(rules)
rules[self.class].(lbl, expr.fold(rules))
end
end
class Fun < Struct.new(:args, :body)
def fold(rules)
rules[self.class].(args, body)
end
end
class App < Struct.new(:fun, :args)
def fold(rules)
rules[self.class].(fun, args)
end
end
def eval(expr)
expr.fold Val => -> val { -> env { [env,val] } },
Var => -> lbl { -> env { [env,env[lbl]] } },
Add => -> x, y { -> env { e1,v1 = x.(env); e2,v2 = y.(env); [env,v1+v2] } },
Seq => -> left, right { -> env { e1,v1 = left.(env); e2,v2 = right.(e1); [env,v2] } },
Asgn => -> lbl, expr { -> env { e1,v = expr.(env); [env.merge(lbl=>v),v] } },
Fun => -> args, body { -> env { [env, Fun[args,body]] } },
App => -> fun, args { -> env {
e1,f = eval(fun).(env)
e2 = env.merge(Hash[*f.args.zip(args.map { |a| eval(a).(env)[1] }).flatten])
eval(f.body).(e2) } },
end
expr = Seq[Asgn[:add, Fun[[:a,:b],
Add[Var[:a],Var[:b]]]],
App[Var[:add], [Val[2], Val[3]]]]
env = {}
puts eval(expr).(env)[1]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment