ikra 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (220) hide show
  1. checksums.yaml +7 -0
  2. data/lib/ast/builder.rb +100 -0
  3. data/lib/ast/lexical_variables_enumerator.rb +34 -0
  4. data/lib/ast/method_definition.rb +37 -0
  5. data/lib/ast/nodes.rb +208 -0
  6. data/lib/ast/printer.rb +99 -0
  7. data/lib/ast/translator.rb +264 -0
  8. data/lib/ast/visitor.rb +173 -0
  9. data/lib/config/configuration.rb +18 -0
  10. data/lib/config/os_configuration.rb +56 -0
  11. data/lib/entity.rb +11 -0
  12. data/lib/ikra.rb +7 -0
  13. data/lib/parsing.rb +32 -0
  14. data/lib/resources/cuda/block_function_head.cpp +1 -0
  15. data/lib/resources/cuda/env_builder_copy_array.cpp +4 -0
  16. data/lib/resources/cuda/header.cpp +46 -0
  17. data/lib/resources/cuda/kernel.cpp +8 -0
  18. data/lib/resources/cuda/kernel_launcher.cpp +28 -0
  19. data/lib/resources/cuda/soa_header.cpp +4 -0
  20. data/lib/scope.rb +166 -0
  21. data/lib/sourcify/Gemfile +10 -0
  22. data/lib/sourcify/HISTORY.txt +88 -0
  23. data/lib/sourcify/LICENSE +20 -0
  24. data/lib/sourcify/README.rdoc +352 -0
  25. data/lib/sourcify/Rakefile +111 -0
  26. data/lib/sourcify/lib/sourcify.rb +44 -0
  27. data/lib/sourcify/lib/sourcify/common/parser/converter.rb +29 -0
  28. data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/comment.rb +23 -0
  29. data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/counter.rb +43 -0
  30. data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/dstring.rb +58 -0
  31. data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/extensions.rb +140 -0
  32. data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/heredoc.rb +26 -0
  33. data/lib/sourcify/lib/sourcify/common/parser/source_code.rb +45 -0
  34. data/lib/sourcify/lib/sourcify/common/ragel/common.rl +5 -0
  35. data/lib/sourcify/lib/sourcify/common/ragel/expressions.rl +38 -0
  36. data/lib/sourcify/lib/sourcify/common/ragel/machines.rl +317 -0
  37. data/lib/sourcify/lib/sourcify/errors.rb +4 -0
  38. data/lib/sourcify/lib/sourcify/method.rb +138 -0
  39. data/lib/sourcify/lib/sourcify/method/methods.rb +3 -0
  40. data/lib/sourcify/lib/sourcify/method/methods/to_raw_source.rb +30 -0
  41. data/lib/sourcify/lib/sourcify/method/methods/to_sexp.rb +30 -0
  42. data/lib/sourcify/lib/sourcify/method/methods/to_source.rb +30 -0
  43. data/lib/sourcify/lib/sourcify/method/parser.rb +110 -0
  44. data/lib/sourcify/lib/sourcify/method/parser/converter.rb +8 -0
  45. data/lib/sourcify/lib/sourcify/method/parser/raw_scanner.rb +2494 -0
  46. data/lib/sourcify/lib/sourcify/method/parser/raw_scanner.rl +144 -0
  47. data/lib/sourcify/lib/sourcify/method/parser/raw_scanner_extensions.rb +68 -0
  48. data/lib/sourcify/lib/sourcify/method/parser/scanner.rb +52 -0
  49. data/lib/sourcify/lib/sourcify/method/parser/source_code.rb +8 -0
  50. data/lib/sourcify/lib/sourcify/patches.rb +63 -0
  51. data/lib/sourcify/lib/sourcify/proc.rb +183 -0
  52. data/lib/sourcify/lib/sourcify/proc/methods.rb +3 -0
  53. data/lib/sourcify/lib/sourcify/proc/methods/source_location.rb +61 -0
  54. data/lib/sourcify/lib/sourcify/proc/methods/to_raw_source.rb +20 -0
  55. data/lib/sourcify/lib/sourcify/proc/methods/to_sexp.rb +40 -0
  56. data/lib/sourcify/lib/sourcify/proc/methods/to_source.rb +48 -0
  57. data/lib/sourcify/lib/sourcify/proc/parser.rb +51 -0
  58. data/lib/sourcify/lib/sourcify/proc/parser/converter.rb +8 -0
  59. data/lib/sourcify/lib/sourcify/proc/parser/normalizer.rb +43 -0
  60. data/lib/sourcify/lib/sourcify/proc/parser/raw_scanner.rb +2498 -0
  61. data/lib/sourcify/lib/sourcify/proc/parser/raw_scanner.rl +149 -0
  62. data/lib/sourcify/lib/sourcify/proc/parser/raw_scanner_extensions.rb +74 -0
  63. data/lib/sourcify/lib/sourcify/proc/parser/scanner.rb +49 -0
  64. data/lib/sourcify/lib/sourcify/proc/parser/source_code.rb +8 -0
  65. data/lib/sourcify/lib/sourcify/version.rb +3 -0
  66. data/lib/sourcify/sourcify.gemspec +31 -0
  67. data/lib/sourcify/spec/dump_object_space_procs.rb +84 -0
  68. data/lib/sourcify/spec/method/encoding_from_def_end_block_spec.rb +33 -0
  69. data/lib/sourcify/spec/method/encoding_from_define_method_spec.rb +37 -0
  70. data/lib/sourcify/spec/method/others_from_def_end_block_spec.rb +49 -0
  71. data/lib/sourcify/spec/method/others_from_define_method_spec.rb +63 -0
  72. data/lib/sourcify/spec/method/raw_scanner/block_comment_spec.rb +8 -0
  73. data/lib/sourcify/spec/method/raw_scanner/double_colons_spec.rb +8 -0
  74. data/lib/sourcify/spec/method/raw_scanner/double_quote_str_w_interpolation_spec.rb +8 -0
  75. data/lib/sourcify/spec/method/raw_scanner/double_quote_str_wo_interpolation_spec.rb +8 -0
  76. data/lib/sourcify/spec/method/raw_scanner/heredoc_w_indent_spec.rb +8 -0
  77. data/lib/sourcify/spec/method/raw_scanner/heredoc_wo_indent_spec.rb +8 -0
  78. data/lib/sourcify/spec/method/raw_scanner/kw_block_start_alias1_spec.rb +20 -0
  79. data/lib/sourcify/spec/method/raw_scanner/kw_block_start_alias2_spec.rb +20 -0
  80. data/lib/sourcify/spec/method/raw_scanner/per_line_comment_spec.rb +8 -0
  81. data/lib/sourcify/spec/method/raw_scanner/single_quote_str_spec.rb +8 -0
  82. data/lib/sourcify/spec/method/raw_scanner/slash_operator_spec.rb +8 -0
  83. data/lib/sourcify/spec/method/raw_scanner/spec_helper.rb +80 -0
  84. data/lib/sourcify/spec/method/spec_helper.rb +1 -0
  85. data/lib/sourcify/spec/method/to_raw_source_spec.rb +31 -0
  86. data/lib/sourcify/spec/method/to_raw_source_w_specified_strip_enclosure_spec.rb +148 -0
  87. data/lib/sourcify/spec/method/to_sexp_from_def_end_block_w_variables_spec.rb +46 -0
  88. data/lib/sourcify/spec/method/to_sexp_from_def_end_block_within_irb_spec.rb +38 -0
  89. data/lib/sourcify/spec/method/to_sexp_from_def_end_block_within_pry_spec.rb +38 -0
  90. data/lib/sourcify/spec/method/to_sexp_from_define_method_w_multi_blocks_and_specified_attached_to_spec.rb +56 -0
  91. data/lib/sourcify/spec/method/to_sexp_from_define_method_w_variables_spec.rb +52 -0
  92. data/lib/sourcify/spec/method/to_sexp_from_define_method_within_irb_spec.rb +42 -0
  93. data/lib/sourcify/spec/method/to_sexp_from_define_method_within_pry_spec.rb +42 -0
  94. data/lib/sourcify/spec/method/to_sexp_w_specified_strip_enclosure_spec.rb +74 -0
  95. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_19_extras_spec.rb +23 -0
  96. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_begin_spec.rb +35 -0
  97. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_case_spec.rb +35 -0
  98. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_class_spec.rb +51 -0
  99. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_do_end_block_spec.rb +33 -0
  100. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_for_spec.rb +126 -0
  101. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_if_spec.rb +83 -0
  102. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_literal_keyword_spec.rb +141 -0
  103. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_method_spec.rb +33 -0
  104. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_module_spec.rb +59 -0
  105. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_unless_spec.rb +83 -0
  106. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_until_spec.rb +179 -0
  107. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_while_spec.rb +179 -0
  108. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_singleton_method_spec.rb +19 -0
  109. data/lib/sourcify/spec/method/to_source_from_def_end_block_within_irb_spec.rb +30 -0
  110. data/lib/sourcify/spec/method/to_source_from_def_end_block_within_pry_spec.rb +45 -0
  111. data/lib/sourcify/spec/method/to_source_from_def_end_w_multi_blocks_and_many_matches_spec.rb +30 -0
  112. data/lib/sourcify/spec/method/to_source_from_def_end_w_multi_blocks_and_single_match_spec.rb +36 -0
  113. data/lib/sourcify/spec/method/to_source_from_define_method_w_braced_block_spec.rb +113 -0
  114. data/lib/sourcify/spec/method/to_source_from_define_method_w_do_end_block_spec.rb +145 -0
  115. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_many_matches_spec.rb +56 -0
  116. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_single_match_spec.rb +73 -0
  117. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_and_many_matches_spec.rb +36 -0
  118. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_and_no_match_spec.rb +36 -0
  119. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_and_single_match_spec.rb +28 -0
  120. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_spec.rb +103 -0
  121. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_body_matcher_and_many_matches_spec.rb +36 -0
  122. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_body_matcher_and_no_match_spec.rb +36 -0
  123. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_body_matcher_and_single_match_spec.rb +28 -0
  124. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_ignore_nested_spec.rb +36 -0
  125. data/lib/sourcify/spec/method/to_source_from_define_method_within_irb_spec.rb +32 -0
  126. data/lib/sourcify/spec/method/to_source_from_define_method_within_pry_spec.rb +49 -0
  127. data/lib/sourcify/spec/method/to_source_magic_file_var_spec.rb +176 -0
  128. data/lib/sourcify/spec/method/to_source_magic_line_var_spec.rb +298 -0
  129. data/lib/sourcify/spec/method/to_source_w_specified_strip_enclosure_spec.rb +39 -0
  130. data/lib/sourcify/spec/no_method/unsupported_platform_spec.rb +26 -0
  131. data/lib/sourcify/spec/proc/19x_extras.rb +27 -0
  132. data/lib/sourcify/spec/proc/created_on_the_fly_proc_spec.rb +80 -0
  133. data/lib/sourcify/spec/proc/encoding_spec.rb +36 -0
  134. data/lib/sourcify/spec/proc/others_spec.rb +40 -0
  135. data/lib/sourcify/spec/proc/raw_scanner/block_comment_spec.rb +8 -0
  136. data/lib/sourcify/spec/proc/raw_scanner/double_colons_spec.rb +8 -0
  137. data/lib/sourcify/spec/proc/raw_scanner/double_quote_str_w_interpolation_spec.rb +8 -0
  138. data/lib/sourcify/spec/proc/raw_scanner/double_quote_str_wo_interpolation_spec.rb +8 -0
  139. data/lib/sourcify/spec/proc/raw_scanner/heredoc_w_indent_spec.rb +8 -0
  140. data/lib/sourcify/spec/proc/raw_scanner/heredoc_wo_indent_spec.rb +8 -0
  141. data/lib/sourcify/spec/proc/raw_scanner/kw_block_start_alias1_spec.rb +20 -0
  142. data/lib/sourcify/spec/proc/raw_scanner/kw_block_start_alias2_spec.rb +20 -0
  143. data/lib/sourcify/spec/proc/raw_scanner/per_line_comment_spec.rb +8 -0
  144. data/lib/sourcify/spec/proc/raw_scanner/single_quote_str_spec.rb +8 -0
  145. data/lib/sourcify/spec/proc/raw_scanner/slash_operator_spec.rb +8 -0
  146. data/lib/sourcify/spec/proc/raw_scanner/spec_helper.rb +63 -0
  147. data/lib/sourcify/spec/proc/readme +5 -0
  148. data/lib/sourcify/spec/proc/spec_helper.rb +1 -0
  149. data/lib/sourcify/spec/proc/to_raw_source_spec.rb +33 -0
  150. data/lib/sourcify/spec/proc/to_raw_source_w_specified_strip_enclosure_spec.rb +69 -0
  151. data/lib/sourcify/spec/proc/to_sexp_from_multi_blocks_w_specified_attached_to_spec.rb +46 -0
  152. data/lib/sourcify/spec/proc/to_sexp_variables_spec.rb +146 -0
  153. data/lib/sourcify/spec/proc/to_sexp_w_specified_strip_enclosure_spec.rb +60 -0
  154. data/lib/sourcify/spec/proc/to_sexp_within_irb_spec.rb +146 -0
  155. data/lib/sourcify/spec/proc/to_sexp_within_pry_spec.rb +149 -0
  156. data/lib/sourcify/spec/proc/to_source_from_braced_block_w_nested_braced_block_spec.rb +33 -0
  157. data/lib/sourcify/spec/proc/to_source_from_braced_block_w_nested_hash_spec.rb +82 -0
  158. data/lib/sourcify/spec/proc/to_source_from_braced_block_wo_nesting_complication_spec.rb +46 -0
  159. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_begin_spec.rb +35 -0
  160. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_case_spec.rb +35 -0
  161. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_class_spec.rb +89 -0
  162. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_do_end_block_spec.rb +33 -0
  163. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_for_spec.rb +132 -0
  164. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_if_spec.rb +87 -0
  165. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_literal_keyword_spec.rb +103 -0
  166. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_method_spec.rb +33 -0
  167. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_module_spec.rb +49 -0
  168. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_unless_spec.rb +87 -0
  169. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_until_spec.rb +189 -0
  170. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_while_spec.rb +189 -0
  171. data/lib/sourcify/spec/proc/to_source_from_do_end_block_wo_nesting_complication_spec.rb +46 -0
  172. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_many_matches_spec.rb +43 -0
  173. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_single_match_spec.rb +20 -0
  174. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_many_matches_spec.rb +45 -0
  175. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_no_match_spec.rb +45 -0
  176. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_single_match_spec.rb +22 -0
  177. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_spec.rb +84 -0
  178. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_many_matches_spec.rb +45 -0
  179. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_no_match_spec.rb +45 -0
  180. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_single_match_spec.rb +22 -0
  181. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_ignore_nested_spec.rb +43 -0
  182. data/lib/sourcify/spec/proc/to_source_from_multi_do_end_blocks_w_single_match_spec.rb +31 -0
  183. data/lib/sourcify/spec/proc/to_source_magic_file_var_spec.rb +127 -0
  184. data/lib/sourcify/spec/proc/to_source_magic_line_var_spec.rb +127 -0
  185. data/lib/sourcify/spec/proc/to_source_variables_spec.rb +29 -0
  186. data/lib/sourcify/spec/proc/to_source_w_specified_strip_enclosure_spec.rb +33 -0
  187. data/lib/sourcify/spec/proc/to_source_within_irb_spec.rb +38 -0
  188. data/lib/sourcify/spec/proc/to_source_within_pry_spec.rb +61 -0
  189. data/lib/sourcify/spec/raw_scanner/block_comment_shared_spec.rb +57 -0
  190. data/lib/sourcify/spec/raw_scanner/double_colons_shared_spec.rb +11 -0
  191. data/lib/sourcify/spec/raw_scanner/double_quote_str_w_interpolation_shared_spec.rb +60 -0
  192. data/lib/sourcify/spec/raw_scanner/double_quote_str_wo_interpolation_shared_spec.rb +86 -0
  193. data/lib/sourcify/spec/raw_scanner/heredoc_w_indent_shared_spec.rb +69 -0
  194. data/lib/sourcify/spec/raw_scanner/heredoc_wo_indent_shared_spec.rb +70 -0
  195. data/lib/sourcify/spec/raw_scanner/kw_block_start_alias1_shared_spec.rb +73 -0
  196. data/lib/sourcify/spec/raw_scanner/kw_block_start_alias2_shared_spec.rb +73 -0
  197. data/lib/sourcify/spec/raw_scanner/per_line_comment_shared_spec.rb +32 -0
  198. data/lib/sourcify/spec/raw_scanner/shared_specs.rb +3 -0
  199. data/lib/sourcify/spec/raw_scanner/single_quote_str_shared_spec.rb +79 -0
  200. data/lib/sourcify/spec/raw_scanner/slash_operator_shared_spec.rb +71 -0
  201. data/lib/sourcify/spec/run_build.sh +25 -0
  202. data/lib/sourcify/spec/spec_helper.rb +130 -0
  203. data/lib/symbolic/symbolic.rb +248 -0
  204. data/lib/symbolic/visitor.rb +51 -0
  205. data/lib/translator/block_translator.rb +123 -0
  206. data/lib/translator/command_translator.rb +421 -0
  207. data/lib/translator/last_returns_visitor.rb +57 -0
  208. data/lib/translator/local_variables_enumerator.rb +35 -0
  209. data/lib/translator/method_translator.rb +24 -0
  210. data/lib/translator/translator.rb +49 -0
  211. data/lib/type_aware_array.rb +71 -0
  212. data/lib/types/array_type.rb +51 -0
  213. data/lib/types/class_type.rb +128 -0
  214. data/lib/types/object_tracer.rb +162 -0
  215. data/lib/types/primitive_type.rb +73 -0
  216. data/lib/types/ruby_extension.rb +67 -0
  217. data/lib/types/ruby_type.rb +45 -0
  218. data/lib/types/type_inference.rb +382 -0
  219. data/lib/types/union_type.rb +155 -0
  220. metadata +321 -0
