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,43 @@
1
+ module Rubex
2
+ module AST
3
+ module Statement
4
+ class Alias < Base
5
+ def initialize(new_name, old_name, location)
6
+ super(location)
7
+ @new_name = new_name
8
+ @old_name = old_name
9
+ Rubex::CUSTOM_TYPES[@new_name] = @new_name
10
+ end
11
+
12
+ def analyse_statement(local_scope, extern: false)
13
+ original = @old_name[:dtype].gsub('struct ', '').gsub('union ', '')
14
+ var = @old_name[:variables][0]
15
+ ident = var[:ident]
16
+ ptr_level = var[:ptr_level]
17
+
18
+ base_type =
19
+ if ident.is_a?(Hash) # function pointer
20
+ cfunc_return_type = Helpers.determine_dtype(original,
21
+ ident[:return_ptr_level])
22
+ arg_list = ident[:arg_list].analyse_statement(local_scope)
23
+ ptr_level = '*' if ptr_level.empty?
24
+
25
+ Helpers.determine_dtype(
26
+ DataType::CFunction.new(nil, nil, arg_list, cfunc_return_type, nil),
27
+ ptr_level
28
+ )
29
+ else
30
+ Helpers.determine_dtype(original, ptr_level)
31
+ end
32
+
33
+ @type = Rubex::DataType::TypeDef.new(base_type, @new_name, base_type)
34
+ Rubex::CUSTOM_TYPES[@new_name] = @type
35
+ local_scope.declare_type(type: @type, extern: extern) if original != @new_name
36
+ end
37
+
38
+ def generate_code(code, local_scope); end
39
+ end
40
+ end
41
+ end
42
+ end
43
+
@@ -0,0 +1,59 @@
1
+ module Rubex
2
+ module AST
3
+ module Statement
4
+ # This node is used for both formal and actual arguments of functions/methods.
5
+ class ArgumentList < Base
6
+ include Enumerable
7
+
8
+ # args - [ArgDeclaration]
9
+ attr_reader :args
10
+
11
+ def each(&block)
12
+ @args.each(&block)
13
+ end
14
+
15
+ def map!(&block)
16
+ @args.map!(&block)
17
+ end
18
+
19
+ def pop
20
+ @args.pop
21
+ end
22
+
23
+ def initialize(args)
24
+ @args = args
25
+ end
26
+
27
+ def analyse_statement(local_scope, extern: false)
28
+ @args.each do |arg|
29
+ arg.analyse_types(local_scope, extern: extern)
30
+ end
31
+ end
32
+
33
+ def push(arg)
34
+ @args << arg
35
+ end
36
+
37
+ def <<(arg)
38
+ push arg
39
+ end
40
+
41
+ def ==(other)
42
+ self.class == other.class && @args == other.args
43
+ end
44
+
45
+ def size
46
+ @args.size
47
+ end
48
+
49
+ def empty?
50
+ @args.empty?
51
+ end
52
+
53
+ def [](idx)
54
+ @args[idx]
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,35 @@
1
+ module Rubex
2
+ module AST
3
+ module Statement
4
+ class Assign < Base
5
+ def initialize(lhs, rhs, location)
6
+ super(location)
7
+ @lhs = lhs
8
+ @rhs = rhs
9
+ end
10
+
11
+ def analyse_statement(local_scope)
12
+ if @lhs.is_a?(Rubex::AST::Expression::Name)
13
+ @lhs.analyse_declaration @rhs, local_scope
14
+ else
15
+ @lhs.analyse_types(local_scope)
16
+ end
17
+ @lhs.allocate_temps local_scope
18
+ @rhs.analyse_for_target_type(@lhs.type, local_scope)
19
+ @rhs = Helpers.to_lhs_type(@lhs, @rhs)
20
+ @rhs.allocate_temps local_scope
21
+
22
+ @lhs.release_temps local_scope
23
+ @rhs.release_temps local_scope
24
+ end
25
+
26
+ def generate_code(code, local_scope)
27
+ super
28
+ @rhs.generate_evaluation_code code, local_scope
29
+ @lhs.generate_assignment_code @rhs, code, local_scope
30
+ @rhs.generate_disposal_code code
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ module Rubex
2
+ module AST
3
+ module Statement
4
+ module BeginBlock
5
+ class Base < Statement::Base
6
+ def initialize(statements, location)
7
+ @statements = statements
8
+ super(location)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,202 @@
1
+ module Rubex
2
+ module AST
3
+ module Statement
4
+ module BeginBlock
5
+ class Begin < Base
6
+ def initialize(statements, tails, location)
7
+ @tails = tails
8
+ super(statements, location)
9
+ end
10
+
11
+ def analyse_statement(local_scope)
12
+ local_scope.found_begin_block
13
+ declare_error_state_variable local_scope
14
+ declare_error_klass_variable local_scope
15
+ declare_unhandled_error_variable local_scope
16
+ @block_scope = Rubex::SymbolTable::Scope::BeginBlock.new(
17
+ block_name(local_scope), local_scope
18
+ )
19
+ create_c_function_to_house_statements local_scope.outer_scope
20
+ analyse_tails local_scope
21
+ end
22
+
23
+ def generate_code(code, local_scope)
24
+ code.nl
25
+ code << '/* begin-rescue-else-ensure-end block begins: */'
26
+ code.nl
27
+ super
28
+ cb_c_name = local_scope.find(@begin_func.name).c_name
29
+ state_var = local_scope.find(@state_var_name).c_name
30
+ code << "#{state_var} = 0;\n"
31
+ code << "rb_protect(#{cb_c_name}, Qnil, &#{state_var});"
32
+ code.nl
33
+ generate_rescue_else_ensure code, local_scope
34
+ end
35
+
36
+ private
37
+
38
+ def generate_rescue_else_ensure(code, local_scope)
39
+ err_state_var = local_scope.find(@error_var_name).c_name
40
+ set_error_state_variable err_state_var, code, local_scope
41
+ set_unhandled_error_variable code, local_scope
42
+ generate_rescue_blocks err_state_var, code, local_scope
43
+ generate_else_block code, local_scope
44
+ generate_ensure_block code, local_scope
45
+ generate_rb_jump_tag err_state_var, code, local_scope
46
+ code << "rb_set_errinfo(Qnil);\n"
47
+ end
48
+
49
+ def declare_unhandled_error_variable(local_scope)
50
+ @unhandled_err_var_name = 'begin_block_' + local_scope.begin_block_counter.to_s + '_unhandled_error'
51
+ local_scope.declare_var(
52
+ name: @unhandled_err_var_name,
53
+ c_name: Rubex::VAR_PREFIX + @unhandled_err_var_name,
54
+ type: DataType::Int.new
55
+ )
56
+ end
57
+
58
+ def set_unhandled_error_variable(code, local_scope)
59
+ n = local_scope.find(@unhandled_err_var_name).c_name
60
+ code << "#{n} = 0;"
61
+ code.nl
62
+ end
63
+
64
+ def generate_rb_jump_tag(_err_state_var, code, local_scope)
65
+ state_var = local_scope.find(@state_var_name).c_name
66
+ code << "if (#{local_scope.find(@unhandled_err_var_name).c_name})"
67
+ code.block do
68
+ code << "rb_jump_tag(#{state_var});"
69
+ code.nl
70
+ end
71
+ end
72
+
73
+ def generate_ensure_block(code, local_scope)
74
+ ensure_block = @tails.select { |e| e.is_a?(Ensure) }[0]
75
+ ensure_block&.generate_code(code, local_scope)
76
+ end
77
+
78
+ # We use a goto statement to jump to the ensure block so that when a
79
+ # condition arises where no error is raised, the ensure statement will
80
+ # be executed, after which rb_jump_tag() will be called.
81
+ def generate_else_block(code, local_scope)
82
+ else_block = @tails.select { |t| t.is_a?(Else) }[0]
83
+
84
+ code << 'else'
85
+ code.block do
86
+ state_var = local_scope.find(@state_var_name).c_name
87
+ code << '/* If exception not among those captured in raise */'
88
+ code.nl
89
+
90
+ code << "if (#{state_var})"
91
+ code.block do
92
+ code << "#{local_scope.find(@unhandled_err_var_name).c_name} = 1;"
93
+ code.nl
94
+ end
95
+
96
+ if else_block
97
+ code << 'else'
98
+ code.block do
99
+ else_block.generate_code code, local_scope
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ def set_error_state_variable(err_state_var, code, _local_scope)
106
+ code << "#{err_state_var} = rb_errinfo();"
107
+ code.nl
108
+ end
109
+
110
+ def generate_rescue_blocks(err_state_var, code, local_scope)
111
+ if @tails[0].is_a?(Rescue)
112
+ generate_first_rescue_block err_state_var, code, local_scope
113
+
114
+ @tails[1..-1].grep(Rescue).each do |resc|
115
+ else_if_cond = rescue_condition err_state_var, resc, code, local_scope
116
+ code << "else if (#{else_if_cond})"
117
+ code.block do
118
+ resc.generate_code code, local_scope
119
+ end
120
+ end
121
+ else # no rescue blocks present
122
+ code << "if (0) {}\n"
123
+ end
124
+ end
125
+
126
+ def generate_first_rescue_block(err_state_var, code, local_scope)
127
+ code << "if (#{rescue_condition(err_state_var, @tails[0], code, local_scope)})"
128
+ code.block do
129
+ @tails[0].generate_code code, local_scope
130
+ end
131
+ end
132
+
133
+ def rescue_condition(err_state_var, resc, code, local_scope)
134
+ resc.error_klass.generate_evaluation_code code, local_scope
135
+ cond = "RTEST(rb_funcall(#{err_state_var}, rb_intern(\"kind_of?\")"
136
+ cond << ", 1, #{resc.error_klass.c_code(local_scope)}))"
137
+
138
+ cond
139
+ end
140
+
141
+ def declare_error_state_variable(local_scope)
142
+ @state_var_name = 'begin_block_' + local_scope.begin_block_counter.to_s + '_state'
143
+ local_scope.declare_var(
144
+ name: @state_var_name,
145
+ c_name: Rubex::VAR_PREFIX + @state_var_name,
146
+ type: DataType::Int.new
147
+ )
148
+ end
149
+
150
+ def declare_error_klass_variable(local_scope)
151
+ @error_var_name = 'begin_block_' + local_scope.begin_block_counter.to_s + '_exec'
152
+ local_scope.declare_var(
153
+ name: @error_var_name,
154
+ c_name: Rubex::VAR_PREFIX + @error_var_name,
155
+ type: DataType::RubyObject.new
156
+ )
157
+ end
158
+
159
+ def block_name(local_scope)
160
+ 'begin_block_' + local_scope.klass_name + '_' + local_scope.name + '_' +
161
+ local_scope.begin_block_counter.to_s
162
+ end
163
+
164
+ def create_c_function_to_house_statements(scope)
165
+ func_name = @block_scope.name
166
+ arg_list = Statement::ArgumentList.new([
167
+ AST::Expression::ArgDeclaration.new(
168
+ { dtype: 'object', variables: [{ ident: 'dummy' }] }
169
+ )
170
+ ])
171
+ @begin_func = TopStatement::CFunctionDef.new(
172
+ 'object', '', func_name, arg_list, @statements
173
+ )
174
+ arg_list.analyse_statement @block_scope
175
+ add_to_symbol_table @begin_func.name, arg_list, scope
176
+ @begin_func.analyse_statement @block_scope
177
+ @block_scope.upgrade_symbols_to_global
178
+ scope.add_begin_block_callback @begin_func
179
+ end
180
+
181
+ def add_to_symbol_table(func_name, arg_list, scope)
182
+ c_name = Rubex::C_FUNC_PREFIX + func_name
183
+ scope.add_c_method(
184
+ name: func_name,
185
+ c_name: c_name,
186
+ extern: false,
187
+ return_type: DataType::RubyObject.new,
188
+ arg_list: arg_list,
189
+ scope: @block_scope
190
+ )
191
+ end
192
+
193
+ def analyse_tails(local_scope)
194
+ @tails.each do |tail|
195
+ tail.analyse_statement local_scope
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,21 @@
1
+ module Rubex
2
+ module AST
3
+ module Statement
4
+ module BeginBlock
5
+ class Else < Base
6
+ def analyse_statement(local_scope)
7
+ @statements.each do |stmt|
8
+ stmt.analyse_statement local_scope
9
+ end
10
+ end
11
+
12
+ def generate_code(code, local_scope)
13
+ @statements.each do |stmt|
14
+ stmt.generate_code code, local_scope
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Rubex
2
+ module AST
3
+ module Statement
4
+ module BeginBlock
5
+ class Ensure < Base
6
+ def analyse_statement(local_scope)
7
+ @statements.each do |stmt|
8
+ stmt.analyse_statement local_scope
9
+ end
10
+ end
11
+
12
+ def generate_code(code, local_scope)
13
+ @statements.each do |stmt|
14
+ stmt.generate_code code, local_scope
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ module Rubex
2
+ module AST
3
+ module Statement
4
+ module BeginBlock
5
+ class Rescue < Base
6
+ attr_reader :error_klass
7
+
8
+ def initialize(error_klass, error_obj, statements, location)
9
+ super(statements, location)
10
+ @error_klass = error_klass
11
+ @error_obj = error_obj
12
+ end
13
+
14
+ def analyse_statement(local_scope)
15
+ @error_klass.analyse_types local_scope
16
+ unless @error_klass.type.ruby_constant?
17
+ raise "Must pass an error class to raise. Location #{@location}."
18
+ end
19
+
20
+ @statements.each do |stmt|
21
+ stmt.analyse_statement local_scope
22
+ end
23
+ end
24
+
25
+ def generate_code(code, local_scope)
26
+ @statements.each do |stmt|
27
+ stmt.generate_code code, local_scope
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,18 @@
1
+ module Rubex
2
+ module AST
3
+ module Statement
4
+ class Break < Base
5
+ def analyse_statement(local_scope)
6
+ # TODO: figure whether this is a Ruby break or C break. For now
7
+ # assuming C break.
8
+ end
9
+
10
+ def generate_code(code, _local_scope)
11
+ code.write_location @location
12
+ code << 'break;'
13
+ code.nl
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end