「RubyでつくるRuby」の interp.rb
#MinRuby
Rubyで学ぶRuby 第9回 インタプリタの完成、そしてブートストラップへ
https://ascii.jp/elem/000/001/419/1419659/
code:interp.rb
require "minruby"
def evaluate(tree, genv, lenv)
case tree0
when "lit"
tree1
when "+"
evaluate(tree1, genv, lenv) + evaluate(tree2, genv, lenv)
when "-"
evaluate(tree1, genv, lenv) - evaluate(tree2, genv, lenv)
when "*"
evaluate(tree1, genv, lenv) * evaluate(tree2, genv, lenv)
when "/"
evaluate(tree1, genv, lenv) / evaluate(tree2, genv, lenv)
when "%"
evaluate(tree1, genv, lenv) % evaluate(tree2, genv, lenv)
when "<"
evaluate(tree1, genv, lenv) < evaluate(tree2, genv, lenv)
when "<="
evaluate(tree1, genv, lenv) <= evaluate(tree2, genv, lenv)
when "=="
evaluate(tree1, genv, lenv) == evaluate(tree2, genv, lenv)
when "!="
evaluate(tree1, genv, lenv) != evaluate(tree2, genv, lenv)
when ">="
evaluate(tree1, genv, lenv) >= evaluate(tree2, genv, lenv)
when ">"
evaluate(tree1, genv, lenv) > evaluate(tree2, genv, lenv)
when "stmts"
i = 1
last = nil
while treei
last = evaluate(treei, genv, lenv)
i = i + 1
end
last
when "var_assign"
lenv[tree1] = evaluate(tree2, genv, lenv)
when "var_ref"
lenv[tree1]
when "if"
if evaluate(tree1, genv, lenv)
evaluate(tree2, genv, lenv)
else
evaluate(tree3, genv, lenv)
end
when "while"
while evaluate(tree1, genv, lenv)
evaluate(tree2, genv, lenv)
end
when "func_def"
genv[tree1] = ["user_defined", tree2, tree3]
when "func_call"
args = []
i = 0
while treei + 2
argsi = evaluate(treei + 2, genv, lenv)
i = i + 1
end
mhd = genv[tree1]
if mhd0 == "builtin"
minruby_call(mhd1, args)
else
new_lenv = {}
params = mhd1
i = 0
while paramsi
new_lenv[paramsi] = argsi
i = i + 1
end
evaluate(mhd2, genv, new_lenv)
end
when "ary_new"
ary = []
i = 0
while treei + 1
aryi = evaluate(treei + 1, genv, lenv)
i = i + 1
end
ary
when "ary_ref"
ary = evaluate(tree1, genv, lenv)
idx = evaluate(tree2, genv, lenv)
aryidx
when "ary_assign"
ary = evaluate(tree1, genv, lenv)
idx = evaluate(tree2, genv, lenv)
val = evaluate(tree3, genv, lenv)
aryidx = val
when "hash_new"
hsh = {}
i = 0
while treei + 1
key = evaluate(treei + 1, genv, lenv)
val = evaluate(treei + 2, genv, lenv)
hshkey = val
i = i + 2
end
hsh
end
end
# ① プログラムの文字列を読み込む
str = minruby_load()
# ② プログラムの文字列を抽象構文木に変換する
tree = minruby_parse(str)
# ③ 抽象構文木を実行(計算)する
genv = {
"p" => "builtin", "p",
"require" => "builtin", "require",
"minruby_parse" => "builtin", "minruby_parse",
"minruby_load" => "builtin", "minruby_load",
"minruby_call" => "builtin", "minruby_call",
}
lenv = {}
evaluate(tree, genv, lenv)