Skip to content

Instantly share code, notes, and snippets.

@sawaken
Created August 22, 2015 16:34
Show Gist options
  • Save sawaken/0f5e8d610c41d3d673b6 to your computer and use it in GitHub Desktop.
Save sawaken/0f5e8d610c41d3d673b6 to your computer and use it in GitHub Desktop.
Scheme Interpreter Essensentials
# run on irb as follows.
# $ irb -r './type0.rb'
# irb> e [:define, :f, [:lambda, [:v], ["+", :v, 1]]]
# irb> e [:f 1]
# => 2
# ...
module Type0
Environment = Struct.new(:parent, :hash)
Lambda = Struct.new(:env, :params, :exp)
extend self
def resolve(env, var_name)
if env.parent
env.hash[var_name] || resolve(env.parent, var_name)
else
env.hash[var_name]
end
end
def apply(lambda, *args)
eval(Environment.new(lambda.env, lambda.params.zip(args).to_h), lambda.exp)
end
def call_ruby_method(method_name, receiver, *args)
receiver.send(method_name, *args)
end
def eval(env, exp)
case exp
when Numeric, String, TrueClass, FalseClass
exp
when Symbol
resolve(env, exp)
when Array
case exp[0]
when :lambda
Lambda.new(env, exp[1], exp[2])
when :define
env.hash[exp[1]] = eval(env, exp[2])
when :if
eval(env, exp[1]) ? eval(env, exp[2]) : eval(env, exp[3])
when String
call_ruby_method(*exp.map{|e| eval(env, e)})
else
apply(*exp.map{|e| eval(env, e)})
end
end
end
end
def e(exp)
$env ||= Type0::Environment.new(nil, {})
Type0.eval($env, exp)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment