fastruby 0.0.21 → 0.0.22

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 (49) hide show
  1. data/Rakefile +1 -1
  2. data/benchmarks/benchmark.rb +3 -0
  3. data/benchmarks/benchmark.rb~ +3 -12
  4. data/benchmarks/benchmark8.rb +48 -0
  5. data/benchmarks/benchmark8.rb~ +46 -0
  6. data/lib/fastruby.rb +2 -1
  7. data/lib/fastruby.rb~ +2 -1
  8. data/lib/fastruby/builder.rb +18 -1
  9. data/lib/fastruby/builder.rb~ +18 -5
  10. data/lib/fastruby/modules/lvar_type/lasgn.rb~ +41 -0
  11. data/lib/fastruby/modules/translator/block.rb +1 -1
  12. data/lib/fastruby/modules/translator/block.rb~ +128 -0
  13. data/lib/fastruby/modules/translator/call.rb +62 -139
  14. data/lib/fastruby/modules/translator/call.rb~ +61 -140
  15. data/lib/fastruby/modules/translator/defn.rb +49 -105
  16. data/lib/fastruby/modules/translator/defn.rb~ +211 -0
  17. data/lib/fastruby/modules/translator/exceptions.rb +1 -0
  18. data/lib/fastruby/modules/translator/exceptions.rb~ +120 -0
  19. data/lib/fastruby/modules/translator/iter.rb +13 -20
  20. data/lib/fastruby/modules/translator/iter.rb~ +738 -0
  21. data/lib/fastruby/modules/translator/literal.rb +8 -1
  22. data/lib/fastruby/modules/translator/literal.rb~ +157 -0
  23. data/lib/fastruby/modules/translator/nonlocal.rb +7 -0
  24. data/lib/fastruby/modules/translator/nonlocal.rb~ +304 -0
  25. data/lib/fastruby/modules/translator/static.rb +1 -0
  26. data/lib/fastruby/modules/translator/static.rb~ +290 -0
  27. data/lib/fastruby/modules/translator/variable.rb +24 -6
  28. data/lib/fastruby/modules/translator/variable.rb~ +298 -0
  29. data/lib/fastruby/translator/translator.rb +411 -284
  30. data/lib/fastruby/translator/translator.rb~ +1728 -0
  31. data/spec/fastruby_only/base_spec.rb~ +74 -0
  32. data/spec/ruby/base_spec.rb~ +1 -338
  33. data/spec/ruby/block/break_spec.rb~ +21 -0
  34. data/spec/ruby/block/callcc_spec.rb~ +236 -0
  35. data/spec/ruby/block/lambda_spec.rb~ +1 -178
  36. data/spec/ruby/block/next_spec.rb~ +85 -0
  37. data/spec/ruby/block/proc_spec.rb~ +22 -0
  38. data/spec/ruby/block/redo_spec.rb~ +133 -0
  39. data/spec/ruby/block/retry_spec.rb~ +135 -0
  40. data/spec/ruby/block_spec.rb~ +494 -2
  41. data/spec/ruby/call/base_call_spec.rb~ +60 -2
  42. data/spec/ruby/defn/default_args_spec.rb~ +303 -0
  43. data/spec/ruby/defn/multiple_args_spec.rb~ +317 -0
  44. data/spec/ruby/defn/replacement_spec.rb +29 -1
  45. data/spec/ruby/defn/replacement_spec.rb~ +52 -21
  46. data/spec/ruby/exception/internal_ex_spec.rb~ +2 -2
  47. data/spec/ruby/variable_spec.rb~ +46 -23
  48. data/spec/static/flow_spec.rb~ +48 -0
  49. metadata +34 -12
@@ -58,6 +58,7 @@ module FastRuby
58
58
  end
59
59
 
60
60
  if method_name == "inline_c"
61
+ @has_inline_c = true
61
62
  arg = tree[3][1]
62
63
 
63
64
  if arg.node_type != :str