@@ -0,0 +1,73 @@
1
+ require_relative "ruby_type"
2
+
3
+ module Ikra
4
+ module Types
5
+ class PrimitiveType
6
+ include RubyType
7
+
8
+ attr_reader :c_size
9
+
10
+ def initialize(c_type, ruby_type, c_size, ffi_type)
11
+ @c_type = c_type
12
+ @ruby_type = ruby_type
13
+ @c_size = c_size
14
+ @ffi_type = ffi_type
15
+ end
16
+
17
+ Int = self.new("int", Fixnum, 4, :int)
18
+ Float = self.new("float", Float, 4, :float)
19
+ Bool = self.new("bool", TrueClass, 1, :bool)
20
+ Void = self.new("void", nil, 0, :void)
21
+
22
+ def to_ruby_type
23
+ @ruby_type
24
+ end
25
+
26
+ def to_c_type
27
+ @c_type
28
+ end
29
+
30
+ def to_ffi_type
31
+ @ffi_type
32
+ end
33
+
34
+ def is_primitive?
35
+ true
36
+ end
37
+
38
+ def to_s
39
+ "<primitive: #{@c_type}>"
40
+ end
41
+ end
42
+
43
+ class UnknownType
44
+ include RubyType
45
+
46
+ Instance = self.new
47
+ end
48
+ end
49
+ end
50
+
51
+ class Fixnum
52
+ def self.to_ikra_type
53
+ Ikra::Types::PrimitiveType::Int
54
+ end
55
+ end
56
+
57
+ class Float
58
+ def self.to_ikra_type
59
+ Ikra::Types::PrimitiveType::Float
60
+ end
61
+ end
62
+
63
+ class TrueClass
64
+ def self.to_ikra_type
65
+ Ikra::Types::PrimitiveType::Bool
66
+ end
67
+ end
68
+
69
+ class FalseClass
70
+ def self.to_ikra_type
71
+ Ikra::Types::PrimitiveType::Bool
72
+ end
73
+ end
@@ -0,0 +1,67 @@
1
+ require "set"
2
+ require_relative "primitive_type"
3
+ require_relative "union_type"
4
+
5
+ class Fixnum
6
+ class << self
7
+ def to_ikra_type
8
+ Ikra::Types::PrimitiveType::Int
9
+ end
10
+
11
+ def _ikra_t_to_f(receiver_type)
12
+ Ikra::Types::UnionType.create_float
13
+ end
14
+
15
+ def _ikra_c_to_f(receiver)
16
+ "(float) #{receiver}"
17
+ end
18
+
19
+ def _ikra_t_to_i(receiver_type)
20
+ Ikra::Types::UnionType.create_int
21
+ end
22
+
23
+ def _ikra_c_to_i(receiver)
24
+ "#{receiver}"
25
+ end
26
+ end
27
+ end
28
+
29
+ class Float
30
+ class << self
31
+ def to_ikra_type
32
+ Ikra::Types::PrimitiveType::Float
33
+ end
34
+
35
+ def _ikra_t_to_f(receiver_type)
36
+ Ikra::Types::UnionType.create_float
37
+ end
38
+
39
+ def _ikra_c_to_f(receiver)
40
+ "#{receiver}"
41
+ end
42
+
43
+ def _ikra_t_to_i(receiver_type)
44
+ Ikra::Types::UnionType.create_int
45
+ end
46
+
47
+ def _ikra_c_to_i(receiver)
48
+ "(int) #{receiver}"
49
+ end
50
+ end
51
+ end
52
+
53
+ class TrueClass
54
+ class << self
55
+ def to_ikra_type
56
+ Ikra::Types::PrimitiveType::Bool
57
+ end
58
+ end
59
+ end
60
+
61
+ class FalseClass
62
+ class << self
63
+ def to_ikra_type
64
+ Ikra::Types::PrimitiveType::Bool
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,45 @@
1
+
2
+ require "set"
3
+
4
+ module Ikra
5
+ module Types
6
+
7
+ # Defines the minimal interface for Ikra types. Instances of {UnionType} are expected in most cases.
8
+ module RubyType
9
+ @@next_class_id = 0
10
+
11
+ def to_ruby_type
12
+ raise NotImplementedError
13
+ end
14
+
15
+ def to_c_type
16
+ raise NotImplementedError
17
+ end
18
+
19
+ def is_primitive?
20
+ false
21
+ end
22
+
23
+ def is_union_type?
24
+ false
25
+ end
26
+
27
+ def class_id
28
+ if @class_id == nil
29
+ @class_id = @@next_class_id
30
+ @@next_class_id += 1
31
+ end
32
+
33
+ @class_id
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ class Array
40
+ def to_type_array_string
41
+ "[" + map do |set|
42
+ set.to_s
43
+ end.join(", ") + "]"
44
+ end
45
+ end
@@ -0,0 +1,382 @@
1
+ require "set"
2
+ require_relative "primitive_type"
3
+ require_relative "union_type"
4
+ require_relative "ruby_extension"
5
+ require_relative "../ast/nodes.rb"
6
+ require_relative "../ast/visitor.rb"
7
+ require_relative "../ast/method_definition"
8
+ require_relative "../scope.rb"
9
+
10
+ module Ikra
11
+ module AST
12
+ class Node
13
+ def get_type
14
+ @type ||= Types::UnionType.new
15
+ end
16
+ end
17
+ end
18
+
19
+ module TypeInference
20
+ class Visitor < AST::Visitor
21
+ attr_reader :methods
22
+
23
+ def initialize
24
+ # methods: Ikra type x selector --> MethodDefinition
25
+ @methods = Hash.new
26
+ @methods.default_proc = proc do |hash, key|
27
+ hash[key] = Hash.new
28
+ end
29
+
30
+ # Top of stack is the method that is currently processed
31
+ @method_stack = []
32
+
33
+ # Method definitions that must be processed
34
+ @worklist = Set.new
35
+ end
36
+
37
+ def symbol_table
38
+ current_method.symbol_table
39
+ end
40
+
41
+ def binding
42
+ current_method.binding
43
+ end
44
+
45
+ def current_method
46
+ @method_stack.last
47
+ end
48
+
49
+ # This is used as an entry point for the visitor
50
+ def process_method(method_definition)
51
+ Log.info("Type inference: proceed into method #{method_definition.type}.#{method_definition.selector}(#{Types::UnionType.parameter_hash_to_s(method_definition.parameter_variables)})")
52
+
53
+ @method_stack.push(method_definition)
54
+ ast = method_definition.ast
55
+ # TODO: handle multiple types
56
+ recv_type = method_definition.type
57
+
58
+ # Set up new symbol table (pushing a frame is not sufficient here)
59
+ return_value_type = nil
60
+ symbol_table.new_frame do # lexical variables, parameters defined on this level
61
+ # Add parameters to symbol table (name -> type)
62
+ method_definition.parameter_variables.each do |name, type|
63
+ symbol_table.declare_expand_type(name, type)
64
+ end
65
+ # Add lexical variables to symbol table (name -> type)
66
+ method_definition.lexical_variables.each do |name, type|
67
+ symbol_table.declare_expand_type(name, type)
68
+ end
69
+
70
+ symbol_table.new_function_frame do # local variables defined on this level
71
+ # Add return statements
72
+ ast.accept(Translator::LastStatementReturnsVisitor.new)
73
+
74
+ # Infer types
75
+ ast.accept(self)
76
+ return_value_type = symbol_table.top_frame.return_type
77
+
78
+ # Get local variable definitons
79
+ local_variables_enumerator = Translator::LocalVariablesEnumerator.new
80
+ ast.accept(local_variables_enumerator)
81
+ method_definition.local_variables = local_variables_enumerator.local_variables.reject do |name, type|
82
+ symbol_table.previous_frame.variable_names.include?(name) # no lexical vars or parameters
83
+ end
84
+ end
85
+
86
+ # Determine read/written lexical variables
87
+ (symbol_table.read_and_written_variables(-1) - method_definition.parameter_variables.keys).each do |var|
88
+ method_definition.accessed_lexical_variables[var] = symbol_table.get_type(var)
89
+ end
90
+ end
91
+
92
+ Log.info("Type inference: method return type is #{return_value_type.to_s}")
93
+
94
+ @method_stack.pop
95
+
96
+ method_definition.return_type = return_value_type
97
+ return_value_type
98
+ end
99
+
100
+ def visit_method_call(send_node)
101
+ recv_type = send_node.receiver.get_type
102
+ selector = send_node.selector
103
+ return_type = Types::UnionType.new
104
+
105
+ recv_type.types.each do |recv_singleton_type|
106
+ parameter_names = recv_singleton_type.method_parameters(selector)
107
+ arg_types = send_node.arguments.map do |arg| arg.get_type end
108
+ ast = recv_singleton_type.method_ast(selector)
109
+ method_visited_before = nil
110
+
111
+ if not @methods[recv_singleton_type].include?(selector)
112
+ # This method was never visited before
113
+ parameter_variables =
114
+ @methods[recv_singleton_type][selector] = AST::MethodDefinition.new(
115
+ type: recv_singleton_type,
116
+ selector: selector,
117
+ parameter_variables: Hash[*parameter_names.zip(
118
+ Array.new(arg_types.size) do
119
+ Types::UnionType.new
120
+ end).flatten],
121
+ return_type: Types::UnionType.new,
122
+ ast: ast)
123
+ method_visited_before = false
124
+ else
125
+ method_visited_before = true
126
+ end
127
+
128
+ method_def = @methods[recv_singleton_type][selector]
129
+ # Method needs processing if any parameter is expanded (or method was never visited before)
130
+ needs_processing = !method_visited_before or parameter_names.map.with_index do |name, index|
131
+ method_def.parameter_variables[name].expand(arg_types[index]) # returns true if expanded
132
+ end.reduce(:|)
133
+
134
+ last_return_type = method_def.return_type # return value type from the last pass
135
+
136
+ if needs_processing
137
+ process_method(method_def)
138
+ end
139
+
140
+ if not last_return_type.include_all?(method_def.return_type)
141
+ # Return type was expanded during this pass, reprocess all callers (except for current method)
142
+ @worklist += (method_def.callers - [current_method])
143
+ end
144
+
145
+ method_def.callers.add(current_method)
146
+
147
+ # Return value of all visit methods should be the type
148
+ return_type.expand(method_def.return_type)
149
+ end
150
+
151
+ send_node.get_type.expand(return_type)
152
+ return_type
153
+ end
154
+
155
+ def assert_singleton_type(union_type, expected_type)
156
+ if union_type.singleton_type != expected_type
157
+ raise "Expected type #{expected_type} but found #{union_type.singleton_type}"
158
+ end
159
+ end
160
+
161
+ def visit_root_node(node)
162
+ node.get_type.expand_return_type(node.child.accept(self))
163
+ end
164
+
165
+ def visit_const_node(node)
166
+ if not @binding
167
+ raise "Unable to resolve constants without Binding"
168
+ end
169
+
170
+ node.get_type.expand_return_type(
171
+ Types::UnionType.new([@binding.eval(node.identifier.to_s).class.to_ikra_type]))
172
+ end
173
+
174
+ def visit_lvar_read_node(node)
175
+ symbol_table.read!(node.identifier)
176
+ node.get_type.expand_return_type(symbol_table.get_type(node.identifier))
177
+ end
178
+
179
+ def visit_lvar_write_node(node)
180
+ type = node.value.accept(self)
181
+ symbol_table.declare_expand_type(node.identifier, type)
182
+ symbol_table.written!(node.identifier)
183
+ node.get_type.expand_return_type(type)
184
+ end
185
+
186
+ def visit_ivar_read_node(node)
187
+ cls_type = node.class_owner.to_ikra_type
188
+ cls_type.inst_var_read!(node.identifier)
189
+ cls_type.inst_vars_types[node.identifier]
190
+ end
191
+
192
+ def visit_int_node(node)
193
+ node.get_type.expand_return_type(Types::UnionType.create_int)
194
+ end
195
+
196
+ def visit_float_node(node)
197
+ node.get_type.expand_return_type(Types::UnionType.create_float)
198
+ end
199
+
200
+ def visit_bool_node(node)
201
+ node.get_type.expand_return_type(Types::UnionType.create_bool)
202
+ end
203
+
204
+ def visit_for_node(node)
205
+ assert_singleton_type(node.range_from.accept(self), Types::PrimitiveType::Int)
206
+ assert_singleton_type(node.range_to.accept(self), Types::PrimitiveType::Int)
207
+
208
+ changed = symbol_table.declare_expand_type(node.iterator_identifier, Types::UnionType.create_int)
209
+
210
+ super(node)
211
+
212
+ # TODO: Should return range
213
+
214
+ node.get_type.expand_return_type(Types::UnionType.create_int)
215
+ end
216
+
217
+ def visit_break_node(node)
218
+ Types::UnionType.create_void
219
+ end
220
+
221
+ def visit_if_node(node)
222
+ assert_singleton_type(node.condition.accept(self), Types::PrimitiveType::Bool)
223
+
224
+ type = Types::UnionType.new
225
+ type.expand(node.true_body_stmts.accept(self)) # Begin always has type of last stmt
226
+
227
+ if node.false_body_stmts == nil
228
+ type.expand(Types::UnionType.create_void)
229
+ else
230
+ type.expand(node.false_body_stmts.accept(self))
231
+ end
232
+
233
+ node.get_type.expand_return_type(type)
234
+ end
235
+
236
+ def visit_begin_node(node)
237
+ node.body_stmts[0...-1].each do |stmt|
238
+ stmt.accept(self)
239
+ end
240
+
241
+ # TODO: need to handle empty BeginNode?
242
+ type = node.body_stmts.last.accept(self)
243
+ node.get_type.expand_return_type(type)
244
+ end
245
+
246
+ def visit_return_node(node)
247
+ type = node.value.accept(self)
248
+ symbol_table.add_return_type(type)
249
+ node.get_type.expand_return_type(type)
250
+ end
251
+
252
+
253
+ ArithOperators = [:+, :-, :*, :/, :%]
254
+ CompareOperators = [:<, :<=, :>, :>=]
255
+ EqualityOperators = [:==, :!=]
256
+ LogicOperators = [:&, :'&&', :|, :'||', :^]
257
+ PrimitiveOperators = ArithOperators + CompareOperators + EqualityOperators + LogicOperators
258
+
259
+ def visit_send_node(node)
260
+ # TODO: handle self sends
261
+ receiver_type = nil
262
+
263
+ if node.receiver == nil
264
+ receiver_type = Types::UnionType.create_int
265
+ else
266
+ receiver_type = node.receiver.accept(self)
267
+ end
268
+ type = Types::UnionType.new
269
+
270
+ if PrimitiveOperators.include?(node.selector)
271
+ if node.arguments.size != 1
272
+ raise "Expected 1 argument for binary selector (#{node.arguments.size} given)"
273
+ end
274
+
275
+ # Process every combination of recv_type x operand_type
276
+ operand_type = node.arguments.first.accept(self)
277
+ for recv_type in receiver_type.types
278
+ for op_type in operand_type.types
279
+ type.expand(primitive_operator_type(node.selector, recv_type, op_type))
280
+ end
281
+ end
282
+ else
283
+ for recv_type in receiver_type.types
284
+ if recv_type.to_ruby_type.singleton_methods.include?(("_ikra_t_" + node.selector.to_s).to_sym)
285
+ # TODO: pass arguments
286
+ type.expand(recv_type.to_ruby_type.send(("_ikra_t_" + node.selector.to_s).to_sym, receiver_type))
287
+ else
288
+ node.arguments.each do |arg|
289
+ arg.accept(self)
290
+ end
291
+
292
+ type.expand(visit_method_call(node))
293
+ end
294
+ end
295
+ end
296
+
297
+ node.get_type.expand_return_type(type)
298
+ end
299
+
300
+ def primitive_operator_type(selector, receiver_type, operand_type)
301
+ # receiver_type and operand_type are singleton types, return value is union type
302
+
303
+ arg_types = [receiver_type, operand_type]
304
+
305
+ if ArithOperators.include?(selector)
306
+ type_mapping = {[Types::PrimitiveType::Int, Types::PrimitiveType::Int] => Types::UnionType.create_int,
307
+ [Types::PrimitiveType::Int, Types::PrimitiveType::Float] => Types::UnionType.create_float,
308
+ [Types::PrimitiveType::Float, Types::PrimitiveType::Float] => Types::UnionType.create_float}
309
+
310
+ if type_mapping.has_key?(arg_types)
311
+ return type_mapping[arg_types]
312
+ elsif type_mapping.has_key?(arg_types.reverse)
313
+ return type_mapping[arg_types.reverse]
314
+ else
315
+ raise "Types #{receiver_type} and #{operand_type} not applicable for primitive operator #{selector.to_s}"
316
+ end
317
+ elsif CompareOperators.include?(selector)
318
+ type_mapping = {[Types::PrimitiveType::Int, Types::PrimitiveType::Int] => Types::UnionType.create_bool,
319
+ [Types::PrimitiveType::Int, Types::PrimitiveType::Float] => Types::UnionType.create_bool,
320
+ [Types::PrimitiveType::Float, Types::PrimitiveType::Float] => Types::UnionType.create_bool}
321
+
322
+ if type_mapping.has_key?(arg_types)
323
+ return type_mapping[arg_types]
324
+ elsif type_mapping.has_key?(arg_types.reverse)
325
+ return type_mapping[arg_types.reverse]
326
+ else
327
+ raise "Types #{receiver_type} and #{operand_type} not applicable for primitive operator #{selector.to_s}"
328
+ end
329
+ elsif EqualityOperators.include?(selector)
330
+ type_mapping = {[Types::PrimitiveType::Bool, Types::PrimitiveType::Bool] => Types::UnionType.create_bool,
331
+ [Types::PrimitiveType::Int, Types::PrimitiveType::Int] => Types::UnionType.create_bool,
332
+ [Types::PrimitiveType::Int, Types::PrimitiveType::Float] => Types::UnionType.create_bool,
333
+ [Types::PrimitiveType::Float, Types::PrimitiveType::Float] => Types::UnionType.create_bool}
334
+
335
+ if type_mapping.has_key?(arg_types)
336
+ return type_mapping[arg_types]
337
+ elsif type_mapping.has_key?(arg_types.reverse)
338
+ return type_mapping[arg_types.reverse]
339
+ elsif not arg_types.include?(Types::PrimitiveType::Void) and receiver.type.is_primitive? and operand.type.is_primitive?
340
+ # TODO: this should also return a translation result: selector == :== ? "false" : "true"
341
+ return Types::UnionType.create_bool
342
+ else
343
+ raise "Types #{receiver_type} and #{operand_type} not applicable for primitive operator #{selector.to_s}"
344
+ end
345
+ elsif LogicOperators.include?(selector)
346
+ # TODO: need proper implementation
347
+ int_float = [Types::PrimitiveType::Int, Types::PrimitiveType::Float].to_set
348
+ if selector == :'&&'
349
+ if (int_float + arg_types).size == 2
350
+ # Both are int/float
351
+ # TODO: this should return the operand
352
+ return Types::UnionType.new(operand_type)
353
+ elsif operand_type == PrimitiveType::Bool and receiver_type == Types::PrimitiveType::Bool
354
+ return Types::UnionType.create_bool
355
+ else
356
+ raise "Cannot handle types #{receiver_type} and #{operand_type} for primitive operator #{selector.to_s}"
357
+ end
358
+ elsif selector == :'||'
359
+ if (int_float + arg_types).size == 2
360
+ # Both are int/float
361
+ # TODO: this should return the receiver
362
+ return Types::UnionType.new(receiver_type)
363
+ elsif operand_type == Types::PrimitiveType::Bool and receiver_type == Types::PrimitiveType::Bool
364
+ return Types::UnionType.create_bool
365
+ else
366
+ raise "Cannot handle types #{receiver_type} and #{operand_type} for primitive operator #{selector.to_s}"
367
+ end
368
+ elsif selector == :& or selector == :| or selector == :^
369
+ type_mapping = {[Types::PrimitiveType::Bool, Types::PrimitiveType::Bool] => Types::UnionType.create_bool,
370
+ [Types::PrimitiveType::Int, Types::PrimitiveType::Int] => Types::UnionType.create_int}
371
+
372
+ if type_mapping.has_key?(arg_types)
373
+ return type_mapping[arg_types]
374
+ else
375
+ raise "Types #{receiver_type} and #{operand_type} not applicable for primitive operator #{selector.to_s}"
376
+ end
377
+ end
378
+ end
379
+ end
380
+ end
381
+ end
382
+ end