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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
# File 'lib/minruby.rb', line 13
def simplify(exp)
case exp[0]
when :program, :bodystmt
make_stmts(exp[1])
when :def
name = exp[1][1]
params = exp[2]
params = params[1] if params[0] == :paren
params = (params[1] || []).map {|a| a[1] }
body = simplify(exp[3])
["func_def", name, params, body]
when :call
recv = simplify(exp[1])
name = exp[3][1]
["method_call", recv, name, []]
when :fcall
name = exp[1][1]
["func_call", name]
when :method_add_arg
call = simplify(exp[1])
e = exp[2]
e = e[1] || [] if e[0] == :arg_paren
e = e[1] || [] if e[0] == :args_add_block
e = e.map {|e_| simplify(e_) }
call[(call[0] == "func_call" ? 2 : 3)..-1] = e
call
when :command
name = exp[1][1]
args = exp[2][1].map {|e_| simplify(e_) }
["func_call", name, *args]
when :if, :elsif
cond_exp = simplify(exp[1])
then_exp = make_stmts(exp[2])
if exp[3]
if exp[3][0] == :elsif
else_exp = simplify(exp[3])
else
else_exp = make_stmts(exp[3][1])
end
end
["if", cond_exp, then_exp, else_exp]
when :ifop
cond_exp = simplify(exp[1])
then_exp = simplify(exp[2])
else_exp = simplify(exp[3])
["if", cond_exp, then_exp, else_exp]
when :if_mod
cond_exp = simplify(exp[1])
then_exp = make_stmts([exp[2]])
["if", cond_exp, then_exp, nil]
when :while
cond_exp = simplify(exp[1])
body_exp = make_stmts(exp[2])
["while", cond_exp, body_exp]
when :while_mod
cond_exp = simplify(exp[1])
body_exp = make_stmts(exp[2][1][1])
["while2", cond_exp, body_exp]
when :binary
exp1 = simplify(exp[1])
op = exp[2]
exp2 = simplify(exp[3])
[op.to_s, exp1, exp2]
when :var_ref
case exp[1][0]
when :@kw
case exp[1][1]
when "nil" then ["lit", nil]
when "true" then ["lit", true]
when "false" then ["lit", false]
else
raise
end
when :@ident
["var_ref", exp[1][1]]
when :@const
["const_ref", exp[1][1]]
end
when :@int
["lit", exp[1].to_i]
when :unary
v = simplify(exp[2])
raise if v[0] != "lit"
["lit", -v[1]]
when :string_literal
["lit", exp[1][1] ? exp[1][1][1] : ""]
when :symbol_literal
["lit", exp[1][1][1].to_sym]
when :assign
case exp[1][0]
when :var_field
["var_assign", exp[1][1][1], simplify(exp[2])]
when :aref_field
["ary_assign", simplify(exp[1][1]), simplify(exp[1][2][1][0]), simplify(exp[2])]
else
raise
end
when :case
arg = simplify(exp[1])
when_clauses = []
exp = exp[2]
while exp && exp[0] == :when
pat = exp[1].map {|e_| simplify(e_) }
when_clauses << [pat, make_stmts(exp[2])]
exp = exp[3]
end
else_clause = make_stmts(exp[1]) if exp
exp = else_clause
when_clauses.reverse_each do |patterns, stmts|
patterns.each do |pattern|
exp = ["if", ["==", arg, pattern], stmts, exp]
end
end
exp
when :method_add_block
call = simplify(exp[1])
blk_params = exp[2][1][1][1].map {|a| a[1] }
blk_body = exp[2][2].map {|e_| simplify(e_) }
call << blk_params << blk_body
when :aref
["ary_ref", simplify(exp[1]), *exp[2][1].map {|e_| simplify(e_) }]
when :array
["ary_new", *(exp[1] ? exp[1].map {|e_| simplify(e_) } : [])]
when :hash
kvs = ["hash_new"]
if exp[1]
exp[1][1].each do |e_|
key = simplify(e_[1])
val = simplify(e_[2])
kvs << key << val
end
end
kvs
when :void_stmt
["lit", nil]
when :paren
simplify(exp[1][0])
else
pp exp
raise "unsupported node: #{ exp[0] }"
end
end
|