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
@@ -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