fastruby 0.0.17 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. data/CHANGELOG +10 -0
  2. data/Rakefile +4 -2
  3. data/benchmarks/benchmark.rb +20 -44
  4. data/benchmarks/benchmark.rb~ +47 -0
  5. data/benchmarks/benchmark2.rb +19 -45
  6. data/benchmarks/benchmark2.rb~ +46 -0
  7. data/benchmarks/benchmark3.rb +19 -45
  8. data/benchmarks/benchmark3.rb~ +46 -0
  9. data/benchmarks/benchmark4.rb +30 -65
  10. data/benchmarks/benchmark4.rb~ +61 -0
  11. data/benchmarks/benchmark5.rb +25 -55
  12. data/benchmarks/benchmark5.rb~ +54 -0
  13. data/benchmarks/benchmark6.rb +19 -40
  14. data/benchmarks/benchmark6.rb~ +41 -0
  15. data/benchmarks/benchmark7.rb +23 -52
  16. data/benchmarks/benchmark7.rb~ +48 -0
  17. data/ext/fastruby_base/fastruby_base.inl +1 -0
  18. data/lib/fastruby/builder.rb +128 -76
  19. data/lib/fastruby/cache/cache.rb +9 -5
  20. data/lib/fastruby/fastruby_sexp.rb +18 -0
  21. data/lib/fastruby/inliner/inliner.rb +68 -0
  22. data/lib/fastruby/inliner/modules/call.rb +150 -0
  23. data/lib/fastruby/inliner/modules/recursive.rb +35 -0
  24. data/lib/fastruby/object.rb +17 -32
  25. data/lib/fastruby/reductor/modules/case.rb +49 -0
  26. data/lib/{fastruby.rb~ → fastruby/reductor/modules/for.rb} +11 -13
  27. data/lib/fastruby/reductor/modules/nontree.rb +31 -0
  28. data/lib/fastruby/reductor/modules/recursive.rb +31 -0
  29. data/lib/fastruby/reductor/reductor.rb +39 -0
  30. data/lib/fastruby/set_tree.rb +7 -1
  31. data/lib/fastruby/sexp_extension.rb +6 -0
  32. data/lib/fastruby/translator/modules/block.rb +4 -4
  33. data/lib/fastruby/translator/modules/call.rb +9 -26
  34. data/lib/fastruby/translator/modules/defn.rb +5 -3
  35. data/lib/fastruby/translator/modules/directive.rb +42 -0
  36. data/lib/fastruby/translator/modules/exceptions.rb +12 -30
  37. data/lib/fastruby/translator/modules/flow.rb +33 -83
  38. data/lib/fastruby/translator/modules/iter.rb +4 -7
  39. data/lib/fastruby/translator/modules/literal.rb +11 -25
  40. data/lib/fastruby/translator/modules/logical.rb +5 -3
  41. data/lib/fastruby/translator/modules/method_group.rb +4 -3
  42. data/lib/fastruby/translator/modules/nonlocal.rb +7 -5
  43. data/lib/fastruby/translator/modules/static.rb +242 -0
  44. data/lib/fastruby/translator/modules/variable.rb +16 -9
  45. data/lib/fastruby/translator/scope_mode_helper.rb +2 -27
  46. data/lib/fastruby/translator/translator.rb +131 -60
  47. data/lib/fastruby/translator/translator_modules.rb +6 -2
  48. data/lib/fastruby.rb +1 -1
  49. data/spec/reductor/base_spec.rb +46 -0
  50. data/spec/ruby/base_spec.rb~ +394 -0
  51. data/spec/ruby/block/arguments_spec.rb~ +214 -0
  52. data/spec/ruby/block/proc_as_block_spec.rb~ +23 -0
  53. data/spec/ruby/block/retry_spec.rb~ +43 -0
  54. data/spec/ruby/block_spec.rb~ +520 -0
  55. data/spec/ruby/defn/replacement_spec.rb~ +102 -0
  56. data/spec/ruby/integrity_spec.rb~ +40 -0
  57. data/spec/ruby/singleton_spec.rb~ +76 -0
  58. data/spec/scope_mode/base_spec.rb +14 -5
  59. data/spec/scope_mode/block_spec.rb +18 -9
  60. data/spec/scope_mode/call_spec.rb +11 -2
  61. data/spec/scope_mode/exception_spec.rb +11 -2
  62. data/spec/scope_mode/flow_spec.rb +18 -8
  63. data/spec/scope_mode/optimization_spec.rb +21 -13
  64. data/spec/static/base_spec.rb +54 -0
  65. data/spec/static/flow_spec.rb +48 -0
  66. data/spec/static/operator_spec.rb +104 -0
  67. metadata +58 -8
