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
@@ -9,1173 +9,22 @@ module Rubex
9
9
  # File name and line number of statement in "file_name:lineno" format.
10
10
  attr_reader :location
11
11
 
12
- def initialize location
12
+ def initialize(location)
13
13
  @location = location
14
14
  end
15
15
 
16
- def statement?; true; end
16
+ def statement?
17
+ true
18
+ end
17
19
 
18
- def == other
20
+ def ==(other)
19
21
  self.class == other.class
20
22
  end
21
23
 
22
- def generate_code code, local_scope
24
+ def generate_code(code, _local_scope)
23
25
  code.write_location @location
24
26
  end
25
- end # class Base
26
-
27
- class CBaseType < Base
28
- attr_reader :type, :name, :value
29
-
30
- def initialize type, name, value=nil
31
- @type, @name, @value = type, name, value
32
- end
33
-
34
- def == other
35
- self.class == other.class &&
36
- self.type == other.class &&
37
- self.name == other.name &&
38
- self.value == other.value
39
- end
40
-
41
- def analyse_statement local_scope
42
- @type = Rubex::Helpers.determine_dtype @type
43
- end
44
- end # class CBaseType
45
-
46
- class VarDecl < Base
47
- # The name with which this particular variable can be identified with
48
- # in the symbol table.
49
- attr_reader :name
50
- attr_reader :type, :value
51
-
52
- def initialize type, name, value, location
53
- super(location)
54
- @name, @value = name, value
55
- @type = type
56
- end
57
-
58
- def analyse_statement local_scope, extern: false
59
- # TODO: Have type checks for knowing if correct literal assignment
60
- # is taking place. For example, a char should not be assigned a float.
61
- @type = Helpers.determine_dtype @type, ""
62
- c_name = extern ? @name : Rubex::VAR_PREFIX + @name
63
- if @value
64
- @value.analyse_for_target_type(@type, local_scope)
65
- @value.allocate_temp local_scope, @value.type
66
- @value = Helpers.to_lhs_type(self, @value)
67
- @value.release_temp local_scope
68
- end
69
-
70
- local_scope.declare_var name: @name, c_name: c_name, type: @type,
71
- value: @value, extern: extern
72
- end
73
-
74
- def rescan_declarations scope
75
- if @type.is_a? String
76
- @type = Rubex::CUSTOM_TYPES[@type]
77
- scope[@name].type = @type
78
- end
79
- end
80
-
81
- def generate_code code, local_scope
82
- if @value
83
- @value.generate_evaluation_code code, local_scope
84
- lhs = local_scope.find(@name).c_name
85
- code << "#{lhs} = #{@value.c_code(local_scope)};"
86
- code.nl
87
- @value.generate_disposal_code code
88
- end
89
- end
90
- end # class VarDecl
91
-
92
- class CPtrDecl < Base
93
- attr_reader :entry, :type
94
-
95
- # type - Specifies the type of the pointer. Is a string in case of a
96
- # normal pointer denoting the data type and pointer level (like `int`
97
- # for a pointerto an integer). Can be a Hash in case of func pointer
98
- # declaration.
99
- # name [String] - name of the variable.
100
- def initialize type, name, value, ptr_level, location
101
- super(location)
102
- @name, @type, @value, @ptr_level = name, type, value, ptr_level
103
- end
104
-
105
- def analyse_statement local_scope, extern: false
106
- c_name = extern ? @name : Rubex::POINTER_PREFIX + @name
107
-
108
- if @type.is_a?(Hash) # function ptr
109
- ident = @type[:ident]
110
- ident[:arg_list].analyse_statement(local_scope, inside_func_ptr: true)
111
- @type = DataType::CFunction.new(
112
- @name,
113
- c_name,
114
- ident[:arg_list],
115
- Helpers.determine_dtype(@type[:dtype], ident[:return_ptr_level]),
116
- nil
117
- )
118
- end
119
- @type = Helpers.determine_dtype @type, @ptr_level
120
- if @value
121
- @value.analyse_for_target_type(@type, local_scope)
122
- @value = Helpers.to_lhs_type(self, @value)
123
- end
124
-
125
- @entry = local_scope.declare_var name: @name, c_name: c_name,
126
- type: @type, value: @value, extern: extern
127
- end
128
-
129
- # FIXME: This feels jugaadu. Try to scan all declarations before you
130
- # scan individual statements.
131
- def rescan_declarations local_scope
132
- base_type = @entry.type.base_type
133
- if base_type.is_a? String
134
- type = Helpers.determine_dtype base_type, @ptr_level
135
- local_scope[@name].type = type
136
- end
137
- end
138
-
139
- def generate_code code, local_scope
140
- if @value
141
- @value.generate_evaluation_code code, local_scope
142
- code << "#{local_scope.find(@name).c_name} = #{@value.c_code(local_scope)};"
143
- code.nl
144
- @value.generate_disposal_code code
145
- end
146
- end
147
- end
148
-
149
- class CArrayDecl < Base
150
- attr_reader :type, :array_list, :name, :dimension
151
-
152
- def initialize type, array_ref, array_list, location
153
- super(location)
154
- @name, @array_list = array_ref.name, array_list
155
- @dimension = array_ref.pos
156
- @type = Rubex::TYPE_MAPPINGS[type].new
157
- end
158
-
159
- def analyse_statement local_scope, extern: false
160
- @dimension.analyse_statement local_scope
161
- create_symbol_table_entry local_scope
162
- return if @array_list.nil?
163
- analyse_array_list local_scope
164
- verify_array_list_types local_scope
165
- end
166
-
167
- def generate_code code, local_scope
168
-
169
- end
170
-
171
- def rescan_declarations local_scope
172
-
173
- end
174
-
175
- private
176
-
177
- def analyse_array_list local_scope
178
- @array_list.each do |expr|
179
- expr.analyse_statement(local_scope)
180
- end
181
- end
182
-
183
- def verify_array_list_types local_scope
184
- @array_list.all? do |expr|
185
- return true if @type >= expr.type
186
- raise "Specified type #{@type} but list contains #{expr.type}."
187
- end
188
- end
189
-
190
- def create_symbol_table_entry local_scope
191
- local_scope.add_carray(name: @name, c_name: Rubex::ARRAY_PREFIX + @name,
192
- dimension: @dimension, type: @type, value: @array_list)
193
- end
194
- end # class CArrayDecl
195
-
196
- class CStructOrUnionDef < Base
197
- attr_reader :name, :declarations, :type, :kind, :entry, :scope
198
-
199
- def initialize kind, name, declarations, location
200
- super(location)
201
- @declarations = declarations
202
- if /struct/.match kind
203
- @kind = :struct
204
- elsif /union/.match kind
205
- @kind = :union
206
- end
207
- @name = name
208
- end
209
-
210
- def analyse_statement outer_scope, extern: false
211
- @scope = Rubex::SymbolTable::Scope::StructOrUnion.new(
212
- @name, outer_scope)
213
- if extern
214
- c_name = @kind.to_s + " " + @name
215
- else
216
- c_name = Rubex::TYPE_PREFIX + @scope.klass_name + "_" + @name
217
- end
218
- @type = Rubex::DataType::CStructOrUnion.new(@kind, @name, c_name,
219
- @scope)
220
-
221
- @declarations.each do |decl|
222
- decl.analyse_statement @scope, extern: extern
223
- end
224
- Rubex::CUSTOM_TYPES[@name] = @type
225
- @entry = outer_scope.declare_sue(name: @name, c_name: c_name,
226
- type: @type, extern: extern)
227
- end
228
-
229
- def generate_code code, local_scope=nil
230
-
231
- end
232
-
233
- def rescan_declarations local_scope
234
- @declarations.each do |decl|
235
- decl.respond_to?(:rescan_declarations) and
236
- decl.rescan_declarations(@scope)
237
- end
238
- end
239
27
  end
