fastruby 0.0.13 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -336,12 +336,44 @@ module FastRuby
336
336
  #{literal_value signature}
337
337
  );
338
338
 
339
- rb_define_method(#{literal_value klass}, RSTRING(method_name)->ptr, #{alt_method_name}, #{size});
339
+ ID id = rb_intern(RSTRING(method_name)->ptr);
340
+
341
+ rb_funcall(
342
+ #{literal_value FastRuby},
343
+ #{intern_num :set_builder_module},
344
+ 1,
345
+ #{literal_value klass}
346
+ );
347
+
348
+ VALUE rb_method_hash;
349
+ void** address = 0;
350
+ rb_method_hash = rb_funcall(#{literal_value klass}, #{intern_num :method_hash},1,#{literal_value method_name});
351
+
352
+ if (rb_method_hash != Qnil) {
353
+ VALUE tmp = rb_hash_aref(rb_method_hash, LONG2FIX(id));
354
+ if (tmp != Qnil) {
355
+ address = (void*)FIX2LONG(tmp);
356
+ }
357
+ }
358
+
359
+ if (address == 0) {
360
+ address = malloc(sizeof(void*));
361
+ }
362
+ *address = #{alt_method_name};
363
+
364
+ rb_funcall(
365
+ #{literal_value klass},
366
+ #{intern_num :register_method_value},
367
+ 3,
368
+ #{literal_value method_name},
369
+ LONG2FIX(id),
370
+ LONG2FIX(address)
371
+ );
340
372
  }
341
373
  "
342
374
  end
343
375
 
344
- def to_c_method(tree)
376
+ def to_c_method(tree, signature = nil)
345
377
  method_name = tree[1]
346
378
  args_tree = tree[2]
347
379
  impl_tree = tree[3][1]
@@ -350,7 +382,7 @@ module FastRuby
350
382
  initialize_method_structs(args_tree)
351
383
 
352
384
  strargs = if args_tree.size > 1
353
- "VALUE block, VALUE _parent_frame, #{args_tree[1..-1].map{|arg| "VALUE #{arg.to_s.gsub("*","")}" }.join(",") }"
385
+ "VALUE block, VALUE _parent_frame, #{(0..signature.size-1).map{|x| "VALUE arg#{x}"}.join(",")}"
354
386
  else
355
387
  "VALUE block, VALUE _parent_frame"
356
388
  end
@@ -447,16 +479,68 @@ module FastRuby
447
479
  initialize_method_structs(args_tree)
448
480
 
449
481
  strargs = if args_tree.size > 1
450
- "VALUE block, VALUE _parent_frame, #{args_tree[1..-1].map{|arg| "VALUE #{arg.to_s.gsub("*","")}" }.join(",") }"
482
+ "VALUE block, VALUE _parent_frame, #{(0..signature.size-1).map{|x| "VALUE arg#{x}"}.join(",")}"
451
483
  else
452
484
  "VALUE block, VALUE _parent_frame"
453
485
  end
486
+
487
+ is_splat_args = args_tree[1..-1].find{|x| x.to_s.match(/\*/) }
488
+
489
+ if is_splat_args
490
+
491
+ i = -1
492
+
493
+ read_arguments_code = args_tree[1..-2].map { |arg|
494
+ arg = arg.to_s
495
+ i = i + 1
496
+ "plocals->#{arg} = arg#{i};\n"
497
+ }.join("")
498
+
499
+ arguments_array = [(signature.size-1) - (args_tree.size-2)] + (args_tree.size-2..signature.size-1).map{|x| "arg#{x}"}
500
+
501
+ read_arguments_code << "
502
+ plocals->#{args_tree[-1].to_s.gsub("*","")} = rb_ary_new3(
503
+ #{arguments_array.join(",")}
504
+ );
505
+ "
506
+
507
+ validate_arguments_code = if signature.size-1 >= args_tree.size-2
508
+ "
509
+ "
510
+ else
511
+ "
512
+ rb_raise(rb_eArgError, \"wrong number of arguments (#{signature.size} for #{args_tree.size-2})\");
513
+ "
514
+ end
515
+
516
+ else
517
+
518
+ i = -1
519
+
520
+ read_arguments_code = args_tree[1..-1].map { |arg|
521
+ arg = arg.to_s
522
+ i = i + 1
523
+ "plocals->#{arg} = arg#{i};\n"
524
+ }.join("")
525
+
526
+ validate_arguments_code = if signature.size-1 >= args_tree.size-1
527
+ "
528
+ "
529
+ else
530
+ "
531
+ rb_raise(rb_eArgError, \"wrong number of arguments (#{signature.size-1} for #{args_tree.size-1})\");
532
+ "
533
+ end
534
+
535
+ end
536
+
454
537
 
455
538
  ret = "VALUE #{@alt_method_name || method_name}(#{strargs}) {
539
+ #{validate_arguments_code}
456
540
 
457
541
  #{@frame_struct} frame;
458
542
  #{@frame_struct} *pframe;
459
-
543
+
460
544
  frame.parent_frame = (void*)_parent_frame;
461
545
  frame.return_value = Qnil;
462
546
  frame.rescue = 0;
@@ -523,11 +607,7 @@ module FastRuby
523
607
 
524
608
  plocals->self = self;
525
609
 
526
- #{args_tree[1..-1].map { |arg|
527
- arg = arg.to_s
528
- arg.gsub!("*","")
529
- "plocals->#{arg} = #{arg};\n"
530
- }.join("") }
610
+ #{read_arguments_code}
531
611
 
