rubex 0.1 → 0.1.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.
Files changed (197) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +3 -2
  3. data/.travis.yml +9 -1
  4. data/CONTRIBUTING.md +2 -2
  5. data/README.md +4 -1
  6. data/Rakefile +2 -2
  7. data/bin/rubex +4 -5
  8. data/lib/rubex.rb +4 -4
  9. data/lib/rubex/ast.rb +4 -1
  10. data/lib/rubex/ast/expression.rb +22 -1191
  11. data/lib/rubex/ast/expression/actual_arg_list.rb +40 -0
  12. data/lib/rubex/ast/expression/analysed_element_ref.rb +26 -0
  13. data/lib/rubex/ast/expression/analysed_element_ref/c_var_element_ref.rb +30 -0
  14. data/lib/rubex/ast/expression/analysed_element_ref/ruby_object_element_ref.rb +42 -0
  15. data/lib/rubex/ast/expression/arg_declaration.rb +43 -0
  16. data/lib/rubex/ast/expression/binary.rb +57 -0
  17. data/lib/rubex/ast/expression/binary/binary_boolean.rb +23 -0
  18. data/lib/rubex/ast/expression/binary/binary_boolean_special_op.rb +20 -0
  19. data/lib/rubex/ast/expression/binary/empty_classes.rb +62 -0
  20. data/lib/rubex/ast/expression/block_given.rb +15 -0
  21. data/lib/rubex/ast/expression/coerce_object.rb +15 -0
  22. data/lib/rubex/ast/expression/command_call.rb +74 -0
  23. data/lib/rubex/ast/expression/command_call/struct_or_union_member_call.rb +38 -0
  24. data/lib/rubex/ast/expression/element_ref.rb +64 -0
  25. data/lib/rubex/ast/expression/empty.rb +13 -0
  26. data/lib/rubex/ast/expression/from_ruby_object.rb +20 -0
  27. data/lib/rubex/ast/expression/func_ptr_arg_declaration.rb +21 -0
  28. data/lib/rubex/ast/expression/func_ptr_internal_arg_declaration.rb +13 -0
  29. data/lib/rubex/ast/expression/literal.rb +30 -0
  30. data/lib/rubex/ast/expression/literal/array_lit.rb +51 -0
  31. data/lib/rubex/ast/expression/literal/c_null.rb +15 -0
  32. data/lib/rubex/ast/expression/literal/char.rb +36 -0
  33. data/lib/rubex/ast/expression/literal/double.rb +14 -0
  34. data/lib/rubex/ast/expression/literal/false.rb +33 -0
  35. data/lib/rubex/ast/expression/literal/hash_lit.rb +45 -0
  36. data/lib/rubex/ast/expression/literal/int.rb +14 -0
  37. data/lib/rubex/ast/expression/literal/nil.rb +14 -0
  38. data/lib/rubex/ast/expression/literal/ruby_symbol.rb +22 -0
  39. data/lib/rubex/ast/expression/literal/string_lit.rb +45 -0
  40. data/lib/rubex/ast/expression/literal/true.rb +29 -0
  41. data/lib/rubex/ast/expression/method_call.rb +52 -0
  42. data/lib/rubex/ast/expression/method_call/c_function_call.rb +40 -0
  43. data/lib/rubex/ast/expression/method_call/ruby_method_call.rb +83 -0
  44. data/lib/rubex/ast/expression/name.rb +127 -0
  45. data/lib/rubex/ast/expression/ruby_constant.rb +25 -0
  46. data/lib/rubex/ast/expression/ruby_object_element_ref/ruby_array_element_ref.rb +20 -0
  47. data/lib/rubex/ast/expression/ruby_object_element_ref/ruby_hash_element_ref.rb +22 -0
  48. data/lib/rubex/ast/expression/self.rb +15 -0
  49. data/lib/rubex/ast/expression/size_of.rb +22 -0
  50. data/lib/rubex/ast/expression/struct_or_union_member_call/element_ref_member_call.rb +23 -0
  51. data/lib/rubex/ast/expression/to_ruby_object.rb +21 -0
  52. data/lib/rubex/ast/expression/typecast.rb +20 -0
  53. data/lib/rubex/ast/expression/typecast_to.rb +10 -0
  54. data/lib/rubex/ast/expression/unary.rb +37 -0
  55. data/lib/rubex/ast/expression/unary_base.rb +24 -0
  56. data/lib/rubex/ast/expression/unary_base/ampersand.rb +16 -0
  57. data/lib/rubex/ast/expression/unary_base/unary_bit_not.rb +18 -0
  58. data/lib/rubex/ast/expression/unary_base/unary_not.rb +18 -0
  59. data/lib/rubex/ast/expression/unary_base/unary_sub.rb +18 -0
  60. data/lib/rubex/ast/node.rb +111 -111
  61. data/lib/rubex/ast/statement.rb +9 -1160
  62. data/lib/rubex/ast/statement/alias.rb +43 -0
  63. data/lib/rubex/ast/statement/argument_list.rb +59 -0
  64. data/lib/rubex/ast/statement/assign.rb +35 -0
  65. data/lib/rubex/ast/statement/begin_block.rb +14 -0
  66. data/lib/rubex/ast/statement/begin_block/begin.rb +202 -0
  67. data/lib/rubex/ast/statement/begin_block/else.rb +21 -0
  68. data/lib/rubex/ast/statement/begin_block/ensure.rb +21 -0
  69. data/lib/rubex/ast/statement/begin_block/rescue.rb +34 -0
  70. data/lib/rubex/ast/statement/break.rb +18 -0
  71. data/lib/rubex/ast/statement/c_array_decl.rb +49 -0
  72. data/lib/rubex/ast/statement/c_base_type.rb +26 -0
  73. data/lib/rubex/ast/statement/c_function_decl.rb +30 -0
  74. data/lib/rubex/ast/statement/c_ptr_decl.rb +52 -0
  75. data/lib/rubex/ast/statement/c_ptr_decl/c_ptr_func_decl.rb +25 -0
  76. data/lib/rubex/ast/statement/c_struct_or_union_def.rb +49 -0
  77. data/lib/rubex/ast/statement/expression.rb +26 -0
  78. data/lib/rubex/ast/statement/for.rb +73 -0
  79. data/lib/rubex/ast/statement/forward_decl.rb +31 -0
  80. data/lib/rubex/ast/statement/if_block.rb +64 -0
  81. data/lib/rubex/ast/statement/if_block/else.rb +30 -0
  82. data/lib/rubex/ast/statement/if_block/elsif.rb +22 -0
  83. data/lib/rubex/ast/statement/if_block/helper.rb +38 -0
  84. data/lib/rubex/ast/statement/print.rb +49 -0
  85. data/lib/rubex/ast/statement/raise.rb +66 -0
  86. data/lib/rubex/ast/statement/return.rb +45 -0
  87. data/lib/rubex/ast/statement/var_decl.rb +49 -0
  88. data/lib/rubex/ast/statement/while.rb +34 -0
  89. data/lib/rubex/ast/statement/yield.rb +41 -0
  90. data/lib/rubex/ast/top_statement.rb +1 -815
  91. data/lib/rubex/ast/top_statement/c_bindings.rb +145 -0
  92. data/lib/rubex/ast/top_statement/klass.rb +125 -0
  93. data/lib/rubex/ast/top_statement/klass/attached_klass.rb +417 -0
  94. data/lib/rubex/ast/top_statement/method_def.rb +110 -0
  95. data/lib/rubex/ast/top_statement/method_def/c_function_def.rb +26 -0
  96. data/lib/rubex/ast/top_statement/method_def/ruby_method_def.rb +33 -0
  97. data/lib/rubex/cli.rb +26 -0
  98. data/lib/rubex/code_writer.rb +1 -1
  99. data/lib/rubex/compiler.rb +49 -28
  100. data/lib/rubex/compiler_config.rb +4 -2
  101. data/lib/rubex/constants.rb +71 -71
  102. data/lib/rubex/data_type.rb +9 -675
  103. data/lib/rubex/data_type/c_array.rb +33 -0
  104. data/lib/rubex/data_type/c_function.rb +23 -0
  105. data/lib/rubex/data_type/c_ptr.rb +71 -0
  106. data/lib/rubex/data_type/c_str.rb +23 -0
  107. data/lib/rubex/data_type/c_struct_or_union.rb +23 -0
  108. data/lib/rubex/data_type/char.rb +30 -0
  109. data/lib/rubex/data_type/f_32.rb +38 -0
  110. data/lib/rubex/data_type/f_64.rb +38 -0
  111. data/lib/rubex/data_type/int.rb +32 -0
  112. data/lib/rubex/data_type/int/c_boolean.rb +13 -0
  113. data/lib/rubex/data_type/int_16.rb +32 -0
  114. data/lib/rubex/data_type/int_32.rb +32 -0
  115. data/lib/rubex/data_type/int_64.rb +36 -0
  116. data/lib/rubex/data_type/int_8.rb +33 -0
  117. data/lib/rubex/data_type/l_int.rb +38 -0
  118. data/lib/rubex/data_type/l_l_int.rb +26 -0
  119. data/lib/rubex/data_type/ruby_method.rb +22 -0
  120. data/lib/rubex/data_type/ruby_object.rb +19 -0
  121. data/lib/rubex/data_type/ruby_object/boolean.rb +11 -0
  122. data/lib/rubex/data_type/ruby_object/boolean/false_type.rb +5 -0
  123. data/lib/rubex/data_type/ruby_object/boolean/true_type.rb +5 -0
  124. data/lib/rubex/data_type/ruby_object/nil_type.rb +9 -0
  125. data/lib/rubex/data_type/ruby_object/ruby_array.rb +10 -0
  126. data/lib/rubex/data_type/ruby_object/ruby_constant.rb +18 -0
  127. data/lib/rubex/data_type/ruby_object/ruby_constant/ruby_class.rb +18 -0
  128. data/lib/rubex/data_type/ruby_object/ruby_hash.rb +9 -0
  129. data/lib/rubex/data_type/ruby_object/ruby_string.rb +10 -0
  130. data/lib/rubex/data_type/ruby_object/ruby_symbol.rb +10 -0
  131. data/lib/rubex/data_type/type_def.rb +34 -0
  132. data/lib/rubex/data_type/u_char.rb +27 -0
  133. data/lib/rubex/data_type/u_int.rb +32 -0
  134. data/lib/rubex/data_type/u_int_16.rb +22 -0
  135. data/lib/rubex/data_type/u_int_32.rb +22 -0
  136. data/lib/rubex/data_type/u_int_64.rb +26 -0
  137. data/lib/rubex/data_type/u_int_8.rb +22 -0
  138. data/lib/rubex/data_type/u_l_int.rb +36 -0
  139. data/lib/rubex/data_type/u_l_int/size_t.rb +10 -0
  140. data/lib/rubex/data_type/u_l_l_int.rb +26 -0
  141. data/lib/rubex/data_type/void.rb +15 -0
  142. data/lib/rubex/data_type_helpers/float_helpers.rb +8 -0
  143. data/lib/rubex/data_type_helpers/helpers.rb +48 -0
  144. data/lib/rubex/data_type_helpers/int_helpers.rb +10 -0
  145. data/lib/rubex/data_type_helpers/u_int_helpers.rb +11 -0
  146. data/lib/rubex/helpers.rb +35 -118
  147. data/lib/rubex/helpers/node_type_methods.rb +9 -0
  148. data/lib/rubex/helpers/writers.rb +79 -0
  149. data/lib/rubex/parser.racc +83 -34
  150. data/lib/rubex/parser.racc.rb +233 -184
  151. data/lib/rubex/version.rb +2 -2
  152. data/rubex.gemspec +2 -0
  153. data/spec/basic_ruby_method_spec.rb +1 -1
  154. data/spec/binding_ptr_args_spec.rb +2 -2
  155. data/spec/bitwise_operators_spec.rb +1 -1
  156. data/spec/blocks_spec.rb +2 -2
  157. data/spec/c_bindings_spec.rb +1 -1
  158. data/spec/c_constants_spec.rb +1 -1
  159. data/spec/c_function_ptrs_spec.rb +1 -1
  160. data/spec/c_functions_spec.rb +2 -2
  161. data/spec/c_struct_interface_spec.rb +1 -1
  162. data/spec/call_by_reference_spec.rb +2 -2
  163. data/spec/class_methods_spec.rb +2 -2
  164. data/spec/class_spec.rb +4 -4
  165. data/spec/cli_spec.rb +43 -0
  166. data/spec/comments_spec.rb +2 -2
  167. data/spec/default_args_spec.rb +21 -23
  168. data/spec/error_handling_spec.rb +1 -1
  169. data/spec/examples_spec.rb +4 -4
  170. data/spec/expressions_spec.rb +1 -1
  171. data/spec/fixtures/cli/cli.rubex +3 -0
  172. data/spec/fixtures/examples/array_to_hash.rubex +1 -1
  173. data/spec/fixtures/examples/rcsv.rubex +10 -6
  174. data/spec/fixtures/loops/loops.rubex +1 -1
  175. data/spec/fixtures/ruby_strings/string_blank_bm.rb +7 -5
  176. data/spec/fixtures/struct/struct.rubex +7 -2
  177. data/spec/fixtures/temp_allocation/temp_allocation.rubex +8 -0
  178. data/spec/if_else_spec.rb +3 -7
  179. data/spec/implicit_lib_include_spec.rb +1 -1
  180. data/spec/init_ruby_objects_with_literal_syntax_spec.rb +1 -1
  181. data/spec/loops_spec.rb +1 -1
  182. data/spec/recursion_spec.rb +18 -21
  183. data/spec/ruby_constant_method_calls_spec.rb +4 -4
  184. data/spec/ruby_operators_spec.rb +1 -1
  185. data/spec/ruby_raise_spec.rb +1 -1
  186. data/spec/ruby_strings_spec.rb +3 -3
  187. data/spec/ruby_symbols_spec.rb +1 -1
  188. data/spec/ruby_types_spec.rb +2 -2
  189. data/spec/spec_helper.rb +42 -10
  190. data/spec/statement_expression_spec.rb +3 -3
  191. data/spec/static_array_spec.rb +3 -3
  192. data/spec/string_literals_spec.rb +2 -2
  193. data/spec/struct_spec.rb +4 -4
  194. data/spec/temp_allocation_spec.rb +35 -0
  195. data/spec/typecasting_spec.rb +2 -2
  196. data/spec/var_declarions_spec.rb +2 -2
  197. metadata +168 -3