@@ -0,0 +1,290 @@
1
+ =begin
2
+
3
+ This file is part of the fastruby project, http://github.com/tario/fastruby
4
+
5
+ Copyright (c) 2011 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ fastruby is free software: you can redistribute it and/or modify
8
+ it under the terms of the gnu general public license as published by
9
+ the free software foundation, either version 3 of the license, or
10
+ (at your option) any later version.
11
+
12
+ fastruby is distributed in the hope that it will be useful,
13
+ but without any warranty; without even the implied warranty of
14
+ merchantability or fitness for a particular purpose. see the
15
+ gnu general public license for more details.
16
+
17
+ you should have received a copy of the gnu general public license
18
+ along with fastruby. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ =end
21
+ module FastRuby
22
+ class Context
23
+ define_translator_for(:iter, :arity => 1, :priority => 1) { |*x|
24
+ ret = nil
25
+ tree = x.first
26
+ enable_handler_group(:static_call, :to_c) do
27
+ ret = x.size == 1 ? to_c(tree[3]) : to_c(tree[3], x.last)
28
+ end
29
+ ret
30
+ }.condition{ |*x|
31
+ tree = x.first
32
+ tree.node_type == :iter && tree[1][2] == :_static
33
+ }
34
+
35
+ define_translator_for(:iter, :arity => 1, :priority => 1) { |*x|
36
+ ret = nil
37
+ tree = x.first
38
+
39
+ disable_handler_group(:static_call, :to_c) do
40
+ ret = x.size == 1 ? to_c(tree[3]) : to_c(tree[3], x.last)
41
+ end
42
+ ret
43
+ }.condition{ |*x|
44
+ tree = x.first
45
+ tree.node_type == :iter && tree[1][2] == :_dynamic
46
+ }
47
+
48
+ handler_scope(:group => :static_call, :priority => 1000) do
49
+ define_translator_for(:call) do |*x|
50
+ tree, result = x
51
+
52
+ method_name = tree[2].to_s
53
+ recv_tree = tree[1]
54
+
55
+ if method_name == "c_address_of"
56
+ arg = tree[3][1]
57
+ return "&"+to_c(arg)
58
+ end
59
+
60
+ if method_name == "inline_c"
61
+ arg = tree[3][1]
62
+
63
+ if arg.node_type != :str
64
+ raise RuntimeError, "invalid node for inline_c directive #{arg}"
65
+ end
66
+
67
+ next arg[1]
68
+ end
69
+
70
+ if recv_tree and recv_tree.node_type != :self
71
+ if (not tree[2].to_s =~ /^[a-zA-Z]/) and tree[2].to_s.size <= 3
72
+ c_op = tree[2].to_s
73
+ c_op = '==' if tree[2] == :===
74
+ code = "( ( #{to_c(tree[1])} )#{c_op}(#{to_c(tree[3][1])}) )"
75
+ elsif tree[2] == :_invariant
76
+ name = self.add_global_name("VALUE", "Qnil");
77
+
78
+ init_extra << "
79
+ #{name} = #{to_c tree[1]};
80
+ rb_funcall(#{name},#{intern_num :gc_register_object},0);
81
+ "
82
+
83
+ code = name;
84
+ else
85
+ args = tree[3][1..-1].map{|st| to_c(st)}.join(",")
86
+ code = "#{method_name}( #{args} )"
87
+ end
88
+ else
89
+ args = tree[3][1..-1].map{|st| to_c(st)}.join(",")
90
+ code = "#{method_name}( #{args} )"
91
+ end
92
+
93
+ if result
94
+ "#{result} = #{code};"
95
+ else
96
+ code
97
+ end
98
+ end
99
+
100
+ define_translator_for(:lit) do |*x|
101
+ tree, result = x
102
+
103
+ if result
104
+ "#{result} = #{tree[1]};"
105
+ else
106
+ tree[1].to_s
107
+ end
108
+ end
109
+
110
+ define_translator_for(:if) do |*x|
111
+ tree, result_variable_ = x
112
+
113
+ condition_tree = tree[1]
114
+ impl_tree = tree[2]
115
+ else_tree = tree[3]
116
+
117
+ result_variable = result_variable_ || "last_expression"
118
+
119
+ code = proc {"
120
+ {
121
+ VALUE condition_result;
122
+ #{to_c condition_tree, "condition_result"};
123
+ if (condition_result) {
124
+ #{to_c impl_tree, result_variable};
125
+ }#{else_tree ?
126
+ " else {
127
+ #{to_c else_tree, result_variable};
128
+ }
129
+ " : ""
130
+ }
131
+ }
132
+ "}
133
+
134
+ if result_variable_
135
+ code.call
136
+ else
137
+ inline_block(&code) + "; return last_expression;"
138
+ end
139
+ end
140
+
141
+ define_translator_for(:const) do |*x|
142
+ tree, result_var = x
143
+
144
+ if result_var
145
+ "#{result_var} = #{tree[1].to_s};"
146
+ else
147
+ "#{tree[1].to_s}"
148
+ end
149
+ end
150
+
151
+ define_translator_for(:while) do |*x|
152
+ tree, result_var = x
153
+
154
+ begin_while = "begin_while_"+rand(10000000).to_s
155
+ end_while = "end_while_"+rand(10000000).to_s
156
+ aux_varname = "_aux_" + rand(10000000).to_s
157
+ code = proc {"
158
+ {
159
+ VALUE while_condition;
160
+ VALUE #{aux_varname};
161
+
162
+ #{begin_while}:
163
+ #{to_c tree[1], "while_condition"};
164
+ if (!(while_condition)) goto #{end_while};
165
+ #{to_c tree[2], aux_varname};
166
+ goto #{begin_while};
167
+ #{end_while}:
168
+
169
+ #{
170
+ if result_var
171
+ "#{result_var} = Qnil;"
172
+ else
173
+ "return Qnil;"
174
+ end
175
+ }
176
+ }
177
+ "}
178
+
179
+ if result_var
180
+ code.call
181
+ else
182
+ inline_block &code
183
+ end
184
+
185
+ end
186
+
187
+ define_translator_for(:and) do |*x|
188
+ tree, return_var = x
189
+
190
+ if return_var
191
+ "
192
+ {
193
+ VALUE op1 = Qnil;
194
+ VALUE op2 = Qnil;
195
+ #{to_c tree[1], "op1"};
196
+ #{to_c tree[2], "op2"};
197
+ #{return_var} = ((op1) &&(op2));
198
+ }
199
+ "
200
+ else
201
+ "((#{to_c tree[1]}) && (#{to_c tree[2]}))"
202
+ end
203
+
204
+ end
205
+
206
+ define_translator_for(:or) do |*x|
207
+ tree, return_var = x
208
+
209
+ if return_var
210
+ "
211
+ {
212
+ VALUE op1 = Qnil;
213
+ VALUE op2 = Qnil;
214
+ #{to_c tree[1], "op1"};
215
+ #{to_c tree[2], "op2"};
216
+ #{return_var} = ((op1) ||(op2));
217
+ }
218
+ "
219
+ else
220
+ "((#{to_c tree[1]}) || (#{to_c tree[2]}))"
221
+ end
222
+
223
+ end
224
+
225
+ define_translator_for(:not) do |*x|
226
+ tree, return_var = x
227
+
228
+ if return_var
229
+ "
230
+ {
231
+ VALUE op1 = Qnil;
232
+ #{to_c tree[1], "op1"};
233
+ #{return_var} = ((op1) ? 0: 1);
234
+ }
235
+ "
236
+ else
237
+ "((#{to_c tree[1]}) ? 0 : 1)"
238
+ end
239
+ end
240
+
241
+ end
242
+
243
+ define_method_handler(:initialize_to_c){|*x|}.condition do |*x|
244
+ disable_handler_group(:static_call, :to_c); false
245
+ end
246
+
247
+
248
+ define_method_handler(:infer_value) { |*x| tree = x.first;
249
+ Value.new(eval(tree[1].to_s))
250
+ }.condition{|*x| tree = x.first; tree.node_type == :const}
251
+
252
+ define_method_handler(:infer_value) { |*x| tree = x.first;
253
+ args_tree = tree[3]
254
+ receiver_tree = tree[1]
255
+
256
+ value_1 = infer_value(receiver_tree)
257
+ value_2 = infer_value(args_tree[1])
258
+
259
+ next false unless (value_1 and value_2)
260
+
261
+ Value.new(value_1.value == value_2.value)
262
+ }.condition{|*x| tree = x.first;
263
+ next false unless tree.node_type == :call
264
+
265
+ args_tree = tree[3]
266
+ method_name = tree[2]
267
+
268
+ next false unless method_name == :==
269
+ next false if args_tree.size < 2
270
+
271
+ true
272
+ }
273
+ define_method_handler(:infer_value) { |*x| tree = x.first;
274
+ args_tree = tree[3]
275
+ receiver_tree = tree[1]
276
+ infered_type = infer_type(receiver_tree)
277
+
278
+ if infered_type
279
+ Value.new(infered_type)
280
+ else
281
+ nil
282
+ end
283
+ }.condition{|*x| tree = x.first;
284
+ next false unless tree.node_type == :call
285
+ method_name = tree[2]
286
+ next false unless method_name == :_class
287
+ true
288
+ }
289
+ end
290
+ end
@@ -22,7 +22,7 @@ module FastRuby
22
22
  class Context
