fastruby 0.0.4 → 0.0.5

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