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
data/lib/ast/nodes.rb
CHANGED
@@ -3,55 +3,344 @@ module Ikra
|
|
3
3
|
class Node
|
4
4
|
attr_accessor :parent
|
5
5
|
|
6
|
+
def eql?(other)
|
7
|
+
return self == other
|
8
|
+
end
|
9
|
+
|
10
|
+
def ==(other)
|
11
|
+
return self.class == other.class
|
12
|
+
end
|
13
|
+
|
14
|
+
def hash
|
15
|
+
return 1231
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class ProgramNode < Node
|
20
|
+
# First block is program entry point
|
21
|
+
attr_reader :blocks
|
22
|
+
attr_reader :classes
|
23
|
+
|
24
|
+
def initialize(blocks: [], classes: [])
|
25
|
+
@blocks = blocks
|
26
|
+
@classes = classes
|
27
|
+
end
|
28
|
+
|
29
|
+
def clone
|
30
|
+
return ProgramNode.new(
|
31
|
+
blocks: @blocks.map do |b| b.clone end,
|
32
|
+
classes: @classes.map do |c| c.clone end)
|
33
|
+
end
|
34
|
+
|
35
|
+
def ==(other)
|
36
|
+
return super(other) && blocks == other.blocks && classes == other.classes
|
37
|
+
end
|
38
|
+
|
39
|
+
def hash
|
40
|
+
return (blocks.hash + classes.hash) % 4524321
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class ClassDefNode < Node
|
45
|
+
attr_reader :name
|
46
|
+
attr_reader :instance_variables
|
47
|
+
attr_reader :instance_methods
|
48
|
+
attr_reader :ruby_class
|
49
|
+
|
50
|
+
# Class variables/methods are defined as instance variables/methods on the singleton
|
51
|
+
# class ClassDefNode
|
52
|
+
|
53
|
+
def initialize(
|
54
|
+
name:,
|
55
|
+
ruby_class:,
|
56
|
+
instance_variables: [],
|
57
|
+
instance_methods: [],
|
58
|
+
class_variables: [],
|
59
|
+
class_methods: [])
|
60
|
+
@name = name
|
61
|
+
@ruby_class = ruby_class
|
62
|
+
@instance_variables = instance_variables
|
63
|
+
@instance_methods = instance_methods
|
64
|
+
end
|
65
|
+
|
66
|
+
def clone
|
67
|
+
return ClassDefNode.new(
|
68
|
+
name: @name,
|
69
|
+
ruby_class: @ruby_class,
|
70
|
+
instance_variables: @instance_variables.map do |i| i.clone end,
|
71
|
+
instance_methods: @instance_methods.map do |i| i.clone end,
|
72
|
+
class_variables: @class_variables.map do |c| c.clone end,
|
73
|
+
class_methods: @class_methods.map do |c| c.clone end)
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_instance_variable(inst_var)
|
77
|
+
instance_variables.push(inst_var)
|
78
|
+
inst_meth.parent = self
|
79
|
+
end
|
80
|
+
|
81
|
+
def add_instance_method(inst_meth)
|
82
|
+
instance_methods.push(inst_meth)
|
83
|
+
inst_meth.parent = self
|
84
|
+
end
|
85
|
+
|
86
|
+
def has_instance_method?(selector)
|
87
|
+
return instance_method(selector) != nil
|
88
|
+
end
|
89
|
+
|
90
|
+
def instance_method(selector)
|
91
|
+
return instance_methods.find do |meth|
|
92
|
+
meth.name == selector
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def enclosing_class
|
97
|
+
return self
|
98
|
+
end
|
99
|
+
|
100
|
+
def ==(other)
|
101
|
+
return super(other) &&
|
102
|
+
name == other.name &&
|
103
|
+
ruby_class == other.ruby_class &&
|
104
|
+
instance_variables == other.instance_variables &&
|
105
|
+
instance_methods == other.instance_methods &&
|
106
|
+
class_variables == other.class_variables &&
|
107
|
+
class_methods == other.class_methods
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class VarDefNode < Node
|
112
|
+
attr_reader :name
|
113
|
+
attr_accessor :read
|
114
|
+
attr_accessor :written
|
115
|
+
|
116
|
+
def initialize(name:, read: false, written: false)
|
117
|
+
@name = name
|
118
|
+
@read = read
|
119
|
+
@written = written
|
120
|
+
end
|
121
|
+
|
122
|
+
def clone
|
123
|
+
return VarDefNode.new(
|
124
|
+
name: @name,
|
125
|
+
read: @read,
|
126
|
+
written: @written)
|
127
|
+
end
|
128
|
+
|
129
|
+
def ==(other)
|
130
|
+
return super(other) &&
|
131
|
+
name == other.name &&
|
132
|
+
read == other.read &&
|
133
|
+
written == other.written
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
class BehaviorNode < Node
|
138
|
+
def find_behavior_node
|
139
|
+
return self
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
class MethDefNode < BehaviorNode
|
144
|
+
attr_reader :name
|
145
|
+
attr_reader :ruby_method
|
146
|
+
attr_reader :body
|
147
|
+
|
148
|
+
def initialize(name:, body:, ruby_method:, method_binding: nil)
|
149
|
+
@name = name
|
150
|
+
@body = body
|
151
|
+
@ruby_method = ruby_method
|
152
|
+
@binding = method_binding
|
153
|
+
|
154
|
+
body.parent = self
|
155
|
+
end
|
156
|
+
|
157
|
+
def clone
|
158
|
+
return MethodDefNode.new(
|
159
|
+
name: @name,
|
160
|
+
body: @body.clone,
|
161
|
+
ruby_method: @ruby_method)
|
162
|
+
end
|
163
|
+
|
164
|
+
def binding
|
165
|
+
if @binding != nil
|
166
|
+
return @binding
|
167
|
+
elsif ruby_method == nil
|
168
|
+
return nil
|
169
|
+
else
|
170
|
+
return ruby_method.send(:binding)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def ==(other)
|
175
|
+
return super(other) && name == other.name && body == other.body
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
class BlockDefNode < BehaviorNode
|
180
|
+
attr_reader :body
|
181
|
+
attr_reader :ruby_block
|
182
|
+
attr_reader :parameters
|
183
|
+
|
184
|
+
def initialize(body:, ruby_block:, parameters: nil)
|
185
|
+
@body = body
|
186
|
+
@ruby_block = ruby_block
|
187
|
+
@parameters = parameters
|
188
|
+
|
189
|
+
body.parent = self
|
190
|
+
end
|
191
|
+
|
192
|
+
def clone
|
193
|
+
return BlockDefNode.new(
|
194
|
+
body: @body.clone,
|
195
|
+
ruby_block: @ruby_block,
|
196
|
+
parameters: @parameters == nil ? nil : @parameters.dup)
|
197
|
+
end
|
198
|
+
|
199
|
+
def binding
|
200
|
+
return ruby_block.binding
|
201
|
+
end
|
202
|
+
|
203
|
+
def ==(other)
|
204
|
+
return super(other) && body == other.body && parameters == other.parameters
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
class TreeNode < Node
|
6
209
|
def is_begin_node?
|
7
210
|
false
|
8
211
|
end
|
9
212
|
|
10
213
|
def replace(another_node)
|
214
|
+
# Sometimes, this method does not work as expected, if the `parent` of the `self`
|
215
|
+
# is already modified before calling this method.
|
11
216
|
parent.replace_child(self, another_node)
|
12
217
|
end
|
13
218
|
|
14
219
|
def replace_child(node, another_node)
|
15
220
|
instance_variables.each do |inst_var|
|
16
|
-
if instance_variable_get(inst_var)
|
221
|
+
if instance_variable_get(inst_var).equal?(node)
|
17
222
|
instance_variable_set(inst_var, another_node)
|
18
223
|
another_node.parent = self
|
19
224
|
end
|
20
225
|
end
|
21
226
|
end
|
22
227
|
|
23
|
-
def
|
24
|
-
@parent.
|
228
|
+
def enclosing_class
|
229
|
+
@parent.enclosing_class
|
230
|
+
end
|
231
|
+
|
232
|
+
def find_behavior_node
|
233
|
+
return parent.find_behavior_node
|
234
|
+
end
|
235
|
+
|
236
|
+
TYPE_INFO_VARS = [:@return_type_by_recv_type, :@type]
|
237
|
+
|
238
|
+
def ==(other)
|
239
|
+
if self.class != other.class
|
240
|
+
return false
|
241
|
+
end
|
242
|
+
|
243
|
+
# Ignore types
|
244
|
+
if (instance_variables - TYPE_INFO_VARS) != (other.instance_variables - TYPE_INFO_VARS)
|
245
|
+
|
246
|
+
return false
|
247
|
+
end
|
248
|
+
|
249
|
+
for var_name in instance_variables
|
250
|
+
if var_name != :@parent && !TYPE_INFO_VARS.include?(var_name)
|
251
|
+
# Avoid cycles via :parent... There could still be other cycles though
|
252
|
+
if instance_variable_get(var_name) != other.instance_variable_get(var_name)
|
253
|
+
return false
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
return true
|
25
259
|
end
|
26
260
|
end
|
27
|
-
|
28
|
-
class RootNode < Node
|
29
|
-
attr_reader :child
|
30
|
-
attr_accessor :class_owner # @return [Class] The class where this method is defined
|
31
261
|
|
32
|
-
|
33
|
-
|
34
|
-
|
262
|
+
# Need to wrap block bodies in RootNode, so that the first node can be replaced if necessary (LastStatementReturnsVisitor)
|
263
|
+
class RootNode < TreeNode
|
264
|
+
attr_reader :single_child
|
265
|
+
|
266
|
+
def initialize(single_child:)
|
267
|
+
@single_child = single_child
|
268
|
+
single_child.parent = self
|
269
|
+
end
|
270
|
+
|
271
|
+
def clone
|
272
|
+
return RootNode.new(single_child: @single_child.clone)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
class ArrayNode < TreeNode
|
277
|
+
attr_reader :values
|
278
|
+
|
279
|
+
def initialize(values:)
|
280
|
+
@values = values
|
281
|
+
|
282
|
+
for value in values
|
283
|
+
value.parent = self
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
def clone
|
288
|
+
return ArrayNode.new(
|
289
|
+
values: @values.map do |v| v.clone end)
|
35
290
|
end
|
36
291
|
end
|
37
292
|
|
38
|
-
|
293
|
+
# A synthetic AST node. Contains its string translation directly.
|
294
|
+
class SourceCodeExprNode < TreeNode
|
295
|
+
attr_reader :code
|
296
|
+
|
297
|
+
def initialize(code:)
|
298
|
+
@code = code
|
299
|
+
end
|
300
|
+
|
301
|
+
def clone
|
302
|
+
return SourceCodeExprNode.new(code: @code)
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
class HashNode < TreeNode
|
307
|
+
attr_reader :hash
|
308
|
+
|
309
|
+
def initialize(hash:)
|
310
|
+
@hash = hash
|
311
|
+
end
|
312
|
+
|
313
|
+
def clone
|
314
|
+
# TODO: Clone properly
|
315
|
+
return HashNode.new(hash: @hash.clone)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
class ConstNode < TreeNode
|
39
320
|
attr_reader :identifier
|
40
321
|
|
41
322
|
def initialize(identifier:)
|
42
323
|
@identifier = identifier
|
43
324
|
end
|
325
|
+
|
326
|
+
def clone
|
327
|
+
return ConstNode.new(identifier: @identifier)
|
328
|
+
end
|
44
329
|
end
|
45
330
|
|
46
|
-
class LVarReadNode <
|
331
|
+
class LVarReadNode < TreeNode
|
47
332
|
attr_reader :identifier
|
48
333
|
|
49
334
|
def initialize(identifier:)
|
50
335
|
@identifier = identifier
|
51
336
|
end
|
337
|
+
|
338
|
+
def clone
|
339
|
+
return LVarReadNode.new(identifier: @identifier)
|
340
|
+
end
|
52
341
|
end
|
53
342
|
|
54
|
-
class LVarWriteNode <
|
343
|
+
class LVarWriteNode < TreeNode
|
55
344
|
attr_reader :identifier
|
56
345
|
attr_reader :value
|
57
346
|
|
@@ -61,41 +350,91 @@ module Ikra
|
|
61
350
|
|
62
351
|
value.parent = self
|
63
352
|
end
|
353
|
+
|
354
|
+
def clone
|
355
|
+
return LVarWriteNode.new(
|
356
|
+
identifier: @identifier,
|
357
|
+
value: @value.clone)
|
358
|
+
end
|
64
359
|
end
|
65
360
|
|
66
|
-
class IVarReadNode <
|
361
|
+
class IVarReadNode < TreeNode
|
67
362
|
attr_reader :identifier
|
68
363
|
|
69
364
|
def initialize(identifier:)
|
70
365
|
@identifier = identifier
|
71
366
|
end
|
367
|
+
|
368
|
+
def clone
|
369
|
+
return IVarReadNode.new(identifier: @identifier)
|
370
|
+
end
|
72
371
|
end
|
73
372
|
|
74
|
-
class
|
373
|
+
class IntLiteralNode < TreeNode
|
75
374
|
attr_reader :value
|
76
375
|
|
77
376
|
def initialize(value:)
|
78
377
|
@value = value
|
79
378
|
end
|
379
|
+
|
380
|
+
def clone
|
381
|
+
return IntLiteralNode.new(value: @value)
|
382
|
+
end
|
80
383
|
end
|
81
384
|
|
82
|
-
class
|
385
|
+
class FloatLiteralNode < TreeNode
|
83
386
|
attr_reader :value
|
84
387
|
|
85
388
|
def initialize(value:)
|
86
389
|
@value = value
|
87
390
|
end
|
391
|
+
|
392
|
+
def clone
|
393
|
+
return FloatLiteralNode.new(value: @value)
|
394
|
+
end
|
88
395
|
end
|
89
396
|
|
90
|
-
class
|
397
|
+
class BoolLiteralNode < TreeNode
|
91
398
|
attr_reader :value
|
92
399
|
|
93
400
|
def initialize(value:)
|
94
401
|
@value = value
|
95
402
|
end
|
403
|
+
|
404
|
+
def clone
|
405
|
+
return BoolLiteralNode.new(value: @value)
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
class NilLiteralNode < TreeNode
|
410
|
+
|
96
411
|
end
|
97
412
|
|
98
|
-
class
|
413
|
+
class SymbolLiteralNode < TreeNode
|
414
|
+
attr_reader :value
|
415
|
+
|
416
|
+
def initialize(value:)
|
417
|
+
@value = value
|
418
|
+
end
|
419
|
+
|
420
|
+
def clone
|
421
|
+
return SymbolLiteralNode.new(value: @value)
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
class StringLiteralNode < TreeNode
|
426
|
+
attr_reader :value
|
427
|
+
|
428
|
+
def initialize(value:)
|
429
|
+
@value = value
|
430
|
+
end
|
431
|
+
|
432
|
+
def clone
|
433
|
+
return StringLiteralNode.new(value: @value)
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
class ForNode < TreeNode
|
99
438
|
attr_reader :iterator_identifier
|
100
439
|
attr_reader :range_from
|
101
440
|
attr_reader :range_to
|
@@ -111,32 +450,153 @@ module Ikra
|
|
111
450
|
range_to.parent = self
|
112
451
|
body_stmts.parent = self
|
113
452
|
end
|
453
|
+
|
454
|
+
def clone
|
455
|
+
return ForNode.new(
|
456
|
+
iterator_identifier: @iterator_identifier,
|
457
|
+
range_from: @range_from.clone,
|
458
|
+
range_to: @range_to.clone,
|
459
|
+
body_stmts: @body_stmts.clone)
|
460
|
+
end
|
114
461
|
end
|
115
462
|
|
116
|
-
class
|
463
|
+
class WhileNode < TreeNode
|
464
|
+
attr_reader :condition
|
465
|
+
attr_reader :body_stmts
|
466
|
+
|
467
|
+
def initialize(condition:, body_stmts:)
|
468
|
+
@condition = condition
|
469
|
+
@body_stmts = body_stmts
|
470
|
+
|
471
|
+
condition.parent = self
|
472
|
+
body_stmts.parent = self
|
473
|
+
end
|
474
|
+
|
475
|
+
def clone
|
476
|
+
return WhileNode.new(
|
477
|
+
condition: @condition.clone,
|
478
|
+
body_stmts: @body_stmts.clone)
|
479
|
+
end
|
480
|
+
end
|
117
481
|
|
482
|
+
class WhilePostNode < TreeNode
|
483
|
+
attr_reader :condition
|
484
|
+
attr_reader :body_stmts
|
485
|
+
|
486
|
+
def initialize(condition:, body_stmts:)
|
487
|
+
@condition = condition
|
488
|
+
@body_stmts = body_stmts
|
489
|
+
|
490
|
+
condition.parent = self
|
491
|
+
body_stmts.parent = self
|
492
|
+
end
|
493
|
+
|
494
|
+
def clone
|
495
|
+
return WhilePostNode.new(
|
496
|
+
condition: @condition.clone,
|
497
|
+
body_stmts: @body_stmts.clone)
|
498
|
+
end
|
118
499
|
end
|
119
500
|
|
120
|
-
class
|
501
|
+
class UntilNode < TreeNode
|
502
|
+
attr_reader :condition
|
503
|
+
attr_reader :body_stmts
|
504
|
+
|
505
|
+
def initialize(condition:, body_stmts:)
|
506
|
+
@condition = condition
|
507
|
+
@body_stmts = body_stmts
|
508
|
+
|
509
|
+
condition.parent = self
|
510
|
+
body_stmts.parent = self
|
511
|
+
end
|
512
|
+
|
513
|
+
def clone
|
514
|
+
return UntilNode.new(
|
515
|
+
condition: @condition.clone,
|
516
|
+
body_stmts: @body_stmts.clone)
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
class UntilPostNode < TreeNode
|
521
|
+
attr_reader :condition
|
522
|
+
attr_reader :body_stmts
|
523
|
+
|
524
|
+
def initialize(condition:, body_stmts:)
|
525
|
+
@condition = condition
|
526
|
+
@body_stmts = body_stmts
|
527
|
+
|
528
|
+
condition.parent = self
|
529
|
+
body_stmts.parent = self
|
530
|
+
end
|
531
|
+
|
532
|
+
def clone
|
533
|
+
return UntilPostNode.new(
|
534
|
+
condition: @condition.clone,
|
535
|
+
body_stmts: @body_stmts.clone)
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
class BreakNode < TreeNode
|
540
|
+
|
541
|
+
end
|
542
|
+
|
543
|
+
class IfNode < TreeNode
|
121
544
|
attr_reader :condition
|
122
545
|
attr_reader :true_body_stmts
|
123
546
|
attr_reader :false_body_stmts
|
124
547
|
|
125
548
|
def initialize(condition:, true_body_stmts:, false_body_stmts: nil)
|
549
|
+
if true_body_stmts == nil
|
550
|
+
# Handle empty `true` block
|
551
|
+
true_body_stmts = BeginNode.new
|
552
|
+
end
|
553
|
+
|
554
|
+
if false_body_stmts == nil
|
555
|
+
# Handle empty `false` block
|
556
|
+
false_body_stmts = BeginNode.new
|
557
|
+
end
|
558
|
+
|
126
559
|
@condition = condition
|
127
560
|
@true_body_stmts = true_body_stmts
|
128
561
|
@false_body_stmts = false_body_stmts
|
129
562
|
|
130
563
|
condition.parent = self
|
131
|
-
true_body_stmts.parent = self
|
564
|
+
true_body_stmts.parent = self
|
565
|
+
false_body_stmts.parent = self
|
566
|
+
end
|
132
567
|
|
133
|
-
|
134
|
-
|
135
|
-
|
568
|
+
def clone
|
569
|
+
return IfNode.new(
|
570
|
+
condition: @condition.clone,
|
571
|
+
true_body_stmts: @true_body_stmts.clone,
|
572
|
+
false_body_stmts: @false_body_stmts.clone)
|
136
573
|
end
|
137
574
|
end
|
138
575
|
|
139
|
-
class
|
576
|
+
class TernaryNode < TreeNode
|
577
|
+
attr_reader :condition
|
578
|
+
attr_reader :true_val
|
579
|
+
attr_reader :false_val
|
580
|
+
|
581
|
+
def initialize(condition:, true_val:, false_val:)
|
582
|
+
@condition = condition
|
583
|
+
@true_val = true_val
|
584
|
+
@false_val = false_val
|
585
|
+
|
586
|
+
condition.parent = self
|
587
|
+
true_val.parent = self
|
588
|
+
false_val.parent = self
|
589
|
+
end
|
590
|
+
|
591
|
+
def clone
|
592
|
+
return TernaryNode.new(
|
593
|
+
condition: @condition.clone,
|
594
|
+
true_val: @true_val.clone,
|
595
|
+
false_val: @false_val.clone)
|
596
|
+
end
|
597
|
+
end
|
598
|
+
|
599
|
+
class BeginNode < TreeNode
|
140
600
|
attr_reader :body_stmts
|
141
601
|
|
142
602
|
def initialize(body_stmts: [])
|
@@ -146,10 +606,20 @@ module Ikra
|
|
146
606
|
stmt.parent = self
|
147
607
|
end
|
148
608
|
end
|
609
|
+
|
610
|
+
def clone
|
611
|
+
return BeginNode.new(
|
612
|
+
body_stmts: @body_stmts.map do |s| s.clone end)
|
613
|
+
end
|
614
|
+
|
615
|
+
def add_statement(node)
|
616
|
+
body_stmts.push(node)
|
617
|
+
node.parent = self
|
618
|
+
end
|
149
619
|
|
150
620
|
def replace_child(node, another_node)
|
151
621
|
@body_stmts = @body_stmts.map do |stmt|
|
152
|
-
if node
|
622
|
+
if node.equal?(stmt)
|
153
623
|
another_node.parent = self
|
154
624
|
another_node
|
155
625
|
else
|
@@ -163,15 +633,17 @@ module Ikra
|
|
163
633
|
end
|
164
634
|
end
|
165
635
|
|
166
|
-
class SendNode <
|
636
|
+
class SendNode < TreeNode
|
167
637
|
attr_reader :receiver
|
168
638
|
attr_reader :selector
|
169
639
|
attr_reader :arguments
|
640
|
+
attr_reader :block_argument
|
170
641
|
|
171
|
-
def initialize(receiver:, selector:, arguments: [])
|
642
|
+
def initialize(receiver:, selector:, arguments: [], block_argument: nil)
|
172
643
|
@receiver = receiver
|
173
644
|
@selector = selector
|
174
645
|
@arguments = arguments
|
646
|
+
@block_argument = block_argument
|
175
647
|
|
176
648
|
receiver.parent = self
|
177
649
|
arguments.each do |arg|
|
@@ -179,13 +651,22 @@ module Ikra
|
|
179
651
|
end
|
180
652
|
end
|
181
653
|
|
654
|
+
def clone
|
655
|
+
return SendNode.new(
|
656
|
+
receiver: @receiver.clone,
|
657
|
+
selector: @selector,
|
658
|
+
arguments: @arguments.map do |a| a.clone end,
|
659
|
+
block_argument: block_argument == nil ? nil : block_argument.clone)
|
660
|
+
end
|
661
|
+
|
182
662
|
def replace_child(node, another_node)
|
183
|
-
if @receiver
|
663
|
+
if @receiver.equal?(node)
|
184
664
|
@receiver = another_node
|
665
|
+
another_node.parent = self
|
185
666
|
end
|
186
667
|
|
187
668
|
@arguments = @arguments.map do |arg|
|
188
|
-
if node
|
669
|
+
if node.equal?(arg)
|
189
670
|
another_node.parent = self
|
190
671
|
another_node
|
191
672
|
else
|
@@ -193,9 +674,14 @@ module Ikra
|
|
193
674
|
end
|
194
675
|
end
|
195
676
|
end
|
677
|
+
|
678
|
+
# Setter required for [HostSectionBuilder]
|
679
|
+
def block_argument=(value)
|
680
|
+
@block_argument = value
|
681
|
+
end
|
196
682
|
end
|
197
683
|
|
198
|
-
class ReturnNode <
|
684
|
+
class ReturnNode < TreeNode
|
199
685
|
attr_reader :value
|
200
686
|
|
201
687
|
def initialize(value:)
|
@@ -203,6 +689,10 @@ module Ikra
|
|
203
689
|
|
204
690
|
value.parent = self
|
205
691
|
end
|
692
|
+
|
693
|
+
def clone
|
694
|
+
return ReturnNode.new(value: value.clone)
|
695
|
+
end
|
206
696
|
end
|
207
697
|
end
|
208
698
|
end
|