fastruby 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ 0.0.5 Support for case..when..end
2
+
3
+ Fixes on wrapping/translation of fastruby frames through ruby calls
4
+
1
5
  0.0.4 Basic support fot non-local goto: return, break, next
2
6
 
3
7
  Basic support for exceptions
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ require "rspec/core/rake_task"
7
7
 
8
8
  spec = Gem::Specification.new do |s|
9
9
  s.name = 'fastruby'
10
- s.version = '0.0.4'
10
+ s.version = '0.0.5'
11
11
  s.author = 'Dario Seminara'
12
12
  s.email = 'robertodarioseminara@gmail.com'
13
13
  s.platform = Gem::Platform::RUBY
@@ -22,9 +22,11 @@ require "fastruby/translator"
22
22
  require "fastruby/builder"
23
23
  require "fastruby/getlocals"
24
24
  require "fastruby/method_extension"
25
+ require "fastruby/translator"
25
26
  require "ruby_parser"
26
27
  require "inline"
27
28
 
29
+
28
30
  # clean rubyinline cache
29
31
  system("rm -fr #{ENV["HOME"]}/.ruby_inline/*")
30
32
 
@@ -292,7 +294,23 @@ class Object
292
294
 
293
295
  int aux = setjmp(frame.jmp);
294
296
  if (aux != 0) {
295
- rb_funcall(self, #{:raise.to_i}, 1, frame.exception);
297
+ if (frame.target_frame == (void*)-1) {
298
+ rb_funcall(self, #{:raise.to_i}, 1, frame.exception);
299
+ }
300
+
301
+ if (frame.target_frame != &frame) {
302
+ VALUE ex = rb_funcall(
303
+ (VALUE)#{FastRuby::Context::UnwindFastrubyFrame.internal_value},
304
+ #{:new.to_i},
305
+ 3,
306
+ frame.exception,
307
+ LONG2FIX(frame.target_frame),
308
+ frame.return_value
309
+ );
310
+
311
+ rb_funcall(self, #{:raise.to_i}, 1, ex);
312
+ }
313
+
296
314
  return Qnil;
297
315
  }
298
316
 
@@ -286,24 +286,21 @@ module FastRuby
286
286
  str_arg_initialization
287
287
 
288
288
  block_code = proc { |name| "
289
- static VALUE #{name}(VALUE arg, VALUE _parent_frame) {
289
+ static VALUE #{name}(VALUE arg, VALUE _plocals) {
290
290
  // block for call to #{call_tree[2]}
291
291
  VALUE last_expression = Qnil;
292
292
 
293
293
  #{@frame_struct} frame;
294
294
  #{@frame_struct} *pframe = (void*)&frame;
295
- #{@frame_struct} *parent_frame = (void*)_parent_frame;
296
- #{@locals_struct} *plocals;
295
+ #{@locals_struct} *plocals = (void*)_plocals;
297
296
 
298
- frame.plocals = parent_frame->plocals;
299
- frame.parent_frame = parent_frame;
297
+ frame.plocals = plocals;
298
+ frame.parent_frame = 0;
300
299
  frame.return_value = Qnil;
301
300
  frame.target_frame = &frame;
302
301
  frame.exception = Qnil;
303
302
  frame.rescue = 0;
304
303
 
305
- plocals = frame.plocals;
306
-
307
304
  if (setjmp(frame.jmp) != 0) {
308
305
  if (pframe->target_frame != pframe) {
309
306
  if (pframe->target_frame == (void*)-3) {
@@ -318,6 +315,7 @@ module FastRuby
318
315
  LONG2FIX(pframe->target_frame),
319
316
  pframe->return_value
320
317
  );
318
+
321
319
  rb_funcall(plocals->self, #{:raise.to_i}, 1, ex);
322
320
  }
323
321
  return frame.return_value;
@@ -332,7 +330,7 @@ module FastRuby
332
330
  "
333
331
  }
334
332
 
335
- protected_block("rb_iterate(#{anonymous_function(&caller_code)}, (VALUE)pframe, #{anonymous_function(&block_code)}, (VALUE)pframe)", true)
333
+ protected_block("rb_iterate(#{anonymous_function(&caller_code)}, (VALUE)pframe, #{anonymous_function(&block_code)}, (VALUE)plocals)", true)
336
334
 
337
335
  elsif convention == :fastruby
338
336
 
@@ -474,11 +472,13 @@ module FastRuby
474
472
  @yield_signature = new_yield_signature
475
473
  end
476
474
 
477
- if tree.size > 1
478
- anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){#{tree[1..-1].map{|subtree| to_c subtree}.join(",")}})"
479
- else
480
- anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){})"
481
- end
475
+ ret = if tree.size > 1
476
+ anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){#{tree[1..-1].map{|subtree| to_c subtree}.join(",")}})"
477
+ else
478
+ anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){})"
479
+ end
480
+
481
+ protected_block(ret, true)
482
482
  end
483
483
 
484
484
  def to_c_block(tree)
@@ -503,7 +503,7 @@ module FastRuby
503
503
  end
504
504
 
505
505
  def to_c_return(tree)
506
- "pframe->target_frame = ((typeof(pframe))plocals->pframe); plocals->return_value = #{to_c(tree[1])}; longjmp(pframe->jmp, 1);\n"
506
+ "pframe->target_frame = ((typeof(pframe))plocals->pframe); plocals->return_value = #{to_c(tree[1])}; longjmp(pframe->jmp, 1); return Qnil;\n"
507
507
  end
508
508
 
509
509
  def to_c_break(tree)
@@ -621,6 +621,36 @@ module FastRuby
621
621
  end
622
622
  end
623
623
 
624
+ def to_c_case(tree)
625
+
626
+ tmpvarname = "tmp" + rand(1000000).to_s;
627
+
628
+ code = tree[2..-2].map{|subtree|
629
+
630
+ # this subtree is a when
631
+ subtree[1][1..-1].map{|subsubtree|
632
+ c_calltree = s(:call, nil, :inline_c, s(:arglist, s(:str, tmpvarname), s(:false)))
633
+ calltree = s(:call, subsubtree, :===, s(:arglist, c_calltree))
634
+ "
635
+ if (RTEST(#{to_c_call(calltree, tmpvarname)})) {
636
+ return #{to_c(subtree[2])};
637
+ }
638
+
639
+ "
640
+ }.join("\n")
641
+
642
+ }.join("\n")
643
+
644
+ inline_block "
645
+
646
+ VALUE #{tmpvarname} = #{to_c tree[1]};
647
+
648
+ #{code};
649
+
650
+ return #{to_c tree[-1]};
651
+ "
652
+ end
653
+
624
654
  def to_c_const(tree)
625
655
  "rb_const_get(CLASS_OF(plocals->self), #{tree[1].to_i})"
626
656
  end
@@ -966,7 +996,7 @@ module FastRuby
966
996
  end
967
997
  end
968
998
 
969
- def to_c_call(tree)
999
+ def to_c_call(tree, repass_var = nil)
970
1000
  directive_code = directive(tree)
971
1001
  if directive_code
972
1002
  return directive_code
@@ -1046,8 +1076,13 @@ module FastRuby
1046
1076
  len = getlen(mobject)
1047
1077
  end
1048
1078
 
1049
- extraargs = ""
1050
- extraargs = ", Qfalse" if convention == :fastruby
1079
+ if repass_var
1080
+ extraargs = ","+repass_var
1081
+ extraargs_signature = ",VALUE " + repass_var
1082
+ else
1083
+ extraargs = ""
1084
+ extraargs_signature = ""
1085
+ end
1051
1086
 
1052
1087
  if address then
1053
1088
  if argnum == 0
@@ -1072,7 +1107,7 @@ module FastRuby
1072
1107
  protected_block(
1073
1108
 
1074
1109
  anonymous_function{ |name| "
1075
- static VALUE #{name}(VALUE recv) {
1110
+ static VALUE #{name}(VALUE recv#{extraargs_signature}) {
1076
1111
  // call to #{recvtype}##{mname}
1077
1112
  if (rb_block_given_p()) {
1078
1113
  // no passing block, recall
@@ -1081,8 +1116,7 @@ module FastRuby
1081
1116
  return ((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{str_incall_args});
1082
1117
  }
1083
1118
  }
1084
- " } + "(#{to_c(recv)})"
1085
- )
1119
+ " } + "(#{to_c(recv)}#{extraargs})", false, repass_var)
1086
1120
  end
1087
1121
  else
1088
1122
  value_cast = ( ["VALUE"]*(args.size) ).join(",")
@@ -1116,24 +1150,24 @@ module FastRuby
1116
1150
  return ((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{str_incall_args});
1117
1151
  }
1118
1152
  }
1119
- " } + "(#{to_c(recv)}, #{strargs})"
1153
+ " } + "(#{to_c(recv)}, #{strargs})", false, repass_var
1120
1154
  )
1121
1155
  end
1122
1156
  end
1123
1157
  else
1124
1158
 
1125
1159
  if argnum == 0
1126
- protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, 0)")
1160
+ protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, 0)", false, repass_var)
1127
1161
  else
1128
- protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, #{argnum}, #{strargs} )")
1162
+ protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, #{argnum}, #{strargs} )", false, repass_var)
1129
1163
  end
1130
1164
  end
1131
1165
 
1132
1166
  else
1133
1167
  if argnum == 0
1134
- protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, 0)")
1168
+ protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, 0)", false, repass_var)
1135
1169
  else
1136
- protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, #{argnum}, #{strargs} )")
1170
+ protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, #{argnum}, #{strargs} )", false, repass_var)
1137
1171
  end
1138
1172
  end
1139
1173
  end
@@ -1212,16 +1246,23 @@ module FastRuby
1212
1246
  elsif mname == :block_given?
1213
1247
  return "#{locals_accessor}block_function_address == 0 ? Qfalse : Qtrue"
1214
1248
  elsif mname == :inline_c
1249
+
1215
1250
  code = args[1][1]
1216
1251
 
1217
- return anonymous_function{ |name| "
1218
- static VALUE #{name}(VALUE param) {
1219
- #{@locals_struct} *plocals = (void*)param;
1220
- #{code};
1221
- return Qnil;
1222
- }
1223
- "
1224
- }+"((VALUE)plocals)"
1252
+ unless (args[2] == s(:false))
1253
+ return anonymous_function{ |name| "
1254
+ static VALUE #{name}(VALUE param) {
1255
+ #{@frame_struct} *pframe = (void*)param;
1256
+ #{@locals_struct} *plocals = (void*)pframe->plocals;
1257
+ #{code};
1258
+ return Qnil;
1259
+ }
1260
+ "
1261
+ }+"((VALUE)pframe)"
1262
+ else
1263
+ code
1264
+ end
1265
+
1225
1266
  else
