fastruby 0.0.5 → 0.0.6

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.
@@ -18,34 +18,32 @@ you should have received a copy of the gnu general public license
18
18
  along with fastruby. if not, see <http://www.gnu.org/licenses/>.
19
19
 
20
20
  =end
21
- require "rubygems"
22
- require "inline"
23
21
  require "set"
24
22
  require "fastruby/method_extension"
23
+ require "fastruby/set_tree"
24
+ require "fastruby/exceptions"
25
+ require "rubygems"
26
+ require "sexp"
25
27
 
26
28
  module FastRuby
27
29
  class Context
28
-
29
- class UnwindFastrubyFrame < Exception
30
- def initialize(ex,target_frame,return_value)
31
- @ex = ex
32
- @target_frame = target_frame
33
- @return_value = return_value
34
- end
35
- end
36
-
37
30
  attr_accessor :infer_lvar_map
38
31
  attr_accessor :alt_method_name
39
32
  attr_accessor :locals
40
33
  attr_accessor :options
41
34
  attr_accessor :infer_self
35
+ attr_accessor :snippet_hash
36
+ attr_reader :no_cache
37
+ attr_reader :init_extra
42
38
  attr_reader :extra_code
43
39
  attr_reader :yield_signature
44
40
 
45
41
  def initialize(common_func = true)
46
42
  @infer_lvar_map = Hash.new
43
+ @no_cache = false
47
44
  @extra_code = ""
48
45
  @options = {}
46
+ @init_extra = Array.new
49
47
  @frame_struct = "struct {
50
48
  void* parent_frame;
51
49
  void* target_frame;
@@ -62,9 +60,20 @@ module FastRuby
62
60
  void* block_function_param;
63
61
  }"
64
62
 
63
+
65
64
  extra_code << '#include "node.h"
66
65
  '
67
66
 
67
+ ruby_code = "
68
+ $LOAD_PATH << #{FastRuby.fastruby_load_path.inspect}
69
+ require #{FastRuby.fastruby_script_path.inspect}
70
+ "
71
+
72
+ init_extra << "
73
+ rb_eval_string(#{ruby_code.inspect});
74
+ "
75
+
76
+ @common_func = common_func
68
77
  if common_func
69
78
  extra_code << "static VALUE _rb_gvar_set(void* ge,VALUE value) {
70
79
  rb_gvar_set((struct global_entry*)ge,value);
@@ -72,6 +81,10 @@ module FastRuby
72
81
  }
73
82
  "
74
83
 
84
+ extra_code << "static VALUE re_yield(int argc, VALUE* argv, VALUE param, VALUE _parent_frame) {
85
+ return rb_yield_splat(rb_ary_new4(argc,argv));
86
+ }"
87
+
75
88
  extra_code << "static VALUE _rb_ivar_set(VALUE recv,ID idvar, VALUE value) {
76
89
  rb_ivar_set(recv,idvar,value);
77
90
  return value;
@@ -82,6 +95,11 @@ module FastRuby
82
95
  *destination = value;
83
96
  return value;
84
97
  }
98
+
99
+ /*
100
+ #{caller.join("\n")}
101
+ */
102
+
85
103
  "
86
104
  end
87
105
  end
@@ -125,6 +143,8 @@ module FastRuby
125
143
  other_call_tree = call_tree.dup
126
144
  other_call_tree[1] = s(:lvar, :arg)
127
145
 
146
+ mname = call_tree[2]
147
+
128
148
  call_args_tree = call_tree[3]
129
149
 
130
150
  caller_code = nil
@@ -135,8 +155,6 @@ module FastRuby
135
155
  mobject = nil
136
156
  len = nil
137
157
 
138
- convention = :ruby
139
-
140
158
  extra_inference = {}
141
159
 
142
160
  if recvtype
@@ -153,10 +171,7 @@ module FastRuby
153
171
  end
154
172
  end
155
173
 
156
- convention = nil
157
-
158
174
  if recvtype.respond_to? :fastruby_method and inference_complete
159
-
160
175
  method_tree = nil
161
176
  begin
162
177
  method_tree = recvtype.instance_method(call_tree[2]).fastruby.tree
@@ -178,24 +193,8 @@ module FastRuby
178
193
  extra_inference[yield_args[i]] = yield_signature[i]
179
194
  end
180
195
  end
181
-
182
- convention = :fastruby
183
- else
184
- mobject = recvtype.instance_method(call_tree[2])
185
- convention = :cruby
186
196
  end
187
- else
188
- mobject = recvtype.instance_method(call_tree[2])
189
- convention = :cruby
190
- end
191
-
192
- address = getaddress(mobject)
193
- len = getlen(mobject)
194
-
195
- unless address
196
- convention = :ruby
197
197
  end
198
-
199
198
  end
200
199
 
201
200
  anonymous_impl = tree[3]
@@ -238,7 +237,19 @@ module FastRuby
238
237
  end
239
238
  end
240
239
 
241
- if convention == :ruby or convention == :cruby
240
+
241
+ if not args_tree
242
+ str_arg_initialization = ""
243
+ elsif args_tree.first == :lasgn
244
+ str_arg_initialization = "plocals->#{args_tree[1]} = arg;"
245
+ elsif args_tree.first == :masgn
246
+ arguments = args_tree[1][1..-1].map(&:last)
247
+
248
+ (0..arguments.size-1).each do |i|
249
+ str_arg_initialization << "plocals->#{arguments[i]} = rb_ary_entry(arg,#{i});\n"
250
+ end
251
+ end
252
+ rb_funcall_caller_code = nil
242
253
 
243
254
  if call_args_tree.size > 1
244
255
 
@@ -247,12 +258,12 @@ module FastRuby
247
258
 
248
259
  str_recv = "plocals->self" unless recv_tree
249
260
 
