fastruby 0.0.13 → 0.0.14

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