240
-
241
- class ForwardDecl < Base
242
- attr_reader :kind, :name, :type, :c_name
243
-
244
- def initialize kind, name, location
245
- super(location)
246
- @name = name
247
- if /struct/.match kind
248
- @kind = :struct
249
- elsif /union/.match kind
250
- @kind = :union
251
- end
252
- Rubex::CUSTOM_TYPES[@name] = @name
253
- end
254
-
255
- def analyse_statement local_scope, extern: false
256
- @c_name = Rubex::TYPE_PREFIX + local_scope.klass_name + "_" + @name
257
- @type = Rubex::DataType::TypeDef.new("#{@kind} #{@name}", @c_name, type)
258
- local_scope.declare_type type: @type, extern: extern
259
- end
260
-
261
- def rescan_declarations local_scope
262
- @type = Rubex::DataType::TypeDef.new("#{@kind} #{@name}", @c_name,
263
- Rubex::CUSTOM_TYPES[@name])
264
- end
265
-
266
- def generate_code code, local_scope
267
-
268
- end
269
- end # class ForwardDecl
270
-
271
- class Print < Base
272
- # An Array containing expressions that are passed to the print statement.
273
- # Can either contain a single string containing interpolated exprs or
274
- # a set of comma separated exprs. For example, the print statement can
275
- # either be of like:
276
- # print "Hello #{a} world!"
277
- # OR
278
- # print "Hello", a, " world!"
279
- attr_reader :expressions
280
-
281
- def initialize expressions, location
282
- super(location)
283
- @expressions = expressions
284
- end
285
-
286
- def analyse_statement local_scope
287
- @expressions.each do |expr|
288
- expr.analyse_statement local_scope
289
- expr.allocate_temps local_scope
290
- expr.allocate_temp local_scope, expr.type
291
- expr.release_temps local_scope
292
- expr.release_temp local_scope
293
- end
294
- end
295
-
296
- def generate_code code, local_scope
297
- super
298
- @expressions.each do |expr|
299
- expr.generate_evaluation_code code, local_scope
300
-
301
- str = "printf("
302
- str << "\"#{expr.type.p_formatter}\""
303
- str << ", #{inspected_expr(expr, local_scope)}"
304
- str << ");"
305
- code << str
306
- code.nl
307
-
308
- expr.generate_disposal_code code
309
- end
310
-
311
- code.nl
312
- end
313
-
314
- private
315
-
316
- def inspected_expr expr, local_scope
317
- obj = expr.c_code(local_scope)
318
- if expr.type.object?
319
- "RSTRING_PTR(rb_funcall(#{obj}, rb_intern(\"inspect\"), 0, NULL))"
320
- else
321
- obj
322
- end
323
- end
324
- end # class Print
325
-
326
- class Return < Base
327
- attr_reader :expression, :type
328
-
329
- def initialize expression, location
330
- super(location)
331
- @expression = expression
332
- end
333
-
334
- def analyse_statement local_scope
335
- unless @expression
336
- if local_scope.type.ruby_method?
337
- @expression = Rubex::AST::Expression::Literal::Nil.new 'Qnil'
338
- elsif local_scope.type.c_function?
339
- @expression = Rubex::AST::Expression::Empty.new
340
- end # FIXME: print a warning for type mismatch if none of above
341
- end
342
-
343
- @expression.analyse_statement local_scope
344
- @expression.allocate_temps local_scope
345
- @expression.allocate_temp local_scope, @expression.type
346
- @expression.release_temps local_scope
347
- @expression.release_temp local_scope
348
- t = @expression.type
349
-
350
- @type =
351
- if t.c_function? || t.alias_type?
352
- t.type
353
- else
354
- t
355
- end
356
- @expression = @expression.to_ruby_object if local_scope.type.type.object?
357
-
358
- # TODO: Raise error if type as inferred from the
359
- # is not compatible with the return statement type.
360
- end
361
-
362
- def generate_code code, local_scope
363
- super
364
- @expression.generate_evaluation_code code, local_scope
365
- code << "return #{@expression.c_code(local_scope)};"
366
- code.nl
367
- end
368
- end # class Return
369
-
370
- class Assign < Base
371
- attr_reader :lhs, :rhs
372
-
373
- def initialize lhs, rhs, location
374
- super(location)
375
- @lhs, @rhs = lhs, rhs
376
- end
377
-
378
- def analyse_statement local_scope
379
- if @lhs.is_a?(Rubex::AST::Expression::Name)
380
- @lhs.analyse_declaration @rhs, local_scope
381
- else
382
- @lhs.analyse_statement(local_scope)
383
- end
384
- @lhs.allocate_temps local_scope
385
- @lhs.allocate_temp local_scope, @lhs.type
386
-
387
- @rhs.analyse_for_target_type(@lhs.type, local_scope)
388
- @rhs = Helpers.to_lhs_type(@lhs, @rhs)
389
-
390
- @rhs.allocate_temps local_scope
391
- @rhs.allocate_temp local_scope, @rhs.type
392
-
393
- @lhs.release_temps local_scope
394
- @lhs.release_temp local_scope
395
- @rhs.release_temps local_scope
396
- @rhs.release_temp local_scope
397
- end
398
-
399
- def generate_code code, local_scope
400
- super
401
- @rhs.generate_evaluation_code code, local_scope
402
- @lhs.generate_assignment_code @rhs, code, local_scope
403
- @rhs.generate_disposal_code code
404
- end
405
- end # class Assign
406
-
407
- class IfBlock < Base
408
- module Helper
409
- def analyse_statement local_scope
410
- @statements.each do |stat|
411
- stat.analyse_statement local_scope
412
- end
413
-
414
- @if_tail.analyse_statement(local_scope) if @if_tail
415
- end
416
-
417
- def generate_code_for_statement stat, code, local_scope, node
418
- if stat != "else"
419
- condition = node.expr.c_code(local_scope)
420
- expr_condition = node.expr.type.object? ? "RTEST(#{condition})" : condition
421
- code << "#{stat} (#{expr_condition}) "
422
- else
423
- code << "#{stat}"
424
- end
425
-
426
- code.block do
427
- node.statements.each do |stat|
428
- stat.generate_code code, local_scope
429
- code.nl
430
- end
431
- end
432
-
433
- if stat != "else"
434
- node.if_tail.generate_code(code, local_scope) if node.if_tail
435
- end
436
- end
437
- end # module Helper
438
-
439
- attr_reader :expr, :statements, :if_tail
440
- include Rubex::AST::Statement::IfBlock::Helper
441
-
442
- def initialize expr, statements, if_tail, location
443
- super(location)
444
- @expr, @statements, @if_tail = expr, statements, if_tail
445
- end
446
-
447
- def analyse_statement local_scope
448
- @tail_exprs = if_tail_exprs
449
- @tail_exprs.each do |tail|
450
- tail.analyse_statement local_scope
451
- tail.allocate_temps local_scope
452
- tail.allocate_temp local_scope, tail.type
453
- end
454
- @tail_exprs.each do |tail|
455
- tail.release_temps local_scope
456
- tail.release_temp local_scope
457
- end
458
- super
459
- end
460
-
461
- def if_tail_exprs
462
- tail_exprs = []
463
- temp = self
464
- while temp.respond_to?(:if_tail) &&
465
- !temp.is_a?(Rubex::AST::Statement::IfBlock::Else)
466
- tail_exprs << temp.expr
467
- temp = temp.if_tail
468
- end
469
-
470
- tail_exprs
471
- end
472
-
473
- def generate_code code, local_scope
474
- @tail_exprs.each do |tail|
475
- tail.generate_evaluation_code(code, local_scope)
476
- end
477
- generate_code_for_statement "if", code, local_scope, self
478
-
479
- tail = @if_tail
480
- while tail
481
- if tail.is_a?(Elsif)
482
- generate_code_for_statement "else if", code, local_scope, tail
483
- elsif tail.is_a?(Else)
484
- generate_code_for_statement "else", code, local_scope, tail
485
- end
486
- tail = tail.if_tail
487
- end
488
-
489
- @tail_exprs.each do |tail|
490
- tail.generate_disposal_code code
491
- end
492
- end
493
-
494
- class Elsif < Base
495
- attr_reader :expr, :statements, :if_tail
496
- include Rubex::AST::Statement::IfBlock::Helper
497
-
498
- def initialize expr, statements, if_tail, location
499
- super(location)
500
- @expr, @statements, @if_tail = expr, statements, if_tail
501
- end
502
-
503
- def generate_code code, local_scope
504
- end
505
- end # class Elsif
506
-
507
- class Else < Base
508
- attr_reader :statements
509
- include Rubex::AST::Statement::IfBlock::Helper
510
-
511
- def initialize statements, location
512
- super(location)
513
- @statements = statements
514
- end
515
-
516
- def analyse_statement local_scope
517
- @statements.each do |stat|
518
- stat.analyse_statement local_scope
519
- end
520
- end
521
-
522
- def generate_code code, local_scope
523
- end
524
-
525
- def if_tail; nil; end
526
- end # class Else
527
- end # class IfBlock
528
-
529
- class For < Base
530
- attr_reader :left_expr, :left_op, :middle, :right_op, :right_expr,
531
- :statements, :order
532
-
533
- def initialize left_expr, left_op, middle, right_op, right_expr,
534
- statements, location
535
- super(location)
536
- @left_expr, @left_op, @middle, @right_op, @right_expr =
537
- left_expr, left_op, middle, right_op, right_expr
538
- @statements, @order = statements, order
539
- end
540
-
541
- def analyse_statement local_scope
542
- @left_expr.analyse_statement local_scope
543
- @right_expr.analyse_statement local_scope
544
-
545
- [ @left_expr, @right_expr ].each do |e|
546
- e.allocate_temps local_scope
547
- e.allocate_temp local_scope, e.type
548
- end
549
- [ @left_expr, @right_expr ].each do |e|
550
- e.release_temps local_scope
551
- e.release_temp local_scope
552
- end
553
-
554
- @middle = local_scope[@middle] # middle will not be an expr.
555
- @statements.each do |stat|
556
- stat.analyse_statement local_scope
557
- end
558
- end
559
-
560
- def generate_code code, local_scope
561
- code << for_loop_header(code, local_scope)
562
- code.block do
563
- @statements.each do |stat|
564
- stat.generate_code code, local_scope
565
- end
566
- end
567
- @left_expr.generate_disposal_code code
568
- @right_expr.generate_disposal_code code
569
- end
570
-
571
- private
572
-
573
- def for_loop_header code, local_scope
574
- @left_expr.generate_evaluation_code code, local_scope
575
- @right_expr.generate_evaluation_code code, local_scope
576
- for_stmt = ""
577
- for_stmt << "for (#{@middle.c_name} = #{@left_expr.c_code(local_scope)}"
578
-
579
- if @left_op == '<'
580
- for_stmt << " + 1"
581
- elsif @left_op == '>'
582
- for_stmt << " - 1"
583
- end
584
-
585
- for_stmt << "; #{@middle.c_name} #{@right_op} #{@right_expr.c_code(local_scope)}; "
586
- for_stmt << "#{@middle.c_name}"
587
-
588
- if ['>', '>='].include? @right_op
589
- for_stmt << "--"
590
- elsif ['<', '<='].include? @right_op
591
- for_stmt << "++"
592
- end
593
-
594
- for_stmt << ")"
595
-
596
- for_stmt
597
- end
598
- end # class For
599
-
600
- class While < Base
601
- attr_reader :expr, :statements
602
-
603
- def initialize expr, statements, location
604
- super(location)
605
- @expr, @statements = expr, statements
606
- end
607
-
608
- def analyse_statement local_scope
609
- @expr.analyse_statement local_scope
610
- @expr.allocate_temp local_scope, @expr.type
611
- @expr.release_temp local_scope
612
- @statements.each do |stat|
613
- stat.analyse_statement local_scope
614
- end
615
- end
616
-
617
- def generate_code code, local_scope
618
- @expr.generate_evaluation_code code, local_scope
619
- stmt = "while (#{@expr.c_code(local_scope)})"
620
- code << stmt
621
- code.block do
622
- @statements.each do |stat|
623
- stat.generate_code code, local_scope
624
- end
625
- end
626
- @expr.generate_disposal_code code
627
- end
628
- end # class While
629
-
630
- class Alias < Base
631
- attr_reader :new_name, :type, :old_name
632
-
633
- def initialize new_name, old_name, location
634
- super(location)
635
- @new_name, @old_name = new_name, old_name
636
- Rubex::CUSTOM_TYPES[@new_name] = @new_name
637
- end
638
-
639
- def analyse_statement local_scope, extern: false
640
- original = @old_name[:dtype].gsub("struct ", "").gsub("union ", "")
641
- var = @old_name[:variables][0]
642
- ident = var[:ident]
643
- ptr_level = var[:ptr_level]
644
-
645
- base_type =
646
- if ident.is_a?(Hash) # function pointer
647
- cfunc_return_type = Helpers.determine_dtype(original,
648
- ident[:return_ptr_level])
649
- arg_list = ident[:arg_list].analyse_statement(local_scope,
650
- inside_func_ptr: true)
651
- ptr_level = "*" if ptr_level.empty?
652
-
653
- Helpers.determine_dtype(
654
- DataType::CFunction.new(nil, nil, arg_list, cfunc_return_type, nil),
655
- ptr_level)
656
- else
657
- Helpers.determine_dtype(original, ptr_level)
658
- end
659
-
660
- @type = Rubex::DataType::TypeDef.new(base_type, @new_name, base_type)
661
- Rubex::CUSTOM_TYPES[@new_name] = @type
662
- local_scope.declare_type(type: @type, extern: extern) if original != @new_name
663
- end
664
-
665
- def generate_code code, local_scope
666
-
667
- end
668
- end # class Alias
669
-
670
- class Expression < Base
671
- attr_reader :expr
672
- attr_accessor :typecast
673
-
674
- def initialize expr, location
675
- super(location)
676
- @expr = expr
677
- end
678
-
679
- def analyse_statement local_scope
680
- @expr.analyse_statement local_scope
681
- @expr.allocate_temps local_scope
682
- @expr.allocate_temp local_scope, @expr.type
683
- end
684
-
685
- def generate_code code, local_scope
686
- super
687
- @expr.generate_evaluation_code code, local_scope
688
- code << @expr.c_code(local_scope) + ";"
689
- code.nl
690
- @expr.generate_disposal_code code
691
- end
692
- end # class Expression
693
-
694
- class CFunctionDecl < Base
695
- attr_reader :entry
696
-
697
- def initialize type, return_ptr_level, name, arg_list
698
- @type, @return_ptr_level, @name, @arg_list = type, return_ptr_level,
699
- name, arg_list
700
- end
701
-
702
- def analyse_statement local_scope, extern: false
703
- @arg_list.analyse_statement(local_scope, extern: extern) if @arg_list
704
- c_name = extern ? @name : (Rubex::C_FUNC_PREFIX + @name)
705
- # type = Rubex::DataType::CFunction.new(@name, c_name, @arg_list,
706
- # Helpers.determine_dtype(@type, @return_ptr_level), nil)
707
- @entry = local_scope.add_c_method(
708
- name: @name,
709
- c_name: c_name,
710
- return_type: Helpers.determine_dtype(@type, @return_ptr_level),
711
- arg_list: @arg_list,
712
- scope: nil,
713
- extern: extern)
714
- end
715
-
716
- def generate_code code, local_scope
717
- super
718
- code << "/* C function #{@name} declared.*/" if @entry.extern?
719
- end
720
- end # class CFunctionDecl
721
-
722
- # This node is used for both formal and actual arguments of functions/methods.
723
- class ArgumentList < Base
724
- include Enumerable
725
-
726
- # args - [ArgDeclaration]
727
- attr_reader :args
728
-
729
- def each &block
730
- @args.each(&block)
731
- end
732
-
733
- def map! &block
734
- @args.map!(&block)
735
- end
736
-
737
- def pop
738
- @args.pop
739
- end
740
-
741
- def initialize args
742
- @args = args
743
- end
744
-
745
- # func_ptr - switch that determines if this ArgList is part of the
746
- # argument list of an argument that is a function pointer.
747
- # For eg -
748
- # cfunc int foo(int (*bar)(int, float)).
749
- # ^^^ This is an arg list inside a function.
750
- def analyse_statement local_scope, inside_func_ptr: false, extern: false
751
- @args.each do |arg|
752
- arg.analyse_statement(local_scope, inside_func_ptr: inside_func_ptr,
753
- extern: extern)
754
- end
755
- end
756
-
757
- def push arg
758
- @args << arg
759
- end
760
-
761
- def << arg
762
- push arg
763
- end
764
-
765
- def == other
766
- self.class == other.class && @args == other.args
767
- end
768
-
769
- def size
770
- @args.size
771
- end
772
-
773
- def empty?
774
- @args.empty?
775
- end
776
-
777
- def [] idx
778
- @args[idx]
779
- end
780
- end # class ArgumentList
781
-
782
- class ActualArgList < ArgumentList
783
- def analyse_statement local_scope
784
- @args.each do |arg|
785
- arg.analyse_statement local_scope
786
- end
787
- end
788
-
789
- def allocate_temps local_scope
790
- @args.each { |a| a.allocate_temp(local_scope, a.type) }
791
- end
792
-
793
- def release_temps local_scope
794
- @args.each { |a| a.release_temp(local_scope) }
795
- end
796
-
797
- def generate_evaluation_code code, local_scope
798
- @args.each do |a|
799
- a.generate_evaluation_code code, local_scope
800
- end
801
- end
802
-
803
- def generate_disposal_code code
804
- @args.each do |a|
805
- a.generate_disposal_code code
806
- end
807
- end
808
- end # class ActualArgList
809
-
810
- class Raise < Base
811
- def initialize args
812
- @args = args
813
- end
814
-
815
- def analyse_statement local_scope
816
- @args.analyse_statement local_scope
817
- @args.allocate_temps local_scope
818
- @args.release_temps local_scope
819
- unless @args.empty? || @args[0].is_a?(AST::Expression::Name) ||
820
- @args[0].is_a?(AST::Expression::Literal::StringLit)
821
- raise Rubex::TypeMismatchError, "Wrong argument list #{@args.inspect} for raise."
822
- end
823
- end
824
-
825
- def generate_code code, local_scope
826
- @args.generate_evaluation_code code, local_scope
827
- str = ""
828
- str << "rb_raise("
829
-
830
- if @args[0].is_a?(AST::Expression::Name)
831
- str << @args[0].c_code(local_scope) + ','
832
- args = @args[1..-1]
833
- else
834
- str << Rubex::DEFAULT_CLASS_MAPPINGS["RuntimeError"] + ','
835
- args = @args
836
- end
837
-
838
- unless args.empty?
839
- str << "\"#{prepare_format_string(args)}\" ,"
840
- str << args.map { |arg| "#{inspected_expr(arg, local_scope)}" }.join(',')
841
- else
842
- str << "\"\""
843
- end
844
- str << ");"
845
- code << str
846
- code.nl
847
- @args.generate_disposal_code code
848
- end
849
-
850
- private
851
-
852
- def prepare_format_string args
853
- format_string = ""
854
- args.each do |expr|
855
- format_string << expr.type.p_formatter
856
- end
857
-
858
- format_string
859
- end
860
-
861
- def inspected_expr expr, local_scope
862
- obj = expr.c_code(local_scope)
863
- if expr.type.object?
864
- "RSTRING_PTR(rb_funcall(#{obj}, rb_intern(\"inspect\"), 0, NULL))"
865
- else
866
- obj
867
- end
868
- end
869
- end # class Raise
870
-
871
- class Break < Base
872
- def analyse_statement local_scope
873
- # TODO: figure whether this is a Ruby break or C break. For now
874
- # assuming C break.
875
- end
876
-
877
- def generate_code code, local_scope
878
- code.write_location @location
879
- code << "break;"
880
- code.nl
881
- end
882
- end # class Break
883
-
884
- class Yield < Base
885
- def initialize args
886
- @args = args
887
- end
888
-
889
- def analyse_statement local_scope
890
- @args = @args.map do |arg|
891
- arg.analyse_statement local_scope
892
- arg.allocate_temps local_scope
893
- arg.allocate_temp local_scope, arg.type
894
- arg.to_ruby_object
895
- end
896
-
897
- @args.each do |arg|
898
- arg.release_temps local_scope
899
- arg.release_temp local_scope
900
- end
901
- end
902
-
903
- def generate_code code, local_scope
904
- @args.each do |a|
905
- a.generate_evaluation_code code, local_scope
906
- end
907
-
908
- if @args.size > 0
909
- code << "rb_yield_values(#{@args.size}, "
910
- code << "#{@args.map { |a| a.c_code(local_scope) }.join(',')}"
911
- code << ");"
912
- else
913
- code << "rb_yield(Qnil);"
914
- end
915
- code.nl
916
-
917
- @args.each do |a|
918
- a.generate_disposal_code code
919
- end
920
- end
921
- end # class Yield
922
-
923
- module BeginBlock
924
- class Base < Statement::Base
925
- attr_reader :statements
926
-
927
- def initialize statements, location
928
- @statements = statements
929
- super(location)
930
- end
931
- end # class Base
932
-
933
- class Begin < Base
934
- def initialize statements, tails, location
935
- @tails = tails
936
- super(statements, location)
937
- end
938
-
939
- def analyse_statement local_scope
940
- local_scope.found_begin_block
941
- declare_error_state_variable local_scope
942
- declare_error_klass_variable local_scope
943
- declare_unhandled_error_variable local_scope
944
- @block_scope = Rubex::SymbolTable::Scope::BeginBlock.new(
945
- block_name(local_scope), local_scope)
946
- create_c_function_to_house_statements local_scope.outer_scope
947
- analyse_tails local_scope
948
- end
949
-
950
- def generate_code code, local_scope
951
- code.nl
952
- code << "/* begin-rescue-else-ensure-end block begins: */"
953
- code.nl
954
- super
955
- cb_c_name = local_scope.find(@begin_func.name).c_name
956
- state_var = local_scope.find(@state_var_name).c_name
957
- code << "#{state_var} = 0;\n"
958
- code << "rb_protect(#{cb_c_name}, Qnil, &#{state_var});"
959
- code.nl
960
- generate_rescue_else_ensure code, local_scope
961
- end
962
-
963
- private
964
-
965
- def generate_rescue_else_ensure code, local_scope
966
- err_state_var = local_scope.find(@error_var_name).c_name
967
- set_error_state_variable err_state_var, code, local_scope
968
- set_unhandled_error_variable code, local_scope
969
- generate_rescue_blocks err_state_var, code, local_scope
970
- generate_else_block code, local_scope
971
- generate_ensure_block code, local_scope
972
- generate_rb_jump_tag err_state_var, code, local_scope
973
- code << "rb_set_errinfo(Qnil);\n"
974
- end
975
-
976
- def declare_unhandled_error_variable local_scope
977
- @unhandled_err_var_name = "begin_block_" + local_scope.begin_block_counter.to_s + "_unhandled_error"
978
- local_scope.declare_var(
979
- name: @unhandled_err_var_name,
980
- c_name: Rubex::VAR_PREFIX + @unhandled_err_var_name,
981
- type: DataType::Int.new
982
- )
983
- end
984
-
985
- def set_unhandled_error_variable code, local_scope
986
- n = local_scope.find(@unhandled_err_var_name).c_name
987
- code << "#{n} = 0;"
988
- code.nl
989
- end
990
-
991
- def generate_rb_jump_tag err_state_var, code, local_scope
992
- state_var = local_scope.find(@state_var_name).c_name
993
- code << "if (#{local_scope.find(@unhandled_err_var_name).c_name})"
994
- code.block do
995
- code << "rb_jump_tag(#{state_var});"
996
- code.nl
997
- end
998
- end
999
-
1000
- def generate_ensure_block code, local_scope
1001
- ensure_block = @tails.select { |e| e.is_a?(Ensure) }[0]
1002
- ensure_block.generate_code(code, local_scope) unless ensure_block.nil?
1003
- end
1004
-
1005
- # We use a goto statement to jump to the ensure block so that when a
1006
- # condition arises where no error is raised, the ensure statement will
1007
- # be executed, after which rb_jump_tag() will be called.
1008
- def generate_else_block code, local_scope
1009
- else_block = @tails.select { |t| t.is_a?(Else) }[0]
1010
-
1011
- code << "else"
1012
- code.block do
1013
- state_var = local_scope.find(@state_var_name).c_name
1014
- code << "/* If exception not among those captured in raise */"
1015
- code.nl
1016
-
1017
- code << "if (#{state_var})"
1018
- code.block do
1019
- code << "#{local_scope.find(@unhandled_err_var_name).c_name} = 1;"
1020
- code.nl
1021
- end
1022
-
1023
- if else_block
1024
- code << "else"
1025
- code.block do
1026
- else_block.generate_code code, local_scope
1027
- end
1028
- end
1029
- end
1030
- end
1031
-
1032
- def set_error_state_variable err_state_var, code, local_scope
1033
- code << "#{err_state_var} = rb_errinfo();"
1034
- code.nl
1035
- end
1036
-
1037
- def generate_rescue_blocks err_state_var, code, local_scope
1038
- if @tails[0].is_a?(Rescue)
1039
- generate_first_rescue_block err_state_var, code, local_scope
1040
-
1041
- @tails[1..-1].grep(Rescue).each do |resc|
1042
- else_if_cond = rescue_condition err_state_var, resc, code, local_scope
1043
- code << "else if (#{else_if_cond})"
1044
- code.block do
1045
- resc.generate_code code, local_scope
1046
- end
1047
- end
1048
- else # no rescue blocks present
1049
- code << "if (0) {}\n"
1050
- end
1051
- end
1052
-
1053
- def generate_first_rescue_block err_state_var, code, local_scope
1054
- code << "if (#{rescue_condition(err_state_var, @tails[0], code, local_scope)})"
1055
- code.block do
1056
- @tails[0].generate_code code, local_scope
1057
- end
1058
- end
1059
-
1060
- def rescue_condition err_state_var, resc, code, local_scope
1061
- resc.error_klass.generate_evaluation_code code, local_scope
1062
- cond = "RTEST(rb_funcall(#{err_state_var}, rb_intern(\"kind_of?\")"
1063
- cond << ", 1, #{resc.error_klass.c_code(local_scope)}))"
1064
-
1065
- cond
1066
- end
1067
-
1068
- def declare_error_state_variable local_scope
1069
- @state_var_name = "begin_block_" + local_scope.begin_block_counter.to_s + "_state"
1070
- local_scope.declare_var(
1071
- name: @state_var_name,
1072
- c_name: Rubex::VAR_PREFIX + @state_var_name,
1073
- type: DataType::Int.new
1074
- )
1075
- end
1076
-
1077
- def declare_error_klass_variable local_scope
1078
- @error_var_name = "begin_block_" + local_scope.begin_block_counter.to_s + "_exec"
1079
- local_scope.declare_var(
1080
- name: @error_var_name,
1081
- c_name: Rubex::VAR_PREFIX + @error_var_name,
1082
- type: DataType::RubyObject.new
1083
- )
1084
- end
1085
-
1086
- def block_name local_scope
1087
- "begin_block_" + local_scope.klass_name + "_" + local_scope.name + "_" +
1088
- local_scope.begin_block_counter.to_s
1089
- end
1090
-
1091
- def create_c_function_to_house_statements scope
1092
- func_name = @block_scope.name
1093
- arg_list = Statement::ArgumentList.new([
1094
- AST::Expression::ArgDeclaration.new(
1095
- { dtype:'object', variables: [{ident: 'dummy'}]})
1096
- ])
1097
- @begin_func = TopStatement::CFunctionDef.new(
1098
- 'object', '', func_name, arg_list, @statements)
1099
- arg_list.analyse_statement @block_scope
1100
- add_to_symbol_table @begin_func.name, arg_list, scope
1101
- @begin_func.analyse_statement @block_scope
1102
- @block_scope.upgrade_symbols_to_global
1103
- scope.add_begin_block_callback @begin_func
1104
- end
1105
-
1106
- def add_to_symbol_table func_name, arg_list, scope
1107
- c_name = Rubex::C_FUNC_PREFIX + func_name
1108
- scope.add_c_method(
1109
- name: func_name,
1110
- c_name: c_name,
1111
- extern: false,
1112
- return_type: DataType::RubyObject.new,
1113
- arg_list: arg_list,
1114
- scope: @block_scope
1115
- )
1116
- end
1117
-
1118
- def analyse_tails local_scope
1119
- @tails.each do |tail|
1120
- tail.analyse_statement local_scope
1121
- end
1122
- end
1123
- end # class Begin
1124
-
1125
- class Else < Base
1126
- def analyse_statement local_scope
1127
- @statements.each do |stmt|
1128
- stmt.analyse_statement local_scope
1129
- end
1130
- end
1131
-
1132
- def generate_code code, local_scope
1133
- @statements.each do |stmt|
1134
- stmt.generate_code code, local_scope
1135
- end
1136
- end
1137
- end # class Else
1138
-
1139
- class Rescue < Base
1140
- attr_reader :error_klass
1141
-
1142
- def initialize error_klass, error_obj, statements, location
1143
- super(statements, location)
1144
- @error_klass, @error_obj = error_klass, error_obj
1145
- end
1146
-
1147
- def analyse_statement local_scope
1148
- @error_klass.analyse_statement local_scope
1149
- if !@error_klass.name.type.ruby_constant?
1150
- raise "Must pass an error class to raise. Location #{@location}."
1151
- end
1152
-
1153
- @statements.each do |stmt|
1154
- stmt.analyse_statement local_scope
1155
- end
1156
- end
1157
-
1158
- def generate_code code, local_scope
1159
- @statements.each do |stmt|
1160
- stmt.generate_code code, local_scope
1161
- end
1162
- end
1163
- end # class Rescue
1164
-
1165
- class Ensure < Base
1166
- def analyse_statement local_scope
1167
- @statements.each do |stmt|
1168
- stmt.analyse_statement local_scope
1169
- end
1170
- end
1171
-
1172
- def generate_code code, local_scope
1173
- @statements.each do |stmt|
1174
- stmt.generate_code code, local_scope
1175
- end
1176
- end
1177
- end # class Ensure
1178
- end # module BeginBlock
1179
- end # module Statement
1180
- end # module AST
1181
- end # module Rubex
28
+ end
29
+ end
30
+ end