@@ -0,0 +1,45 @@
1
+ module Rubex
2
+ module AST
3
+ module Expression
4
+ module Literal
5
+ class StringLit < Base
6
+ def analyse_for_target_type(target_type, local_scope)
7
+ if target_type.char_ptr?
8
+ @type = Rubex::DataType::CStr.new
9
+ elsif target_type.object?
10
+ @type = Rubex::DataType::RubyString.new
11
+ analyse_types local_scope
12
+ else
13
+ raise Rubex::TypeError, "Cannot assign #{target_type} to string."
14
+ end
15
+ end
16
+
17
+ def analyse_types(_local_scope)
18
+ @type ||= Rubex::DataType::RubyString.new
19
+ @has_temp = true
20
+ end
21
+
22
+ def generate_evaluation_code(code, _local_scope)
23
+ if @type.cstr?
24
+ @c_code = "\"#{@name}\""
25
+ else
26
+ code << "#{@c_code} = rb_str_new2(\"#{@name}\");"
27
+ code.nl
28
+ end
29
+ end
30
+
31
+ def generate_disposal_code(code)
32
+ if @type.object?
33
+ code << "#{@c_code} = 0;"
34
+ code.nl
35
+ end
36
+ end
37
+
38
+ def c_code(_local_scope)
39
+ @c_code
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,29 @@
1
+ module Rubex
2
+ module AST
3
+ module Expression
4
+ module Literal
5
+ class True < Base
6
+ def analyse_for_target_type(target_type, _local_scope)
7
+ @type = if target_type.object?
8
+ Rubex::DataType::TrueType.new
9
+ else
10
+ Rubex::DataType::CBoolean.new
11
+ end
12
+ end
13
+
14
+ def analyse_types(_local_scope)
15
+ @type = Rubex::DataType::TrueType.new
16
+ end
17
+
18
+ def c_code(_local_scope)
19
+ if @type.object?
20
+ @name
21
+ else
22
+ '1'
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,52 @@
1
+ module Rubex
2
+ module AST
3
+ module Expression
4
+ class MethodCall < Base
5
+ def initialize(invoker, method_name, arg_list)
6
+ @method_name = method_name
7
+ @invoker = invoker
8
+ @arg_list = arg_list
9
+ end
10
+
11
+ def analyse_types(local_scope)
12
+ if method_not_within_scope? local_scope
13
+ raise Rubex::NoMethodError, "Cannot call #{@method_name} from this method."
14
+ end
15
+ super
16
+ end
17
+
18
+ def generate_evaluation_code code, local_scope
19
+ @arg_list.each { |a| a.generate_evaluation_code(code, local_scope) }
20
+ end
21
+
22
+ private
23
+
24
+ def type_check_arg_types(entry)
25
+ @arg_list.map!.with_index do |arg, idx|
26
+ Helpers.to_lhs_type(entry.type.base_type.arg_list[idx], arg)
27
+ end
28
+ end
29
+
30
+ # Checks if method being called is of the same type of the caller. For
31
+ # example, only instance methods can call instance methods and only
32
+ # class methods can call class methods. C functions are accessible from
33
+ # both instance methods and class methods.
34
+ #
35
+ # Since there is no way to determine whether methods outside the scope
36
+ # of the compiled Rubex file are singletons or not, Rubex will assume
37
+ # that they belong to the correct scope and will compile a call to those
38
+ # methods anyway. Error, if any, will be caught only at runtime.
39
+ def method_not_within_scope?(local_scope)
40
+ caller_entry = local_scope.find local_scope.name
41
+ if (caller_entry.singleton? && @entry.singleton?) ||
42
+ (!caller_entry.singleton? && !@entry.singleton?) ||
43
+ @entry.c_function?
44
+ false
45
+ else
46
+ true
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,40 @@
1
+ module Rubex
2
+ module AST
3
+ module Expression
4
+ class CFunctionCall < MethodCall
5
+ def analyse_types(local_scope)
6
+ @entry = local_scope.find(@method_name)
7
+ super
8
+ append_self_argument unless @entry.extern?
9
+ @arg_list.analyse_types local_scope
10
+ @arg_list.allocate_temps local_scope
11
+ @arg_list.release_temps local_scope
12
+ @type = @entry.type.base_type
13
+ type_check_arg_types @entry
14
+ end
15
+
16
+ def generate_evaluation_code code, local_scope
17
+ super
18
+ @c_code = code_for_c_method_call local_scope
19
+ end
20
+
21
+ def c_code(local_scope)
22
+ @c_code
23
+ end
24
+
25
+ private
26
+
27
+ def append_self_argument
28
+ @arg_list << Expression::Self.new
29
+ end
30
+
31
+ def code_for_c_method_call(local_scope)
32
+ str = "#{@entry.c_name}("
33
+ str << @arg_list.map { |a| a.c_code(local_scope) }.join(',')
34
+ str << ')'
35
+ str
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,83 @@
1
+ module Rubex
2
+ module AST
3
+ module Expression
4
+ class RubyMethodCall < MethodCall
5
+ def analyse_types(local_scope)
6
+ @entry = local_scope.find(@method_name)
7
+ add_as_ruby_method_to_symtab(local_scope) unless @entry
8
+ super
9
+ @arg_list.analyse_types local_scope
10
+ @type = Rubex::DataType::RubyObject.new
11
+ @arg_list.map! { |a| a.to_ruby_object }
12
+ @arg_list.allocate_temps local_scope
13
+ @arg_list.release_temps local_scope
14
+ prepare_arg_list(local_scope) if !@entry.extern? && !@arg_list.empty?
15
+ @has_temp = true
16
+ end
17
+
18
+ def generate_evaluation_code code, local_scope
19
+ super
20
+ code_for_ruby_method_call code, local_scope
21
+ end
22
+
23
+ def c_code(local_scope)
24
+ @c_code
25
+ end
26
+
27
+ private
28
+
29
+ def add_as_ruby_method_to_symtab(local_scope)
30
+ @entry = local_scope.add_ruby_method(
31
+ name: @method_name,
32
+ c_name: @method_name,
33
+ extern: true,
34
+ arg_list: @arg_list,
35
+ scope: nil
36
+ )
37
+ end
38
+
39
+ def prepare_arg_list(local_scope)
40
+ @arg_list_var = @entry.c_name + Rubex::ACTUAL_ARGS_SUFFIX
41
+ args_size = @entry.type.arg_list&.size || 0
42
+ local_scope.add_carray(name: @arg_list_var, c_name: @arg_list_var,
43
+ dimension: Literal::Int.new(args_size.to_s),
44
+ type: @type)
45
+ end
46
+
47
+ def code_for_ruby_method_call(code, local_scope)
48
+ str = "#{@c_code} = "
49
+ if @entry.extern?
50
+ str << "rb_funcall(#{@invoker.c_code(local_scope)}, "
51
+ str << "rb_intern(\"#{@method_name}\"), "
52
+ str << @arg_list.size.to_s
53
+ @arg_list.each do |arg|
54
+ str << " ,#{arg.c_code(local_scope)}"
55
+ end
56
+ str << ', NULL' if @arg_list.empty?
57
+ str << ");\n"
58
+ else
59
+ str << populate_method_args_into_value_array(local_scope)
60
+ str << actual_ruby_method_call(local_scope)
61
+ end
62
+ code << str
63
+ end
64
+
65
+ def actual_ruby_method_call(local_scope)
66
+ str = "#{@entry.c_name}(#{@arg_list.size}, #{@arg_list_var || 'NULL'},"
67
+ str << "#{local_scope.self_name});"
68
+ end
69
+
70
+ def populate_method_args_into_value_array(local_scope)
71
+ str = ''
72
+ @arg_list.each_with_index do |arg, idx|
73
+ str = "#{@arg_list_var}[#{idx}] = "
74
+ str << arg.c_code(local_scope).to_s
75
+ str << ";\n"
76
+ end
77
+
78
+ str
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,127 @@
1
+ module Rubex
2
+ module AST
3
+ module Expression
4
+ # Singular name node with no sub expressions.
5
+ class Name < Base
6
+ def initialize(name)
7
+ @name = name
8
+ end
9
+
10
+ # Used when the node is a LHS of an assign statement.
11
+ def analyse_declaration(_rhs, local_scope)
12
+ @entry = local_scope.find @name
13
+ unless @entry
14
+ local_scope.add_ruby_obj(name: @name, c_name: Rubex::VAR_PREFIX + @name, value: @rhs)
15
+ @entry = local_scope[@name]
16
+ end
17
+ @type = @entry.type
18
+ end
19
+
20
+ def analyse_for_target_type(target_type, local_scope)
21
+ @entry = local_scope.find @name
22
+
23
+ if @entry&.type&.c_function? && target_type.c_function_ptr?
24
+ @type = @entry.type
25
+ else
26
+ analyse_types local_scope
27
+ end
28
+ end
29
+
30
+ # Analyse a Name node. This can either be a variable name or a method call
31
+ # without parenthesis. Code in this method that creates a RubyMethodCall
32
+ # node primarily exists because in Ruby methods without arguments can
33
+ # be called without parentheses. These names can potentially be Ruby
34
+ # methods that are not visible to Rubex, but are present in the Ruby
35
+ # run time. For example, a program like this:
36
+ #
37
+ # def foo
38
+ # bar
39
+ # #^^^ this is a name node
40
+ # end
41
+ def analyse_types(local_scope)
42
+ @entry = local_scope.find @name
43
+ unless @entry
44
+ if ruby_constant?
45
+ analyse_as_ruby_constant local_scope
46
+ else
47
+ add_as_ruby_method_to_scope local_scope
48
+ end
49
+ end
50
+ analyse_as_ruby_method(local_scope) if @entry.type.ruby_method?
51
+ assign_type_based_on_whether_wrapped_type
52
+ if @name.is_a?(Expression::Base)
53
+ @name.allocate_temps local_scope
54
+ @name.release_temps local_scope
55
+ end
56
+ super
57
+ end
58
+
59
+ def generate_evaluation_code(code, local_scope)
60
+ if @name.respond_to? :generate_evaluation_code
61
+ @name.generate_evaluation_code code, local_scope
62
+ end
63
+ end
64
+
65
+ def generate_disposal_code(code)
66
+ if @name.respond_to? :generate_disposal_code
67
+ @name.generate_disposal_code code
68
+ end
69
+ end
70
+
71
+ def generate_assignment_code(rhs, code, local_scope)
72
+ code << "#{c_code(local_scope)} = #{rhs.c_code(local_scope)};"
73
+ code.nl
74
+ rhs.generate_disposal_code code
75
+ end
76
+
77
+ def c_code(local_scope)
78
+ code = super
79
+ code <<
80
+ if @name.is_a?(Rubex::AST::Expression::Base)
81
+ @name.c_code(local_scope)
82
+ else
83
+ @entry.c_name
84
+ end
85
+ code
86
+ end
87
+
88
+ private
89
+
90
+ def ruby_constant?
91
+ @name[0].match(/[A-Z]/)
92
+ end
93
+
94
+ def analyse_as_ruby_constant(local_scope)
95
+ @name = Expression::RubyConstant.new @name
96
+ @name.analyse_types local_scope
97
+ @entry = @name.entry
98
+ end
99
+
100
+ def add_as_ruby_method_to_scope(local_scope)
101
+ @entry = local_scope.add_ruby_method(
102
+ name: @name,
103
+ c_name: @name,
104
+ extern: true,
105
+ scope: nil,
106
+ arg_list: Expression::ActualArgList.new([])
107
+ )
108
+ end
109
+
110
+ def analyse_as_ruby_method(local_scope)
111
+ @name = Rubex::AST::Expression::RubyMethodCall.new(
112
+ Expression::Self.new, @name, Expression::ActualArgList.new([])
113
+ )
114
+ @name.analyse_types local_scope
115
+ end
116
+
117
+ def assign_type_based_on_whether_wrapped_type
118
+ if @entry.type.alias_type? || @entry.type.ruby_method? || @entry.type.c_function?
119
+ @type = @entry.type.type
120
+ else
121
+ @type = @entry.type
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,25 @@
1
+ module Rubex
2
+ module AST
3
+ module Expression
4
+ class RubyConstant < Base
5
+ def initialize(name)
6
+ @name = name
7
+ end
8
+
9
+ def analyse_types(_local_scope)
10
+ @type = Rubex::DataType::RubyConstant.new @name
11
+ c_name = Rubex::DEFAULT_CLASS_MAPPINGS[@name]
12
+ @entry = Rubex::SymbolTable::Entry.new @name, c_name, @type, nil
13
+ end
14
+
15
+ def c_code(local_scope)
16
+ if @entry.c_name # built-in constant.
17
+ @entry.c_name
18
+ else
19
+ "rb_const_get(CLASS_OF(#{local_scope.self_name}), rb_intern(\"#{@entry.name}\"))"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ module Rubex
2
+ module AST
3
+ module Expression
4
+ class RubyArrayElementRef < RubyObjectElementRef
5
+ def analyse_types(local_scope)
6
+ @has_temp = true
7
+ @pos.analyse_types local_scope
8
+ @subexprs << @pos
9
+ end
10
+
11
+ def generate_evaluation_code(code, local_scope)
12
+ generate_and_dispose_subexprs(code, local_scope) do
13
+ code << "#{@c_code} = RARRAY_AREF(#{@entry.c_name}, #{@pos.c_code(local_scope)});"
14
+ code.nl
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ module Rubex
2
+ module AST
3
+ module Expression
4
+ class RubyHashElementRef < RubyObjectElementRef
5
+ def generate_evaluation_code(code, local_scope)
6
+ generate_and_dispose_subexprs(code, local_scope) do
7
+ code << "#{@c_code} = rb_hash_aref(#{@entry.c_name}, #{@pos.c_code(local_scope)});"
8
+ code.nl
9
+ end
10
+ end
11
+
12
+ def generate_assignment_code(rhs, code, local_scope)
13
+ generate_and_dispose_subexprs(code, local_scope) do
14
+ code << "rb_hash_aset(#{@entry.c_name}, #{@pos.c_code(local_scope)},"
15
+ code << "#{rhs.c_code(local_scope)});"
16
+ code.nl
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end