532
612
  pblock = (void*)block;
533
613
  if (pblock) {
@@ -934,8 +1014,11 @@ module FastRuby
934
1014
 
935
1015
  def encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name = nil)
936
1016
  name = self.add_global_name("void*", 0);
937
- cruby_name = self.add_global_name("void*", 0);
938
- cruby_len = self.add_global_name("int", 0);
1017
+ address_name = self.add_global_name("void**", 0);
1018
+ @last_address_name = address_name
1019
+ cfunc_address_name = self.add_global_name("void**", 0);
1020
+ cfunc_real_address_name = self.add_global_name("void*", 0);
1021
+ tree_pointer_name = self.add_global_name("VALUE*", 0);
939
1022
  args_tree = call_tree[3]
940
1023
  method_tree = nil
941
1024
 
@@ -944,7 +1027,6 @@ module FastRuby
944
1027
  rescue NoMethodError
945
1028
  end
946
1029
 
947
-
948
1030
  strargs_signature = (0..args_tree.size-2).map{|x| "VALUE arg#{x}"}.join(",")
949
1031
  strargs = (0..args_tree.size-2).map{|x| "arg#{x}"}.join(",")
950
1032
  inprocstrargs = (1..args_tree.size-1).map{|x| "((VALUE*)method_arguments)[#{x}]"}.join(",")
@@ -958,54 +1040,105 @@ module FastRuby
958
1040
  toprocstrargs = "self"
959
1041
  end
960
1042
 
961
- ruby_wrapper = anonymous_function{ |funcname| "
1043
+ value_cast = ( ["VALUE"]*(args_tree.size) ).join(",") + ",VALUE,VALUE"
1044
+
1045
+ recvdump = nil
1046
+
1047
+ begin
1048
+ recvdump = literal_value recvtype
1049
+ rescue
1050
+ end
1051
+
1052
+ pureruby_wrapper = anonymous_function{ |funcname| "
962
1053
  static VALUE #{funcname}(VALUE self,void* block,void* frame#{strargs_signature}){
963
1054
  #{@frame_struct}* pframe = frame;
964
-
965
1055
  VALUE method_arguments[#{args_tree.size}] = {#{toprocstrargs}};
966
-
1056
+
967
1057
  return #{
968
1058
  protected_block "rb_funcall(((VALUE*)method_arguments)[0], #{intern_num mname.to_sym}, #{args_tree.size-1}#{inprocstrargs});", false, "method_arguments"
969
1059
  };
970
1060
  }
971
- "
1061
+ "
972
1062
  }
