forked from kanaka/mal
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstep2_eval.rb
68 lines (59 loc) · 1.33 KB
/
step2_eval.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
require_relative "mal_readline"
require_relative "types"
require_relative "reader"
require_relative "printer"
# read
def READ(str)
return read_str(str)
end
# eval
def eval_ast(ast, env)
return case ast
when Symbol
raise "'" + ast.to_s + "' not found" if not env.key? ast
env[ast]
when List
List.new ast.map{|a| EVAL(a, env)}
when Vector
Vector.new ast.map{|a| EVAL(a, env)}
when Hash
new_hm = {}
ast.each{|k,v| new_hm[EVAL(k,env)] = EVAL(v, env)}
new_hm
else
ast
end
end
def EVAL(ast, env)
#puts "EVAL: #{_pr_str(ast, true)}"
if not ast.is_a? List
return eval_ast(ast, env)
end
if ast.empty?
return ast
end
# apply list
el = eval_ast(ast, env)
f = el[0]
return f[*el.drop(1)]
end
# print
def PRINT(exp)
return _pr_str(exp, true)
end
# repl
repl_env = {}
REP = lambda {|str| PRINT(EVAL(READ(str), repl_env)) }
repl_env[:+] = lambda {|a,b| a + b}
repl_env[:-] = lambda {|a,b| a - b}
repl_env[:*] = lambda {|a,b| a * b}
repl_env[:/] = lambda {|a,b| a / b}
# repl loop
while line = _readline("user> ")
begin
puts REP[line]
rescue Exception => e
puts "Error: #{e}"
puts "\t#{e.backtrace.join("\n\t")}"
end
end