1226
1267
  nil
1227
1268
  end
@@ -1249,9 +1290,9 @@ module FastRuby
1249
1290
  }
1250
1291
  end
1251
1292
 
1252
- def inline_block(code)
1293
+ def inline_block(code, repass_var = nil)
1253
1294
  anonymous_function{ |name| "
1254
- static VALUE #{name}(VALUE param) {
1295
+ static VALUE #{name}(VALUE param#{repass_var ? ",VALUE " + repass_var : "" }) {
1255
1296
  #{@frame_struct} *pframe = (void*)param;
1256
1297
  #{@locals_struct} *plocals = (void*)pframe->plocals;
1257
1298
  VALUE last_expression = Qnil;
@@ -1259,7 +1300,7 @@ module FastRuby
1259
1300
  #{code}
1260
1301
  }
1261
1302
  "
1262
- } + "((VALUE)pframe)"
1303
+ } + "((VALUE)pframe#{repass_var ? ", " + repass_var : "" })"
1263
1304
  end
1264
1305
 
1265
1306
  def inline_ruby(proced, parameter)
@@ -1274,7 +1315,7 @@ module FastRuby
1274
1315
  ")
1275
1316
  end
1276
1317
 
1277
- def protected_block(inner_code, always_rescue = false)
1318
+ def protected_block(inner_code, always_rescue = false,repass_var = nil)
1278
1319
  wrapper_code = "
