ikra 0.0.1
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 +7 -0
- data/lib/ast/builder.rb +100 -0
- data/lib/ast/lexical_variables_enumerator.rb +34 -0
- data/lib/ast/method_definition.rb +37 -0
- data/lib/ast/nodes.rb +208 -0
- data/lib/ast/printer.rb +99 -0
- data/lib/ast/translator.rb +264 -0
- data/lib/ast/visitor.rb +173 -0
- data/lib/config/configuration.rb +18 -0
- data/lib/config/os_configuration.rb +56 -0
- data/lib/entity.rb +11 -0
- data/lib/ikra.rb +7 -0
- data/lib/parsing.rb +32 -0
- data/lib/resources/cuda/block_function_head.cpp +1 -0
- data/lib/resources/cuda/env_builder_copy_array.cpp +4 -0
- data/lib/resources/cuda/header.cpp +46 -0
- data/lib/resources/cuda/kernel.cpp +8 -0
- data/lib/resources/cuda/kernel_launcher.cpp +28 -0
- data/lib/resources/cuda/soa_header.cpp +4 -0
- data/lib/scope.rb +166 -0
- data/lib/sourcify/Gemfile +10 -0
- data/lib/sourcify/HISTORY.txt +88 -0
- data/lib/sourcify/LICENSE +20 -0
- data/lib/sourcify/README.rdoc +352 -0
- data/lib/sourcify/Rakefile +111 -0
- data/lib/sourcify/lib/sourcify.rb +44 -0
- data/lib/sourcify/lib/sourcify/common/parser/converter.rb +29 -0
- data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/comment.rb +23 -0
- data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/counter.rb +43 -0
- data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/dstring.rb +58 -0
- data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/extensions.rb +140 -0
- data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/heredoc.rb +26 -0
- data/lib/sourcify/lib/sourcify/common/parser/source_code.rb +45 -0
- data/lib/sourcify/lib/sourcify/common/ragel/common.rl +5 -0
- data/lib/sourcify/lib/sourcify/common/ragel/expressions.rl +38 -0
- data/lib/sourcify/lib/sourcify/common/ragel/machines.rl +317 -0
- data/lib/sourcify/lib/sourcify/errors.rb +4 -0
- data/lib/sourcify/lib/sourcify/method.rb +138 -0
- data/lib/sourcify/lib/sourcify/method/methods.rb +3 -0
- data/lib/sourcify/lib/sourcify/method/methods/to_raw_source.rb +30 -0
- data/lib/sourcify/lib/sourcify/method/methods/to_sexp.rb +30 -0
- data/lib/sourcify/lib/sourcify/method/methods/to_source.rb +30 -0
- data/lib/sourcify/lib/sourcify/method/parser.rb +110 -0
- data/lib/sourcify/lib/sourcify/method/parser/converter.rb +8 -0
- data/lib/sourcify/lib/sourcify/method/parser/raw_scanner.rb +2494 -0
- data/lib/sourcify/lib/sourcify/method/parser/raw_scanner.rl +144 -0
- data/lib/sourcify/lib/sourcify/method/parser/raw_scanner_extensions.rb +68 -0
- data/lib/sourcify/lib/sourcify/method/parser/scanner.rb +52 -0
- data/lib/sourcify/lib/sourcify/method/parser/source_code.rb +8 -0
- data/lib/sourcify/lib/sourcify/patches.rb +63 -0
- data/lib/sourcify/lib/sourcify/proc.rb +183 -0
- data/lib/sourcify/lib/sourcify/proc/methods.rb +3 -0
- data/lib/sourcify/lib/sourcify/proc/methods/source_location.rb +61 -0
- data/lib/sourcify/lib/sourcify/proc/methods/to_raw_source.rb +20 -0
- data/lib/sourcify/lib/sourcify/proc/methods/to_sexp.rb +40 -0
- data/lib/sourcify/lib/sourcify/proc/methods/to_source.rb +48 -0
- data/lib/sourcify/lib/sourcify/proc/parser.rb +51 -0
- data/lib/sourcify/lib/sourcify/proc/parser/converter.rb +8 -0
- data/lib/sourcify/lib/sourcify/proc/parser/normalizer.rb +43 -0
- data/lib/sourcify/lib/sourcify/proc/parser/raw_scanner.rb +2498 -0
- data/lib/sourcify/lib/sourcify/proc/parser/raw_scanner.rl +149 -0
- data/lib/sourcify/lib/sourcify/proc/parser/raw_scanner_extensions.rb +74 -0
- data/lib/sourcify/lib/sourcify/proc/parser/scanner.rb +49 -0
- data/lib/sourcify/lib/sourcify/proc/parser/source_code.rb +8 -0
- data/lib/sourcify/lib/sourcify/version.rb +3 -0
- data/lib/sourcify/sourcify.gemspec +31 -0
- data/lib/sourcify/spec/dump_object_space_procs.rb +84 -0
- data/lib/sourcify/spec/method/encoding_from_def_end_block_spec.rb +33 -0
- data/lib/sourcify/spec/method/encoding_from_define_method_spec.rb +37 -0
- data/lib/sourcify/spec/method/others_from_def_end_block_spec.rb +49 -0
- data/lib/sourcify/spec/method/others_from_define_method_spec.rb +63 -0
- data/lib/sourcify/spec/method/raw_scanner/block_comment_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/double_colons_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/double_quote_str_w_interpolation_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/double_quote_str_wo_interpolation_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/heredoc_w_indent_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/heredoc_wo_indent_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/kw_block_start_alias1_spec.rb +20 -0
- data/lib/sourcify/spec/method/raw_scanner/kw_block_start_alias2_spec.rb +20 -0
- data/lib/sourcify/spec/method/raw_scanner/per_line_comment_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/single_quote_str_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/slash_operator_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/spec_helper.rb +80 -0
- data/lib/sourcify/spec/method/spec_helper.rb +1 -0
- data/lib/sourcify/spec/method/to_raw_source_spec.rb +31 -0
- data/lib/sourcify/spec/method/to_raw_source_w_specified_strip_enclosure_spec.rb +148 -0
- data/lib/sourcify/spec/method/to_sexp_from_def_end_block_w_variables_spec.rb +46 -0
- data/lib/sourcify/spec/method/to_sexp_from_def_end_block_within_irb_spec.rb +38 -0
- data/lib/sourcify/spec/method/to_sexp_from_def_end_block_within_pry_spec.rb +38 -0
- data/lib/sourcify/spec/method/to_sexp_from_define_method_w_multi_blocks_and_specified_attached_to_spec.rb +56 -0
- data/lib/sourcify/spec/method/to_sexp_from_define_method_w_variables_spec.rb +52 -0
- data/lib/sourcify/spec/method/to_sexp_from_define_method_within_irb_spec.rb +42 -0
- data/lib/sourcify/spec/method/to_sexp_from_define_method_within_pry_spec.rb +42 -0
- data/lib/sourcify/spec/method/to_sexp_w_specified_strip_enclosure_spec.rb +74 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_19_extras_spec.rb +23 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_begin_spec.rb +35 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_case_spec.rb +35 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_class_spec.rb +51 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_do_end_block_spec.rb +33 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_for_spec.rb +126 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_if_spec.rb +83 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_literal_keyword_spec.rb +141 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_method_spec.rb +33 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_module_spec.rb +59 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_unless_spec.rb +83 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_until_spec.rb +179 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_while_spec.rb +179 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_singleton_method_spec.rb +19 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_within_irb_spec.rb +30 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_within_pry_spec.rb +45 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_w_multi_blocks_and_many_matches_spec.rb +30 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_w_multi_blocks_and_single_match_spec.rb +36 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_braced_block_spec.rb +113 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_do_end_block_spec.rb +145 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_many_matches_spec.rb +56 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_single_match_spec.rb +73 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_and_many_matches_spec.rb +36 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_and_no_match_spec.rb +36 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_and_single_match_spec.rb +28 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_spec.rb +103 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_body_matcher_and_many_matches_spec.rb +36 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_body_matcher_and_no_match_spec.rb +36 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_body_matcher_and_single_match_spec.rb +28 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_ignore_nested_spec.rb +36 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_within_irb_spec.rb +32 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_within_pry_spec.rb +49 -0
- data/lib/sourcify/spec/method/to_source_magic_file_var_spec.rb +176 -0
- data/lib/sourcify/spec/method/to_source_magic_line_var_spec.rb +298 -0
- data/lib/sourcify/spec/method/to_source_w_specified_strip_enclosure_spec.rb +39 -0
- data/lib/sourcify/spec/no_method/unsupported_platform_spec.rb +26 -0
- data/lib/sourcify/spec/proc/19x_extras.rb +27 -0
- data/lib/sourcify/spec/proc/created_on_the_fly_proc_spec.rb +80 -0
- data/lib/sourcify/spec/proc/encoding_spec.rb +36 -0
- data/lib/sourcify/spec/proc/others_spec.rb +40 -0
- data/lib/sourcify/spec/proc/raw_scanner/block_comment_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/double_colons_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/double_quote_str_w_interpolation_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/double_quote_str_wo_interpolation_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/heredoc_w_indent_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/heredoc_wo_indent_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/kw_block_start_alias1_spec.rb +20 -0
- data/lib/sourcify/spec/proc/raw_scanner/kw_block_start_alias2_spec.rb +20 -0
- data/lib/sourcify/spec/proc/raw_scanner/per_line_comment_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/single_quote_str_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/slash_operator_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/spec_helper.rb +63 -0
- data/lib/sourcify/spec/proc/readme +5 -0
- data/lib/sourcify/spec/proc/spec_helper.rb +1 -0
- data/lib/sourcify/spec/proc/to_raw_source_spec.rb +33 -0
- data/lib/sourcify/spec/proc/to_raw_source_w_specified_strip_enclosure_spec.rb +69 -0
- data/lib/sourcify/spec/proc/to_sexp_from_multi_blocks_w_specified_attached_to_spec.rb +46 -0
- data/lib/sourcify/spec/proc/to_sexp_variables_spec.rb +146 -0
- data/lib/sourcify/spec/proc/to_sexp_w_specified_strip_enclosure_spec.rb +60 -0
- data/lib/sourcify/spec/proc/to_sexp_within_irb_spec.rb +146 -0
- data/lib/sourcify/spec/proc/to_sexp_within_pry_spec.rb +149 -0
- data/lib/sourcify/spec/proc/to_source_from_braced_block_w_nested_braced_block_spec.rb +33 -0
- data/lib/sourcify/spec/proc/to_source_from_braced_block_w_nested_hash_spec.rb +82 -0
- data/lib/sourcify/spec/proc/to_source_from_braced_block_wo_nesting_complication_spec.rb +46 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_begin_spec.rb +35 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_case_spec.rb +35 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_class_spec.rb +89 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_do_end_block_spec.rb +33 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_for_spec.rb +132 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_if_spec.rb +87 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_literal_keyword_spec.rb +103 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_method_spec.rb +33 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_module_spec.rb +49 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_unless_spec.rb +87 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_until_spec.rb +189 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_while_spec.rb +189 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_wo_nesting_complication_spec.rb +46 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_many_matches_spec.rb +43 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_single_match_spec.rb +20 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_many_matches_spec.rb +45 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_no_match_spec.rb +45 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_single_match_spec.rb +22 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_spec.rb +84 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_many_matches_spec.rb +45 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_no_match_spec.rb +45 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_single_match_spec.rb +22 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_ignore_nested_spec.rb +43 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_do_end_blocks_w_single_match_spec.rb +31 -0
- data/lib/sourcify/spec/proc/to_source_magic_file_var_spec.rb +127 -0
- data/lib/sourcify/spec/proc/to_source_magic_line_var_spec.rb +127 -0
- data/lib/sourcify/spec/proc/to_source_variables_spec.rb +29 -0
- data/lib/sourcify/spec/proc/to_source_w_specified_strip_enclosure_spec.rb +33 -0
- data/lib/sourcify/spec/proc/to_source_within_irb_spec.rb +38 -0
- data/lib/sourcify/spec/proc/to_source_within_pry_spec.rb +61 -0
- data/lib/sourcify/spec/raw_scanner/block_comment_shared_spec.rb +57 -0
- data/lib/sourcify/spec/raw_scanner/double_colons_shared_spec.rb +11 -0
- data/lib/sourcify/spec/raw_scanner/double_quote_str_w_interpolation_shared_spec.rb +60 -0
- data/lib/sourcify/spec/raw_scanner/double_quote_str_wo_interpolation_shared_spec.rb +86 -0
- data/lib/sourcify/spec/raw_scanner/heredoc_w_indent_shared_spec.rb +69 -0
- data/lib/sourcify/spec/raw_scanner/heredoc_wo_indent_shared_spec.rb +70 -0
- data/lib/sourcify/spec/raw_scanner/kw_block_start_alias1_shared_spec.rb +73 -0
- data/lib/sourcify/spec/raw_scanner/kw_block_start_alias2_shared_spec.rb +73 -0
- data/lib/sourcify/spec/raw_scanner/per_line_comment_shared_spec.rb +32 -0
- data/lib/sourcify/spec/raw_scanner/shared_specs.rb +3 -0
- data/lib/sourcify/spec/raw_scanner/single_quote_str_shared_spec.rb +79 -0
- data/lib/sourcify/spec/raw_scanner/slash_operator_shared_spec.rb +71 -0
- data/lib/sourcify/spec/run_build.sh +25 -0
- data/lib/sourcify/spec/spec_helper.rb +130 -0
- data/lib/symbolic/symbolic.rb +248 -0
- data/lib/symbolic/visitor.rb +51 -0
- data/lib/translator/block_translator.rb +123 -0
- data/lib/translator/command_translator.rb +421 -0
- data/lib/translator/last_returns_visitor.rb +57 -0
- data/lib/translator/local_variables_enumerator.rb +35 -0
- data/lib/translator/method_translator.rb +24 -0
- data/lib/translator/translator.rb +49 -0
- data/lib/type_aware_array.rb +71 -0
- data/lib/types/array_type.rb +51 -0
- data/lib/types/class_type.rb +128 -0
- data/lib/types/object_tracer.rb +162 -0
- data/lib/types/primitive_type.rb +73 -0
- data/lib/types/ruby_extension.rb +67 -0
- data/lib/types/ruby_type.rb +45 -0
- data/lib/types/type_inference.rb +382 -0
- data/lib/types/union_type.rb +155 -0
- metadata +321 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
require_relative "../ast/nodes.rb"
|
|
2
|
+
require_relative "../ast/builder.rb"
|
|
3
|
+
require_relative "../ast/translator.rb"
|
|
4
|
+
require_relative "../types/type_inference"
|
|
5
|
+
require_relative "../types/primitive_type"
|
|
6
|
+
require_relative "../parsing"
|
|
7
|
+
require_relative "../scope"
|
|
8
|
+
require_relative "../ast/printer"
|
|
9
|
+
require_relative "../ast/method_definition"
|
|
10
|
+
|
|
11
|
+
module Ikra
|
|
12
|
+
module Translator
|
|
13
|
+
|
|
14
|
+
# The result of Ruby-to-CUDA translation of a block using {Translator}
|
|
15
|
+
class BlockTranslationResult
|
|
16
|
+
|
|
17
|
+
# @return [String] Generated CUDA source code
|
|
18
|
+
attr_accessor :block_source
|
|
19
|
+
|
|
20
|
+
# @return [UnionType] Return value type of method/block
|
|
21
|
+
attr_accessor :result_type
|
|
22
|
+
|
|
23
|
+
# @return [String] Name of function in CUDA source code
|
|
24
|
+
attr_accessor :function_name
|
|
25
|
+
|
|
26
|
+
# @return [Array<Ikra::AST::MethodDefinition>] Auxiliary methods that are called by this block (including transitive method calls)
|
|
27
|
+
attr_accessor :aux_methods
|
|
28
|
+
|
|
29
|
+
def initialize(c_source:, result_type:, function_name:, aux_methods: [])
|
|
30
|
+
@block_source = c_source
|
|
31
|
+
@result_type = result_type
|
|
32
|
+
@function_name = function_name
|
|
33
|
+
@aux_methods = aux_methods
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def generated_source
|
|
37
|
+
@aux_methods.map do |meth|
|
|
38
|
+
meth.to_c_source
|
|
39
|
+
end.join("\n\n") + @block_source
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
BlockSelectorDummy = :"<BLOCK>"
|
|
44
|
+
|
|
45
|
+
class << self
|
|
46
|
+
# Translates a Ruby block to CUDA source code.
|
|
47
|
+
# @param [AST::Node] ast abstract syntax tree of the block
|
|
48
|
+
# @param [EnvironmentBuilder] environment_builder environment builder instance collecting information about lexical variables (environment)
|
|
49
|
+
# @param [Hash{Symbol => UnionType}] block_parameter_types types of arguments passed to the block
|
|
50
|
+
# @param [Hash{Symbol => Object}] lexical_variables all lexical variables that are accessed within the block
|
|
51
|
+
# @param [Fixnum] command_id a unique identifier of the block
|
|
52
|
+
# @return [BlockTranslationResult]
|
|
53
|
+
def translate_block(ast:, environment_builder:, command_id:, block_parameter_types: {}, lexical_variables: {})
|
|
54
|
+
parameter_types_string = "[" + block_parameter_types.map do |id, type| "#{id}: #{type}" end.join(", ") + "]"
|
|
55
|
+
Log.info("Translating block with input types #{parameter_types_string}")
|
|
56
|
+
|
|
57
|
+
# Define MethodDefinition for block
|
|
58
|
+
block_def = AST::MethodDefinition.new(
|
|
59
|
+
type: Types::UnionType.new, # TODO: what to pass in here?
|
|
60
|
+
selector: BlockSelectorDummy,
|
|
61
|
+
parameter_variables: block_parameter_types,
|
|
62
|
+
return_type: Types::UnionType.new,
|
|
63
|
+
ast: ast)
|
|
64
|
+
|
|
65
|
+
# Lexical variables
|
|
66
|
+
lexical_variables.each do |name, value|
|
|
67
|
+
block_def.lexical_variables[name] = Types::UnionType.new(value.class.to_ikra_type)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Type inference
|
|
71
|
+
type_inference_visitor = TypeInference::Visitor.new
|
|
72
|
+
return_type = type_inference_visitor.process_method(block_def)
|
|
73
|
+
# The following method returns nested dictionaries, but we only need the values
|
|
74
|
+
aux_methods = type_inference_visitor.methods.values.map do |hash|
|
|
75
|
+
hash.values
|
|
76
|
+
end.flatten
|
|
77
|
+
|
|
78
|
+
# Translate to CUDA/C++ code
|
|
79
|
+
translation_result = ast.translate_statement
|
|
80
|
+
|
|
81
|
+
# Load environment variables
|
|
82
|
+
lexical_variables.each do |name, value|
|
|
83
|
+
type = value.class.to_ikra_type
|
|
84
|
+
mangled_name = environment_builder.add_object(name, value)
|
|
85
|
+
translation_result.prepend("#{type.to_c_type} #{name} = #{Constants::ENV_IDENTIFIER}->#{mangled_name};\n")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Declare local variables
|
|
89
|
+
block_def.local_variables.each do |name, types|
|
|
90
|
+
translation_result.prepend("#{types.singleton_type.to_c_type} #{name};\n")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Function signature
|
|
94
|
+
mangled_name = "_block_k_#{command_id}_"
|
|
95
|
+
|
|
96
|
+
if not return_type.is_singleton?
|
|
97
|
+
raise "Cannot handle polymorphic return types yet"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
function_parameters = ["environment_t *#{Constants::ENV_IDENTIFIER}"]
|
|
101
|
+
block_parameter_types.each do |param|
|
|
102
|
+
function_parameters.push("#{param[1].to_c_type} #{param[0].to_s}")
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
function_head = Translator.read_file(
|
|
106
|
+
file_name: "block_function_head.cpp",
|
|
107
|
+
replacements: {
|
|
108
|
+
"name" => mangled_name,
|
|
109
|
+
"return_type" => return_type.singleton_type.to_c_type,
|
|
110
|
+
"parameters" => function_parameters.join(", ")})
|
|
111
|
+
|
|
112
|
+
translation_result = function_head + wrap_in_c_block(translation_result)
|
|
113
|
+
|
|
114
|
+
# TODO: handle more than one result type
|
|
115
|
+
BlockTranslationResult.new(
|
|
116
|
+
c_source: translation_result,
|
|
117
|
+
result_type: return_type,
|
|
118
|
+
function_name: mangled_name,
|
|
119
|
+
aux_methods: aux_methods)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
require "tempfile"
|
|
2
|
+
require "ffi"
|
|
3
|
+
require_relative "translator"
|
|
4
|
+
require_relative "block_translator"
|
|
5
|
+
require_relative "../config/os_configuration"
|
|
6
|
+
require_relative "../symbolic/symbolic"
|
|
7
|
+
require_relative "../symbolic/visitor"
|
|
8
|
+
require_relative "../types/object_tracer"
|
|
9
|
+
require_relative "../config/configuration"
|
|
10
|
+
|
|
11
|
+
module Ikra
|
|
12
|
+
module Translator
|
|
13
|
+
|
|
14
|
+
# Interface for transferring data to the CUDA side using FFI. Builds a struct containing all required objects (including lexical variables). Traces objects.
|
|
15
|
+
class EnvironmentBuilder
|
|
16
|
+
|
|
17
|
+
class UnionTypeStruct < FFI::Struct
|
|
18
|
+
layout :class_id, :int32, :object_id, :int32
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
attr_accessor :objects
|
|
22
|
+
attr_accessor :device_struct_allocation
|
|
23
|
+
|
|
24
|
+
def initialize
|
|
25
|
+
@objects = {}
|
|
26
|
+
@device_struct_allocation = ""
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Adds an objects as a lexical variable.
|
|
30
|
+
def add_object(command_id, identifier, object)
|
|
31
|
+
cuda_id = "l#{command_id}_#{identifier}"
|
|
32
|
+
objects[cuda_id] = object
|
|
33
|
+
|
|
34
|
+
update_dev_struct_allocation(cuda_id, object)
|
|
35
|
+
|
|
36
|
+
cuda_id
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Adds an object as a base array
|
|
40
|
+
def add_base_array(command_id, object)
|
|
41
|
+
cuda_id = "b#{command_id}_base"
|
|
42
|
+
objects[cuda_id] = object
|
|
43
|
+
|
|
44
|
+
cuda_id_size = "b#{command_id}_size"
|
|
45
|
+
if object.class == FFI::MemoryPointer
|
|
46
|
+
objects[cuda_id_size] = object.size / UnionTypeStruct.size
|
|
47
|
+
else
|
|
48
|
+
objects[cuda_id_size] = object.size
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Generate code for copying data to global memory
|
|
52
|
+
update_dev_struct_allocation(cuda_id, object)
|
|
53
|
+
|
|
54
|
+
cuda_id
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Add an array for the Structure of Arrays object layout
|
|
58
|
+
def add_soa_array(name, object)
|
|
59
|
+
objects[name] = object
|
|
60
|
+
objects["#{name}_size"] = object.size
|
|
61
|
+
|
|
62
|
+
update_dev_struct_allocation(name, object)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def update_dev_struct_allocation(field, object)
|
|
66
|
+
if object.class == Array
|
|
67
|
+
# Allocate new array
|
|
68
|
+
@device_struct_allocation += Translator.read_file(
|
|
69
|
+
file_name: "env_builder_copy_array.cpp",
|
|
70
|
+
replacements: {
|
|
71
|
+
"field" => field,
|
|
72
|
+
"host_env" => Constants::ENV_HOST_IDENTIFIER,
|
|
73
|
+
"dev_env" => Constants::ENV_DEVICE_IDENTIFIER,
|
|
74
|
+
"size_bytes" => (object.first.class.to_ikra_type.c_size * object.size).to_s})
|
|
75
|
+
elsif object.class == FFI::MemoryPointer
|
|
76
|
+
# This is an array of union type structs
|
|
77
|
+
# Allocate new array
|
|
78
|
+
@device_struct_allocation += Translator.read_file(
|
|
79
|
+
file_name: "env_builder_copy_array.cpp",
|
|
80
|
+
replacements: {
|
|
81
|
+
"field" => field,
|
|
82
|
+
"host_env" => Constants::ENV_HOST_IDENTIFIER,
|
|
83
|
+
"dev_env" => Constants::ENV_DEVICE_IDENTIFIER,
|
|
84
|
+
"size_bytes" => object.size.to_s})
|
|
85
|
+
else
|
|
86
|
+
# Nothing to do, this case is handled by mem-copying the struct
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Returns the name of the field containing the base array for a certain identity command.
|
|
91
|
+
def self.base_identifier(command_id)
|
|
92
|
+
"b#{command_id}_base"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def build_struct_definition
|
|
96
|
+
@objects.freeze
|
|
97
|
+
|
|
98
|
+
struct_def = "struct environment_struct\n{\n"
|
|
99
|
+
@objects.each do |key, value|
|
|
100
|
+
if value.class == FFI::MemoryPointer
|
|
101
|
+
# TODO: can this be an extension method of FFI::MemoryPointer?
|
|
102
|
+
struct_def += " union_t * #{key};\n"
|
|
103
|
+
else
|
|
104
|
+
struct_def += " #{value.class.to_ikra_type_obj(value).to_c_type} #{key};\n"
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
struct_def += "};\n"
|
|
108
|
+
|
|
109
|
+
struct_def
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def build_ffi_type
|
|
113
|
+
struct_layout = []
|
|
114
|
+
@objects.each do |key, value|
|
|
115
|
+
if value.class == FFI::MemoryPointer
|
|
116
|
+
# TODO: can this be an extension method of FFI::MemoryPointer?
|
|
117
|
+
struct_layout += [key.to_sym, :pointer]
|
|
118
|
+
else
|
|
119
|
+
struct_layout += [key.to_sym, value.class.to_ikra_type_obj(value).to_ffi_type]
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
struct_type = Class.new(FFI::Struct)
|
|
124
|
+
struct_type.layout(*struct_layout)
|
|
125
|
+
|
|
126
|
+
struct_type
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def build_ffi_object
|
|
130
|
+
struct_type = build_ffi_type
|
|
131
|
+
struct = struct_type.new
|
|
132
|
+
|
|
133
|
+
@objects.each do |key, value|
|
|
134
|
+
# TODO: need proper Array handling
|
|
135
|
+
if value.class == Array
|
|
136
|
+
# Check first element to determine type of array
|
|
137
|
+
# TODO: check for polymorphic
|
|
138
|
+
inner_type = value.first.class.to_ikra_type
|
|
139
|
+
array_ptr = FFI::MemoryPointer.new(value.size * inner_type.c_size)
|
|
140
|
+
|
|
141
|
+
if inner_type == Types::PrimitiveType::Int
|
|
142
|
+
array_ptr.put_array_of_int(0, value)
|
|
143
|
+
elsif inner_type == Types::PrimitiveType::Float
|
|
144
|
+
array_ptr.put_array_of_float(0, value)
|
|
145
|
+
else
|
|
146
|
+
raise NotImplementedError
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
struct[key.to_sym] = array_ptr
|
|
150
|
+
else
|
|
151
|
+
struct[key.to_sym] = value
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
struct.to_ptr
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def [](command_id)
|
|
159
|
+
CurriedBuilder.new(self, command_id)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
class CurriedBuilder
|
|
163
|
+
def initialize(builder, command_id)
|
|
164
|
+
@builder = builder
|
|
165
|
+
@command_id = command_id
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def add_object(identifier, object)
|
|
169
|
+
@builder.add_object(@command_id, identifier, object)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def add_base_array(object)
|
|
173
|
+
@builder.add_base_array(@command_id, object)
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def clone
|
|
178
|
+
result = self.class.new
|
|
179
|
+
result.objects = @objects.clone
|
|
180
|
+
result.device_struct_allocation = @device_struct_allocation
|
|
181
|
+
result
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Result of translating a {Ikra::Symbolic::ArrayCommand}.
|
|
186
|
+
class CommandTranslationResult
|
|
187
|
+
attr_accessor :environment_builder # @return [EnvironmentBuilder] instance that generates the struct containing accessed lexical variables.
|
|
188
|
+
attr_accessor :generated_source # @return [String] containing the currently generated source code.
|
|
189
|
+
attr_accessor :invocation # @return [String] source code used for invoking the block function.
|
|
190
|
+
attr_accessor :size # @return [Fixnum] number of elements in base array
|
|
191
|
+
attr_accessor :return_type # @return [Types::UnionType] return type of the block.
|
|
192
|
+
|
|
193
|
+
def initialize(environment_builder)
|
|
194
|
+
@environment_builder = environment_builder
|
|
195
|
+
@generated_source = ""
|
|
196
|
+
@invocation = "NULL"
|
|
197
|
+
@return_type = Types::UnionType.new
|
|
198
|
+
@size = 0
|
|
199
|
+
|
|
200
|
+
@so_filename = "" # [String] file name of shared library containing CUDA kernel
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def result_size
|
|
204
|
+
@size
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Compiles CUDA source code and generates a shared library.
|
|
208
|
+
def compile
|
|
209
|
+
# Prepare file replacements
|
|
210
|
+
file_replacements = {} # [Hash{String => String}] contains strings that should be replaced when reading a file
|
|
211
|
+
file_replacements["grid_dim[0]"] = "#{[size / 250, 1].max}"
|
|
212
|
+
file_replacements["grid_dim[1]"] = "1"
|
|
213
|
+
file_replacements["grid_dim[2]"] = "1"
|
|
214
|
+
file_replacements["block_dim[0]"] = "#{size >= 250 ? 250 : size}"
|
|
215
|
+
file_replacements["block_dim[1]"] = "1"
|
|
216
|
+
file_replacements["block_dim[2]"] = "1"
|
|
217
|
+
file_replacements["result_type"] = @return_type.singleton_type.to_c_type
|
|
218
|
+
file_replacements["result_size"] = "#{result_size}"
|
|
219
|
+
file_replacements["block_invocation"] = @invocation
|
|
220
|
+
file_replacements["env_identifier"] = Constants::ENV_IDENTIFIER
|
|
221
|
+
file_replacements["copy_env"] = @environment_builder.device_struct_allocation
|
|
222
|
+
file_replacements["dev_env"] = Constants::ENV_DEVICE_IDENTIFIER
|
|
223
|
+
file_replacements["host_env"] = Constants::ENV_HOST_IDENTIFIER
|
|
224
|
+
|
|
225
|
+
# Generate source code
|
|
226
|
+
source = Translator.read_file(file_name: "header.cpp", replacements: file_replacements) +
|
|
227
|
+
@environment_builder.build_struct_definition +
|
|
228
|
+
@generated_source +
|
|
229
|
+
Translator.read_file(file_name: "kernel.cpp", replacements: file_replacements) +
|
|
230
|
+
Translator.read_file(file_name: "kernel_launcher.cpp", replacements: file_replacements)
|
|
231
|
+
|
|
232
|
+
line_no_digits = Math.log(source.lines.count, 10).ceil
|
|
233
|
+
source_with_line_numbers = source.lines.each_with_index.map do |line, num|
|
|
234
|
+
"[#{(num + 1).to_s.rjust(line_no_digits, "0")}] #{line}"
|
|
235
|
+
end.join("")
|
|
236
|
+
|
|
237
|
+
Log.info("Generated source code:\n#{source_with_line_numbers}")
|
|
238
|
+
|
|
239
|
+
# Write source code to temporary file
|
|
240
|
+
file = Tempfile.new(["ikra_kernel", ".cu"])
|
|
241
|
+
file.write(source)
|
|
242
|
+
file.close
|
|
243
|
+
|
|
244
|
+
# Write to codegen_expect
|
|
245
|
+
if Configuration.codegen_expect_file_name != nil
|
|
246
|
+
expect_file = File.new(Configuration.codegen_expect_file_name, "w+")
|
|
247
|
+
expect_file.write(source)
|
|
248
|
+
expect_file.close
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Run compiler
|
|
252
|
+
@so_filename = "#{file.path}.#{Configuration.so_suffix}"
|
|
253
|
+
nvcc_command = Configuration.nvcc_invocation_string(file.path, @so_filename)
|
|
254
|
+
|
|
255
|
+
Log.info("Compiling kernel: #{nvcc_command}")
|
|
256
|
+
time_before = Time.now
|
|
257
|
+
compile_status = %x(#{nvcc_command})
|
|
258
|
+
Log.info("Done, took #{Time.now - time_before} s")
|
|
259
|
+
|
|
260
|
+
if $? != 0
|
|
261
|
+
raise "nvcc failed: #{compile_status}"
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Attaches a the compiled shared library via Ruby FFI and invokes the kernel.
|
|
266
|
+
def execute
|
|
267
|
+
if !File.exist?(@so_filename)
|
|
268
|
+
compile
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
time_before = Time.now
|
|
272
|
+
ffi_interface = Module.new
|
|
273
|
+
ffi_interface.extend(FFI::Library)
|
|
274
|
+
ffi_interface.ffi_lib(@so_filename)
|
|
275
|
+
ffi_interface.attach_function(:launch_kernel, [:pointer], :pointer)
|
|
276
|
+
environment_object = @environment_builder.build_ffi_object
|
|
277
|
+
Log.info("FFI transfer time: #{Time.now - time_before} s")
|
|
278
|
+
|
|
279
|
+
time_before = Time.now
|
|
280
|
+
result = ffi_interface.launch_kernel(environment_object)
|
|
281
|
+
Log.info("Kernel time: #{Time.now - time_before} s")
|
|
282
|
+
|
|
283
|
+
if return_type.singleton_type == Types::PrimitiveType::Int
|
|
284
|
+
result.read_array_of_int(result_size)
|
|
285
|
+
elsif return_type.singleton_type == Types::PrimitiveType::Float
|
|
286
|
+
result.read_array_of_float(result_size)
|
|
287
|
+
else
|
|
288
|
+
raise NotImplementedError
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
# A visitor traversing the tree (currently list) of symbolic array commands. Every command is converted into a {CommandTranslationResult} and possibly merged with the result of dependent (previous) results. This is how kernel fusion is implemented.
|
|
294
|
+
class ArrayCommandVisitor < Symbolic::Visitor
|
|
295
|
+
|
|
296
|
+
def initialize(environment_builder)
|
|
297
|
+
@environment_builder = environment_builder
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def visit_array_new_command(command)
|
|
301
|
+
# create brand new result
|
|
302
|
+
command_translation_result = CommandTranslationResult.new(@environment_builder)
|
|
303
|
+
|
|
304
|
+
block_translation_result = Translator.translate_block(
|
|
305
|
+
ast: command.ast,
|
|
306
|
+
# only one block parameter (int)
|
|
307
|
+
block_parameter_types: {command.block_parameter_names.first => Types::UnionType.create_int},
|
|
308
|
+
environment_builder: @environment_builder[command.unique_id],
|
|
309
|
+
lexical_variables: command.lexical_externals,
|
|
310
|
+
command_id: command.unique_id)
|
|
311
|
+
|
|
312
|
+
command_translation_result.generated_source = block_translation_result.generated_source
|
|
313
|
+
|
|
314
|
+
tid = "threadIdx.x + blockIdx.x * blockDim.x"
|
|
315
|
+
command_translation_result.invocation = "#{block_translation_result.function_name}(#{Constants::ENV_IDENTIFIER}, #{tid})"
|
|
316
|
+
command_translation_result.size = command.size
|
|
317
|
+
command_translation_result.return_type = block_translation_result.result_type
|
|
318
|
+
|
|
319
|
+
command_translation_result
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
def visit_array_identity_command(command)
|
|
323
|
+
# create brand new result
|
|
324
|
+
command_translation_result = CommandTranslationResult.new(@environment_builder)
|
|
325
|
+
|
|
326
|
+
# no source code generation
|
|
327
|
+
|
|
328
|
+
if Configuration::JOB_REORDERING
|
|
329
|
+
reordering_array = command.target.each_with_index.sort do |a, b|
|
|
330
|
+
a.first.class.object_id <=> b.first.class.object_id
|
|
331
|
+
end.map(&:last)
|
|
332
|
+
|
|
333
|
+
# Generate debug output
|
|
334
|
+
dbg_elements = []
|
|
335
|
+
dbg_last = command.target[reordering_array[0]].class
|
|
336
|
+
dbg_counter = 1
|
|
337
|
+
|
|
338
|
+
for idx in 1..(command.target.size - 1)
|
|
339
|
+
dbg_next = command.target[reordering_array[idx]].class
|
|
340
|
+
|
|
341
|
+
if dbg_next == dbg_last
|
|
342
|
+
dbg_counter += 1
|
|
343
|
+
else
|
|
344
|
+
dbg_elements.push("#{dbg_last.to_s} (#{dbg_counter})")
|
|
345
|
+
dbg_last = dbg_next
|
|
346
|
+
dbg_counter = 1
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
dbg_elements.push("#{dbg_last.to_s} (#{dbg_counter})")
|
|
350
|
+
|
|
351
|
+
Log.info("Generated job reordering array, resulting in: [#{dbg_elements.join(", ")}]")
|
|
352
|
+
|
|
353
|
+
reordering_array_name = @environment_builder.add_base_array("#{command.unique_id}j", reordering_array)
|
|
354
|
+
command_translation_result.invocation = "#{Constants::ENV_IDENTIFIER}->#{EnvironmentBuilder.base_identifier(command.unique_id)}[#{Constants::ENV_IDENTIFIER}->#{reordering_array_name}[threadIdx.x + blockIdx.x * blockDim.x]]"
|
|
355
|
+
else
|
|
356
|
+
command_translation_result.invocation = "#{Constants::ENV_IDENTIFIER}->#{EnvironmentBuilder.base_identifier(command.unique_id)}[threadIdx.x + blockIdx.x * blockDim.x]"
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
command_translation_result.size = command.size
|
|
360
|
+
command_translation_result.return_type = command.base_type
|
|
361
|
+
|
|
362
|
+
command_translation_result
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
def visit_array_map_command(command)
|
|
366
|
+
dependent_result = super # visit target (dependent) command
|
|
367
|
+
command_translation_result = CommandTranslationResult.new(@environment_builder)
|
|
368
|
+
|
|
369
|
+
block_translation_result = Translator.translate_block(
|
|
370
|
+
ast: command.ast,
|
|
371
|
+
block_parameter_types: {command.block_parameter_names.first => dependent_result.return_type},
|
|
372
|
+
environment_builder: @environment_builder[command.unique_id],
|
|
373
|
+
lexical_variables: command.lexical_externals,
|
|
374
|
+
command_id: command.unique_id)
|
|
375
|
+
|
|
376
|
+
command_translation_result.generated_source = dependent_result.generated_source + "\n\n" + block_translation_result.generated_source
|
|
377
|
+
|
|
378
|
+
command_translation_result.invocation = "#{block_translation_result.function_name}(#{Constants::ENV_IDENTIFIER}, #{dependent_result.invocation})"
|
|
379
|
+
command_translation_result.size = dependent_result.size
|
|
380
|
+
command_translation_result.return_type = block_translation_result.result_type
|
|
381
|
+
|
|
382
|
+
command_translation_result
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
# Retrieves all base arrays and registers them with the {EnvironmentBuilder}. Yhis functionality is in a separate class to avoid scattering with object tracer calls.
|
|
387
|
+
class BaseArrayRegistrator < Symbolic::Visitor
|
|
388
|
+
def initialize(environment_builder, object_tracer)
|
|
389
|
+
@environment_builder = environment_builder
|
|
390
|
+
@object_tracer = object_tracer
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
def visit_array_identity_command(command)
|
|
394
|
+
need_union_type = !command.base_type.is_singleton?
|
|
395
|
+
transformed_base_array = @object_tracer.convert_base_array(command.target, need_union_type)
|
|
396
|
+
@environment_builder.add_base_array(command.unique_id, transformed_base_array)
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
class << self
|
|
401
|
+
def translate_command(command)
|
|
402
|
+
environment_builder = EnvironmentBuilder.new
|
|
403
|
+
|
|
404
|
+
# Run type inference for objects/classes and trace objects
|
|
405
|
+
object_tracer = TypeInference::ObjectTracer.new(command)
|
|
406
|
+
all_objects = object_tracer.trace_all
|
|
407
|
+
|
|
408
|
+
# Translate command
|
|
409
|
+
command_translation_result = command.accept(ArrayCommandVisitor.new(environment_builder))
|
|
410
|
+
|
|
411
|
+
# Add SoA arrays to environment
|
|
412
|
+
object_tracer.register_soa_arrays(environment_builder)
|
|
413
|
+
|
|
414
|
+
# Add base arrays to environment
|
|
415
|
+
command.accept(BaseArrayRegistrator.new(environment_builder, object_tracer))
|
|
416
|
+
|
|
417
|
+
command_translation_result
|
|
418
|
+
end
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
end
|