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.
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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 86447e8ed8423243fd4a85d47c6f6193d401456d
4
- data.tar.gz: ead0343c4c707bb0ea133943085e6e5ca24f3372
3
+ metadata.gz: fd8028a7dd6a39dd8762d70b31d08b036d4513cc
4
+ data.tar.gz: 7f64a61eb6b018859b6ae0b03734eb6f9c041798
5
5
  SHA512:
6
- metadata.gz: e9cbfc562bb7529053e755e07763a431b57d802535fa2b5deed201828a07a326bc1ecce7597898d333f1dd9c7a14bbb1eed5bcbf052524f0c6a2bfc8e376fc79
7
- data.tar.gz: 4c66b35a3ec55cc68e9f22fe1a7db78bd3e209491fb774f47d0dbccf4bada876966d164a47901cb03e0cb9763489399f60600b0a992265f6a080a4e91615be85
6
+ metadata.gz: f26e50272fdf7c18b01a15ff3dad17e640e94eb1a3bf7ec9fdddb9eda709d1057277b291d05719490926741295b8a7d105a150089946bf5fd3fef20b254f3ef2
7
+ data.tar.gz: af61029cc2b3bb898eab63359241a8da4b445a3e658c4c1d406f9a4d0b860c6a17bec16ec4e553c894b57d96d1ceab08995f90d97c58dcc2defaf795c3d46055
@@ -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
- module Builder
8
- class << self
9
- def from_parser_ast(node)
10
- RootNode.new(child: translate_node(node))
11
- end
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
- def translate_node(node)
14
- if node == nil
15
- nil
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
- send("translate_#{node.type.to_s}".to_sym, node)
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
- def translate_int(node)
27
- IntNode.new(value: node.children[0])
28
- end
29
-
30
- def translate_float(node)
31
- FloatNode.new(value: node.children[0])
32
- end
33
-
34
- def translate_bool(node)
35
- BoolNode.new(value: node.children[0])
36
- end
37
-
38
- def translate_lvar(node)
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
- def translate_if(node)
51
- IfNode.new(condition: translate_node(node.children[0]),
52
- true_body_stmts: translate_node(node.children[1]),
53
- false_body_stmts: translate_node(node.children[2]))
54
- end
55
-
56
- def extract_begin_single_statement(node, should_return = false)
57
- next_node = node
58
- while next_node.type == :begin
59
- if next_node.children.size != 1
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
- next_node
62
+
63
+ full_const_string = current_const.children[1].to_s + "::" + full_const_string
67
64
  end
68
-
69
- def translate_for(node)
70
- if node.children[0].type == :lvasgn and extract_begin_single_statement(node.children[1]).type == :irange
71
- range = extract_begin_single_statement(node.children[1])
72
-
73
- ForNode.new(iterator_identifier: node.children[0].children[0],
74
- range_from: translate_node(range.children[0]),
75
- range_to: translate_node(range.children[1]),
76
- body_stmts: translate_node(node.children[2]))
77
- else
78
- raise "Can only handle simple For loops at the moment"
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
- def translate_break(node)
83
- BreakNode.new
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
- def translate_send(node)
87
- SendNode.new(receiver: translate_node(node.children[0]),
88
- selector: node.children[1],
89
- arguments: node.children[2..-1].map do |arg|
90
- translate_node(arg) end)
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
- def translate_begin(node)
94
- BeginNode.new(body_stmts: node.children.map do |stmt|
95
- translate_node(stmt) end)
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: does a method have access to lexical variables?
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)