1279
1320
  if (pframe->last_error != Qnil) {
1280
1321
  if (CLASS_OF(pframe->last_error)==(VALUE)#{UnwindFastrubyFrame.internal_value}) {
@@ -1292,6 +1333,7 @@ module FastRuby
1292
1333
  return Qnil;
1293
1334
 
1294
1335
  } else {
1336
+
1295
1337
  // raise emulation
1296
1338
  #{@frame_struct} *pframe = (void*)param;
1297
1339
  pframe->target_frame = (void*)-1;
@@ -1302,7 +1344,29 @@ module FastRuby
1302
1344
 
1303
1345
  }
1304
1346
  "
1305
- rescue_code = "rb_rescue2(#{inline_block_reference "return #{inner_code};"},(VALUE)pframe,#{anonymous_function{|name| "
1347
+
1348
+
1349
+ body = nil
1350
+ rescue_args = nil
1351
+ if repass_var
1352
+ body = anonymous_function{ |name| "
1353
+ static VALUE #{name}(VALUE param) {
1354
+ #{@frame_struct} *pframe = ((void**)param)[0];
1355
+ #{@locals_struct} *plocals = pframe->plocals;
1356
+ VALUE #{repass_var} = (VALUE)((void**)param)[1];
1357
+ return #{inner_code};
1358
+ }
1359
+ "
1360
+ }
1361
+
1362
+ rescue_args = ""
1363
+ rescue_args = "(VALUE)(VALUE[]){(VALUE)pframe,#{repass_var}}"
1364
+ else
1365
+ body = inline_block_reference("return #{inner_code}")
1366
+ rescue_args = "(VALUE)pframe"
1367
+ end
1368
+
1369
+ rescue_code = "rb_rescue2(#{body},#{rescue_args},#{anonymous_function{|name| "
1306
1370
  static VALUE #{name}(VALUE param, VALUE error) {