@@ -26,6 +26,7 @@ require "fastruby/set_tree"
26
26
  require "fastruby/exceptions"
27
27
  require "fastruby/translator/translator_modules"
28
28
  require "fastruby/translator/scope_mode_helper"
29
+ require "define_method_handler"
29
30
 
30
31
  module FastRuby
31
32
  class Context
@@ -39,12 +40,66 @@ module FastRuby
39
40
  attr_reader :init_extra
40
41
  attr_reader :extra_code
41
42
 
42
- TranslatorModules.instance.load_under(FastRuby.fastruby_load_path + "/fastruby/translator/modules/")
43
- TranslatorModules.instance.modls.each do |modl|
44
- include modl
43
+ class Value
44
+ attr_accessor :value
45
+ def initialize(v); @value = v; end
46
+ end
47
+
48
+ def self.define_translator_for(ntype, options = {}, &blk)
49
+ condition_blk = proc do |*x|
50
+ tree = x.first; tree.node_type == ntype
51
+ end
52
+
53
+ if options[:arity]
54
+ if options[:arity] == 1
55
+ condition_blk = proc do |*x|
56
+ tree = x.first; x.size == 1 and tree.node_type == ntype
57
+ end
58
+ end
59
+ end
60
+
61
+ define_method_handler(:to_c, options, &blk).condition &condition_blk
62
+ end
63
+
64
+ define_method_handler(:to_c, :priority => 10000){|*x|
65
+ "Qnil"
66
+ }.condition{|*x| x.size == 1 and (not x.first)}
67
+
68
+ define_method_handler(:to_c, :priority => 1000){|tree, result_var|
69
+ "#{result_var} = #{to_c(tree)};"
70
+ }.condition{|*x| x.size == 2 and (not x.first)}
71
+
72
+ define_method_handler(:to_c, :priority => -9000){ |tree, result_var|
73
+ "#{result_var} = #{to_c(tree)};"
74
+ }.condition{|*x| x.size == 2 }
75
+
76
+ define_method_handler(:to_c, :priority => -10000) do |tree, result_var=nil|
77
+ raise "undefined translator for node type :#{tree.node_type}"
78
+ end
79
+
80
+ define_method_handler(:initialize_to_c){|*x|}.condition{|*x|false}
81
+
82
+ define_translator_for(:call, :priority => 100){ |tree, result_var=nil|
83
+ tree[2] = :fastruby_require
84
+ to_c(tree)
85
+ }.condition{|*x|
86
+ tree = x.first; tree.node_type == :call && tree[2] == :require
87
+ }
88
+
89
+ define_method_handler(:infer_value, :priority => -1000) do |tree|
90
+ nil
91
+ end
92
+
93
+ TranslatorModules.instance.each_under(FastRuby.fastruby_load_path + "/fastruby/translator/modules/") do |path|
94
+ groupname = path.split("/").last.split(".").first.to_sym
95
+ handler_scope(:group => groupname) do
96
+ require path
97
+ end
45
98
  end
46
99
 
47
100
  def initialize(common_func = true)
101
+ initialize_to_c
102
+
48
103
  @infer_lvar_map = Hash.new
49
104
  @no_cache = false
50
105
  @extra_code = ""
@@ -183,22 +238,32 @@ module FastRuby
183
238
  end
184
239
  end
185
240
 