973
-
974
- value_cast = ( ["VALUE"]*(args_tree.size) ).join(",")
975
-
976
- cruby_wrapper = anonymous_function{ |funcname| "
1063
+
1064
+ generic_wrapper = anonymous_function{ |funcname| "
977
1065
  static VALUE #{funcname}(VALUE self,void* block,void* frame#{strargs_signature}){
1066
+
978
1067
  #{@frame_struct}* pframe = frame;
979
-
980
1068
  VALUE method_arguments[#{args_tree.size}] = {#{toprocstrargs}};
981
-
982
- // call to #{recvtype}::#{mname}
983
-
984
- if (#{cruby_len} == -1) {
985
- return #{
986
- protected_block "((VALUE(*)(int,VALUE*,VALUE))#{cruby_name})(#{args_tree.size-1}, ((VALUE*)method_arguments)+1,*((VALUE*)method_arguments));", false, "method_arguments"
987
- };
988
-
989
- } else if (#{cruby_len} == -2) {
1069
+
1070
+ void* fptr = 0;
1071
+
1072
+ if (*#{address_name} == 0) {
1073
+ if (#{tree_pointer_name} != 0) {
1074
+ if (*#{tree_pointer_name} != Qnil) {
1075
+ VALUE signature = #{literal_value signature};
1076
+ VALUE recvtype = #{recvdump};
1077
+ VALUE mname = #{literal_value mname};
1078
+
1079
+ rb_funcall(recvtype, #{intern_num :build}, 2, signature, mname);
1080
+ }
1081
+ }
1082
+ }
1083
+
1084
+ fptr = *#{address_name};
1085
+
1086
+ #{
1087
+ if args_tree.size < 25
1088
+ "
1089
+ if (fptr == 0) {
1090
+ fptr = *#{cfunc_address_name};
1091
+ if (fptr != 0) {
1092
+ VALUE params[2] = {self,LONG2FIX(#{args_tree.size-1})};
1093
+ return ( (VALUE(*)(#{value_cast})) (fptr) )((VALUE)params,(VALUE)block,(VALUE)frame#{inprocstrargs});
1094
+ }
1095
+ }
1096
+ "
1097
+ end
1098
+ }
1099
+
1100
+ if (fptr == 0) {
990
1101
  return #{
991
- protected_block "((VALUE(*)(VALUE,VALUE))#{cruby_name})(*((VALUE*)method_arguments), rb_ary_new4(#{args_tree.size-1},((VALUE*)method_arguments)+1) );", false, "method_arguments"
1102
+ protected_block "rb_funcall(((VALUE*)method_arguments)[0], #{intern_num mname.to_sym}, #{args_tree.size-1}#{inprocstrargs});", false, "method_arguments"
992
1103
  };
993
-
994
1104
  } else {
995
- return #{
996
- protected_block "((VALUE(*)(#{value_cast}))#{cruby_name})(((VALUE*)method_arguments)[0] #{inprocstrargs});", false, "method_arguments"
997
- };
1105
+ return ( (VALUE(*)(#{value_cast})) (fptr) )(self,(VALUE)block,(VALUE)frame#{inprocstrargs});
998
1106
  }
999
1107
  }
1000
1108
  "
1001
1109
  }
1002
1110
 
1003
- recvdump = nil
1004
1111
 
1005
- begin
1006
- recvdump = literal_value recvtype
1007
- rescue
1008
- end
1112
+ cfunc_value_cast = (["VALUE"]*args_tree.size).join(",")
1113
+ cfunc_wrapper = anonymous_function{ |funcname| "
1114
+ static VALUE #{funcname}(VALUE* params, void* block,void* frame#{strargs_signature}){
1115
+ VALUE self = params[0];
1116
+ VALUE method_arguments[#{args_tree.size}] = {#{toprocstrargs}};
1117
+ return ( (VALUE(*)(#{cfunc_value_cast})) (#{cfunc_real_address_name}) )(self#{inprocstrargs});
1118
+ }
1119
+ "
1120
+ }
1121
+
1122
+ toprocstrargs = (0..25).map{|x| "arg#{x}"}.join(",")
1123
+ strargs_signature = (0..25).map{|x| "VALUE arg#{x}"}.join(",")
1124
+
1125
+ cfunc_wrapper_1 = anonymous_function{ |funcname| "
1126
+ static VALUE #{funcname}(VALUE* params, void* block,void* frame, #{strargs_signature}){
1127
+ VALUE self = params[0];
1128
+ VALUE method_arguments[26] = {#{toprocstrargs}};
1129
+ return ( (VALUE(*)(int, VALUE*, VALUE)) (#{cfunc_real_address_name}) )(FIX2LONG(params[1]),method_arguments,self);
1130
+ }
1131
+ "
1132
+ }
1133
+
1134
+ cfunc_wrapper_2 = anonymous_function{ |funcname| "
1135
+ static VALUE #{funcname}(VALUE* params, void* block,void* frame, #{strargs_signature}){
1136
+ VALUE self = params[0];
1137
+ VALUE args = rb_ary_new3(FIX2LONG(params[1]),#{toprocstrargs});
1138
+ return ( (VALUE(*)(VALUE,VALUE)) (#{cfunc_real_address_name}) )(self,args);
1139
+ }
1140
+ "
1141
+ }
1009
1142
 
1010
1143
  if recvdump and recvtype
1011
1144
  init_extra << "
@@ -1015,67 +1148,96 @@ module FastRuby
1015
1148
  VALUE signature = #{literal_value signature};
1016
1149
  VALUE mname = #{literal_value mname};
1017
1150
  VALUE tree = #{literal_value method_tree};
1018
- VALUE convention = rb_funcall(recvtype, #{intern_num :convention}, 3,signature,mname,#{inference_complete ? "Qtrue" : "Qfalse"});
1019
- VALUE mobject = rb_funcall(recvtype, #{intern_num :method_from_signature},3,signature,mname,#{inference_complete ? "Qtrue" : "Qfalse"});
1020
-
1021
- struct METHOD {
1022
- VALUE klass, rklass;
1023
- VALUE recv;
1024
- ID id, oid;
1025
- int safe_level;
1026
- NODE *body;
1027
- };
1028
-
1029
- int len = 0;
1030
- void* address = 0;
1031
-
1032
- if (mobject != Qnil) {
1033
-
1034
- struct METHOD *data;
1035
- Data_Get_Struct(mobject, struct METHOD, data);
1036
-
1037
- if (nd_type(data->body) == NODE_CFUNC) {
1038
- address = data->body->nd_cfnc;
1039
- len = data->body->nd_argc;
1151
+ VALUE rb_str_signature = rb_funcall(
1152
+ #{literal_value FastRuby},
1153
+ #{intern_num :make_str_signature},
1154
+ 2,
1155
+ mname,
1156
+ signature);
1157
+
1158
+
1159
+
1160
+ VALUE fastruby_method = rb_funcall(recvtype, #{intern_num :fastruby_method}, 1, mname);
1161
+ #{tree_pointer_name} = (VALUE*)FIX2LONG(fastruby_method_tree_pointer(fastruby_method));
1162
+
1163
+ ID id;
1164
+ ID default_id = rb_intern(\"default\");
1165
+ VALUE rb_method_hash;
1166
+ void** address = 0;
1167
+ void** default_address = 0;
1168
+ id = rb_intern(RSTRING(rb_str_signature)->ptr);
1169
+ rb_method_hash = rb_funcall(recvtype, #{intern_num :method_hash},1,mname);
1170
+
1171
+ if (rb_method_hash != Qnil) {
1172
+ VALUE tmp = rb_hash_aref(rb_method_hash, LONG2FIX(id));
1173
+ if (tmp != Qnil) {
1174
+ address = (void*)FIX2LONG(tmp);
1175
+ }
1176
+
1177
+ tmp = rb_hash_aref(rb_method_hash, LONG2FIX(default_id));
1178
+ if (tmp != Qnil) {
1179
+ default_address = (void*)FIX2LONG(tmp);
1040
1180
  }
1041
1181
  }
1042
-
1043
- if (address==0) convention = #{literal_value :ruby};
1044
-
1045
- #{convention_global_name ? convention_global_name + " = 0;" : ""}
1046
- if (recvtype != Qnil) {
1047
-
1048
- if (convention == #{literal_value :fastruby}) {
1049
- #{convention_global_name ? convention_global_name + " = 1;" : ""}
1050
- #{name} = address;
1051
- } else if (convention == #{literal_value :fastruby_array}) {
1052
- // ruby, wrap rb_funcall
1053
- #{name} = (void*)#{ruby_wrapper};
1054
- } else if (convention == #{literal_value :cruby}) {
1055
- // cruby, wrap direct call
1056
- #{cruby_name} = address;
1057
-
1058
- if (#{cruby_name} == 0) {
1059
- #{name} = (void*)#{ruby_wrapper};
1060
- } else {
1061
- #{cruby_len} = len;
1062
- #{name} = (void*)#{cruby_wrapper};
1182
+
1183
+ if (default_address==0) {
1184
+ default_address = malloc(sizeof(void*));
1185
+ NODE* body = rb_method_node(recvtype,#{intern_num mname});
1186
+ *default_address = 0;
1187
+
1188
+ if (body != 0) {
1189
+ if (nd_type(body) == NODE_CFUNC) {
1190
+ if (body->nd_argc == #{args_tree.size-1}) {
1191
+ *default_address = #{cfunc_wrapper};
1192
+ #{cfunc_real_address_name} = (void*)body->nd_cfnc;
1193
+ } else if (body->nd_argc == -1) {
1194
+ *default_address = #{cfunc_wrapper_1};
1195
+ #{cfunc_real_address_name} = (void*)body->nd_cfnc;
1196
+ } else if (body->nd_argc == -2) {
1197
+ *default_address = #{cfunc_wrapper_2};
1198
+ #{cfunc_real_address_name} = (void*)body->nd_cfnc;
1199
+ }
1063
1200
  }
1064
- } else {
1065
- // ruby, wrap rb_funcall
1066
- #{name} = (void*)#{ruby_wrapper};
1067
1201
  }
1068
- } else {
1069
- // ruby, wrap rb_funcall
1070
- #{name} = (void*)#{ruby_wrapper};
1202
+
1203
+ if (recvtype != Qnil) {
1204
+ rb_funcall(
1205
+ recvtype,
1206
+ #{intern_num :register_method_value},
1207
+ 3,
1208
+ #{literal_value mname},
1209
+ LONG2FIX(default_id),
1210
+ LONG2FIX(default_address)
1211
+ );
1212
+ }
1071
1213
  }
1072
1214
 
1215
+ if (address==0) {
1216
+ address = malloc(sizeof(void*));
1217
+
1218
+ if (recvtype != Qnil) {
1219
+ rb_funcall(
1220
+ recvtype,
1221
+ #{intern_num :register_method_value},
1222
+ 3,
1223
+ #{literal_value mname},
1224
+ LONG2FIX(id),
1225
+ LONG2FIX(address)
1226
+ );
1227
+ }
1228
+
1229
+ *address = 0; //(void*)
1230
+ }
1231
+
1232
+ #{address_name} = address;
1233
+ #{cfunc_address_name} = default_address;
1234
+ #{name} = (void*)#{generic_wrapper};
1073
1235
  }
1074
1236
  "
1075
1237
  else
1076
1238
  init_extra << "
1077
1239
  // ruby, wrap rb_funcall
1078
- #{name} = (void*)#{ruby_wrapper};
1240
+ #{name} = (void*)#{pureruby_wrapper};
1079
1241
  "
1080
1242
  end
1081
1243
 
data/lib/fastruby.rb CHANGED
@@ -25,14 +25,5 @@ require "fastruby/custom_require"
25
25
  require "fastruby/set_tree"
26
26
 
27
27
  module FastRuby
28
- class << self
29
- attr_accessor :fastruby_script_path
30
- attr_accessor :fastruby_load_path
31
- end
32
-
33
- FastRuby.fastruby_script_path = File.expand_path(__FILE__)
34
- FastRuby.fastruby_load_path = File.expand_path(File.dirname(__FILE__))
35
-
36
- VERSION = "0.0.13" unless defined? FastRuby::VERSION
28
+ VERSION = "0.0.14" unless defined? FastRuby::VERSION
37
29
  end
38
-
@@ -0,0 +1,29 @@
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 << self
23
+ attr_accessor :fastruby_script_path
24
+ attr_accessor :fastruby_load_path
25
+ end
26
+
27
+ FastRuby.fastruby_script_path = File.expand_path(__FILE__)
28
+ FastRuby.fastruby_load_path = File.expand_path(File.dirname(__FILE__))
29
+ end
@@ -0,0 +1,82 @@
1
+ require "fastruby"
2
+
3
+ describe FastRuby, "fastruby" do
4
+ def self.test_arguments(x)
5
+ it "should allow #{x} arguments calling to cfunc" do
6
+
7
+ arguments = (0..x).map(&:to_s).join(",")
8
+
9
+ fastruby "
10
+ class ::CYR#{x}
11
+ def foo
12
+ a = []
13
+ a.infer(Array).push(#{arguments})
14
+ a
15
+ end
16
+ end
17
+ "
18
+
19
+ eval("::CYR#{x}").new.foo.should be == eval("[#{arguments}]")
20
+ end
21
+ end
22
+
23
+ test_arguments(10)
24
+ test_arguments(15)
25
+ test_arguments(20)
26
+
27
+ (23..27).each do |i|
28
+ test_arguments(i)
29
+ end
30
+
31
+ test_arguments(20)
32
+
33
+
34
+ def self.test_fastruby_arguments(argnum)
35
+ it "should allow #{argnum} arguments calling fastruby" do
36
+
37
+ arguments_name = (0..argnum-1).map{|x| "a"+x.to_s}.join(",")
38
+ arguments = (0..argnum-1).map(&:to_s).join(",")
39
+
40
+ fastruby "
41
+ class ::CYR1_#{argnum}
42
+ def foo(#{arguments_name})
43
+ [#{arguments_name}]
44
+ end
45
+ end
46
+ "
47
+
48
+ array = eval("[#{arguments}]")
49
+
50
+ eval("::CYR1_#{argnum}").new.foo(*array).should be == array
51
+ end
52
+ end
53
+
54
+ (8..12).each do |i|
55
+ test_fastruby_arguments(i)
56
+ end
57
+
58
+ def self.test_invalid_fastruby_arguments(argnum)
59
+ it "should allow #{argnum} arguments calling fastruby" do
60
+
61
+ arguments_name = (0..argnum-1).map{|x| "a"+x.to_s}.join(",")
62
+ arguments = (0..argnum-1).map(&:to_s).join(",")
63
+
64
+ fastruby "
65
+ class ::CYR1_#{argnum}
66
+ def foo(#{arguments_name})
67
+ [#{arguments_name}]
68
+ end
69
+ end
70
+ "
71
+
72
+ array = eval("[#{arguments}]")
73
+
74
+ lambda {
75
+ eval("::CYR1_#{argnum}").new.foo(*array).should be == array
76
+ }.should raise_error(ArgumentError)
77
+ end
78
+ end
79
+
80
+ test_invalid_fastruby_arguments(15)
81
+
82
+ end
@@ -268,4 +268,15 @@ describe FastRuby, "fastruby" do
268
268
  }.should raise_error(ArgumentError)
269
269
  end
270
270
 
271
+ it "should call Array#to_s when infering array type for splat argument" do
272
+ fastruby "
273
+ class ::CF18
274
+ def foo(*x)
275
+ x.to_s
276
+ end
277
+ end
278
+ "
279
+
280
+ ::CF18.new.foo(1,2,3,4,5).should be == "12345"
281
+ end
271
282
  end
@@ -0,0 +1,102 @@
1
+ require "fastruby"
2
+
3
+ describe FastRuby, "fastruby" do
4
+ it "should allow replace methods after they are called and compiled at runtime" do
5
+ fastruby "
6
+ class JU1
7
+ def foo
8
+ 6
9
+ end
10
+ end
11
+ "
12
+
13
+ ::JU1.new.foo
14
+
15
+ fastruby "
16
+ class JU1
17
+ def foo
18
+ 9
19
+ end
20
+ end
21
+ "
22
+
23
+ ::JU1.new.foo.should be == 9
24
+ end
25
+
26
+ it "should allow replace methods after they are called and compiled at runtime (through other method)" do
27
+ fastruby "
28
+ class JU2
29
+ def foo
30
+ 6
31
+ end
32
+
33
+ def bar
34
+ foo
35
+ end
36
+ end
37
+ "
38
+
39
+ ::JU2.new.bar
40
+
41
+ fastruby "
42
+ class JU2
43
+ def foo
44
+ 9
45
+ end
46
+ end
47
+ "
48
+
49
+ ::JU2.new.bar.should be == 9
50
+ end
51
+
52
+ it "should allow replace methods using ruby after they are called and compiled at runtime (through other method)" do
53
+ fastruby "
54
+ class ::JU3
55
+ def foo
56
+ 6
57
+ end
58
+
59
+ def bar
60
+ foo
61
+ end
62
+ end
63
+ "
64
+
65
+ ::JU3.new.bar
66
+
67
+ class ::JU3
68
+ def foo
69
+ 9
70
+ end
71
+ end
72
+
73
+ ::JU3.new.bar.should be == 9
74
+ end
75
+
76
+ it "should allow replace methods using indentical code string" do
77
+ code = "
78
+ class ::JU4
79
+ def foo
80
+ 6
81
+ end
82
+ end
83
+ "
84
+
85
+ fastruby code
86
+
87
+ ::JU4.new.foo.should be == 6
88
+
89
+ fastruby "class ::JU4
90
+ def foo
91
+ 9
92
+ end
93
+ end
94
+ "
95
+
96
+ ::JU4.new.foo.should be == 9
97
+
98
+ fastruby code
99
+
100
+ ::JU4.new.foo.should be == 6
101
+ end
102
+ end