1307
1371
  #{@frame_struct} *pframe = (void*)param;
1308
1372
  pframe->last_error = error;
@@ -1318,7 +1382,7 @@ module FastRuby
1318
1382
  #{wrapper_code}
1319
1383
 
1320
1384
  return result;
1321
- "
1385
+ ", repass_var
1322
1386
  else
1323
1387
  inline_block "
1324
1388
  VALUE result;
@@ -1333,7 +1397,7 @@ module FastRuby
1333
1397
  #{wrapper_code}
1334
1398
 
1335
1399
  return result;
1336
- "
1400
+ ", repass_var
1337
1401
  end
1338
1402
 
1339
1403
  end
@@ -1382,6 +1446,7 @@ module FastRuby
1382
1446
  "
1383
1447
  end
1384
1448
 
1449
+
1385
1450
  def frame(code, jmp_code, not_jmp_code = "", rescued = nil)
1386
1451
 
1387
1452
  anonymous_function{ |name| "
@@ -1414,7 +1479,6 @@ module FastRuby
1414
1479
  pframe->exception = original_frame->exception;
1415
1480
  pframe->target_frame = original_frame->target_frame;
1416
1481
  pframe->return_value = original_frame->return_value;
1417
-
1418
1482
  longjmp(pframe->jmp,1);
1419
1483
  }
1420
1484
 
data/lib/fastruby.rb CHANGED
@@ -24,5 +24,5 @@ require "fastruby/exceptions"
24
24
  require "fastruby/custom_require"
25
25
 
26
26
  module FastRuby
27
- VERSION = "0.0.3"
27
+ VERSION = "0.0.5"
28
28
  end
data/spec/block_spec.rb CHANGED
@@ -415,4 +415,90 @@ describe FastRuby, "fastruby" do
415
415
  y28 = ::Y28.new
416
416
  y28.foo(::Y27.new, 713).should be == 713
417
417
  end
418
+
419
+ class ::Y29
420
+ fastruby "
421
+ def foo(ary)
422
+ cc = nil
423
+ ary.each do |x|
424
+ cc = x
425
+ end
426
+ cc
427
+ end
428
+ "
429
+ end
430
+
431
+ it "should assign variables from inside a block" do
432
+ ::Y29.new.foo([1,2,3]).should be == 3
433
+ end
434
+
435
+
436
+ class ::Y30
437
+ attr_accessor :a, :b, :c
438
+
439
+ def bar
440
+ begin
441
+ doo do
442
+ yield
443
+ end
444
+ ensure
445
+ @a = 15
446
+ end
447
+ end
448
+
449
+ fastruby "
450
+
451
+ def doo
452
+ begin
453
+ yield
454
+ ensure
455
+ @b = 16
456
+ end
457
+ end
458
+
459
+ def foo
460
+ cc = nil
461
+ bar do
462
+ return
463
+ end
464
+ ensure
465
+ @c = 17
466
+ end
467
+ "
468
+ end
469
+
470
+ it "should assign variables from inside a block" do
471
+ y = ::Y30.new
472
+ y.foo
473
+
474
+ y.a.should be == 15
475
+ y.b.should be == 16
476
+ y.c.should be == 17
477
+ end
478
+
479
+ class ::Y31
480
+ fastruby "
481
+
482
+ def bar
483
+ begin
484
+ yield
485
+ rescue
486
+ end
487
+ end
488
+
489
+ def foo
490
+ bar do
491
+ return 8
492
+ end
493
+ return 0
494
+ end
495
+ "
496
+ end
497
+
498
+ it "should return values from block through rescue" do
499
+ y = ::Y31.new
500
+ y.foo.should be == 8
501
+ end
502
+
503
+
418
504
  end
