ikra 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/ast/builder.rb +225 -77
- data/lib/ast/host_section_builder.rb +38 -0
- data/lib/ast/interpreter.rb +67 -0
- data/lib/ast/lexical_variables_enumerator.rb +3 -2
- data/lib/ast/nodes.rb +521 -31
- data/lib/ast/printer.rb +116 -18
- data/lib/ast/ssa_generator.rb +192 -0
- data/lib/ast/visitor.rb +235 -21
- data/lib/config/configuration.rb +28 -3
- data/lib/config/os_configuration.rb +62 -9
- data/lib/cpu/cpu_implementation.rb +39 -0
- data/lib/ikra.rb +13 -3
- data/lib/resources/cuda/allocate_device_memory.cpp +5 -0
- data/lib/resources/cuda/allocate_host_memory.cpp +1 -0
- data/lib/resources/cuda/allocate_memcpy_environment_to_device.cpp +11 -0
- data/lib/resources/cuda/ast/assignment.cpp +1 -0
- data/lib/resources/cuda/block_function_head.cpp +7 -1
- data/lib/resources/cuda/entry_point.cpp +47 -0
- data/lib/resources/cuda/env_builder_copy_array.cpp +8 -2
- data/lib/resources/cuda/free_device_memory.cpp +3 -0
- data/lib/resources/cuda/free_memory_for_command.cpp +24 -0
- data/lib/resources/cuda/header.cpp +23 -9
- data/lib/resources/cuda/header_structs.cpp +92 -0
- data/lib/resources/cuda/host_section_block_function_head.cpp +12 -0
- data/lib/resources/cuda/host_section_entry_point.cpp +55 -0
- data/lib/resources/cuda/host_section_free_device_memory.cpp +18 -0
- data/lib/resources/cuda/host_section_launch_parallel_section.cpp +14 -0
- data/lib/resources/cuda/host_section_malloc_memcpy_device_to_host.cpp +10 -0
- data/lib/resources/cuda/kernel.cpp +9 -2
- data/lib/resources/cuda/launch_kernel.cpp +5 -0
- data/lib/resources/cuda/memcpy_device_to_host.cpp +3 -0
- data/lib/resources/cuda/memcpy_device_to_host_expr.cpp +10 -0
- data/lib/resources/cuda/reduce_body.cpp +88 -0
- data/lib/resources/cuda/stencil_array_reconstruction.cpp +2 -0
- data/lib/resources/cuda/stencil_body.cpp +16 -0
- data/lib/resources/cuda/struct_definition.cpp +4 -0
- data/lib/ruby_core/array.rb +34 -0
- data/lib/ruby_core/array_command.rb +313 -0
- data/lib/ruby_core/core.rb +103 -0
- data/lib/ruby_core/interpreter.rb +16 -0
- data/lib/ruby_core/math.rb +32 -0
- data/lib/ruby_core/ruby_integration.rb +256 -0
- data/lib/symbolic/host_section.rb +115 -0
- data/lib/symbolic/input.rb +87 -0
- data/lib/symbolic/input_visitor.rb +68 -0
- data/lib/symbolic/symbolic.rb +793 -117
- data/lib/symbolic/visitor.rb +70 -8
- data/lib/translator/array_command_struct_builder.rb +163 -0
- data/lib/translator/ast_translator.rb +572 -0
- data/lib/translator/block_translator.rb +104 -48
- data/lib/translator/commands/array_combine_command.rb +41 -0
- data/lib/translator/commands/array_identity_command.rb +28 -0
- data/lib/translator/commands/array_index_command.rb +52 -0
- data/lib/translator/commands/array_reduce_command.rb +135 -0
- data/lib/translator/commands/array_stencil_command.rb +129 -0
- data/lib/translator/commands/array_zip_command.rb +30 -0
- data/lib/translator/commands/command_translator.rb +264 -0
- data/lib/translator/cuda_errors.rb +32 -0
- data/lib/translator/environment_builder.rb +263 -0
- data/lib/translator/host_section/array_host_section_command.rb +150 -0
- data/lib/translator/host_section/array_in_host_section_command.rb +41 -0
- data/lib/translator/host_section/ast_translator.rb +14 -0
- data/lib/translator/host_section/parallel_section_invocation_visitor.rb +20 -0
- data/lib/translator/host_section/program_builder.rb +89 -0
- data/lib/translator/input_translator.rb +226 -0
- data/lib/translator/kernel_builder.rb +137 -0
- data/lib/translator/kernel_launcher/for_loop_kernel_launcher.rb +40 -0
- data/lib/translator/kernel_launcher/kernel_launcher.rb +259 -0
- data/lib/translator/kernel_launcher/while_loop_kernel_launcher.rb +38 -0
- data/lib/translator/last_returns_visitor.rb +19 -10
- data/lib/translator/program_builder.rb +197 -0
- data/lib/translator/program_launcher.rb +273 -0
- data/lib/translator/struct_type.rb +55 -0
- data/lib/translator/translator.rb +34 -11
- data/lib/translator/variable_classifier_visitor.rb +56 -0
- data/lib/types/inference/ast_inference.rb +586 -0
- data/lib/types/inference/clear_types_visitor.rb +11 -0
- data/lib/types/inference/command_inference.rb +101 -0
- data/lib/types/inference/input_inference.rb +62 -0
- data/lib/types/{object_tracer.rb → inference/object_tracer.rb} +5 -6
- data/lib/types/inference/ruby_extension.rb +35 -0
- data/lib/types/inference/symbol_table.rb +131 -0
- data/lib/types/types.rb +14 -0
- data/lib/types/types/array_command_type.rb +123 -0
- data/lib/types/types/array_type.rb +137 -0
- data/lib/types/{class_type.rb → types/class_type.rb} +42 -18
- data/lib/types/{primitive_type.rb → types/primitive_type.rb} +20 -7
- data/lib/types/types/ruby_type.rb +88 -0
- data/lib/types/types/struct_type.rb +179 -0
- data/lib/types/types/union_type.rb +239 -0
- metadata +160 -18
- data/lib/ast/method_definition.rb +0 -37
- data/lib/ast/translator.rb +0 -264
- data/lib/resources/cuda/kernel_launcher.cpp +0 -28
- data/lib/scope.rb +0 -166
- data/lib/translator/command_translator.rb +0 -421
- data/lib/translator/local_variables_enumerator.rb +0 -35
- data/lib/translator/method_translator.rb +0 -24
- data/lib/types/array_type.rb +0 -51
- data/lib/types/ruby_extension.rb +0 -67
- data/lib/types/ruby_type.rb +0 -45
- data/lib/types/type_inference.rb +0 -382
- data/lib/types/union_type.rb +0 -155
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fd8028a7dd6a39dd8762d70b31d08b036d4513cc
|
4
|
+
data.tar.gz: 7f64a61eb6b018859b6ae0b03734eb6f9c041798
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f26e50272fdf7c18b01a15ff3dad17e640e94eb1a3bf7ec9fdddb9eda709d1057277b291d05719490926741295b8a7d105a150089946bf5fd3fef20b254f3ef2
|
7
|
+
data.tar.gz: af61029cc2b3bb898eab63359241a8da4b445a3e658c4c1d406f9a4d0b860c6a17bec16ec4e553c894b57d96d1ceab08995f90d97c58dcc2defaf795c3d46055
|
data/lib/ast/builder.rb
CHANGED
@@ -3,98 +3,246 @@ require_relative "nodes"
|
|
3
3
|
module Ikra
|
4
4
|
module AST
|
5
5
|
|
6
|
-
# Builds an Ikra AST from a Parser RubyGem AST
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
# Builds an Ikra (Ruby) AST from a Parser RubyGem AST
|
7
|
+
class Builder
|
8
|
+
def self.from_parser_ast(node)
|
9
|
+
return self.new.from_parser_ast(node)
|
10
|
+
end
|
11
|
+
|
12
|
+
def from_parser_ast(node)
|
13
|
+
return RootNode.new(single_child: translate_node(node))
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
12
17
|
|
13
|
-
|
14
|
-
|
15
|
-
|
18
|
+
def wrap_in_begin(translated_node)
|
19
|
+
if translated_node != nil
|
20
|
+
if translated_node.is_a?(BeginNode)
|
21
|
+
# Is already a `BeginNode`
|
22
|
+
return translated_node
|
16
23
|
else
|
17
|
-
|
24
|
+
return BeginNode.new(body_stmts: [translated_node])
|
18
25
|
end
|
26
|
+
else
|
27
|
+
return nil
|
19
28
|
end
|
20
|
-
|
21
|
-
def translate_const(node)
|
22
|
-
# TODO: what is the meaning of the first child?
|
23
|
-
ConstNode.new(identifier: node.children[1])
|
24
|
-
end
|
29
|
+
end
|
25
30
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
LVarReadNode.new(identifier: node.children[0])
|
40
|
-
end
|
41
|
-
|
42
|
-
def translate_lvasgn(node)
|
43
|
-
LVarWriteNode.new(identifier: node.children[0], value: translate_node(node.children[1]))
|
44
|
-
end
|
45
|
-
|
46
|
-
def translate_ivar(node)
|
47
|
-
IVarReadNode.new(identifier: node.children[0])
|
31
|
+
def translate_node(node)
|
32
|
+
if node == nil
|
33
|
+
return nil
|
34
|
+
else
|
35
|
+
if node.is_a?(Array)
|
36
|
+
# An array of nodes
|
37
|
+
return node.map do |n|
|
38
|
+
send("translate_#{n.type.to_s.gsub("-", "_")}".to_sym, n)
|
39
|
+
end
|
40
|
+
else
|
41
|
+
# A single node
|
42
|
+
return send("translate_#{node.type.to_s.gsub("-", "_")}".to_sym, node)
|
43
|
+
end
|
48
44
|
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def translate_array(node)
|
48
|
+
return ArrayNode.new(values: node.children.map do |n| translate_node(n) end)
|
49
|
+
end
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
raise "Begin node contains more than one statement"
|
61
|
-
end
|
62
|
-
|
63
|
-
next_node = next_node.children[0]
|
51
|
+
def translate_const(node)
|
52
|
+
full_const_string = "#{node.children[1]}"
|
53
|
+
current_const = node
|
54
|
+
|
55
|
+
while current_const.children[0] != nil
|
56
|
+
# First receiver is enclosing class/module
|
57
|
+
current_const = current_const.children[0]
|
58
|
+
|
59
|
+
if current_const.type != :const
|
60
|
+
raise AssertionError.new("Expected :const")
|
64
61
|
end
|
65
|
-
|
66
|
-
|
62
|
+
|
63
|
+
full_const_string = current_const.children[1].to_s + "::" + full_const_string
|
67
64
|
end
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
65
|
+
|
66
|
+
return ConstNode.new(identifier: full_const_string)
|
67
|
+
end
|
68
|
+
|
69
|
+
def translate_int(node)
|
70
|
+
return IntLiteralNode.new(value: node.children[0])
|
71
|
+
end
|
72
|
+
|
73
|
+
def translate_float(node)
|
74
|
+
return FloatLiteralNode.new(value: node.children[0])
|
75
|
+
end
|
76
|
+
|
77
|
+
def translate_bool(node)
|
78
|
+
return BoolLiteralNode.new(value: node.children[0])
|
79
|
+
end
|
80
|
+
|
81
|
+
def translate_true(node)
|
82
|
+
return BoolLiteralNode.new(value: true)
|
83
|
+
end
|
84
|
+
|
85
|
+
def translate_false(node)
|
86
|
+
return BoolLiteralNode.new(value: false)
|
87
|
+
end
|
88
|
+
|
89
|
+
def translate_nil(node)
|
90
|
+
return NilLiteralNode.new
|
91
|
+
end
|
92
|
+
|
93
|
+
def translate_sym(node)
|
94
|
+
return SymbolLiteralNode.new(value: node.children[0])
|
95
|
+
end
|
96
|
+
|
97
|
+
def translate_str(node)
|
98
|
+
return StringLiteralNode.new(value: node.children[0])
|
99
|
+
end
|
100
|
+
|
101
|
+
def translate_hash(node)
|
102
|
+
hash = {}
|
103
|
+
|
104
|
+
node.children.each do |child|
|
105
|
+
if child.type != :pair
|
106
|
+
raise NotImplementedError.new("Expected :pair, found #{child.type}")
|
79
107
|
end
|
108
|
+
|
109
|
+
hash[translate_node(child.children[0])] = translate_node(child.children[1])
|
80
110
|
end
|
81
|
-
|
82
|
-
|
83
|
-
|
111
|
+
|
112
|
+
return HashNode.new(hash: hash)
|
113
|
+
end
|
114
|
+
|
115
|
+
def translate_and(node)
|
116
|
+
return SendNode.new(receiver: translate_node(node.children[0]),
|
117
|
+
selector: :"&&",
|
118
|
+
arguments: [translate_node(node.children[1])])
|
119
|
+
end
|
120
|
+
|
121
|
+
def translate_or(node)
|
122
|
+
return SendNode.new(receiver: translate_node(node.children[0]),
|
123
|
+
selector: :"||",
|
124
|
+
arguments: [translate_node(node.children[1])])
|
125
|
+
end
|
126
|
+
|
127
|
+
def translate_lvar(node)
|
128
|
+
return LVarReadNode.new(identifier: node.children[0])
|
129
|
+
end
|
130
|
+
|
131
|
+
def translate_lvasgn(node)
|
132
|
+
return LVarWriteNode.new(identifier: node.children[0], value: translate_node(node.children[1]))
|
133
|
+
end
|
134
|
+
|
135
|
+
def translate_ivar(node)
|
136
|
+
return IVarReadNode.new(identifier: node.children[0])
|
137
|
+
end
|
138
|
+
|
139
|
+
def translate_if(node)
|
140
|
+
return IfNode.new(condition: translate_node(node.children[0]),
|
141
|
+
true_body_stmts: wrap_in_begin(translate_node(node.children[1])),
|
142
|
+
false_body_stmts: wrap_in_begin(translate_node(node.children[2])))
|
143
|
+
end
|
144
|
+
|
145
|
+
def extract_begin_single_statement(node, should_return = false)
|
146
|
+
next_node = node
|
147
|
+
while next_node.type == :begin
|
148
|
+
if next_node.children.size != 1
|
149
|
+
raise AssertionError.new("Begin node contains more than one statement")
|
150
|
+
end
|
151
|
+
|
152
|
+
next_node = next_node.children[0]
|
84
153
|
end
|
85
154
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
155
|
+
return next_node
|
156
|
+
end
|
157
|
+
|
158
|
+
def translate_for(node)
|
159
|
+
if node.children[0].type == :lvasgn and extract_begin_single_statement(node.children[1]).type == :irange
|
160
|
+
range = extract_begin_single_statement(node.children[1])
|
161
|
+
|
162
|
+
return ForNode.new(iterator_identifier: node.children[0].children[0],
|
163
|
+
range_from: translate_node(range.children[0]),
|
164
|
+
range_to: translate_node(range.children[1]),
|
165
|
+
body_stmts: wrap_in_begin(translate_node(node.children[2])))
|
166
|
+
elsif node.children[0].type == :lvasgn and extract_begin_single_statement(node.children[1]).type == :erange
|
167
|
+
# Convert exclusive range to inclusive range
|
168
|
+
range = extract_begin_single_statement(node.children[1])
|
169
|
+
range_to = translate_node(range.children[1])
|
170
|
+
range_to_inclusive = SendNode.new(
|
171
|
+
receiver: range_to,
|
172
|
+
selector: :-,
|
173
|
+
arguments: [IntLiteralNode.new(value: 1)])
|
174
|
+
|
175
|
+
return ForNode.new(iterator_identifier: node.children[0].children[0],
|
176
|
+
range_from: translate_node(range.children[0]),
|
177
|
+
range_to: range_to_inclusive,
|
178
|
+
body_stmts: wrap_in_begin(translate_node(node.children[2])))
|
179
|
+
else
|
180
|
+
raise NotImplementedError.new("Can only handle simple For loops at the moment")
|
91
181
|
end
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
182
|
+
end
|
183
|
+
|
184
|
+
def translate_while(node)
|
185
|
+
return WhileNode.new(
|
186
|
+
condition: translate_node(node.children[0]),
|
187
|
+
body_stmts: wrap_in_begin(translate_node(node.children[1])))
|
188
|
+
end
|
189
|
+
|
190
|
+
def translate_while_post(node)
|
191
|
+
return WhilePostNode.new(
|
192
|
+
condition: translate_node(node.children[0]),
|
193
|
+
body_stmts: wrap_in_begin(translate_node(node.children[1])))
|
194
|
+
end
|
195
|
+
|
196
|
+
def translate_until(node)
|
197
|
+
return UntilNode.new(
|
198
|
+
condition: (SendNode.new(receiver: translate_node(node.children[0]),
|
199
|
+
selector: :^,
|
200
|
+
arguments: [BoolLiteralNode.new(value: true)])),
|
201
|
+
body_stmts: wrap_in_begin(translate_node(node.children[1])))
|
202
|
+
end
|
203
|
+
|
204
|
+
def translate_until_post(node)
|
205
|
+
return UntilPostNode.new(
|
206
|
+
condition: (SendNode.new(receiver: translate_node(node.children[0]),
|
207
|
+
selector: :^,
|
208
|
+
arguments: [BoolLiteralNode.new(value: true)])),
|
209
|
+
body_stmts: wrap_in_begin(translate_node(node.children[1])))
|
210
|
+
end
|
211
|
+
|
212
|
+
def translate_break(node)
|
213
|
+
return BreakNode.new
|
214
|
+
end
|
215
|
+
|
216
|
+
def translate_return(node)
|
217
|
+
return ReturnNode.new(value: translate_node(node.children[0]))
|
218
|
+
end
|
219
|
+
|
220
|
+
def translate_send(node)
|
221
|
+
receiver = nil
|
222
|
+
|
223
|
+
if node.children[0] == nil
|
224
|
+
# Implicit receiver
|
225
|
+
# TODO: Assuming Object for now, but this is not always correct
|
226
|
+
receiver = ConstNode.new(identifier: :Object)
|
227
|
+
else
|
228
|
+
receiver = translate_node(node.children[0])
|
96
229
|
end
|
230
|
+
|
231
|
+
return SendNode.new(receiver: receiver,
|
232
|
+
selector: node.children[1],
|
233
|
+
arguments: node.children[2..-1].map do |arg|
|
234
|
+
translate_node(arg) end)
|
235
|
+
end
|
236
|
+
|
237
|
+
def translate_begin(node)
|
238
|
+
return BeginNode.new(body_stmts: node.children.map do |stmt|
|
239
|
+
translate_node(stmt) end)
|
240
|
+
end
|
241
|
+
|
242
|
+
def translate_kwbegin(node)
|
243
|
+
return BeginNode.new(body_stmts: node.children.map do |stmt|
|
244
|
+
translate_node(stmt) end)
|
97
245
|
end
|
98
246
|
end
|
99
247
|
end
|
100
|
-
end
|
248
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Ikra
|
2
|
+
module AST
|
3
|
+
class HostSectionBuilder < Builder
|
4
|
+
|
5
|
+
protected
|
6
|
+
|
7
|
+
def translate_block(node)
|
8
|
+
if node.children[0].type != :send
|
9
|
+
raise AssertionError.new("Unknown AST construct: Send node expected")
|
10
|
+
end
|
11
|
+
|
12
|
+
send_node = node.children[0]
|
13
|
+
built_block_node = BlockDefNode.new(
|
14
|
+
body: translate_node(node.children[2]),
|
15
|
+
parameters: translate_node(node.children[1]),
|
16
|
+
ruby_block: nil)
|
17
|
+
|
18
|
+
if send_node.children[0] == nil && send_node.children[1] == :proc
|
19
|
+
# Defining a stand-alone block
|
20
|
+
return built_block_node
|
21
|
+
else
|
22
|
+
# Block should be part of a message send
|
23
|
+
built_send_node = translate_node(send_node)
|
24
|
+
built_send_node.block_argument = built_block_node
|
25
|
+
return built_send_node
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def translate_args(node)
|
30
|
+
return translate_node(node.children)
|
31
|
+
end
|
32
|
+
|
33
|
+
def translate_arg(node)
|
34
|
+
return node.children.first
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Ikra
|
2
|
+
module AST
|
3
|
+
# Executes this AST in the Ruby interpreter. Not possible for all nodes.
|
4
|
+
class Interpreter < Visitor
|
5
|
+
def self.interpret(node)
|
6
|
+
return node.accept(self.new)
|
7
|
+
end
|
8
|
+
|
9
|
+
def visit_int_node(node)
|
10
|
+
return node.value
|
11
|
+
end
|
12
|
+
|
13
|
+
def visit_float_node(node)
|
14
|
+
return node.value
|
15
|
+
end
|
16
|
+
|
17
|
+
def visit_bool_node(node)
|
18
|
+
return node.value
|
19
|
+
end
|
20
|
+
|
21
|
+
def visit_nil_node(node)
|
22
|
+
return nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def visit_symbol_node(node)
|
26
|
+
return node.value
|
27
|
+
end
|
28
|
+
|
29
|
+
def visit_string_node(node)
|
30
|
+
return node.value
|
31
|
+
end
|
32
|
+
|
33
|
+
def visit_array_node(node)
|
34
|
+
return node.values.map do |value|
|
35
|
+
value.accept(self)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def visit_const_node(node)
|
40
|
+
return node.find_behavior_node.binding.eval(node.identifier)
|
41
|
+
end
|
42
|
+
|
43
|
+
def visit_hash_node(node)
|
44
|
+
result = {}
|
45
|
+
|
46
|
+
node.hash.each do |key, value|
|
47
|
+
result[key.accept(self)] = value.accept(self)
|
48
|
+
end
|
49
|
+
|
50
|
+
return result
|
51
|
+
end
|
52
|
+
|
53
|
+
def visit_send_node(node)
|
54
|
+
receiver = node.receiver.accept(self)
|
55
|
+
arguments = node.arguments.map do |arg| arg.accept(self) end
|
56
|
+
|
57
|
+
if node.block_argument == nil
|
58
|
+
return receiver.send(node.selector, *arguments)
|
59
|
+
else
|
60
|
+
# TODO: Implement
|
61
|
+
block = receiver.block_argument.accept(self)
|
62
|
+
return receiver.send(node.selector, *arguments, &block)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -5,8 +5,8 @@ require_relative "visitor"
|
|
5
5
|
module Ikra
|
6
6
|
module AST
|
7
7
|
|
8
|
-
# Visitor for determining the names all lexical variables that are accessed by a block (or method??)
|
9
|
-
# TODO:
|
8
|
+
# Visitor for determining the names all lexical variables that are accessed by a block (or method??). Lexical variables that are in scope are determined when translating the Ruby code and passed to this visitor.
|
9
|
+
# TODO(matthias): Does a method have access to lexical variables?
|
10
10
|
class LexicalVariablesEnumerator < Visitor
|
11
11
|
attr_reader :lexical_variables
|
12
12
|
|
@@ -15,6 +15,7 @@ module Ikra
|
|
15
15
|
@lexical_variables = Set.new
|
16
16
|
end
|
17
17
|
|
18
|
+
# Register usage of lexical variable
|
18
19
|
def add_lvar_access(identifier)
|
19
20
|
if @lexical_var_names.include?(identifier)
|
20
21
|
@lexical_variables.add(identifier)
|