rubex 0.1 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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,22 @@
1
+ require_relative 'helper'
2
+ module Rubex
3
+ module AST
4
+ module Statement
5
+ class IfBlock < Base
6
+ class Elsif < Base
7
+ attr_reader :expr, :statements, :if_tail
8
+ include Rubex::AST::Statement::IfBlock::Helper
9
+
10
+ def initialize(expr, statements, if_tail, location)
11
+ super(location)
12
+ @expr = expr
13
+ @statements = statements
14
+ @if_tail = if_tail
15
+ end
16
+
17
+ def generate_code(code, local_scope); end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,38 @@
1
+ module Rubex
2
+ module AST
3
+ module Statement
4
+ class IfBlock < Base
5
+ module Helper
6
+ def analyse_statement(local_scope)
7
+ @statements.each do |stat|
8
+ stat.analyse_statement local_scope
9
+ end
10
+
11
+ @if_tail&.analyse_statement(local_scope)
12
+ end
13
+
14
+ def generate_code_for_statement(stat, code, local_scope, node)
15
+ if stat != 'else'
16
+ condition = node.expr.c_code(local_scope)
17
+ expr_condition = node.expr.type.object? ? "RTEST(#{condition})" : condition
18
+ code << "#{stat} (#{expr_condition}) "
19
+ else
20
+ code << stat.to_s
21
+ end
22
+
23
+ code.block do
24
+ node.statements.each do |stat|
25
+ stat.generate_code code, local_scope
26
+ code.nl
27
+ end
28
+ end
29
+
30
+ if stat != 'else'
31
+ node.if_tail&.generate_code(code, local_scope)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,49 @@
1
+ module Rubex
2
+ module AST
3
+ module Statement
4
+ class Print < Base
5
+ def initialize(expressions, location)
6
+ super(location)
7
+ @expressions = expressions
8
+ end
9
+
10
+ def analyse_statement(local_scope)
11
+ @expressions.each do |expr|
12
+ expr.analyse_types local_scope
13
+ expr.allocate_temps local_scope
14
+ expr.release_temps local_scope
15
+ end
16
+ end
17
+
18
+ def generate_code(code, local_scope)
19
+ super
20
+ @expressions.each do |expr|
21
+ expr.generate_evaluation_code code, local_scope
22
+
23
+ str = 'printf('
24
+ str << "\"#{expr.type.p_formatter}\""
25
+ str << ", #{inspected_expr(expr, local_scope)}"
26
+ str << ');'
27
+ code << str
28
+ code.nl
29
+
30
+ expr.generate_disposal_code code
31
+ end
32
+
33
+ code.nl
34
+ end
35
+
36
+ private
37
+
38
+ def inspected_expr(expr, local_scope)
39
+ obj = expr.c_code(local_scope)
40
+ if expr.type.object?
41
+ "RSTRING_PTR(rb_funcall(#{obj}, rb_intern(\"inspect\"), 0, NULL))"
42
+ else
43
+ obj
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,66 @@
1
+ module Rubex
2
+ module AST
3
+ module Statement
4
+ class Raise < Base
5
+ def initialize(args)
6
+ @args = args
7
+ end
8
+
9
+ def analyse_statement(local_scope)
10
+ @args.analyse_types local_scope
11
+ @args.allocate_temps local_scope
12
+ @args.release_temps local_scope
13
+ unless @args.empty? || @args[0].is_a?(AST::Expression::Name) ||
14
+ @args[0].is_a?(AST::Expression::Literal::StringLit)
15
+ raise Rubex::TypeMismatchError, "Wrong argument list #{@args.inspect} for raise."
16
+ end
17
+ end
18
+
19
+ def generate_code(code, local_scope)
20
+ @args.generate_evaluation_code code, local_scope
21
+ str = ''
22
+ str << 'rb_raise('
23
+
24
+ if @args[0].is_a?(AST::Expression::Name)
25
+ str << @args[0].c_code(local_scope) + ','
26
+ args = @args[1..-1]
27
+ else
28
+ str << Rubex::DEFAULT_CLASS_MAPPINGS['RuntimeError'] + ','
29
+ args = @args
30
+ end
31
+
32
+ unless args.empty?
33
+ str << "\"#{prepare_format_string(args)}\" ,"
34
+ str << args.map { |arg| (inspected_expr(arg, local_scope)).to_s }.join(',')
35
+ else
36
+ str << '""'
37
+ end
38
+ str << ');'
39
+ code << str
40
+ code.nl
41
+ @args.generate_disposal_code code
42
+ end
43
+
44
+ private
45
+
46
+ def prepare_format_string(args)
47
+ format_string = ''
48
+ args.each do |expr|
49
+ format_string << expr.type.p_formatter
50
+ end
51
+
52
+ format_string
53
+ end
54
+
55
+ def inspected_expr(expr, local_scope)
56
+ obj = expr.c_code(local_scope)
57
+ if expr.type.object?
58
+ "RSTRING_PTR(rb_funcall(#{obj}, rb_intern(\"inspect\"), 0, NULL))"
59
+ else
60
+ obj
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,45 @@
1
+ module Rubex
2
+ module AST
3
+ module Statement
4
+ class Return < Base
5
+ def initialize(expression, location)
6
+ super(location)
7
+ @expression = expression
8
+ end
9
+
10
+ def analyse_statement(local_scope)
11
+ unless @expression
12
+ if local_scope.type.ruby_method?
13
+ @expression = Rubex::AST::Expression::Literal::Nil.new 'Qnil'
14
+ elsif local_scope.type.c_function?
15
+ @expression = Rubex::AST::Expression::Empty.new
16
+ end # FIXME: print a warning for type mismatch if none of above
17
+ end
18
+
19
+ @expression.analyse_types local_scope
20
+ @expression.allocate_temps local_scope
21
+ @expression.release_temps local_scope
22
+ t = @expression.type
23
+
24
+ @type =
25
+ if t.c_function? || t.alias_type?
26
+ t.type
27
+ else
28
+ t
29
+ end
30
+ @expression = @expression.to_ruby_object if local_scope.type.type.object?
31
+
32
+ # TODO: Raise error if type as inferred from the
33
+ # is not compatible with the return statement type.
34
+ end
35
+
36
+ def generate_code(code, local_scope)
37
+ super
38
+ @expression.generate_evaluation_code code, local_scope
39
+ code << "return #{@expression.c_code(local_scope)};"
40
+ code.nl
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,49 @@
1
+ module Rubex
2
+ module AST
3
+ module Statement
4
+ class VarDecl < Base
5
+ attr_reader :type, :value
6
+
7
+ def initialize(type, name, value, location)
8
+ super(location)
9
+ @name = name
10
+ @value = value
11
+ @type = type
12
+ end
13
+
14
+ def analyse_statement(local_scope, extern: false)
15
+ # TODO: Have type checks for knowing if correct literal assignment
16
+ # is taking place. For example, a char should not be assigned a float.
17
+ @type = Helpers.determine_dtype @type, ''
18
+ c_name = extern ? @name : Rubex::VAR_PREFIX + @name
19
+ if @value
20
+ @value.analyse_for_target_type(@type, local_scope)
21
+ @value.allocate_temps local_scope
22
+ @value = Helpers.to_lhs_type(self, @value)
23
+ @value.release_temps local_scope
24
+ end
25
+
26
+ local_scope.declare_var name: @name, c_name: c_name, type: @type,
27
+ value: @value, extern: extern
28
+ end
29
+
30
+ def rescan_declarations(scope)
31
+ if @type.is_a? String
32
+ @type = Rubex::CUSTOM_TYPES[@type]
33
+ scope[@name].type = @type
34
+ end
35
+ end
36
+
37
+ def generate_code(code, local_scope)
38
+ if @value
39
+ @value.generate_evaluation_code code, local_scope
40
+ lhs = local_scope.find(@name).c_name
41
+ code << "#{lhs} = #{@value.c_code(local_scope)};"
42
+ code.nl
43
+ @value.generate_disposal_code code
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,34 @@
1
+ module Rubex
2
+ module AST
3
+ module Statement
4
+ class While < Base
5
+ def initialize(expr, statements, location)
6
+ super(location)
7
+ @expr = expr
8
+ @statements = statements
9
+ end
10
+
11
+ def analyse_statement(local_scope)
12
+ @expr.analyse_types local_scope
13
+ @expr.release_temps local_scope
14
+ @statements.each do |stat|
15
+ stat.analyse_statement local_scope
16
+ end
17
+ @expr.release_temps local_scope
18
+ end
19
+
20
+ def generate_code(code, local_scope)
21
+ @expr.generate_evaluation_code code, local_scope
22
+ stmt = "while (#{@expr.c_code(local_scope)})"
23
+ code << stmt
24
+ code.block do
25
+ @statements.each do |stat|
26
+ stat.generate_code code, local_scope
27
+ end
28
+ end
29
+ @expr.generate_disposal_code code
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,41 @@
1
+ module Rubex
2
+ module AST
3
+ module Statement
4
+ class Yield < Base
5
+ def initialize(args)
6
+ @args = args
7
+ end
8
+
9
+ def analyse_statement(local_scope)
10
+ @args = @args.map do |arg|
11
+ arg.analyse_types local_scope
12
+ arg.allocate_temps local_scope
13
+ arg.to_ruby_object
14
+ end
15
+ @args.each do |arg|
16
+ arg.release_temps local_scope
17
+ end
18
+ end
19
+
20
+ def generate_code(code, local_scope)
21
+ @args.each do |a|
22
+ a.generate_evaluation_code code, local_scope
23
+ end
24
+
25
+ if !@args.empty?
26
+ code << "rb_yield_values(#{@args.size}, "
27
+ code << (@args.map { |a| a.c_code(local_scope) }.join(',')).to_s
28
+ code << ');'
29
+ else
30
+ code << 'rb_yield(Qnil);'
31
+ end
32
+ code.nl
33
+
34
+ @args.each do |a|
35
+ a.generate_disposal_code code
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,815 +1 @@
1
- module Rubex
2
- module AST
3
- module TopStatement
4
- class CBindings
5
- attr_reader :lib, :declarations, :location
6
-
7
- def initialize lib, comp_opts, declarations, location
8
- @lib, @comp_opts, @declarations, @location = lib, comp_opts,
9
- declarations, location
10
- end
11
-
12
- def analyse_statement local_scope
13
- unless @declarations
14
- @declarations = []
15
- load_predecided_declarations
16
- end
17
- @declarations.each do |stat|
18
- stat.analyse_statement local_scope, extern: true
19
- end
20
- local_scope.include_files.push @lib
21
- update_compiler_config
22
- end
23
-
24
- def generate_code code
25
-
26
- end
27
-
28
- private
29
- def update_compiler_config
30
- @comp_opts.each do |h|
31
- if h[:link]
32
- Rubex::Compiler::CONFIG.add_link h[:link]
33
- end
34
- end
35
- end
36
-
37
- def load_predecided_declarations
38
- if @lib == 'rubex/ruby'
39
- load_ruby_functions_and_types
40
- @lib = '<ruby.h>'
41
- elsif @lib == 'rubex/ruby/encoding'
42
- load_ruby_encoding_functions_and_type
43
- @lib = '<ruby/encoding.h>'
44
- elsif @lib == 'rubex/stdlib'
45
- load_stdlib_functions_and_types
46
- @lib = '<stdlib.h>'
47
- else
48
- raise Rubex::LibraryNotFoundError, "Cannot find #{@lib}."
49
- end
50
- end
51
-
52
- def load_ruby_functions_and_types
53
- @declarations << xmalloc
54
- @declarations << xfree
55
- @declarations << type_get
56
- @declarations.concat type_identifiers
57
- @declarations << rb_str_new
58
- @declarations << rb_ary_includes
59
- end
60
-
61
- def load_ruby_encoding_functions_and_type
62
- @declarations << rb_enc_associate_index
63
- @declarations << rb_enc_find_index
64
- end
65
-
66
- def load_stdlib_functions_and_types
67
- @declarations.concat atox_functions
68
- end
69
-
70
- def rb_ary_includes
71
- cfunc_decl('object', '', 'rb_ary_includes',
72
- arg_list([arg('object', '','ary'), arg('object', '','item')]))
73
- end
74
-
75
- def atox_functions
76
- [
77
- ['int', 'atoi'], ['long', 'atol'], ['long long', 'atoll'],
78
- ['double', 'atof']
79
- ].map do |type, ident|
80
- cfunc_decl(type, '', ident, arg_list([arg('char', '*', 'str')]))
81
- end
82
- end
83
-
84
- def rb_enc_find_index
85
- cfunc_decl('int', '', 'rb_enc_find_index',
86
- arg_list([arg('char', '*', 'enc')]))
87
- end
88
-
89
- def rb_enc_associate_index
90
- args = arg_list([arg('object', '', 'string'), arg('int', '', 'enc')])
91
- cfunc_decl('object', '', 'rb_enc_associate_index', args)
92
- end
93
-
94
- def rb_str_new
95
- args = arg_list([arg('char', '*', 'str'), arg('long', '', 'length')])
96
- cfunc_decl('object', '', 'rb_str_new', args)
97
- end
98
-
99
- def type_get
100
- cfunc_decl('int', '', 'TYPE', arg_list([arg('object', '', 'dummy')]))
101
- end
102
-
103
- def type_identifiers
104
- stmts = [
105
- 'T_ARRAY', 'T_NIL', 'T_TRUE', 'T_FALSE', 'T_FLOAT', 'T_FIXNUM',
106
- 'T_BIGNUM', 'T_REGEXP', 'T_STRING'
107
- ].map do |ident|
108
- Statement::VarDecl.new('int', ident, nil, @location)
109
- end
110
-
111
- stmts
112
- end
113
-
114
- def xmalloc
115
- args = Statement::ArgumentList.new([
116
- Expression::ArgDeclaration.new({
117
- dtype: 'size_t', variables: [{ident: 'dummy'}] })
118
- ])
119
- Statement::CFunctionDecl.new('void', '*', 'xmalloc', args)
120
- end
121
-
122
- def xfree
123
- cfunc_decl 'void', '', 'xfree', arg_list([arg('void', '*', 'dummy')])
124
- end
125
-
126
- private
127
-
128
- def arg type, ptr_level, ident
129
- Expression::ArgDeclaration.new({
130
- dtype: type, variables: [{ ident: ident, ptr_level: ptr_level }]
131
- })
132
- end
133
-
134
- def cfunc_decl return_type, return_ptr_level, ident, args
135
- Statement::CFunctionDecl.new(return_type, return_ptr_level, ident, args)
136
- end
137
-
138
- def arg_list args
139
- Statement::ArgumentList.new args
140
- end
141
- end # class CBindings
142
-
143
- class MethodDef
144
- include Rubex::Helpers::Writers
145
- # Ruby name of the method.
146
- attr_reader :name
147
- # Method arguments. Accessor because arguments need to be modified in
148
- # case of auxillary C functions of attach classes.
149
- attr_accessor :arg_list
150
- # The statments/expressions contained within the method.
151
- attr_reader :statements
152
- # Symbol Table entry.
153
- attr_reader :entry
154
- # Instance of Scope::Local for this method.
155
- attr_reader :scope
156
- # Variable name that identifies 'self'
157
- attr_reader :self_name
158
-
159
- def initialize name, arg_list, statements
160
- @name, @arg_list, @statements = name, arg_list, statements
161
- @self_name = Rubex::ARG_PREFIX + "self"
162
- end
163
-
164
- def analyse_statement outer_scope
165
- @entry = outer_scope.find @name
166
- @scope = @entry.type.scope
167
- @scope.type = @entry.type
168
- @scope.self_name = @self_name
169
- @arg_list = @entry.type.arg_list
170
- @statements.each do |stat|
171
- stat.analyse_statement @scope
172
- end
173
- end
174
-
175
- # Option c_function - When set to true, certain code that is not required
176
- # for Ruby methods will be generated too.
177
- def generate_code code, c_function: false
178
- code.block do
179
- generate_function_definition code, c_function: c_function
180
- end
181
- end
182
-
183
- def rescan_declarations scope
184
- @statements.each do |stat|
185
- stat.respond_to?(:rescan_declarations) and
186
- stat.rescan_declarations(@scope)
187
- end
188
- end
189
-
190
- private
191
- def generate_function_definition code, c_function:
192
- declare_types code, @scope
193
- declare_args code unless c_function
194
- declare_vars code, @scope
195
- declare_carrays code, @scope
196
- declare_ruby_objects code, @scope
197
- declare_temps code, @scope
198
- generate_arg_checking code unless c_function
199
- init_args code unless c_function
200
- declare_carrays_using_init_var_value code
201
- generate_statements code
202
- end
203
-
204
- def declare_args code
205
- @scope.arg_entries.each do |arg|
206
- code.declare_variable type: arg.type.to_s, c_name: arg.c_name
207
- end
208
- end
209
-
210
- def generate_statements code
211
- @statements.each do |stat|
212
- stat.generate_code code, @scope
213
- end
214
- end
215
-
216
- def init_args code
217
- @scope.arg_entries.each_with_index do |arg, i|
218
- code << arg.c_name + '=' + arg.type.from_ruby_object("argv[#{i}]") + ';'
219
- code.nl
220
- end
221
- end
222
-
223
- def declare_carrays_using_init_var_value code
224
- @scope.carray_entries.select { |s|
225
- !s.type.dimension.is_a?(Rubex::AST::Expression::Literal::Base)
226
- }. each do |arr|
227
- type = arr.type.type.to_s
228
- c_name = arr.c_name
229
- dimension = arr.type.dimension.c_code(@scope)
230
- value = arr.value.map { |a| a.c_code(@scope) } if arr.value
231
- code.declare_carray(type: type, c_name: c_name, dimension: dimension,
232
- value: value)
233
- end
234
- end
235
-
236
- def generate_arg_checking code
237
- code << 'if (argc < ' + @scope.arg_entries.size.to_s + ")"
238
- code.block do
239
- code << %Q{rb_raise(rb_eArgError, "Need #{@scope.arg_entries.size} args, not %d", argc);\n}
240
- end
241
- end
242
- end
243
-
244
- class RubyMethodDef < MethodDef
245
- attr_reader :singleton
246
-
247
- def initialize name, arg_list, statements, singleton: false
248
- super(name, arg_list, statements)
249
- @singleton = singleton
250
- end
251
-
252
- def analyse_statement local_scope
253
- super
254
- @entry.singleton = @singleton
255
- end
256
-
257
- def generate_code code
258
- code.write_ruby_method_header(type: @entry.type.type.to_s,
259
- c_name: @entry.c_name)
260
- super
261
- end
262
-
263
- def == other
264
- self.class == other.class && @name == other.name &&
265
- @c_name == other.c_name && @arg_list == other.arg_list &&
266
- @statements == other.statements && @entry == other.entry &&
267
- @type == other.type
268
- end
269
- end # class RubyMethodDef
270
-
271
- class CFunctionDef < MethodDef
272
- attr_reader :type, :return_ptr_level
273
-
274
- def initialize type, return_ptr_level, name, arg_list, statements
275
- super(name, arg_list, statements)
276
- @type = type
277
- @return_ptr_level = return_ptr_level
278
- end
279
-
280
- def analyse_statement outer_scope, extern: false
281
- super(outer_scope)
282
- end
283
-
284
- def generate_code code
285
- code.write_c_method_header(type: @entry.type.type.to_s,
286
- c_name: @entry.c_name, args: Helpers.create_arg_arrays(@arg_list))
287
- super code, c_function: true
288
- end
289
- end # class CFunctionDef
290
-
291
- class Klass
292
- include Rubex::Helpers::Writers
293
- # Stores the scope of the class. Rubex::SymbolTable::Scope::Klass.
294
- attr_reader :scope
295
-
296
- attr_reader :name
297
-
298
- attr_reader :ancestor
299
-
300
- attr_reader :statements
301
-
302
- attr_reader :entry
303
-
304
- # Name of the class. Ancestor can be Scope::Klass or String object
305
- # depending on whether invoker is another higher level scope or
306
- # the parser. Statements are the statements inside the class.
307
- def initialize name, ancestor, statements
308
- @name, @ancestor, @statements = name, ancestor, statements
309
- @ancestor = 'Object' if @ancestor.nil?
310
- end
311
-
312
- def analyse_statement local_scope, attach_klass: false
313
- @entry = local_scope.find(@name)
314
- @scope = @entry.type.scope
315
- @ancestor = @entry.type.ancestor
316
- add_statement_symbols_to_symbol_table
317
- if !attach_klass
318
- @statements.each do |stat|
319
- stat.analyse_statement @scope
320
- end
321
- end
322
- end
323
-
324
- def rescan_declarations local_scope
325
- @statements.each do |stat|
326
- stat&.rescan_declarations(@scope)
327
- end
328
- end
329
-
330
- def generate_code code
331
- @scope.begin_block_callbacks.each do |cb|
332
- cb.generate_code code
333
- end
334
-
335
- @statements.each do |stat|
336
- stat.generate_code code
337
- end
338
- end
339
-
340
- protected
341
-
342
- def add_statement_symbols_to_symbol_table
343
- @statements.each do |stmt|
344
- if ruby_method_or_c_function?(stmt)
345
- f_name, f_scope = prepare_name_and_scope_of_functions(stmt)
346
- if !auxillary_c_function_for_attached_klass?(f_name)
347
- stmt.arg_list.analyse_statement(f_scope)
348
- if stmt.is_a? Rubex::AST::TopStatement::RubyMethodDef
349
- add_ruby_method_to_scope f_name, f_scope, stmt.arg_list
350
- elsif stmt.is_a? Rubex::AST::TopStatement::CFunctionDef
351
- return_type = Helpers.determine_dtype(stmt.type, stmt.return_ptr_level)
352
- add_c_function_to_scope f_name, f_scope, stmt.arg_list, return_type
353
- end
354
- end
355
- end
356
- end
357
- end
358
-
359
- def auxillary_c_function_for_attached_klass? f_name
360
- self.is_a?(AttachedKlass) and [
361
- Rubex::ALLOC_FUNC_NAME, Rubex::DEALLOC_FUNC_NAME,
362
- Rubex::MEMCOUNT_FUNC_NAME, Rubex::GET_STRUCT_FUNC_NAME
363
- ].include?(f_name)
364
- end
365
-
366
- def add_c_function_to_scope f_name, f_scope, arg_list, return_type
367
- c_name = c_func_c_name(f_name)
368
- arg_list.each do |arg|
369
- if arg.entry.value
370
- e = arg.entry
371
- e.value = Rubex::Helpers.to_lhs_type(e, e.value)
372
- end
373
- end
374
- @scope.add_c_method(
375
- name: f_name,
376
- c_name: c_name,
377
- extern: false,
378
- return_type: return_type,
379
- arg_list: arg_list,
380
- scope: f_scope
381
- )
382
- end
383
-
384
- def add_ruby_method_to_scope f_name, f_scope, arg_list
385
- c_name = Rubex::RUBY_FUNC_PREFIX + @name + "_" +
386
- f_name.gsub("?", "_qmark").gsub("!", "_bang")
387
- @scope.add_ruby_method(
388
- name: f_name,
389
- c_name: c_name,
390
- scope: f_scope,
391
- arg_list: arg_list
392
- )
393
- end
394
-
395
- def prepare_name_and_scope_of_functions stmt
396
- f_name = stmt.name
397
- f_scope = Rubex::SymbolTable::Scope::Local.new f_name, @scope
398
- [f_name, f_scope]
399
- end
400
-
401
- def ruby_method_or_c_function? stmt
402
- stmt.is_a?(Rubex::AST::TopStatement::RubyMethodDef) ||
403
- stmt.is_a?(Rubex::AST::TopStatement::CFunctionDef)
404
- end
405
-
406
- def c_func_c_name name
407
- Rubex::C_FUNC_PREFIX + @name + "_" + name
408
- end
409
- end # class Klass
410
-
411
- class AttachedKlass < Klass
412
-
413
- attr_reader :attached_type
414
-
415
- ALLOC_FUNC_NAME = Rubex::ALLOC_FUNC_NAME
416
- DEALLOC_FUNC_NAME = Rubex::DEALLOC_FUNC_NAME
417
- MEMCOUNT_FUNC_NAME = Rubex::MEMCOUNT_FUNC_NAME
418
- GET_STRUCT_FUNC_NAME = Rubex::GET_STRUCT_FUNC_NAME
419
-
420
- def initialize name, attached_type, ancestor, statements, location
421
- @attached_type = attached_type
422
- @location = location
423
- super(name, ancestor, statements)
424
- end
425
-
426
- def analyse_statement outer_scope
427
- super(outer_scope, attach_klass: true)
428
- prepare_data_holding_struct
429
- prepare_rb_data_type_t_struct
430
- detach_and_modify_auxillary_c_functions_from_statements
431
- add_auxillary_functions_to_klass_scope
432
- prepare_auxillary_c_functions
433
- @statements[1..-1].each do |stmt| # 0th stmt is the data struct
434
- if ruby_method_or_c_func?(stmt)
435
- rewrite_method_with_data_fetching stmt
436
- end
437
- stmt.analyse_statement @scope
438
- end
439
- analyse_auxillary_c_functions
440
- end
441
-
442
- def generate_code code
443
- write_auxillary_c_functions code
444
- write_data_type_t_struct code
445
- write_get_struct_c_function code
446
- write_alloc_c_function code
447
- super
448
- end
449
-
450
- private
451
-
452
- # Since auxillary functions are detached from the klass statements,
453
- # analyse their arg_list separately and add function names to the
454
- # class scope so that their statements can be analysed properly later.
455
- def add_auxillary_functions_to_klass_scope
456
- @auxillary_c_functions.each_value do |func|
457
- f_name, f_scope = prepare_name_and_scope_of_functions func
458
- func.arg_list.analyse_statement(f_scope)
459
- return_type = Helpers.determine_dtype(func.type, func.return_ptr_level)
460
- add_c_function_to_scope f_name, f_scope, func.arg_list, return_type
461
- end
462
- end
463
-
464
- def analyse_auxillary_c_functions
465
- @auxillary_c_functions.each_value do |func|
466
- func.analyse_statement(@scope)
467
- end
468
- end
469
-
470
- # Detach the user-supplied auxlically C functions from the class and
471
- # store them in Hash @auxillary_c_functions. Make modifications to
472
- # them if necessary and also set an ivar that indicates if an
473
- # auxillary function is user-supplied or not.
474
- def detach_and_modify_auxillary_c_functions_from_statements
475
- @auxillary_c_functions = {}
476
-
477
- indexes = []
478
- @statements.each_with_index do |stmt, idx|
479
- if stmt.is_a?(CFunctionDef)
480
- if stmt.name == ALLOC_FUNC_NAME
481
- @auxillary_c_functions[ALLOC_FUNC_NAME] = stmt
482
- @user_defined_alloc = true
483
- indexes << idx
484
- elsif stmt.name == DEALLOC_FUNC_NAME
485
- @auxillary_c_functions[DEALLOC_FUNC_NAME] = stmt
486
- @user_defined_dealloc = true
487
- modify_dealloc_func stmt
488
- indexes << idx
489
- elsif stmt.name == MEMCOUNT_FUNC_NAME
490
- @auxillary_c_functions[MEMCOUNT_FUNC_NAME] = stmt
491
- @user_defined_memcount = true
492
- indexes << idx
493
- elsif stmt.name == GET_STRUCT_FUNC_NAME
494
- @auxillary_c_functions[GET_STRUCT_FUNC_NAME] = stmt
495
- @user_defined_get_struct = true
496
- indexes << idx
497
- end
498
- end
499
- end
500
-
501
- indexes.each do |idx|
502
- @statements.delete_at idx
503
- end
504
- end
505
-
506
- def write_auxillary_c_functions code
507
- write_dealloc_c_function code
508
- write_memcount_c_function code
509
- end
510
-
511
- # Actually write the alloc function into C code.
512
- def write_alloc_c_function code
513
- if user_defined_alloc?
514
- @auxillary_c_functions[ALLOC_FUNC_NAME].generate_code code
515
- else
516
- code.write_c_method_header(
517
- type: @alloc_c_func.type.type.to_s,
518
- c_name: @alloc_c_func.c_name,
519
- args: Helpers.create_arg_arrays(@alloc_c_func.type.arg_list))
520
- code.block do
521
- lines = ""
522
- lines << "#{@data_struct.entry.c_name} *data;\n\n"
523
-
524
- lines << "data = (#{@data_struct.entry.c_name}*)xmalloc("
525
- lines << "sizeof(#{@data_struct.entry.c_name}));\n"
526
-
527
- lines << member_struct_allocations
528
-
529
- lines << "return TypedData_Wrap_Struct("
530
- lines << "#{@alloc_c_func.type.arg_list[0].entry.c_name},"
531
- lines << "&#{@data_type_t}, data);\n"
532
-
533
- code << lines
534
- end
535
- end
536
- end
537
-
538
- #TODO: modify for supporting inheritance
539
- def member_struct_allocations
540
- c_name = @scope.find(@attached_type).c_name
541
- "data->#{Rubex::POINTER_PREFIX + @attached_type} = (#{c_name}*)xmalloc(sizeof(#{c_name}));\n"
542
- end
543
-
544
- # Actually write the dealloc function into C code.
545
- def write_dealloc_c_function code
546
- if user_defined_dealloc?
547
- @auxillary_c_functions[DEALLOC_FUNC_NAME].generate_code code
548
- else
549
- # TODO: define dealloc if user hasnt supplied.
550
- end
551
- end
552
-
553
- # Actually write the memcount function into C code.
554
- def write_memcount_c_function code
555
- if user_defined_memcount?
556
- @auxillary_c_functions[MEMCOUNT_FUNC_NAME].generate_code code
557
- else
558
- code.write_c_method_header(
559
- type: @memcount_c_func.type.type.to_s,
560
- c_name: @memcount_c_func.c_name,
561
- args: Helpers.create_arg_arrays(@memcount_c_func.type.arg_list))
562
- code.block do
563
- code << "return sizeof(#{@memcount_c_func.type.arg_list[0].entry.c_name})"
564
- code.colon
565
- code.nl
566
- end
567
- end
568
- end
569
-
570
- # Actually write the get_struct function into C code.
571
- def write_get_struct_c_function code
572
- if user_defined_get_struct?
573
- @auxillary_c_functions[GET_STRUCT_FUNC_NAME].generate_code code
574
- else
575
- code.write_c_method_header(
576
- type: @get_struct_c_func.type.type.to_s,
577
- c_name: @get_struct_c_func.c_name,
578
- args: Helpers.create_arg_arrays(@get_struct_c_func.type.arg_list))
579
- code.block do
580
- lines = ""
581
- lines << "#{@data_struct.entry.c_name} *data;\n\n"
582
- lines << "TypedData_Get_Struct("
583
- lines << "#{@get_struct_c_func.type.arg_list[0].entry.c_name}, "
584
- lines << "#{@data_struct.entry.c_name}, &#{@data_type_t}, data);\n"
585
- lines << "return data;\n"
586
-
587
- code << lines
588
- end
589
- end
590
- end
591
-
592
- def write_data_type_t_struct code
593
- decl = ""
594
- decl << "static const rb_data_type_t #{@data_type_t} = {\n"
595
- decl << " \"#{@name}\",\n"
596
- decl << " {0, #{@dealloc_c_func.c_name}, #{@memcount_c_func.c_name},\n"
597
- decl << " 0}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY\n"
598
- decl << "};\n"
599
-
600
- code << decl
601
- code.new_line
602
- end
603
-
604
- # Prepare the data holding struct 'data' that will hold a pointer to the
605
- # struct that is attached to this class.
606
- def prepare_data_holding_struct
607
- struct_name = @name + "_data_struct"
608
- declarations = declarations_for_data_struct
609
- @data_struct = Statement::CStructOrUnionDef.new(
610
- :struct, struct_name, declarations, @location)
611
- @data_struct.analyse_statement(@scope)
612
- @statements.unshift @data_struct
613
- end
614
-
615
- # TODO: support inherited attached structs.
616
- def declarations_for_data_struct
617
- stmts = []
618
- stmts << Statement::CPtrDecl.new(@attached_type, @attached_type, nil,
619
- "*", @location)
620
-
621
- stmts
622
- end
623
-
624
- def prepare_rb_data_type_t_struct
625
- @data_type_t = Rubex::ATTACH_CLASS_PREFIX + "_" + @name + "_data_type_t"
626
- end
627
-
628
- # Prepare auxillary function in case they have not been supplied by user
629
- # and create ivars for their Symbol Table entries for easy accesss later.
630
- def prepare_auxillary_c_functions
631
- prepare_alloc_c_function
632
- prepare_memcount_c_function
633
- prepare_deallocation_c_function
634
- prepare_get_struct_c_function
635
- end
636
-
637
- def ruby_method_or_c_func? stmt
638
- stmt.is_a?(RubyMethodDef) || stmt.is_a?(CFunctionDef)
639
- end
640
-
641
- # Rewrite method `stmt` so that the `data` variable becomes available
642
- # inside the scope of the method.
643
- def rewrite_method_with_data_fetching stmt
644
- data_stmt = Statement::CPtrDecl.new(@data_struct.name, 'data',
645
- get_struct_func_call(stmt), "*", @location)
646
- stmt.statements.unshift data_stmt
647
- end
648
-
649
- def get_struct_func_call stmt
650
- Expression::CommandCall.new(nil, @get_struct_c_func.name,
651
- Statement::ArgumentList.new([]))
652
- end
653
-
654
- # Create an alloc function if it is not supplied by user.
655
- def prepare_alloc_c_function
656
- if user_defined_alloc?
657
- @alloc_c_func = @scope.find(ALLOC_FUNC_NAME)
658
- else
659
- c_name = c_func_c_name(ALLOC_FUNC_NAME)
660
- scope = Rubex::SymbolTable::Scope::Local.new(ALLOC_FUNC_NAME, @scope)
661
- arg_list = Statement::ArgumentList.new([
662
- Expression::ArgDeclaration.new({
663
- dtype: 'object',
664
- variables: [
665
- {
666
- ident: 'self'
667
- }
668
- ]
669
- })
670
- ])
671
- arg_list.analyse_statement(scope)
672
- @alloc_c_func = @scope.add_c_method(
673
- name: ALLOC_FUNC_NAME,
674
- c_name: c_name,
675
- arg_list: arg_list,
676
- return_type: DataType::RubyObject.new,
677
- scope: scope)
678
- end
679
- end
680
-
681
- # Create a memcount function if it is not supplied by user.
682
- def prepare_memcount_c_function
683
- if user_defined_memcount?
684
- @memcount_c_func = @scope.find(MEMCOUNT_FUNC_NAME)
685
- else
686
- c_name = c_func_c_name(MEMCOUNT_FUNC_NAME)
687
- scope = Rubex::SymbolTable::Scope::Local.new(MEMCOUNT_FUNC_NAME, @scope)
688
- arg_list = Statement::ArgumentList.new([
689
- Expression::ArgDeclaration.new({
690
- dtype: "void",
691
- variables: [
692
- {
693
- ptr_level: "*",
694
- ident: "raw_data"
695
- }
696
- ]
697
- })
698
- ])
699
- arg_list.analyse_statement(scope)
700
- @memcount_c_func = @scope.add_c_method(
701
- name: MEMCOUNT_FUNC_NAME,
702
- c_name: c_name,
703
- arg_list: arg_list,
704
- return_type: DataType::Size_t.new,
705
- scope: scope)
706
- end
707
- end
708
-
709
- # Create a deallocate function if it is not supplied by user.
710
- def prepare_deallocation_c_function
711
- if user_defined_dealloc?
712
- @dealloc_c_func = @scope.find(DEALLOC_FUNC_NAME)
713
- else
714
- c_name = c_func_c_name(DEALLOC_FUNC_NAME)
715
- scope = Rubex::SymbolTable::Scope::Local.new(DEALLOC_FUNC_NAME, @scope)
716
- arg_list = Statement::ArgumentList.new([
717
- Expression::ArgDeclaration.new({
718
- dtype: "void",
719
- variables: [
720
- {
721
- ptr_level: "*",
722
- ident: "raw_data"
723
- }
724
- ]
725
- })
726
- ])
727
- arg_list.analyse_statement(scope)
728
- @dealloc_c_func = @scope.add_c_method(
729
- name: DEALLOC_FUNC_NAME,
730
- c_name: c_name,
731
- return_type: DataType::Void.new,
732
- scope: scope,
733
- arg_list: arg_list)
734
- end
735
- end
736
-
737
- # Create a get_struct function if it is not supplied by user.
738
- def prepare_get_struct_c_function
739
- if user_defined_get_struct?
740
- @get_struct_c_func = @scope.find(GET_STRUCT_FUNC_NAME)
741
- else
742
- c_name = c_func_c_name(GET_STRUCT_FUNC_NAME)
743
- scope = Rubex::SymbolTable::Scope::Local.new(
744
- GET_STRUCT_FUNC_NAME, @scope)
745
- arg_list = Statement::ArgumentList.new([
746
- Expression::ArgDeclaration.new({
747
- dtype: "object",
748
- variables: [
749
- {
750
- ident: "obj"
751
- }
752
- ]
753
- })
754
- ])
755
- arg_list.analyse_statement(scope)
756
- return_type = DataType::CPtr.new(
757
- DataType::CStructOrUnion.new(
758
- :struct, @data_struct.name, @data_struct.entry.c_name, nil)
759
- )
760
- @get_struct_c_func = @scope.add_c_method(
761
- name: GET_STRUCT_FUNC_NAME,
762
- c_name: c_name,
763
- return_type: return_type,
764
- arg_list: arg_list,
765
- scope: scope
766
- )
767
- end
768
- end
769
-
770
- # Modify the dealloc function by adding an argument of type void* so
771
- # that it is compatible with what Ruby expects. This is done so that
772
- # the user is not burdened with additional knowledge of knowing the
773
- # the correct argument for deallocate.
774
- def modify_dealloc_func func
775
- func.arg_list = Statement::ArgumentList.new([
776
- Expression::ArgDeclaration.new({
777
- dtype: "void",
778
- variables: [
779
- {
780
- ptr_level: "*",
781
- ident: "raw_data"
782
- }
783
- ]
784
- })
785
- ])
786
- value = Expression::Name.new('raw_data')
787
- value.typecast = Expression::Typecast.new(@data_struct.name, "*")
788
- data_var = Statement::CPtrDecl.new(@data_struct.name, 'data', value,
789
- "*", @location)
790
- xfree = Expression::CommandCall.new(nil, 'xfree',
791
- [Expression::Name.new('data')])
792
- data_xfree = Statement::Expression.new xfree, @location
793
- func.statements.unshift data_var
794
- func.statements.push data_xfree
795
- end
796
-
797
- def user_defined_dealloc?
798
- @user_defined_dealloc
799
- end
800
-
801
- def user_defined_alloc?
802
- @user_defined_alloc
803
- end
804
-
805
- def user_defined_memcount?
806
- @user_defined_memcount
807
- end
808
-
809
- def user_defined_get_struct?
810
- @user_defined_get_struct
811
- end
812
- end # class AttachedKlass
813
- end # module TopStatement
814
- end # module AST
815
- end # module Rubex
1
+ Dir['./lib/rubex/ast/top_statement/**/*.rb'].sort.each { |f| require f }