ikra 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ast/builder.rb +225 -77
  3. data/lib/ast/host_section_builder.rb +38 -0
  4. data/lib/ast/interpreter.rb +67 -0
  5. data/lib/ast/lexical_variables_enumerator.rb +3 -2
  6. data/lib/ast/nodes.rb +521 -31
  7. data/lib/ast/printer.rb +116 -18
  8. data/lib/ast/ssa_generator.rb +192 -0
  9. data/lib/ast/visitor.rb +235 -21
  10. data/lib/config/configuration.rb +28 -3
  11. data/lib/config/os_configuration.rb +62 -9
  12. data/lib/cpu/cpu_implementation.rb +39 -0
  13. data/lib/ikra.rb +13 -3
  14. data/lib/resources/cuda/allocate_device_memory.cpp +5 -0
  15. data/lib/resources/cuda/allocate_host_memory.cpp +1 -0
  16. data/lib/resources/cuda/allocate_memcpy_environment_to_device.cpp +11 -0
  17. data/lib/resources/cuda/ast/assignment.cpp +1 -0
  18. data/lib/resources/cuda/block_function_head.cpp +7 -1
  19. data/lib/resources/cuda/entry_point.cpp +47 -0
  20. data/lib/resources/cuda/env_builder_copy_array.cpp +8 -2
  21. data/lib/resources/cuda/free_device_memory.cpp +3 -0
  22. data/lib/resources/cuda/free_memory_for_command.cpp +24 -0
  23. data/lib/resources/cuda/header.cpp +23 -9
  24. data/lib/resources/cuda/header_structs.cpp +92 -0
  25. data/lib/resources/cuda/host_section_block_function_head.cpp +12 -0
  26. data/lib/resources/cuda/host_section_entry_point.cpp +55 -0
  27. data/lib/resources/cuda/host_section_free_device_memory.cpp +18 -0
  28. data/lib/resources/cuda/host_section_launch_parallel_section.cpp +14 -0
  29. data/lib/resources/cuda/host_section_malloc_memcpy_device_to_host.cpp +10 -0
  30. data/lib/resources/cuda/kernel.cpp +9 -2
  31. data/lib/resources/cuda/launch_kernel.cpp +5 -0
  32. data/lib/resources/cuda/memcpy_device_to_host.cpp +3 -0
  33. data/lib/resources/cuda/memcpy_device_to_host_expr.cpp +10 -0
  34. data/lib/resources/cuda/reduce_body.cpp +88 -0
  35. data/lib/resources/cuda/stencil_array_reconstruction.cpp +2 -0
  36. data/lib/resources/cuda/stencil_body.cpp +16 -0
  37. data/lib/resources/cuda/struct_definition.cpp +4 -0
  38. data/lib/ruby_core/array.rb +34 -0
  39. data/lib/ruby_core/array_command.rb +313 -0
  40. data/lib/ruby_core/core.rb +103 -0
  41. data/lib/ruby_core/interpreter.rb +16 -0
  42. data/lib/ruby_core/math.rb +32 -0
  43. data/lib/ruby_core/ruby_integration.rb +256 -0
  44. data/lib/symbolic/host_section.rb +115 -0
  45. data/lib/symbolic/input.rb +87 -0
  46. data/lib/symbolic/input_visitor.rb +68 -0
  47. data/lib/symbolic/symbolic.rb +793 -117
  48. data/lib/symbolic/visitor.rb +70 -8
  49. data/lib/translator/array_command_struct_builder.rb +163 -0
  50. data/lib/translator/ast_translator.rb +572 -0
  51. data/lib/translator/block_translator.rb +104 -48
  52. data/lib/translator/commands/array_combine_command.rb +41 -0
  53. data/lib/translator/commands/array_identity_command.rb +28 -0
  54. data/lib/translator/commands/array_index_command.rb +52 -0
  55. data/lib/translator/commands/array_reduce_command.rb +135 -0
  56. data/lib/translator/commands/array_stencil_command.rb +129 -0
  57. data/lib/translator/commands/array_zip_command.rb +30 -0
  58. data/lib/translator/commands/command_translator.rb +264 -0
  59. data/lib/translator/cuda_errors.rb +32 -0
  60. data/lib/translator/environment_builder.rb +263 -0
  61. data/lib/translator/host_section/array_host_section_command.rb +150 -0
  62. data/lib/translator/host_section/array_in_host_section_command.rb +41 -0
  63. data/lib/translator/host_section/ast_translator.rb +14 -0
  64. data/lib/translator/host_section/parallel_section_invocation_visitor.rb +20 -0
  65. data/lib/translator/host_section/program_builder.rb +89 -0
  66. data/lib/translator/input_translator.rb +226 -0
  67. data/lib/translator/kernel_builder.rb +137 -0
  68. data/lib/translator/kernel_launcher/for_loop_kernel_launcher.rb +40 -0
  69. data/lib/translator/kernel_launcher/kernel_launcher.rb +259 -0
  70. data/lib/translator/kernel_launcher/while_loop_kernel_launcher.rb +38 -0
  71. data/lib/translator/last_returns_visitor.rb +19 -10
  72. data/lib/translator/program_builder.rb +197 -0
  73. data/lib/translator/program_launcher.rb +273 -0
  74. data/lib/translator/struct_type.rb +55 -0
  75. data/lib/translator/translator.rb +34 -11
  76. data/lib/translator/variable_classifier_visitor.rb +56 -0
  77. data/lib/types/inference/ast_inference.rb +586 -0
  78. data/lib/types/inference/clear_types_visitor.rb +11 -0
  79. data/lib/types/inference/command_inference.rb +101 -0
  80. data/lib/types/inference/input_inference.rb +62 -0
  81. data/lib/types/{object_tracer.rb → inference/object_tracer.rb} +5 -6
  82. data/lib/types/inference/ruby_extension.rb +35 -0
  83. data/lib/types/inference/symbol_table.rb +131 -0
  84. data/lib/types/types.rb +14 -0
  85. data/lib/types/types/array_command_type.rb +123 -0
  86. data/lib/types/types/array_type.rb +137 -0
  87. data/lib/types/{class_type.rb → types/class_type.rb} +42 -18
  88. data/lib/types/{primitive_type.rb → types/primitive_type.rb} +20 -7
  89. data/lib/types/types/ruby_type.rb +88 -0
  90. data/lib/types/types/struct_type.rb +179 -0
  91. data/lib/types/types/union_type.rb +239 -0
  92. metadata +160 -18
  93. data/lib/ast/method_definition.rb +0 -37
  94. data/lib/ast/translator.rb +0 -264
  95. data/lib/resources/cuda/kernel_launcher.cpp +0 -28
  96. data/lib/scope.rb +0 -166
  97. data/lib/translator/command_translator.rb +0 -421
  98. data/lib/translator/local_variables_enumerator.rb +0 -35
  99. data/lib/translator/method_translator.rb +0 -24
  100. data/lib/types/array_type.rb +0 -51
  101. data/lib/types/ruby_extension.rb +0 -67
  102. data/lib/types/ruby_type.rb +0 -45
  103. data/lib/types/type_inference.rb +0 -382
  104. data/lib/types/union_type.rb +0 -155
@@ -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) == node
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 class_owner
24
- @parent.class_owner
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
- def initialize(child:)
33
- @child = child
34
- child.parent = self
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
- class ConstNode < Node
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 < Node
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 < Node
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 < Node
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 IntNode < Node
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 FloatNode < Node
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 BoolNode < Node
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 ForNode < Node
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 BreakNode < Node
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 IfNode < Node
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
- if false_body_stmts != nil
134
- false_body_stmts.parent = self
135
- end
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 BeginNode < Node
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 == stmt
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 < Node
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 == node
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 == arg
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 < Node
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