@@ -0,0 +1,136 @@
1
+ require "fastruby"
2
+
3
+ describe FastRuby, "case statement" do
4
+ class ::O1
5
+ fastruby '
6
+ def foo(a)
7
+ case a
8
+ when 1
9
+ 2
10
+ when 2
11
+ 10
12
+ when 3
13
+ 9
14
+ else
15
+ 11
16
+ end
17
+ end
18
+ '
19
+ end
20
+
21
+ it "should execute" do
22
+ o1 = ::O1.new
23
+ o1.foo(1).should be == 2
24
+ o1.foo(2).should be == 10
25
+ o1.foo(3).should be == 9
26
+ o1.foo(4).should be == 11
27
+ end
28
+
29
+ class ::O2
30
+ fastruby '
31
+ def foo(a)
32
+ case a
33
+ when 34
34
+ 32
35
+ end
36
+ end
37
+ '
38
+ end
39
+
40
+ it "should return nil when any option is matched" do
41
+ o2 = ::O2.new
42
+ o2.foo(1).should be == nil
43
+ end
44
+
45
+ class ::O3
46
+ fastruby '
47
+ def foo(a,b,c,d)
48
+ case a
49
+ when b
50
+ 32
51
+ when c
52
+ 15
53
+ when d
54
+ 16
55
+ end
56
+ end
57
+ '
58
+ end
59
+
60
+ it "should call === on each comparison" do
61
+ obj = Object.new
62
+
63
+ b = ""
64
+ c = ""
65
+ d = ""
66
+
67
+ b.should_receive(:===).with(obj)
68
+ c.should_receive(:===).with(obj)
69
+ d.should_receive(:===).with(obj)
70
+
71
+ o3 = ::O3.new
72
+ o3.foo(obj,b,c,d).should be == nil
73
+ end
74
+
75
+ class ::O4
76
+ fastruby '
77
+ def foo(a)
78
+ case a
79
+ when 1,3
80
+ 2
81
+ when 2,4
82
+ 10
83
+ end
84
+ end
85
+ '
86
+ end
87
+
88
+ it "should execute case with arrays in when" do
89
+ o4 = ::O4.new
90
+ o4.foo(1).should be == 2
91
+ o4.foo(2).should be == 10
92
+ o4.foo(3).should be == 2
93
+ o4.foo(4).should be == 10
94
+ end
95
+
96
+ class ::O5
97
+ fastruby '
98
+ def foo(a)
99
+ case a
100
+ when /a/
101
+ 2
102
+ else
103
+ nil
104
+ end
105
+ end
106
+ '
107
+ end
108
+
109
+ it "should execute case with regular expressions" do
110
+ o5 = ::O5.new
111
+ o5.foo("aaa").should be == 2
112
+ end
113
+
114
+
115
+ class ::O6
116
+ fastruby '
117
+ def foo(a)
118
+ case a
119
+ when 5..10
120
+ 2
121
+ else
122
+ nil
123
+ end
124
+ end
125
+ '
126
+ end
127
+
128
+ it "should execute case with ranges" do
129
+ o6 = ::O6.new
130
+
131
+ (5..10).each do |i|
132
+ o6.foo(i).should be == 2
133
+ end
134
+ end
135
+
136
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastruby
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 21
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 4
10
- version: 0.0.4
9
+ - 5
10
+ version: 0.0.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Dario Seminara
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-08-14 00:00:00 -03:00
18
+ date: 2011-08-20 00:00:00 -03:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -89,6 +89,7 @@ files:
89
89
  - spec/block/next_spec.rb
90
90
  - spec/block/break_spec.rb
91
91
  - spec/block_spec.rb
92
+ - spec/flow_control/case_spec.rb
92
93
  - spec/sugar_spec.rb
93
94
  - spec/literal_spec.rb
94
95
  - spec/singleton_spec.rb