186
- def to_c(tree, result_variable = nil)
187
- return "Qnil" unless tree
188
-
189
- mname = "to_c_" + tree[0].to_s
190
-
191
- if result_variable
192
- if method(mname).arity == 1
193
- "#{result_variable} = #{send(mname, tree)};\n"
194
- else
195
- send(mname, tree, result_variable)
196
- end
241
+
242
+ def _raise(class_tree, message_tree = nil)
243
+ class_tree = to_c class_tree unless class_tree.instance_of? String
244
+
245
+ if message_tree.instance_of? String
246
+ message_tree = "rb_str_new2(#{message_tree.inspect})"
197
247
  else
198
- send(mname, tree)
248
+ message_tree = to_c message_tree
249
+ end
250
+
251
+ if message_tree
252
+ return inline_block("
253
+ pframe->thread_data->exception = rb_funcall(#{class_tree}, #{intern_num :exception},1,#{message_tree});
254
+ longjmp(pframe->jmp, FASTRUBY_TAG_RAISE);
255
+ return Qnil;
256
+ ")
257
+ else
258
+ return inline_block("
259
+ pframe->thread_data->exception = rb_funcall(#{class_tree}, #{intern_num :exception},0);
260
+ longjmp(pframe->jmp, FASTRUBY_TAG_RAISE);
261
+ return Qnil;
262
+ ")
199
263
  end
200
- end
201
264
 
265
+ end
266
+
202
267
  def anonymous_function(*x)
203
268
 
204
269
  name = "anonymous" + rand(10000000).to_s
@@ -280,7 +345,7 @@ module FastRuby
280
345
 
281
346
  extra_code << "
282
347
  static VALUE #{@alt_method_name}(VALUE self__);
283
- static VALUE main_proc_call(VALUE self__, VALUE class_self_) {
348
+ static VALUE main_proc_call(VALUE self__, VALUE signature, VALUE class_self_) {
284
349
  #{@alt_method_name}(class_self_);
285
350
  return Qnil;
286
351
  }
@@ -290,23 +355,22 @@ module FastRuby
290
355
  init_extra << "
291
356
  {
292
357
  VALUE newproc = rb_funcall(rb_cObject,#{intern_num :new},0);
293
- rb_define_singleton_method(newproc, \"call\", main_proc_call, 1);
358
+ rb_define_singleton_method(newproc, \"call\", main_proc_call, 2);
294
359
  rb_gv_set(\"$last_obj_proc\", newproc);
295
-
296
360
  }
297
361
  "
298
362
  end
299
363
  end
300
364
 
301
- def define_method_at_init(klass,method_name, size, signature)
302
- init_extra << "
303
- {
365
+ def define_method_at_init(method_name, size, signature)
366
+ extra_code << "
367
+ static VALUE main_proc_call(VALUE self__, VALUE signature, VALUE class_self_) {
304
368
  VALUE method_name = rb_funcall(
305
369
  #{literal_value FastRuby},
306
370
  #{intern_num :make_str_signature},
307
371
  2,
308
372
  #{literal_value method_name},
309
- #{literal_value signature}
373
+ signature
310
374
  );
311
375
 
312
376
  ID id = rb_intern(RSTRING_PTR(method_name));
@@ -315,12 +379,12 @@ module FastRuby
315
379
  #{literal_value FastRuby},
316
380
  #{intern_num :set_builder_module},
317
381
  1,
318
- #{literal_value klass}
382
+ class_self_
319
383
  );
320
384
 
321
385
  VALUE rb_method_hash;
322
386
  void** address = 0;
323
- rb_method_hash = rb_funcall(#{literal_value klass}, #{intern_num :method_hash},1,#{literal_value method_name});
387
+ rb_method_hash = rb_funcall(class_self_, #{intern_num :method_hash},1,#{literal_value method_name});
324
388
 
325
389
  if (rb_method_hash != Qnil) {
326
390
  VALUE tmp = rb_hash_aref(rb_method_hash, PTR2NUM(id));
@@ -335,15 +399,25 @@ module FastRuby
335
399
  *address = #{alt_method_name};
336
400
 
337
401
  rb_funcall(
338
- #{literal_value klass},
402
+ class_self_,
339
403
  #{intern_num :register_method_value},
340
404
  3,
341
405
  #{literal_value method_name},
342
406
  PTR2NUM(id),
343
407
  PTR2NUM(address)
344
408
  );
409
+
410
+ return Qnil;
345
411
  }
346
412
  "
413
+
414
+ init_extra << "
415
+ {
416
+ VALUE newproc = rb_funcall(rb_cObject,#{intern_num :new},0);
417
+ rb_define_singleton_method(newproc, \"call\", main_proc_call, 2);
418
+ rb_gv_set(\"$last_obj_proc\", newproc);
419
+ }
420
+ "
347
421
  end
348
422
 
349
423
  def to_c_method(tree, signature = nil)
@@ -359,7 +433,7 @@ module FastRuby
359
433
  block_argument = tree[3].find{|x| x.to_s[0] == ?&}
360
434
  impl_tree = tree[4][1]
361
435
  end
362
-
436
+
363
437
  args_tree = original_args_tree.select{|x| x.to_s[0] != ?&}
364
438
 
365
439
  initialize_method_structs(original_args_tree)
@@ -1073,22 +1147,31 @@ fastruby_local_next:
1073
1147
  end
1074
1148
 
1075
1149
  pureruby_wrapper = anonymous_function{ |funcname| "
1076
- static VALUE #{funcname}(VALUE self,void* block,void* frame#{strargs_signature}){
1150
+ static VALUE #{funcname}(VALUE self,void* block,void* frame, int argc, VALUE* argv){
1077
1151
  #{@frame_struct}* pframe = frame;
1078
- VALUE method_arguments[#{args_tree.size}] = {#{toprocstrargs}};
1079
-
1152
+ VALUE method_arguments[3];
1153
+
1154
+ method_arguments[0] = (VALUE)argc;
1155
+ method_arguments[1] = (VALUE)argv;
1156
+ method_arguments[2] = (VALUE)self;
1157
+
1080
1158
  return #{
1081
- protected_block "last_expression = rb_funcall(((VALUE*)method_arguments)[0], #{intern_num mname.to_sym}, #{args_tree.size-1}#{inprocstrargs});", false, "method_arguments"
1159
+ protected_block "last_expression = rb_funcall2(((VALUE*)method_arguments)[2], #{intern_num mname.to_sym}, ((int*)method_arguments)[0], ((VALUE**)method_arguments)[1]);", false, "method_arguments"
1082
1160
  };
1083
1161
  }
1084
1162
  "
1085
1163
  }
1086
1164
 
1087
1165
  generic_wrapper = anonymous_function{ |funcname| "
1088
- static VALUE #{funcname}(VALUE self,void* block,void* frame#{strargs_signature}){
1166
+ static VALUE #{funcname}(VALUE self,void* block,void* frame, int argc, VALUE* argv){
1089
1167
 
1090
1168
  #{@frame_struct}* pframe = frame;
1091
- VALUE method_arguments[#{args_tree.size+1}] = {#{toprocstrargs},(VALUE)block};
1169
+ VALUE method_arguments[4];
1170
+
1171
+ method_arguments[0] = (VALUE)argc;
1172
+ method_arguments[1] = (VALUE)argv;
1173
+ method_arguments[2] = (VALUE)self;
1174
+ method_arguments[3] = (VALUE)block;
1092
1175
 
1093
1176
  void* fptr = 0;
1094
1177
 
@@ -1106,40 +1189,30 @@ fastruby_local_next:
1106
1189
 
1107
1190
  fptr = *#{address_name};
1108
1191
 
1109
- #{
1110
- if args_tree.size < 25
1111
- "
1112
1192
  if (fptr == 0) {
1113
1193
  fptr = *#{cfunc_address_name};
1114
1194
  if (fptr != 0) {
1115
- VALUE params[2] = {self,PTR2NUM(#{args_tree.size-1})};
1116
- return ( (VALUE(*)(#{value_cast})) (fptr) )((VALUE)params,(VALUE)block,(VALUE)frame#{inprocstrargs});
1195
+ return ( (VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*) ) (fptr) )(self,(VALUE)block,(VALUE)frame, argc, argv);
1117
1196
  }
1118
1197
  }
1119
- "
1120
- end
1121
- }
1122
-
1198
+
1123
1199
  if (fptr == 0) {
1124
1200
  if (block==0) {
1125
1201
  return #{
1126
- protected_block "last_expression = rb_funcall(((VALUE*)method_arguments)[0], #{intern_num mname.to_sym}, #{args_tree.size-1}#{inprocstrargs});", false, "method_arguments"
1202
+ protected_block "last_expression = rb_funcall2(((VALUE*)method_arguments)[2], #{intern_num mname.to_sym}, ((int*)method_arguments)[0], ((VALUE**)method_arguments)[1]);", false, "method_arguments"
1127
1203
  };
1128
1204
 
1129
1205
  } else {
1130
1206
  return #{
1131
1207
  protected_block "
1132
1208
  #{@block_struct} *pblock;
1133
- pblock = (typeof(pblock))( ((VALUE*)method_arguments)[#{args_tree.size}] );
1209
+ pblock = (typeof(pblock))( ((VALUE*)method_arguments)[3] );
1134
1210
  last_expression = rb_iterate(
1135
1211
  #{anonymous_function{|name|
1136
1212
  "
1137
1213
  static VALUE #{name} (VALUE data) {
1138
1214
  VALUE* method_arguments = (VALUE*)data;
1139
- return rb_funcall(
1140
- ((VALUE*)method_arguments)[0],
1141
- #{intern_num mname.to_sym},
1142
- #{args_tree.size-1}#{inprocstrargs});
1215
+ return rb_funcall2(((VALUE*)method_arguments)[2], #{intern_num mname.to_sym}, ((int*)method_arguments)[0], ((VALUE**)method_arguments)[1]);
1143
1216
  }
1144
1217
  "
1145
1218
  }},
@@ -1180,19 +1253,20 @@ fastruby_local_next:
1180
1253
  }
1181
1254
 
1182
1255
  } else {
1183
- return ( (VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*)) (fptr) )(self,(VALUE)block,(VALUE)frame,#{args_tree.size-1},method_arguments+1);
1256
+ return ( (VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*)) (fptr) )(self,(VALUE)block,(VALUE)frame,argc,argv);
1184
1257
  }
1185
1258
  }
1186
1259
  "
1187
1260
  }
1188
1261
 
1189
1262
 
1263
+ cfuncall1inprocargs = (0..args_tree.size-2).map{|x| "argv[#{x}]"}.join(",")
1264
+ cfuncall1inprocargs = ","+cfuncall1inprocargs if cfuncall1inprocargs != ""
1265
+
1190
1266
  cfunc_value_cast = (["VALUE"]*args_tree.size).join(",")
1191
1267
  cfunc_wrapper = anonymous_function{ |funcname| "
1192
- static VALUE #{funcname}(VALUE* params, void* block,void* frame#{strargs_signature}){
1193
- VALUE self = params[0];
1194
- VALUE method_arguments[#{args_tree.size}] = {#{toprocstrargs}};
1195
- return ( (VALUE(*)(#{cfunc_value_cast})) (#{cfunc_real_address_name}) )(self#{inprocstrargs});
1268
+ static VALUE #{funcname}(VALUE self, void* block,void* frame, int argc, VALUE* argv){
1269
+ return ( (VALUE(*)(#{cfunc_value_cast})) (#{cfunc_real_address_name}) )(self#{cfuncall1inprocargs});
1196
1270
  }
1197
1271
  "
1198
1272
  }
@@ -1201,18 +1275,15 @@ fastruby_local_next:
1201
1275
  strargs_signature = (0..25).map{|x| "VALUE arg#{x}"}.join(",")
1202
1276
 
1203
1277
  cfunc_wrapper_1 = anonymous_function{ |funcname| "
1204
- static VALUE #{funcname}(VALUE* params, void* block,void* frame, #{strargs_signature}){
1205
- VALUE self = params[0];
1206
- VALUE method_arguments[26] = {#{toprocstrargs}};
1207
- return ( (VALUE(*)(int, VALUE*, VALUE)) (#{cfunc_real_address_name}) )(NUM2ULONG(params[1]),method_arguments,self);
1278
+ static VALUE #{funcname}(VALUE self, void* block,void* frame, int argc, VALUE* argv){
1279
+ return ( (VALUE(*)(int, VALUE*, VALUE)) (#{cfunc_real_address_name}) )(argc,argv,self);
1208
1280
  }
1209
1281
  "
1210
1282
  }
1211
1283
 
1212
1284
  cfunc_wrapper_2 = anonymous_function{ |funcname| "
1213
- static VALUE #{funcname}(VALUE* params, void* block,void* frame, #{strargs_signature}){
1214
- VALUE self = params[0];
1215
- VALUE args = rb_ary_new3(NUM2ULONG(params[1]),#{toprocstrargs});
1285
+ static VALUE #{funcname}(VALUE self, void* block,void* frame, int argc, VALUE* argv){
1286
+ VALUE args = rb_ary_new3(argc, argv);
1216
1287
  return ( (VALUE(*)(VALUE,VALUE)) (#{cfunc_real_address_name}) )(self,args);
1217
1288
  }
1218
1289
  "
@@ -34,11 +34,15 @@ module FastRuby
34
34
  @modls << modl
35
35
  end
36
36
 
37
- def load_under(dir)
37
+ def each_under(dir)
38
38
  Dir.glob(dir + "/*.rb") do |x|
39
- require x
39
+ yield x
40
40
  end
41
41
  end
42
+
43
+ def load_under(dir)
44
+ each_under(dir, &method(:require))
45
+ end
42
46
  end
43
47
  end
44
48
 
data/lib/fastruby.rb CHANGED
@@ -32,5 +32,5 @@ class Object
32
32
  end
33
33
 
34
34
  module FastRuby
35
- VERSION = "0.0.17" unless defined? FastRuby::VERSION
35
+ VERSION = "0.0.18" unless defined? FastRuby::VERSION
36
36
  end
@@ -0,0 +1,46 @@
1
+ require "fastruby"
2
+ require "fastruby/reductor/reductor"
3
+ require "fastruby/sexp_extension"
4
+ require "ruby_parser"
5
+
6
+ describe FastRuby, "fastruby" do
7
+
8
+ def self.test_normal_tree(code)
9
+ unmodified_tree = FastRuby::FastRubySexp.from_sexp RubyParser.new.parse code
10
+ it "tree for source #{code} should not be changed by reductor" do
11
+ obtained_tree = FastRuby::Reductor.new.reduce unmodified_tree
12
+ obtained_tree.should be == unmodified_tree
13
+ end
14
+ end
15
+
16
+ it "should reduce for statements into each calls" do
17
+ reductor = FastRuby::Reductor.new
18
+
19
+ original_tree = fs(:for, fs(:call, nil, :b, fs(:arglist)), fs(:lasgn, :a), fs(:call, nil, :c, fs(:arglist)))
20
+ expected_tree = fs(:iter, fs(:call, fs(:call, nil, :b, fs(:arglist)), :each, fs(:arglist)), fs(:lasgn, :a), fs(:call, nil, :c, fs(:arglist)))
21
+ obtained_tree = reductor.reduce original_tree
22
+
23
+ obtained_tree.should be == expected_tree
24
+ end
25
+
26
+ test_normal_tree "a.foo(b)"
27
+ test_normal_tree "if (x); y; else; z; end"
28
+
29
+ it "should reduce call statements into if arrays" do
30
+ reductor = FastRuby::Reductor.new
31
+
32
+ original_tree = fs(:case,
33
+ fs(:call, nil, :a, fs(:arglist)),
34
+ fs(:when, fs(:array, fs(:call, nil, :b, fs(:arglist))), fs(:call, nil, :c, fs(:arglist))),
35
+ nil)
36
+
37
+ obtained_tree = reductor.reduce original_tree
38
+
39
+ obtained_tree.node_type.should be == :block
40
+ obtained_tree[1].node_type.should be == :lasgn
41
+ obtained_tree[1].last.should be == s(:call, nil, :a, s(:arglist)).to_fastruby_sexp
42
+ obtained_tree[2].node_type.should be == :if
43
+ obtained_tree[2][1].node_type.should be == :or
44
+ obtained_tree[2][2].should be == original_tree.find_tree(:when).last
45
+ end
46
+ end