250
- caller_code = proc { |name| "
261
+ rb_funcall_caller_code = proc { |name| "
251
262
  static VALUE #{name}(VALUE param) {
252
263
  // call to #{call_tree[2]}
253
264
 
254
265
  #{str_lvar_initialization}
255
- return rb_funcall(#{str_recv}, #{call_tree[2].to_i}, #{call_args_tree.size-1}, #{str_called_code_args});
266
+ return rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, #{call_args_tree.size-1}, #{str_called_code_args});
256
267
  }
257
268
  "
258
269
  }
@@ -261,31 +272,18 @@ module FastRuby
261
272
  str_recv = to_c recv_tree
262
273
  str_recv = "plocals->self" unless recv_tree
263
274
 
264
- caller_code = proc { |name| "
275
+ rb_funcall_caller_code = proc { |name| "
265
276
  static VALUE #{name}(VALUE param) {
266
277
  // call to #{call_tree[2]}
267
278
  #{str_lvar_initialization}
268
- return rb_funcall(#{str_recv}, #{call_tree[2].to_i}, 0);
279
+ return rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);
269
280
  }
270
281
  "
271
282
  }
272
283
  end
273
284
 
274
- if not args_tree
275
- str_arg_initialization = ""
276
- elsif args_tree.first == :lasgn
277
- str_arg_initialization = "plocals->#{args_tree[1]} = arg;"
278
- elsif args_tree.first == :masgn
279
- arguments = args_tree[1][1..-1].map(&:last)
280
-
281
- (0..arguments.size-1).each do |i|
282
- str_arg_initialization << "plocals->#{arguments[i]} = rb_ary_entry(arg,#{i});\n"
283
- end
284
- end
285
-
286
- str_arg_initialization
287
285
 
288
- block_code = proc { |name| "
286
+ rb_funcall_block_code = proc { |name| "
289
287
  static VALUE #{name}(VALUE arg, VALUE _plocals) {
290
288
  // block for call to #{call_tree[2]}
291
289
  VALUE last_expression = Qnil;
@@ -308,15 +306,15 @@ module FastRuby
308
306
  }
309
307
 
310
308
  VALUE ex = rb_funcall(
311
- (VALUE)#{UnwindFastrubyFrame.internal_value},
312
- #{:new.to_i},
309
+ #{literal_value FastRuby::Context::UnwindFastrubyFrame},
310
+ #{intern_num :new},
313
311
  3,
314
312
  pframe->exception,
315
313
  LONG2FIX(pframe->target_frame),
316
314
  pframe->return_value
317
315
  );
318
316
 
319
- rb_funcall(plocals->self, #{:raise.to_i}, 1, ex);
317
+ rb_funcall(plocals->self, #{intern_num :raise}, 1, ex);
320
318
  }
321
319
  return frame.return_value;
322
320
  }
@@ -330,21 +328,18 @@ module FastRuby
330
328
  "
331
329
  }
332
330
 
333
- protected_block("rb_iterate(#{anonymous_function(&caller_code)}, (VALUE)pframe, #{anonymous_function(&block_code)}, (VALUE)plocals)", true)
334
-
335
- elsif convention == :fastruby
336
331
 
337
- str_arg_initialization = ""
332
+ fastruby_str_arg_initialization = ""
338
333
 
339
334
  if not args_tree
340
- str_arg_initialization = ""
335
+ fastruby_str_arg_initialization = ""
341
336
  elsif args_tree.first == :lasgn
342
- str_arg_initialization = "plocals->#{args_tree[1]} = argv[0];"
337
+ fastruby_str_arg_initialization = "plocals->#{args_tree[1]} = argv[0];"
343
338
  elsif args_tree.first == :masgn
344
339
  arguments = args_tree[1][1..-1].map(&:last)
345
340
 
346
341
  (0..arguments.size-1).each do |i|
347
- str_arg_initialization << "plocals->#{arguments[i]} = #{i} < argc ? argv[#{i}] : Qnil;\n"
342
+ fastruby_str_arg_initialization << "plocals->#{arguments[i]} = #{i} < argc ? argv[#{i}] : Qnil;\n"
348
343
  end
349
344
  end
350
345
 
@@ -380,7 +375,7 @@ module FastRuby
380
375
 
381
376
  }
382
377
 
383
- #{str_arg_initialization}
378
+ #{fastruby_str_arg_initialization}
384
379
  #{str_impl}
385
380
 
386
381
  return last_expression;
@@ -388,16 +383,17 @@ module FastRuby
388
383
  "
389
384
  }
390
385
 
391
-
392
386
  str_recv = "plocals->self"
393
387
 
394
388
  if recv_tree
395
389
  str_recv = to_c recv_tree
396
390
  end
397
391
 
392
+ caller_code = nil
393
+ convention_global_name = add_global_name("int",0)
394
+
398
395
  if call_args_tree.size > 1
399
- value_cast = ( ["VALUE"]*(call_tree[3].size) ).join(",")
400
- value_cast = value_cast + ", VALUE, VALUE" if convention == :fastruby
396
+ value_cast = ( ["VALUE"]*(call_tree[3].size) ).join(",") + ", VALUE, VALUE"
401
397
 
402
398
  str_called_code_args = call_tree[3][1..-1].map{|subtree| to_c subtree}.join(",")
403
399
 
@@ -411,7 +407,7 @@ module FastRuby
411
407
 
412
408
  // call to #{call_tree[2]}
413
409
 
414
- return ((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{str_recv}, (VALUE)&block, (VALUE)pframe, #{str_called_code_args});
410
+ return ((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name)})(#{str_recv}, (VALUE)&block, (VALUE)pframe, #{str_called_code_args});
415
411
  }
416
412
  "
417
413
  }
@@ -427,14 +423,21 @@ module FastRuby
427
423
 
428
424
  // call to #{call_tree[2]}
429
425
 
430
- return ((VALUE(*)(VALUE,VALUE,VALUE))0x#{address.to_s(16)})(#{str_recv}, (VALUE)&block, (VALUE)pframe);
426
+ return ((VALUE(*)(VALUE,VALUE,VALUE))#{encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name)})(#{str_recv}, (VALUE)&block, (VALUE)pframe);
431
427
  }
432
428
  "
433
429
  }
434
430
  end
435
431
 
436
- "#{anonymous_function(&caller_code)}((VALUE)plocals, (VALUE)pframe)"
437
- end
432
+ inline_block "
433
+ if (#{convention_global_name}) {
434
+ return #{anonymous_function(&caller_code)}((VALUE)plocals, (VALUE)pframe);
435
+ } else {
436
+ return #{
437
+ protected_block("rb_iterate(#{anonymous_function(&rb_funcall_caller_code)}, (VALUE)pframe, #{anonymous_function(&rb_funcall_block_code)}, (VALUE)plocals)", true)
438
+ };
439
+ }
440
+ "
438
441
  end
439
442
 
440
443
  def to_c_yield(tree)
@@ -478,7 +481,7 @@ module FastRuby
478
481
  anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){})"
479
482
  end
480
483
 
481
- protected_block(ret, true)
484
+ protected_block(ret, false)
482
485
  end
483
486
 
484
487
  def to_c_block(tree)
@@ -518,7 +521,7 @@ module FastRuby
518
521
  else
