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.
- data/CHANGELOG +6 -0
- data/README +3 -2
- data/Rakefile +1 -1
- data/benchmarks/benchmark7.rb +77 -0
- data/ext/fastruby_base/fastruby_base.c +3 -1
- data/ext/fastruby_base/fastruby_base.inl +79 -1
- data/lib/fastruby/builder.rb +43 -75
- data/lib/fastruby/object.rb +1 -1
- data/lib/fastruby/set_tree.rb +6 -0
- data/lib/fastruby/translator/modules/call.rb +2 -3
- data/lib/fastruby/translator/modules/defn.rb +51 -73
- data/lib/fastruby/translator/modules/iter.rb +16 -20
- data/lib/fastruby/translator/translator.rb +253 -91
- data/lib/fastruby.rb +1 -10
- data/lib/fastruby_load_path.rb +29 -0
- data/spec/call/base_call_spec.rb +82 -0
- data/spec/defn/multiple_args_spec.rb +11 -0
- data/spec/defn/replacement_spec.rb +102 -0
- metadata +8 -4
@@ -336,12 +336,44 @@ module FastRuby
|
|
336
336
|
#{literal_value signature}
|
337
337
|
);
|
338
338
|
|
339
|
-
|
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, #{
|
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, #{
|
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
|
-
#{
|
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
|
-
|
938
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
983
|
-
|
984
|
-
if (
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
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
|
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
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
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
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
};
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
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 (
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
if (
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
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
|
-
|
1069
|
-
|
1070
|
-
|
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*)#{
|
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
|
-
|
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
|