23
23
  define_translator_for(:cvar, :method => :to_c_cvar, :arity => 1)
24
24
  def to_c_cvar(tree)
25
- "rb_cvar_get(CLASS_OF(plocals->self) != rb_cClass ? CLASS_OF(plocals->self) : plocals->self,#{intern_num tree[1]})"
25
+ "rb_cvar_get(CLASS_OF(#{var_self}) != rb_cClass ? CLASS_OF(#{var_self}) : #{var_self},#{intern_num tree[1]})"
26
26
  end
27
27
 
28
28
  define_translator_for(:cvasgn, :method => :to_c_cvasgn)
@@ -30,7 +30,7 @@ module FastRuby
30
30
  if result_var
31
31
  "
32
32
  {
33
- VALUE recv = CLASS_OF(plocals->self) != rb_cClass ? CLASS_OF(plocals->self) : plocals->self;
33
+ VALUE recv = CLASS_OF(#{var_self}) != rb_cClass ? CLASS_OF(#{var_self}) : #{var_self};
34
34
 
35
35
  #{to_c tree[2], result_var};
36
36
 
@@ -45,7 +45,7 @@ module FastRuby
45
45
  }
46
46
  "
47
47
  else
48
- "__rb_cvar_set(CLASS_OF(plocals->self) != rb_cClass ? CLASS_OF(plocals->self) : plocals->self,#{intern_num tree[1]},#{to_c tree[2]},Qfalse)"
48
+ "__rb_cvar_set(CLASS_OF(#{var_self}) != rb_cClass ? CLASS_OF(#{var_self}) : #{var_self},#{intern_num tree[1]},#{to_c tree[2]},Qfalse)"
49
49
  end
50
50
  end
51
51
 
@@ -92,7 +92,7 @@ module FastRuby
92
92
  end
93
93
 
94
94
  define_translator_for(:const, :arity => 1) do |*x| tree = x.first;
95
- "rb_const_get(CLASS_OF(plocals->self), #{intern_num(tree[1])})"
95
+ "rb_const_get(CLASS_OF(#{var_self}), #{intern_num(tree[1])})"
96
96
  end
97
97
 
98
98
  define_translator_for(:cdecl, :method => :to_c_cdecl)
@@ -215,9 +215,27 @@ module FastRuby
215
215
  "_lvar_assing(&#{locals_accessor}#{tree[1]},#{to_c tree[2]})"
216
216
  end
217
217
  end
218
+
219
+ def is_argument(variable)
220
+ @method_arguments.include?(variable)
221
+ end
218
222
 
219
223
  define_translator_for(:lvar, :arity => 1) do |*x| tree = x.first;
220
- locals_accessor + tree[1].to_s
224
+ if @has_inline_block or (not is_argument(tree[1]))
225
+ locals_accessor + tree[1].to_s
226
+ else
227
+ # search in arguments
228
+ index = @method_arguments.find_index{|argument| argument == tree[1]}
229
+ if index
230
+ "argv[#{index}]"
231
+ else
232
+ locals_accessor + tree[1].to_s
233
+ end
234
+ end
235
+ end
236
+
237
+ def var_self
238
+ @has_inline_block ? locals_accessor + "self" : "self";
221
239
  end
222
240
 
223
241
  define_translator_for(:defined, :method => :to_c_defined, :arity => 1)
@@ -253,7 +271,7 @@ module FastRuby
253
271
  elsif nt == :yield
254
272
  "rb_block_given_p() ? #{literal_value "yield"} : Qnil"
255
273
  elsif nt == :ivar
256
- "rb_ivar_defined(plocals->self,#{intern_num obj_tree[1]}) ? #{literal_value "instance-variable"} : Qnil"
274
+ "rb_ivar_defined(#{var_self},#{intern_num obj_tree[1]}) ? #{literal_value "instance-variable"} : Qnil"
257
275
  elsif nt == :attrset or
258
276
  nt == :op_asgn1 or
259
277
  nt == :op_asgn2 or
@@ -0,0 +1,298 @@
1
+ =begin
2
+
3
+ This file is part of the fastruby project, http://github.com/tario/fastruby
4
+
5
+ Copyright (c) 2011 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ fastruby is free software: you can redistribute it and/or modify
8
+ it under the terms of the gnu general public license as published by
9
+ the free software foundation, either version 3 of the license, or
10
+ (at your option) any later version.
11
+
12
+ fastruby is distributed in the hope that it will be useful,
13
+ but without any warranty; without even the implied warranty of
14
+ merchantability or fitness for a particular purpose. see the
15
+ gnu general public license for more details.
16
+
17
+ you should have received a copy of the gnu general public license
18
+ along with fastruby. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ =end
21
+ module FastRuby
22
+ class Context
23
+ define_translator_for(:cvar, :method => :to_c_cvar, :arity => 1)
24
+ def to_c_cvar(tree)
25
+ "rb_cvar_get(CLASS_OF(plocals->self) != rb_cClass ? CLASS_OF(plocals->self) : plocals->self,#{intern_num tree[1]})"
26
+ end
27
+
28
+ define_translator_for(:cvasgn, :method => :to_c_cvasgn)
29
+ def to_c_cvasgn(tree, result_var = nil)
30
+ if result_var
31
+ "
32
+ {
33
+ VALUE recv = CLASS_OF(plocals->self) != rb_cClass ? CLASS_OF(plocals->self) : plocals->self;
34
+
35
+ #{to_c tree[2], result_var};
36
+
37
+ #{if RUBY_VERSION =~ /^1\.9/
38
+ "rb_cvar_set(recv,#{intern_num tree[1]},#{result_var});"
39
+ elsif RUBY_VERSION =~ /^1\.8/
40
+ "rb_cvar_set(recv,#{intern_num tree[1]},#{result_var},Qfalse);"
41
+ else
42
+ raise RuntimeError, "unsupported ruby version #{RUBY_VERSION}"
43
+ end
44
+ }
45
+ }
46
+ "
47
+ else
48
+ "__rb_cvar_set(CLASS_OF(plocals->self) != rb_cClass ? CLASS_OF(plocals->self) : plocals->self,#{intern_num tree[1]},#{to_c tree[2]},Qfalse)"
49
+ end
50
+ end
51
+
52
+ define_translator_for(:gvar, :method => :to_c_gvar, :arity => 1)
53
+ def to_c_gvar(tree)
54
+ if (tree[1] == :$!)
55
+ "pframe->thread_data->exception"
56
+ else
57
+ "rb_gvar_get((struct global_entry*)#{global_entry(tree[1])})"
58
+ end
59
+ end
60
+
61
+ define_translator_for(:gasgn, :method => :to_c_gasgn)
62
+ def to_c_gasgn(tree, result_var = nil)
63
+ if result_var
64
+ "
65
+ {
66
+ #{to_c tree[2], result_var};
67
+ rb_gvar_set((void*)#{global_entry(tree[1])},#{result_var});
68
+ }
69
+ "
70
+ else
71
+ "_rb_gvar_set((void*)#{global_entry(tree[1])}, #{to_c tree[2]})"
72
+ end
73
+ end
74
+
75
+ define_translator_for(:ivar, :method => :to_c_ivar, :arity => 1)
76
+ def to_c_ivar(tree)
77
+ "rb_ivar_get(#{locals_accessor}self,#{intern_num tree[1]})"
78
+ end
79
+
80
+ define_translator_for(:iasgn, :method => :to_c_iasgn)
81
+ def to_c_iasgn(tree, result_var = nil)
82
+ if result_var
83
+ "
84
+ {
85
+ #{to_c tree[2], result_var};
86
+ rb_ivar_set(#{locals_accessor}self,#{intern_num tree[1]},#{result_var});
87
+ }
88
+ "
89
+ else
90
+ "_rb_ivar_set(#{locals_accessor}self,#{intern_num tree[1]},#{to_c tree[2]})"
91
+ end
92
+ end
93
+
94
+ define_translator_for(:const, :arity => 1) do |*x| tree = x.first;
95
+ "rb_const_get(CLASS_OF(plocals->self), #{intern_num(tree[1])})"
96
+ end
97
+
98
+ define_translator_for(:cdecl, :method => :to_c_cdecl)
99
+ def to_c_cdecl(tree, result_var_ = nil)
100
+
101
+ result_var = result_var_ || "value"
102
+
103
+ if tree[1].instance_of? Symbol
104
+ code = proc{"
105
+ {
106
+ // set constant #{tree[1].to_s}
107
+ #{to_c tree[2], result_var};
108
+ rb_const_set(rb_cObject, #{intern_num tree[1]}, #{result_var});
109
+ }
110
+ "}
111
+ elsif tree[1].instance_of? FastRuby::FastRubySexp
112
+
113
+ if tree[1].node_type == :colon2
114
+ code = proc{"
115
+ {
116
+ // set constant #{tree[1].to_s}
117
+ #{to_c tree[2], result_var};
118
+ VALUE klass = Qnil;
119
+ #{to_c tree[1][1], "klass"};
120
+ rb_const_set(klass, #{intern_num tree[1][2]}, #{result_var});
121
+ }
122
+ "}
123
+ elsif tree[1].node_type == :colon3
124
+ code = proc{"
125
+ {
126
+ // set constant #{tree[1].to_s}
127
+ #{to_c tree[2], result_var};
128
+ rb_const_set(rb_cObject, #{intern_num tree[1][1]}, #{result_var});
129
+ }
130
+ "}
131
+ end
132
+ end
133
+
134
+ if result_var_
135
+ code.call
136
+ else
137
+ inline_block{"VALUE #{result_var} = Qnil;\n" + code.call + "
138
+ return #{result_var};
139
+ "}
140
+ end
141
+ end
142
+
143
+ define_translator_for(:colon3, :method => :to_c_colon3, :arity => 1)
144
+ def to_c_colon3(tree)
145
+ "rb_const_get_from(rb_cObject, #{intern_num tree[1]})"
146
+ end
147
+
148
+ define_translator_for(:colon2, :method => :to_c_colon2)
149
+ def to_c_colon2(tree, result_var = nil)
150
+ code = proc{ "
151
+ {
152
+ VALUE klass = Qnil;
153
+
154
+ #{to_c tree[1],"klass"};
155
+ #{
156
+ if result_var
157
+ "#{result_var} = Qnil;"
158
+ end
159
+ }
160
+
161
+ if (rb_is_const_id(#{intern_num tree[2]})) {
162
+ switch (TYPE(klass)) {
163
+ case T_CLASS:
164
+ case T_MODULE:
165
+ #{
166
+ if result_var
167
+ "#{result_var} = rb_const_get_from(klass, #{intern_num tree[2]});"
168
+ else
169
+ "return rb_const_get_from(klass, #{intern_num tree[2]});"
170
+ end
171
+ }
172
+ break;
173
+ default:
174
+ #{_raise("rb_eTypeError","not a class/module")};
175
+ break;
176
+ }
177
+ }
178
+ else {
179
+ #{
180
+ if result_var
181
+ "#{result_var} = rb_funcall(klass, #{intern_num tree[2]}, 0, 0);"
182
+ else
183
+ "return rb_funcall(klass, #{intern_num tree[2]}, 0, 0);"
184
+ end
185
+ }
186
+ }
187
+
188
+ #{
189
+ unless result_var
190
+ "return Qnil;"
191
+ end
192
+ }
193
+ }
194
+ "}
195
+
196
+ if result_var
197
+ code.call
198
+ else
199
+ inline_block &code
200
+ end
201
+ end
202
+
203
+ define_translator_for(:lasgn, :method => :to_c_lasgn)
204
+ def to_c_lasgn(tree, result_var = nil)
205
+ code = "
206
+ {
207
+ #{to_c tree[2], result_var};
208
+ #{locals_accessor}#{tree[1]} = #{result_var};
209
+ }
210
+ "
211
+
212
+ if result_var
213
+ code
214
+ else
215
+ "_lvar_assing(&#{locals_accessor}#{tree[1]},#{to_c tree[2]})"
216
+ end
217
+ end
218
+
219
+ def is_argument(variable)
220
+ @method_arguments.include?(variable)
221
+ end
222
+
223
+ define_translator_for(:lvar, :arity => 1) do |*x| tree = x.first;
224
+ if @has_inline_block or (not is_argument(tree[1]))
225
+ locals_accessor + tree[1].to_s
226
+ else
227
+ # search in arguments
228
+ index = @method_arguments.find_index{|argument| argument == tree[1]}
229
+ if index
230
+ "argv[#{index}]"
231
+ else
232
+ locals_accessor + tree[1].to_s
233
+ end
234
+ end
235
+ end
236
+
237
+ def var_self
238
+ @has_inline_block ? locals_accessor + "self" : "self";
239
+ end
240
+
241
+ define_translator_for(:defined, :method => :to_c_defined, :arity => 1)
242
+ def to_c_defined(tree)
243
+ obj_tree = tree[1]
244
+
245
+ if obj_tree[0] == :call && obj_tree[2] == :infer
246
+ obj_tree = obj_tree[1]
247
+ end
248
+
249
+ nt = obj_tree.node_type
250
+
251
+ if nt == :self
252
+ 'rb_str_new2("self")'
253
+ elsif nt == :true
254
+ 'rb_str_new2("true")'
255
+ elsif nt == :false
256
+ 'rb_str_new2("false")'
257
+ elsif nt == :nil
258
+ 'rb_str_new2("nil")'
259
+ elsif nt == :lvar
260
+ 'rb_str_new2("local-variable")'
261
+ elsif nt == :gvar
262
+ "rb_gvar_defined((struct global_entry*)#{global_entry(obj_tree[1])}) ? #{literal_value "global-variable"} : Qnil"
263
+ elsif nt == :const
264
+ "rb_const_defined(rb_cObject, #{intern_num obj_tree[1]}) ? #{literal_value "constant"} : Qnil"
265
+ elsif nt == :call
266
+ if RUBY_VERSION =~ /^1\.8/
267
+ "rb_method_node(CLASS_OF(#{to_c obj_tree[1]}), #{intern_num obj_tree[2]}) ? #{literal_value "method"} : Qnil"
268
+ else
269
+ "rb_method_entry(CLASS_OF(#{to_c obj_tree[1]}), #{intern_num obj_tree[2]}) ? #{literal_value "method"} : Qnil"
270
+ end
271
+ elsif nt == :yield
272
+ "rb_block_given_p() ? #{literal_value "yield"} : Qnil"
273
+ elsif nt == :ivar
274
+ "rb_ivar_defined(#{var_self},#{intern_num obj_tree[1]}) ? #{literal_value "instance-variable"} : Qnil"
275
+ elsif nt == :attrset or
276
+ nt == :op_asgn1 or
277
+ nt == :op_asgn2 or
278
+ nt == :op_asgn_or or
279
+ nt == :op_asgn_and or
280
+ nt == :op_asgn_masgn or
281
+ nt == :masgn or
282
+ nt == :lasgn or
283
+ nt == :dasgn or
284
+ nt == :dasgn_curr or
285
+ nt == :gasgn or
286
+ nt == :iasgn or
287
+ nt == :cdecl or
288
+ nt == :cvdecl or
289
+ nt == :cvasgn
290
+ literal_value "assignment"
291
+ else
292
+ literal_value "expression"
293
+ end
294
+ end
295
+
296
+
297
+ end
298
+ end