519
522
  inline_block("
520
523
  pframe->target_frame = (void*)-1;
521
- pframe->exception = (VALUE)#{LocalJumpError.exception.internal_value};
524
+ pframe->exception = #{literal_value LocalJumpError.exception};
522
525
  longjmp(pframe->jmp,1);
523
526
  return Qnil;
524
527
  ")
@@ -532,7 +535,7 @@ module FastRuby
532
535
  else
533
536
  inline_block("
534
537
  pframe->target_frame = (void*)-1;
535
- pframe->exception = (VALUE)#{LocalJumpError.exception.internal_value};
538
+ pframe->exception = #{literal_value LocalJumpError.exception};
536
539
  longjmp(pframe->jmp,1);
537
540
  return Qnil;
538
541
  ")
@@ -541,7 +544,7 @@ module FastRuby
541
544
  end
542
545
 
543
546
  def to_c_lit(tree)
544
- "(VALUE)#{tree[1].internal_value}"
547
+ literal_value tree[1]
545
548
  end
546
549
 
547
550
  def to_c_nil(tree)
@@ -549,7 +552,7 @@ module FastRuby
549
552
  end
550
553
 
551
554
  def to_c_str(tree)
552
- "(VALUE)#{tree[1].internal_value}"
555
+ literal_value tree[1]
553
556
  end
554
557
 
555
558
  def to_c_hash(tree)
@@ -597,24 +600,24 @@ module FastRuby
597
600
  inline_block "
598
601
  // set constant #{tree[1].to_s}
599
602
  VALUE val = #{to_c tree[2]};
600
- rb_const_set(rb_cObject, #{tree[1].to_i}, val);
603
+ rb_const_set(rb_cObject, #{intern_num tree[1]}, val);
601
604
  return val;
602
605
  "
603
- elsif tree[1].instance_of? Sexp
606
+ elsif tree[1].instance_of? FastRuby::FastRubySexp
604
607
 
605
608
  if tree[1].node_type == :colon2
606
609
  inline_block "
607
610
  // set constant #{tree[1].to_s}
608
611
  VALUE val = #{to_c tree[2]};
609
612
  VALUE klass = #{to_c tree[1][1]};
610
- rb_const_set(klass, #{tree[1][2].to_i}, val);
613
+ rb_const_set(klass, #{intern_num tree[1][2]}, val);
611
614
  return val;
612
615
  "
613
616
  elsif tree[1].node_type == :colon3
614
617
  inline_block "
615
618
  // set constant #{tree[1].to_s}
616
619
  VALUE val = #{to_c tree[2]};
617
- rb_const_set(rb_cObject, #{tree[1][1].to_i}, val);
620
+ rb_const_set(rb_cObject, #{intern_num tree[1][1]}, val);
618
621
  return val;
619
622
  "
620
623
  end
@@ -652,11 +655,165 @@ module FastRuby
652
655
  end
653
656
 
654
657
  def to_c_const(tree)
655
- "rb_const_get(CLASS_OF(plocals->self), #{tree[1].to_i})"
658
+ "rb_const_get(CLASS_OF(plocals->self), #{intern_num(tree[1])})"
656
659
  end
657
660
 
658
661
  def to_c_defn(tree)
659
- "rb_funcall(plocals->self,#{:fastruby.to_i},1,(VALUE)#{tree.internal_value})"
662
+
663
+ method_name = tree[1]
664
+ args_tree = tree[2]
665
+
666
+ global_klass_variable = add_global_name("VALUE", "Qnil");
667
+
668
+ hash = Hash.new
669
+ value_cast = ( ["VALUE"]*(args_tree.size+2) ).join(",")
670
+
671
+ strmethodargs = ""
672
+ strmethodargs_class = (["self"] + args_tree[1..-1]).map{|arg| "CLASS_OF(#{arg.to_s})"}.join(",")
673
+
674
+ if args_tree.size > 1
675
+ strmethodargs = "self,block,(VALUE)&frame,#{args_tree[1..-1].map(&:to_s).join(",") }"
676
+ else
677
+ strmethodargs = "self,block,(VALUE)&frame"
678
+ end
679
+
680
+ strmethod_signature = (["self"] + args_tree[1..-1]).map { |arg|
681
+ "sprintf(method_name+strlen(method_name), \"%lu\", FIX2LONG(rb_obj_id(CLASS_OF(#{arg}))));\n"
682
+ }.join
683
+
684
+ anonymous_method_name = anonymous_function{ |anonymous_method_name| "VALUE #{anonymous_method_name}(#{(["self"]+args_tree[1..-1]).map{|arg| "VALUE #{arg}" }.join(",")}) {
685
+
686
+ VALUE klass = #{global_klass_variable};
687
+ char method_name[0x100];
688
+
689
+ method_name[0] = '_';
690
+ method_name[1] = 0;
691
+
692
+ sprintf(method_name+1, \"#{method_name}\");
693
+ #{strmethod_signature}
694
+
695
+ NODE* body;
696
+ ID id;
697
+
698
+ id = rb_intern(method_name);
699
+ body = rb_method_node(klass,id);
700
+
701
+ if (body == 0) {
702
+ VALUE argv_class[] = {#{strmethodargs_class} };
703
+ VALUE signature = rb_ary_new4(#{args_tree.size},argv_class);
704
+
705
+ VALUE mobject = rb_funcall(#{global_klass_variable}, #{intern_num :build}, 2, signature,rb_str_new2(#{method_name.to_s.inspect}));
706
+
707
+ struct METHOD {
708
+ VALUE klass, rklass;
709
+ VALUE recv;
710
+ ID id, oid;
711
+ int safe_level;
712
+ NODE *body;
713
+ };
714
+
715
+ struct METHOD *data;
716
+ Data_Get_Struct(mobject, struct METHOD, data);
717
+ body = data->body;
718
+
719
+ if (body == 0) {
720
+ rb_raise(rb_eRuntimeError,\"method not found after build: '%s'\", method_name);
721
+ }
722
+ }
723
+
724
+ if (nd_type(body) == NODE_CFUNC) {
725
+ struct {
726
+ void* parent_frame;
727
+ void* target_frame;
728
+ void* plocals;
729
+ jmp_buf jmp;
730
+ VALUE return_value;
731
+ VALUE exception;
732
+ int rescue;
733
+ } frame;
734
+
735
+ frame.target_frame = 0;
736
+ frame.parent_frame = 0;
737
+ frame.rescue = 0;
738
+ frame.exception = Qnil;
739
+ frame.return_value = Qnil;
740
+
741
+ int argc = body->nd_argc;
742
+
743
+ VALUE block = Qfalse;
744
+
745
+ if (rb_block_given_p()) {
746
+ struct {
747
+ void *block_function_address;
748
+ void *block_function_param;
749
+ } block_struct;
750
+
751
+ block_struct.block_function_address = re_yield;
752
+ block_struct.block_function_param = 0;
753
+
754
+ block = (VALUE)&block_struct;
755
+ }
756
+
757
+ int aux = setjmp(frame.jmp);
758
+ if (aux != 0) {
759
+ if (frame.target_frame == (void*)-1) {
760
+ rb_funcall(self, #{intern_num :raise}, 1, frame.exception);
761
+ }
762
+
763
+ if (frame.target_frame != &frame) {
764
+ VALUE ex = rb_funcall(
765
+ #{literal_value FastRuby::Context::UnwindFastrubyFrame},
766
+ #{intern_num :new},
767
+ 3,
768
+ frame.exception,
769
+ LONG2FIX(frame.target_frame),
770
+ frame.return_value
771
+ );
772
+
773
+ rb_funcall(self, #{intern_num :raise}, 1, ex);
774
+ }
775
+
776
+ return Qnil;
777
+ }
778
+
779
+ if (argc == #{args_tree.size+1}) {
780
+ return ((VALUE(*)(#{value_cast}))body->nd_cfnc)(#{strmethodargs});
781
+ } else if (argc == -1) {
782
+ VALUE argv[] = {#{(["block,(VALUE)&frame"]+args_tree[1..-1]).map(&:to_s).join(",")} };
783
+ return ((VALUE(*)(int,VALUE*,VALUE))body->nd_cfnc)(#{args_tree.size},argv,self);
784
+ } else if (argc == -2) {
785
+ VALUE argv[] = {#{(["block,(VALUE)&frame"]+args_tree[1..-1]).map(&:to_s).join(",")} };
786
+ return ((VALUE(*)(VALUE,VALUE))body->nd_cfnc)(self, rb_ary_new4(#{args_tree.size},argv));
787
+ } else {
788
+ rb_raise(rb_eArgError, \"wrong number of arguments (#{args_tree.size-1} for %d)\", argc);
789
+ }
790
+ }
791
+
792
+ return Qnil;
793
+ }"
794
+ }
795
+
796
+ alt_options = options.dup
797
+
798
+ alt_options.delete(:self)
799
+ alt_options.delete(:main)
800
+
801
+ inline_block "
802
+ #{global_klass_variable} = plocals->self;
803
+
804
+ // set tree
805
+ rb_funcall(#{literal_value FastRuby}, #{intern_num :set_tree}, 5,
806
+ #{global_klass_variable},
807
+ rb_str_new2(#{method_name.to_s.inspect}),
808
+ #{literal_value tree},
809
+ #{literal_value snippet_hash},
810
+ #{literal_value alt_options}
811
+
812
+ );
813
+
814
+ rb_define_method(plocals->self, #{method_name.to_s.inspect}, #{anonymous_method_name}, #{args_tree.size-1} );
815
+ "
816
+
660
817
  end
661
818
 
662
819
  def to_c_defs(tree)
@@ -665,6 +822,7 @@ module FastRuby
665
822
  tmp = FastRuby.build_defs(tree)
666
823
 
667
824
  extra_code << tmp[0]
825
+ @init_extra = @init_extra + tmp[2]
668
826
 
669
827
  inline_block "
670
828
  rb_define_singleton_method(#{to_c tree[1]}, \"#{tree[2].to_s}\", (void*)#{tmp[1]}, #{args_tree.size-1});
@@ -686,15 +844,15 @@ module FastRuby
686
844
  elsif nt == :lvar
687
845
  'rb_str_new2("local-variable")'
688
846
  elsif nt == :gvar
689
- "rb_gvar_defined((struct global_entry*)0x#{global_entry(tree[1][1]).to_s(16)}) ? #{"global-variable".internal_value} : Qnil"
847
+ "rb_gvar_defined((struct global_entry*)#{global_entry(tree[1][1])}) ? #{literal_value "global-variable"} : Qnil"
690
848
  elsif nt == :const
691
- "rb_const_defined(rb_cObject, #{tree[1][1].to_i}) ? #{"constant".internal_value} : Qnil"
849
+ "rb_const_defined(rb_cObject, #{intern_num tree[1][1]}) ? #{literal_value "constant"} : Qnil"
692
850
  elsif nt == :call
693
- "rb_method_node(CLASS_OF(#{to_c tree[1][1]}), #{tree[1][2].to_i}) ? #{"method".internal_value} : Qnil"
851
+ "rb_method_node(CLASS_OF(#{to_c tree[1][1]}), #{intern_num tree[1][2]}) ? #{literal_value "method"} : Qnil"
694
852
  elsif nt == :yield
695
- "rb_block_given_p() ? #{"yield".internal_value} : Qnil"
853
+ "rb_block_given_p() ? #{literal_value "yield"} : Qnil"
696
854
  elsif nt == :ivar
697
- "rb_ivar_defined(plocals->self,#{tree[1][1].to_i}) ? #{"instance-variable".internal_value} : Qnil"
855
+ "rb_ivar_defined(plocals->self,#{intern_num tree[1][1]}) ? #{literal_value "instance-variable"} : Qnil"
698
856
  elsif nt == :attrset or
699
857
  nt == :op_asgn1 or
700
858
  nt == :op_asgn2 or
@@ -710,9 +868,9 @@ module FastRuby
710
868
  nt == :cdecl or
711
869
  nt == :cvdecl or
712
870
  nt == :cvasgn
713
- "assignment".internal_value
871
+ literal_value "assignment"
714
872
  else
715
- "expression".internal_value
873
+ literal_value "expression"
716
874
  end
717
875
  end
718
876
 
@@ -726,6 +884,27 @@ module FastRuby
726
884
  #{@locals.map{|l| "VALUE #{l};\n"}.join}
727
885
  #{args_tree[1..-1].map{|arg| "VALUE #{arg};\n"}.join};
728
886
  }"
887
+
888
+ if @common_func
889
+ init_extra << "
890
+ #{@frame_struct} frame;
891
+ #{@locals_struct} locals;
892
+
893
+ locals.return_value = Qnil;
894
+ locals.pframe = &frame;
895
+ locals.self = rb_cObject;
896
+
897
+ frame.target_frame = 0;
898
+ frame.plocals = (void*)&locals;
899
+ frame.return_value = Qnil;
900
+ frame.exception = Qnil;
901
+ frame.rescue = 0;
902
+ frame.last_error = Qnil;
903
+
904
+ typeof(&frame) pframe = &frame;
905
+ "
906
+ end
907
+
729
908
  end
730
909
 
731
910
  def to_c_method_defs(tree)
@@ -800,7 +979,7 @@ module FastRuby
800
979
 
801
980
  int aux = setjmp(frame.jmp);
802
981
  if (aux != 0) {
803
- rb_funcall(self, #{:raise.to_i}, 1, frame.exception);
982
+ rb_funcall(self, #{intern_num :raise}, 1, frame.exception);
804
983
  }
805
984
 
806
985
 
@@ -809,39 +988,141 @@ module FastRuby
809
988
  "
810
989
  end
811
990
 
991
+ def add_main
992
+ if options[:main]
993
+
994
+ extra_code << "
995
+ static VALUE #{@alt_method_name}(VALUE self__);
996
+ static VALUE main_proc_call(VALUE self__, VALUE class_self_) {
997
+ #{@alt_method_name}(class_self_);
998
+ return Qnil;
999
+ }
1000
+
1001
+ "
1002
+
1003
+ init_extra << "
1004
+ {
1005
+ VALUE newproc = rb_funcall(rb_cObject,#{intern_num :new},0);
1006
+ rb_define_singleton_method(newproc, \"call\", main_proc_call, 1);
1007
+ rb_gv_set(\"$last_obj_proc\", newproc);
1008
+
1009
+ }
1010
+ "
1011
+ end
1012
+ end
1013
+
1014
+ def define_method_at_init(method_name, size, signature)
1015
+ init_extra << "
1016
+ {
1017
+ VALUE method_name = rb_funcall(
1018
+ #{literal_value FastRuby},
1019
+ #{intern_num :make_str_signature},
1020
+ 2,
1021
+ #{literal_value method_name},
1022
+ #{literal_value signature}
1023
+ );
1024
+
1025
+ rb_define_method(#{to_c s(:gvar, :$class_self)}, RSTRING(method_name)->ptr, #{alt_method_name}, #{size});
1026
+ }
1027
+ "
1028
+ end
1029
+
812
1030
  def to_c_method(tree)
813
1031
  method_name = tree[1]
814
1032
  args_tree = tree[2]
815
-
816
1033
  impl_tree = tree[3][1]
817
1034
 
818
- initialize_method_structs(args_tree)
1035
+ if (options[:main])
1036
+ initialize_method_structs(args_tree)
819
1037
 
820
- strargs = if args_tree.size > 1
821
- "VALUE block, VALUE _parent_frame, #{args_tree[1..-1].map{|arg| "VALUE #{arg}" }.join(",") }"
822
- else
823
- "VALUE block, VALUE _parent_frame"
824
- end
1038
+ strargs = if args_tree.size > 1
1039
+ "VALUE block, VALUE _parent_frame, #{args_tree[1..-1].map{|arg| "VALUE #{arg}" }.join(",") }"
1040
+ else
1041
+ "VALUE block, VALUE _parent_frame"
1042
+ end
825
1043
 
826
- "VALUE #{@alt_method_name || method_name}(#{strargs}) {
1044
+ ret = "VALUE #{@alt_method_name || method_name}() {
827
1045
 
828
- #{func_frame}
1046
+ #{@locals_struct} locals;
1047
+ #{@locals_struct} *plocals = (void*)&locals;
1048
+ #{@frame_struct} frame;
1049
+ #{@frame_struct} *pframe;
829
1050
 
830
- #{args_tree[1..-1].map { |arg|
831
- "locals.#{arg} = #{arg};\n"
832
- }.join("") }
1051
+ frame.plocals = plocals;
1052
+ frame.parent_frame = 0;
1053
+ frame.return_value = Qnil;
1054
+ frame.target_frame = &frame;
1055
+ frame.exception = Qnil;
1056
+ frame.rescue = 0;
1057
+
1058
+ locals.pframe = &frame;
1059
+
1060
+ pframe = (void*)&frame;
1061
+
1062
+ VALUE last_expression = Qnil;
1063
+
1064
+ int aux = setjmp(pframe->jmp);
1065
+ if (aux != 0) {
1066
+
1067
+ if (pframe->target_frame == (void*)-2) {
1068
+ return pframe->return_value;
1069
+ }
1070
+
1071
+ if (pframe->target_frame != pframe) {
1072
+ // raise exception
1073
+ return Qnil;
1074
+ }
1075
+
1076
+ return plocals->return_value;
1077
+ }
1078
+
1079
+ locals.self = self;
1080
+
1081
+ #{args_tree[1..-1].map { |arg|
1082
+ "locals.#{arg} = #{arg};\n"
1083
+ }.join("") }
833
1084
 
834
- pblock = (void*)block;
835
- if (pblock) {
836
- locals.block_function_address = pblock->block_function_address;
837
- locals.block_function_param = (VALUE)pblock->block_function_param;
838
- } else {
839
1085
  locals.block_function_address = 0;
840
1086
  locals.block_function_param = Qnil;
841
- }
842
1087
 
843
- return #{to_c impl_tree};
844
- }"
1088
+ return #{to_c impl_tree};
1089
+ }"
1090
+
1091
+ add_main
1092
+ ret
1093
+ else
1094
+
1095
+ initialize_method_structs(args_tree)
1096
+
1097
+ strargs = if args_tree.size > 1
1098
+ "VALUE block, VALUE _parent_frame, #{args_tree[1..-1].map{|arg| "VALUE #{arg}" }.join(",") }"
1099
+ else
1100
+ "VALUE block, VALUE _parent_frame"
1101
+ end
1102
+
1103
+ ret = "VALUE #{@alt_method_name || method_name}(#{strargs}) {
1104
+
1105
+ #{func_frame}
1106
+
1107
+ #{args_tree[1..-1].map { |arg|
1108
+ "locals.#{arg} = #{arg};\n"
1109
+ }.join("") }
1110
+
1111
+ pblock = (void*)block;
1112
+ if (pblock) {
1113
+ locals.block_function_address = pblock->block_function_address;
1114
+ locals.block_function_param = (VALUE)pblock->block_function_param;
1115
+ } else {
1116
+ locals.block_function_address = 0;
1117
+ locals.block_function_param = Qnil;
1118
+ }
1119
+
1120
+ return #{to_c impl_tree};
1121
+ }"
1122
+
1123
+ add_main
1124
+ ret
1125
+ end
845
1126
  end
846
1127
 
847
1128
  def locals_accessor
@@ -849,33 +1130,33 @@ module FastRuby
849
1130
  end
850
1131
 
851
1132
  def to_c_gvar(tree)
852
- "rb_gvar_get((struct global_entry*)0x#{global_entry(tree[1]).to_s(16)})"
1133
+ "rb_gvar_get((struct global_entry*)#{global_entry(tree[1])})"
853
1134
  end
854
1135
 
855
1136
  def to_c_gasgn(tree)
856
- "_rb_gvar_set((void*)0x#{global_entry(tree[1]).to_s(16)}, #{to_c tree[2]})"
1137
+ "_rb_gvar_set((void*)#{global_entry(tree[1])}, #{to_c tree[2]})"
857
1138
  end
858
1139
 
859
1140
  def to_c_ivar(tree)
860
- "rb_ivar_get(#{locals_accessor}self,#{tree[1].to_i})"
1141
+ "rb_ivar_get(#{locals_accessor}self,#{intern_num tree[1]})"
861
1142
  end
862
1143
 
863
1144
  def to_c_iasgn(tree)
864
- "_rb_ivar_set(#{locals_accessor}self,#{tree[1].to_i},#{to_c tree[2]})"
1145
+ "_rb_ivar_set(#{locals_accessor}self,#{intern_num tree[1]},#{to_c tree[2]})"
865
1146
  end
866
1147
 
867
1148
  def to_c_colon3(tree)
868
- "rb_const_get_from(rb_cObject, #{tree[1].to_i})"
1149
+ "rb_const_get_from(rb_cObject, #{intern_num tree[1]})"
869
1150
  end
870
1151
  def to_c_colon2(tree)
871
1152
  inline_block "
872
1153
  VALUE klass = #{to_c tree[1]};
873
1154
 
874
- if (rb_is_const_id(#{tree[2].to_i})) {
1155
+ if (rb_is_const_id(#{intern_num tree[2]})) {
875
1156
  switch (TYPE(klass)) {
876
1157
  case T_CLASS:
877
1158
  case T_MODULE:
878
- return rb_const_get_from(klass, #{tree[2].to_i});
1159
+ return rb_const_get_from(klass, #{intern_num tree[2]});
879
1160
  break;
880
1161
  default:
881
1162
  rb_raise(rb_eTypeError, \"%s is not a class/module\",
@@ -884,7 +1165,7 @@ module FastRuby
884
1165
  }
885
1166
  }
886
1167
  else {
887
- return rb_funcall(klass, #{tree[2].to_i}, 0, 0);
1168
+ return rb_funcall(klass, #{intern_num tree[2]}, 0, 0);
888
1169
  }
889
1170
 
890
1171
  return Qnil;
@@ -898,7 +1179,7 @@ module FastRuby
898
1179
 
899
1180
  verify_type_function = proc { |name| "
900
1181
  static VALUE #{name}(VALUE arg) {
901
- if (CLASS_OF(arg)!=#{klass.internal_value}) rb_raise(#{TypeMismatchAssignmentException.internal_value}, \"Illegal assignment at runtime (type mismatch)\");
1182
+ if (CLASS_OF(arg)!=#{literal_value klass}) rb_raise(#{literal_value FastRuby::TypeMismatchAssignmentException}, \"Illegal assignment at runtime (type mismatch)\");
902
1183
  return arg;
903
1184
  }
904
1185
  "
@@ -1010,7 +1291,7 @@ module FastRuby
1010
1291
 
1011
1292
  return inline_block("
1012
1293
  pframe->target_frame = (void*)-1;
1013
- pframe->exception = rb_funcall(#{to_c args[1]}, #{:exception.to_i},0);
1294
+ pframe->exception = rb_funcall(#{to_c args[1]}, #{intern_num :exception},0);
1014
1295
  longjmp(pframe->jmp, 1);
1015
1296
  return Qnil;
1016
1297
  ")
@@ -1047,144 +1328,164 @@ module FastRuby
1047
1328
  end
1048
1329
  end
1049
1330
 
1050
- convention = nil
1051
-
1052
- if recvtype.respond_to? :fastruby_method and inference_complete
1053
-
1054
- method_tree = nil
1055
- begin
1056
- method_tree = recvtype.instance_method(tree[2]).fastruby.tree
1057
- rescue NoMethodError
1058
- end
1331
+ if repass_var
1332
+ extraargs = ","+repass_var
1333
+ extraargs_signature = ",VALUE " + repass_var
1334
+ else
1335
+ extraargs = ""
1336
+ extraargs_signature = ""
1337
+ end
1059
1338
 
1060
- if method_tree
1061
- mobject = recvtype.build(signature, tree[2])
1062
- convention = :fastruby
1339
+ if argnum == 0
1340
+ value_cast = "VALUE,VALUE,VALUE"
1341
+ "((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe)"
1063
1342
  else
1064
- mobject = recvtype.instance_method(tree[2])
1065
- convention = :cruby
1343
+ value_cast = ( ["VALUE"]*(args.size) ).join(",") + ",VALUE,VALUE"
1344
+ "((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe, #{strargs})"
1066
1345
  end
1346
+
1347
+ else # else recvtype
1348
+ if argnum == 0
1349
+ protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, 0)", false, repass_var)
1067
1350
  else
1068
- mobject = recvtype.instance_method(tree[2])
1069
- convention = :cruby
1351
+ protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, #{argnum}, #{strargs} )", false, repass_var)
1070
1352
  end
1353
+ end # if recvtype
1354
+ end
1071
1355
 
1072
- address = nil
1073
- len = 0
1074
- if mobject
1075
- address = getaddress(mobject)
1076
- len = getlen(mobject)
1356
+ def get_class_name(argument)
1357
+ if argument.instance_of? Symbol
1358
+ argument.to_s
1359
+ elsif argument.instance_of? FastRuby::FastRubySexp
1360
+ if argument[0] == :colon3
1361
+ get_class_name(argument[1])
1362
+ elsif argument[0] == :colon2
1363
+ get_class_name(argument[2])
1077
1364
  end
1365
+ end
1366
+ end
1078
1367
 
1079
- if repass_var
1080
- extraargs = ","+repass_var
1081
- extraargs_signature = ",VALUE " + repass_var
1082
- else
1083
- extraargs = ""
1084
- extraargs_signature = ""
1368
+ def get_container_tree(argument)
1369
+ if argument.instance_of? Symbol
1370
+ s(:self)
1371
+ elsif argument.instance_of? FastRuby::FastRubySexp
1372
+ if argument[0] == :colon3
1373
+ s(:const, :Object)
1374
+ elsif argument[0] == :colon2
1375
+ argument[1]
1085
1376
  end
1377
+ end
1378
+ end
1086
1379
 
1087
- if address then
1088
- if argnum == 0
1089
- value_cast = "VALUE"
1090
- value_cast = value_cast + ", VALUE,VALUE" if convention == :fastruby
1380
+ def locals_scope(locals)
1381
+ old_locals = @locals
1382
+ old_locals_struct = @locals_struct
1091
1383
 
1092
- if convention == :fastruby
1093
- "((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{to_c recv}, Qfalse, (VALUE)pframe)"
1094
- else
1384
+ @locals = locals
1385
+ @locals_struct = "struct {
1386
+ void* block_function_address;
1387
+ VALUE block_function_param;
1388
+ jmp_buf jmp;
1389
+ VALUE return_value;
1390
+ void* pframe;
1391
+ #{@locals.map{|l| "VALUE #{l};\n"}.join}
1392
+ }"
1095
1393
 
1096
- str_incall_args = nil
1097
- if len == -1
1098
- str_incall_args = "0, (VALUE[]){}, recv"
1099
- value_cast = "int,VALUE*,VALUE"
1100
- elsif len == -2
1101
- str_incall_args = "recv, rb_ary_new4(#{})"
1102
- value_cast = "VALUE,VALUE"
1103
- else
1104
- str_incall_args = "recv"
1105
- end
1394
+ begin
1395
+ yield
1396
+ ensure
1397
+ @locals = old_locals
1398
+ @locals_struct = old_locals_struct
1399
+ end
1400
+ end
1106
1401
 
1107
- protected_block(
1108
-
1109
- anonymous_function{ |name| "
1110
- static VALUE #{name}(VALUE recv#{extraargs_signature}) {
1111
- // call to #{recvtype}##{mname}
1112
- if (rb_block_given_p()) {
1113
- // no passing block, recall
1114
- return rb_funcall(recv, #{tree[2].to_i}, 0);
1115
- } else {
1116
- return ((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{str_incall_args});
1117
- }
1118
- }
1119
- " } + "(#{to_c(recv)}#{extraargs})", false, repass_var)
1120
- end
1121
- else
1122
- value_cast = ( ["VALUE"]*(args.size) ).join(",")
1123
- value_cast = value_cast + ", VALUE, VALUE" if convention == :fastruby
1402
+ def method_group(init_code, tree)
1124
1403
 
1125
- wrapper_func = nil
1126
- if convention == :fastruby
1127
- "((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{to_c recv}, Qfalse, (VALUE)pframe, #{strargs})"
1128
- else
1404
+ alt_locals = Set.new
1405
+ alt_locals << :self
1129
1406
 
1130
- str_incall_args = nil
1131
- if len == -1
1132
- str_incall_args = "#{argnum}, (VALUE[]){#{ (1..argnum).map{|x| "_arg"+x.to_s }.join(",")}}, recv"
1133
- value_cast = "int,VALUE*,VALUE"
1134
- elsif len == -2
1135
- str_incall_args = "recv, rb_ary_new4(#{ (1..argnum).map{|x| "_arg"+x.to_s }.join(",")})"
1136
- value_cast = "VALUE,VALUE"
1137
- else
1138
- str_incall_args = "recv, #{ (1..argnum).map{|x| "_arg"+x.to_s }.join(",")}"
1139
- end
1407
+ FastRuby::GetLocalsProcessor.get_locals(tree).each do |local|
1408
+ alt_locals << local
1409
+ end
1140
1410
 
1141
- protected_block(
1142
-
1143
- anonymous_function{ |name| "
1144
- static VALUE #{name}(VALUE recv, #{ (1..argnum).map{|x| "VALUE _arg"+x.to_s }.join(",")} ) {
1145
- // call to #{recvtype}##{mname}
1146
- if (rb_block_given_p()) {
1147
- // no passing block, recall
1148
- return rb_funcall(recv, #{tree[2].to_i}, #{argnum}, #{ (1..argnum).map{|x| "_arg"+x.to_s }.join(",")});
1149
- } else {
1150
- return ((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{str_incall_args});
1151
- }
1152
- }
1153
- " } + "(#{to_c(recv)}, #{strargs})", false, repass_var
1154
- )
1155
- end
1156
- end
1157
- else
1411
+ fun = nil
1158
1412
 
1159
- if argnum == 0
1160
- protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, 0)", false, repass_var)
1161
- else
1162
- protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, #{argnum}, #{strargs} )", false, repass_var)
1163
- end
1164
- end
1413
+ locals_scope(alt_locals) do
1414
+ fun = anonymous_function { |method_name| "static VALUE #{method_name}(VALUE self) {
1165
1415
 
1166
- else
1167
- if argnum == 0
1168
- protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, 0)", false, repass_var)
1169
- else
1170
- protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, #{argnum}, #{strargs} )", false, repass_var)
1171
- end
1416
+ #{@frame_struct} frame;
1417
+ #{@locals_struct} locals;
1418
+ typeof(&frame) pframe = &frame;
1419
+ typeof(&locals) plocals = &locals;
1420
+
1421
+ frame.plocals = plocals;
1422
+ frame.parent_frame = 0;
1423
+ frame.return_value = Qnil;
1424
+ frame.target_frame = &frame;
1425
+ frame.exception = Qnil;
1426
+ frame.rescue = 0;
1427
+
1428
+ locals.self = self;
1429
+
1430
+ #{to_c tree};
1431
+ return Qnil;
1432
+ }
1433
+ "
1434
+ }
1172
1435
  end
1173
- end
1174
1436
 
1175
- def to_c_class(tree)
1176
1437
  inline_block("
1177
- rb_funcall(plocals->self,#{:fastruby.to_i},1,(VALUE)#{tree.internal_value});
1438
+ #{init_code}
1439
+
1440
+ rb_funcall(tmpklass, #{intern_num :__id__},0);
1441
+
1442
+ #{fun}(tmpklass);
1178
1443
  return Qnil;
1444
+
1445
+
1179
1446
  ")
1180
1447
 
1181
1448
  end
1182
1449
 
1450
+
1451
+
1452
+ def to_c_class(tree)
1453
+ str_class_name = get_class_name(tree[1])
1454
+ container_tree = get_container_tree(tree[1])
1455
+
1456
+ if container_tree == s(:self)
1457
+ method_group("
1458
+ VALUE tmpklass = rb_define_class(
1459
+ #{str_class_name.inspect},
1460
+ #{tree[2] ? to_c(tree[2]) : "rb_cObject"}
1461
+ );
1462
+ ", tree[3])
1463
+ else
1464
+ method_group("
1465
+ VALUE container_klass = #{to_c(container_tree)};
1466
+ VALUE tmpklass = rb_define_class_under(
1467
+ container_klass,
1468
+ #{str_class_name.inspect},
1469
+ #{tree[2] ? to_c(tree[2]) : "rb_cObject"}
1470
+ );
1471
+ ", tree[3])
1472
+ end
1473
+ end
1474
+
1183
1475
  def to_c_module(tree)
1184
- inline_block("
1185
- rb_funcall(plocals->self,#{:fastruby.to_i},1,(VALUE)#{tree.internal_value});
1186
- return Qnil;
1187
- ")
1476
+ str_class_name = get_class_name(tree[1])
1477
+ container_tree = get_container_tree(tree[1])
1478
+
1479
+ if container_tree == s(:self)
1480
+ method_group("
1481
+ VALUE tmpklass = rb_define_module(#{str_class_name.inspect});
1482
+ ", tree[2])
1483
+ else
1484
+ method_group("
1485
+ VALUE container_klass = #{to_c(container_tree)};
1486
+ VALUE tmpklass = rb_define_module_under(container_klass,#{str_class_name.inspect});
1487
+ ", tree[2])
1488
+ end
1188
1489
  end
1189
1490
 
1190
1491
  def to_c_while(tree)
@@ -1271,7 +1572,7 @@ module FastRuby
1271
1572
  def inline_block_reference(arg)
1272
1573
  code = nil
1273
1574
 
1274
- if arg.instance_of? Sexp
1575
+ if arg.instance_of? FastRuby::FastRubySexp
1275
1576
  code = to_c(arg);
1276
1577
  else
1277
1578
  code = arg
@@ -1292,7 +1593,7 @@ module FastRuby
1292
1593
 
1293
1594
  def inline_block(code, repass_var = nil)
1294
1595
  anonymous_function{ |name| "
1295
- static VALUE #{name}(VALUE param#{repass_var ? ",VALUE " + repass_var : "" }) {
1596
+ static VALUE #{name}(VALUE param#{repass_var ? ",void* " + repass_var : "" }) {
1296
1597
  #{@frame_struct} *pframe = (void*)param;
1297
1598
  #{@locals_struct} *plocals = (void*)pframe->plocals;
1298
1599
  VALUE last_expression = Qnil;
@@ -1304,7 +1605,7 @@ module FastRuby
1304
1605
  end
1305
1606
 
1306
1607
  def inline_ruby(proced, parameter)
1307
- "rb_funcall(#{proced.internal_value}, #{:call.to_i}, 1, #{parameter})"
1608
+ "rb_funcall(#{proced.__id__}, #{intern_num :call}, 1, #{parameter})"
1308
1609
  end
1309
1610
 
1310
1611
  def wrapped_break_block(inner_code)
@@ -1318,12 +1619,12 @@ module FastRuby
1318
1619
  def protected_block(inner_code, always_rescue = false,repass_var = nil)
1319
1620
  wrapper_code = "
1320
1621
  if (pframe->last_error != Qnil) {
1321
- if (CLASS_OF(pframe->last_error)==(VALUE)#{UnwindFastrubyFrame.internal_value}) {
1622
+ if (CLASS_OF(pframe->last_error)==#{literal_value FastRuby::Context::UnwindFastrubyFrame}) {
1322
1623
  #{@frame_struct} *pframe = (void*)param;
1323
1624
 
1324
- pframe->target_frame = (void*)FIX2LONG(rb_ivar_get(pframe->last_error, #{:@target_frame.to_i}));
1325
- pframe->exception = rb_ivar_get(pframe->last_error, #{:@ex.to_i});
1326
- pframe->return_value = rb_ivar_get(pframe->last_error, #{:@return_value.to_i});
1625
+ pframe->target_frame = (void*)FIX2LONG(rb_ivar_get(pframe->last_error, #{intern_num :@target_frame}));
1626
+ pframe->exception = rb_ivar_get(pframe->last_error, #{intern_num :@ex});
1627
+ pframe->return_value = rb_ivar_get(pframe->last_error, #{intern_num :@return_value});
1327
1628
 
1328
1629
  if (pframe->target_frame == (void*)-2) {
1329
1630
  return pframe->return_value;
@@ -1360,7 +1661,7 @@ module FastRuby
1360
1661
  }
1361
1662
 
1362
1663
  rescue_args = ""
1363
- rescue_args = "(VALUE)(VALUE[]){(VALUE)pframe,#{repass_var}}"
1664
+ rescue_args = "(VALUE)(VALUE[]){(VALUE)pframe,(VALUE)#{repass_var}}"
1364
1665
  else
1365
1666
  body = inline_block_reference("return #{inner_code}")
1366
1667
  rescue_args = "(VALUE)pframe"
@@ -1446,6 +1747,216 @@ module FastRuby
1446
1747
  "
1447
1748
  end
1448
1749
 
1750
+ def c_escape(str)
1751
+ str.inspect
1752
+ end
1753
+
1754
+ def literal_value(value)
1755
+ @literal_value_hash = Hash.new unless @literal_value_hash
1756
+ return @literal_value_hash[value] if @literal_value_hash[value]
1757
+
1758
+ name = self.add_global_name("VALUE", "Qnil");
1759
+
1760
+ begin
1761
+ str = Marshal.dump(value)
1762
+
1763
+ init_extra << "
1764
+ #{name} = rb_marshal_load(rb_str_new(#{c_escape str}, #{str.size}));
1765
+ rb_funcall(#{name},#{intern_num :gc_register_object},0);
1766
+
1767
+ "
1768
+ rescue TypeError
1769
+ @no_cache = true
1770
+ FastRuby.logger.info "#{value} disabling cache for extension"
1771
+ init_extra << "
1772
+ #{name} = rb_funcall(rb_const_get(rb_cObject, #{intern_num :ObjectSpace}), #{intern_num :_id2ref}, 1, INT2FIX(#{value.__id__}));
1773
+ "
1774
+
1775
+ end
1776
+ @literal_value_hash[value] = name
1777
+
1778
+ name
1779
+ end
1780
+
1781
+ def encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name = nil)
1782
+ name = self.add_global_name("void*", 0);
1783
+ cruby_name = self.add_global_name("void*", 0);
1784
+ cruby_len = self.add_global_name("int", 0);
1785
+ args_tree = call_tree[3]
1786
+ method_tree = nil
1787
+
1788
+ begin
1789
+ method_tree = recvtype.instance_method(@method_name.to_sym).fastruby.tree
1790
+ rescue NoMethodError
1791
+ end
1792
+
1793
+
1794
+ strargs_signature = (0..args_tree.size-2).map{|x| "VALUE arg#{x}"}.join(",")
1795
+ strargs = (0..args_tree.size-2).map{|x| "arg#{x}"}.join(",")
1796
+ inprocstrargs = (1..args_tree.size-1).map{|x| "((VALUE*)method_arguments)[#{x}]"}.join(",")
1797
+
1798
+ if args_tree.size > 1
1799
+ strargs_signature = "," + strargs_signature
1800
+ toprocstrargs = "self,"+strargs
1801
+ strargs = "," + strargs
1802
+ inprocstrargs = ","+inprocstrargs
1803
+ else
1804
+ toprocstrargs = "self"
1805
+ end
1806
+
1807
+ ruby_wrapper = anonymous_function{ |funcname| "
1808
+ static VALUE #{funcname}(VALUE self,void* block,void* frame#{strargs_signature}){
1809
+ #{@frame_struct}* pframe = frame;
1810
+
1811
+ VALUE method_arguments[#{args_tree.size}] = {#{toprocstrargs}};
1812
+
1813
+ return #{
1814
+ protected_block "rb_funcall(((VALUE*)method_arguments)[0], #{intern_num mname.to_sym}, #{args_tree.size-1}#{inprocstrargs});", false, "method_arguments"
1815
+ };
1816
+ }
1817
+ "
1818
+ }
1819
+
1820
+ value_cast = ( ["VALUE"]*(args_tree.size) ).join(",")
1821
+
1822
+ cruby_wrapper = anonymous_function{ |funcname| "
1823
+ static VALUE #{funcname}(VALUE self,void* block,void* frame#{strargs_signature}){
1824
+ #{@frame_struct}* pframe = frame;
1825
+
1826
+ VALUE method_arguments[#{args_tree.size}] = {#{toprocstrargs}};
1827
+
1828
+ // call to #{recvtype}::#{mname}
1829
+
1830
+ if (#{cruby_len} == -1) {
1831
+ return #{
1832
+ protected_block "((VALUE(*)(int,VALUE*,VALUE))#{cruby_name})(#{args_tree.size-1}, ((VALUE*)method_arguments)+1,*((VALUE*)method_arguments));", false, "method_arguments"
1833
+ };
1834
+
1835
+ } else if (#{cruby_len} == -2) {
1836
+ return #{
1837
+ protected_block "((VALUE(*)(VALUE,VALUE))#{cruby_name})(*((VALUE*)method_arguments), rb_ary_new4(#{args_tree.size-1},((VALUE*)method_arguments)+1) );", false, "method_arguments"
1838
+ };
1839
+
1840
+ } else {
1841
+ return #{
1842
+ protected_block "((VALUE(*)(#{value_cast}))#{cruby_name})(((VALUE*)method_arguments)[0] #{inprocstrargs});", false, "method_arguments"
1843
+ };
1844
+ }
1845
+ }
1846
+ "
1847
+ }
1848
+
1849
+ recvdump = nil
1850
+
1851
+ begin
1852
+ recvdump = literal_value recvtype
1853
+ rescue
1854
+ end
1855
+
1856
+ if recvdump and recvtype
1857
+ init_extra << "
1858
+ {
1859
+ VALUE recvtype = #{recvdump};
1860
+ rb_funcall(#{literal_value FastRuby}, #{intern_num :set_builder_module}, 1, recvtype);
1861
+ VALUE signature = #{literal_value signature};
1862
+ VALUE mname = #{literal_value mname};
1863
+ VALUE tree = #{literal_value method_tree};
1864
+ VALUE convention = rb_funcall(recvtype, #{intern_num :convention}, 3,signature,mname,#{inference_complete ? "Qtrue" : "Qfalse"});
1865
+ VALUE mobject = rb_funcall(recvtype, #{intern_num :method_from_signature},3,signature,mname,#{inference_complete ? "Qtrue" : "Qfalse"});
1866
+
1867
+ struct METHOD {
1868
+ VALUE klass, rklass;
1869
+ VALUE recv;
1870
+ ID id, oid;
1871
+ int safe_level;
1872
+ NODE *body;
1873
+ };
1874
+
1875
+ int len = 0;
1876
+ void* address = 0;
1877
+
1878
+ if (mobject != Qnil) {
1879
+
1880
+ struct METHOD *data;
1881
+ Data_Get_Struct(mobject, struct METHOD, data);
1882
+
1883
+ if (nd_type(data->body) == NODE_CFUNC) {
1884
+ address = data->body->nd_cfnc;
1885
+ len = data->body->nd_argc;
1886
+ }
1887
+ }
1888
+
1889
+ #{convention_global_name ? convention_global_name + " = 0;" : ""}
1890
+ if (recvtype != Qnil) {
1891
+
1892
+ if (convention == #{literal_value :fastruby}) {
1893
+ #{convention_global_name ? convention_global_name + " = 1;" : ""}
1894
+ #{name} = address;
1895
+ } else if (convention == #{literal_value :cruby}) {
1896
+ // cruby, wrap direct call
1897
+ #{cruby_name} = address;
1898
+
1899
+ if (#{cruby_name} == 0) {
1900
+ #{name} = (void*)#{ruby_wrapper};
1901
+ } else {
1902
+ #{cruby_len} = len;
1903
+ #{name} = (void*)#{cruby_wrapper};
1904
+ }
1905
+ } else {
1906
+ // ruby, wrap rb_funcall
1907
+ #{name} = (void*)#{ruby_wrapper};
1908
+ }
1909
+ } else {
1910
+ // ruby, wrap rb_funcall
1911
+ #{name} = (void*)#{ruby_wrapper};
1912
+ }
1913
+
1914
+ }
1915
+ "
1916
+ else
1917
+ init_extra << "
1918
+ // ruby, wrap rb_funcall
1919
+ #{name} = (void*)#{ruby_wrapper};
1920
+ "
1921
+ end
1922
+
1923
+ name
1924
+ end
1925
+
1926
+ def intern_num(symbol)
1927
+ @intern_num_hash = Hash.new unless @intern_num_hash
1928
+ return @intern_num_hash[symbol] if @intern_num_hash[symbol]
1929
+
1930
+ name = self.add_global_name("ID", 0);
1931
+
1932
+ init_extra << "
1933
+ #{name} = rb_intern(\"#{symbol.to_s}\");
1934
+ "
1935
+
1936
+ @intern_num_hash[symbol] = name
1937
+
1938
+ name
1939
+ end
1940
+
1941
+ def add_global_name(ctype, default)
1942
+ name = "glb" + rand(1000000000).to_s
1943
+
1944
+ extra_code << "
1945
+ static #{ctype} #{name} = #{default};
1946
+ "
1947
+ name
1948
+ end
1949
+
1950
+ def global_entry(glbname)
1951
+ name = add_global_name("struct global_entry*", 0);
1952
+
1953
+ init_extra << "
1954
+ #{name} = rb_global_entry(SYM2ID(#{literal_value glbname}));
1955
+ "
1956
+
1957
+ name
1958
+ end
1959
+
1449
1960
 
1450
1961
  def frame(code, jmp_code, not_jmp_code = "", rescued = nil)
1451
1962
 
@@ -1498,55 +2009,5 @@ module FastRuby
1498
2009
  "
1499
2010
  } + "((VALUE)pframe)"
1500
2011
  end
1501
-
1502
- inline :C do |builder|
1503
- builder.include "<node.h>"
1504
- builder.c "VALUE getaddress(VALUE method) {
1505
- struct METHOD {
1506
- VALUE klass, rklass;
1507
- VALUE recv;
1508
- ID id, oid;
1509
- int safe_level;
1510
- NODE *body;
1511
- };
1512
-
1513
- struct METHOD *data;
1514
- Data_Get_Struct(method, struct METHOD, data);
1515
-
1516
- if (nd_type(data->body) == NODE_CFUNC) {
1517
- return INT2FIX(data->body->nd_cfnc);
1518
- }
1519
-
1520
- return Qnil;
1521
- }"
1522
-
1523
- builder.c "VALUE getlen(VALUE method) {
1524
- struct METHOD {
1525
- VALUE klass, rklass;
1526
- VALUE recv;
1527
- ID id, oid;
1528
- int safe_level;
1529
- NODE *body;
1530
- };
1531
-
1532
- struct METHOD *data;
1533
- Data_Get_Struct(method, struct METHOD, data);
1534
-
1535
- if (nd_type(data->body) == NODE_CFUNC) {
1536
- return INT2FIX(data->body->nd_argc);
1537
- }
1538
-
1539
- return Qnil;
1540
- }"
1541
-
1542
- builder.c "VALUE global_entry(VALUE global_id) {
1543
- ID id = SYM2ID(global_id);
1544
- struct global_entry* entry;
1545
-
1546
- entry = rb_global_entry(id);
1547
- return INT2FIX(entry);
1548
- }
1549
- "
1550
- end
1551
2012
  end
1552
2013
  end