fastruby 0.0.14 → 0.0.15
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 +12 -0
- data/README +0 -2
- data/Rakefile +1 -1
- data/benchmarks/benchmark.rb +1 -0
- data/benchmarks/benchmark5.rb +3 -1
- data/ext/fastruby_base/fastruby_base.inl +2 -0
- data/lib/fastruby/builder.rb +18 -42
- data/lib/fastruby/exceptions.rb +8 -0
- data/lib/fastruby/getlocals.rb +17 -0
- data/lib/fastruby/object.rb +1 -31
- data/lib/fastruby/translator/modules/block.rb +44 -22
- data/lib/fastruby/translator/modules/call.rb +25 -1
- data/lib/fastruby/translator/modules/defn.rb +85 -57
- data/lib/fastruby/translator/modules/iter.rb +159 -46
- data/lib/fastruby/translator/modules/method_group.rb +7 -0
- data/lib/fastruby/translator/translator.rb +224 -245
- data/lib/fastruby.rb +1 -1
- data/lib/targetted +84 -0
- data/spec/block/arguments_spec.rb +214 -0
- data/spec/block/block_as_proc_spec.rb +98 -0
- data/spec/block/callcc_spec.rb +233 -0
- data/spec/block/proc_as_block_spec.rb +111 -0
- data/spec/call/base_call_spec.rb +3 -2
- data/spec/defn/default_args_spec.rb +303 -0
- data/spec/defn/multiple_args_spec.rb +35 -0
- data/spec/exception/base_spec.rb +26 -0
- metadata +10 -4
data/lib/fastruby.rb
CHANGED
data/lib/targetted
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
fastruby/translator/modules/variable.rb 27| "rb_cvar_get(CLASS_OF(plocals->self) != rb_cClass ? CLASS_OF(plocals->self) : plocals->self,#{intern_num tree[1]})"
|
2
|
+
fastruby/translator/modules/variable.rb 31| "__rb_cvar_set(CLASS_OF(plocals->self) != rb_cClass ? CLASS_OF(plocals->self) : plocals->self,#{intern_num tree[1]},#{to_c tree[2]},Qfalse)"
|
3
|
+
fastruby/translator/modules/variable.rb 55| "rb_const_get(CLASS_OF(plocals->self), #{intern_num(tree[1])})"
|
4
|
+
fastruby/translator/modules/variable.rb 166| "rb_ivar_defined(plocals->self,#{intern_num tree[1][1]}) ? #{literal_value "instance-variable"} : Qnil"
|
5
|
+
fastruby/translator/modules/defn.rb 44| rb_define_method(plocals->self, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1 );
|
6
|
+
fastruby/translator/modules/defn.rb 46| #{global_klass_variable} = plocals->self;
|
7
|
+
fastruby/translator/modules/method_group.rb 116| plocals->active = Qtrue;
|
8
|
+
fastruby/translator/modules/method_group.rb 117| plocals->self = self;
|
9
|
+
fastruby/translator/modules/method_group.rb 118| plocals->targetted = Qfalse;
|
10
|
+
fastruby/translator/modules/method_group.rb 119| plocals->call_frame = LONG2FIX(0);
|
11
|
+
fastruby/translator/modules/method_group.rb 130| plocals->active = Qfalse;
|
12
|
+
fastruby/translator/modules/iter.rb 106| str_arg_initialization << "plocals->#{args_tree[1]} = arg;"
|
13
|
+
fastruby/translator/modules/iter.rb 128| str_arg_initialization << "plocals->#{arguments[i].last} = rb_ary_entry(arg,#{i});\n"
|
14
|
+
fastruby/translator/modules/iter.rb 130| str_arg_initialization << "plocals->#{arg.last.last} = rb_ary_new2(RARRAY(arg)->len-#{i});\n
|
15
|
+
fastruby/translator/modules/iter.rb 134| rb_ary_store(plocals->#{arg.last.last},i-#{i},rb_ary_entry(arg,i));
|
16
|
+
fastruby/translator/modules/iter.rb 146| str_recv = "plocals->self" unless recv_tree
|
17
|
+
fastruby/translator/modules/iter.rb 199| str_recv = "plocals->self" unless recv_tree
|
18
|
+
fastruby/translator/modules/iter.rb 276| if (plocals->targetted == 1) {
|
19
|
+
fastruby/translator/modules/iter.rb 334| if (plocals->targetted == 1) {
|
20
|
+
fastruby/translator/modules/iter.rb 335| if (plocals->active == Qfalse) {
|
21
|
+
fastruby/translator/modules/iter.rb 336| printf(\"return plocals->active == Qfalse\\n\");
|
22
|
+
fastruby/translator/modules/iter.rb 340| printf(\"return plocals->active == Qtrue\\n\");
|
23
|
+
fastruby/translator/modules/iter.rb 447| fastruby_str_arg_initialization = "plocals->#{args_tree[1]} = argv[0];"
|
24
|
+
fastruby/translator/modules/iter.rb 454| fastruby_str_arg_initialization << "plocals->#{arg.last} = #{i} < argc ? argv[#{i}] : Qnil;\n"
|
25
|
+
fastruby/translator/modules/iter.rb 456| fastruby_str_arg_initialization << "plocals->#{arg.last.last} = rb_ary_new2(#{arguments.size-1-i});\n
|
26
|
+
fastruby/translator/modules/iter.rb 460| rb_ary_store(plocals->#{arg.last.last},i-#{i},argv[i]);
|
27
|
+
fastruby/translator/modules/iter.rb 513| str_recv = "plocals->self"
|
28
|
+
fastruby/translator/modules/iter.rb 537| VALUE old_call_frame = plocals->call_frame;
|
29
|
+
fastruby/translator/modules/iter.rb 538| plocals->call_frame = LONG2FIX(&call_frame);
|
30
|
+
fastruby/translator/modules/iter.rb 551| plocals->call_frame = old_call_frame;
|
31
|
+
fastruby/translator/modules/iter.rb 561| pframe->next_recv = #{recv_tree ? to_c(recv_tree) : "plocals->self"};
|
32
|
+
fastruby/translator/modules/iter.rb 649| plocals->call_frame = old_call_frame;
|
33
|
+
fastruby/translator/modules/iter.rb 658| plocals->call_frame = old_call_frame;
|
34
|
+
fastruby/translator/modules/block.rb 36| if (FIX2LONG(plocals->block_function_address) == 0) {
|
35
|
+
fastruby/translator/modules/block.rb 39| return ((VALUE(*)(int,VALUE*,VALUE,VALUE))FIX2LONG(plocals->block_function_address))(size, block_args, FIX2LONG(plocals->block_function_param), (VALUE)pframe);
|
36
|
+
fastruby/translator/modules/nonlocal.rb 27| plocals->return_value = #{to_c(tree[1])};
|
37
|
+
fastruby/translator/modules/nonlocal.rb 28| plocals->targetted = 1;
|
38
|
+
fastruby/translator/modules/nonlocal.rb 41| target_frame_ = (void*)FIX2LONG(plocals->call_frame);
|
39
|
+
fastruby/translator/modules/nonlocal.rb 47| plocals->call_frame = LONG2FIX(0);
|
40
|
+
fastruby/translator/modules/nonlocal.rb 60| target_frame_ = (void*)FIX2LONG(plocals->call_frame);
|
41
|
+
fastruby/translator/translator.rb 189| VALUE old_call_frame = plocals->call_frame;
|
42
|
+
fastruby/translator/translator.rb 190| plocals->call_frame = LONG2FIX(&call_frame);
|
43
|
+
fastruby/translator/translator.rb 202| plocals->call_frame = old_call_frame;
|
44
|
+
fastruby/translator/translator.rb 208| plocals->call_frame = old_call_frame;
|
45
|
+
fastruby/translator/translator.rb 219| plocals->call_frame = old_call_frame;
|
46
|
+
fastruby/translator/translator.rb 372| plocals->active = Qtrue;
|
47
|
+
fastruby/translator/translator.rb 373| plocals->targetted = Qfalse;
|
48
|
+
fastruby/translator/translator.rb 374| plocals->pframe = LONG2FIX(&frame);
|
49
|
+
fastruby/translator/translator.rb 390| printf(\"plocals->active = Qfalse\\n\");
|
50
|
+
fastruby/translator/translator.rb 391| plocals->active = Qfalse;
|
51
|
+
fastruby/translator/translator.rb 392| return plocals->return_value;
|
52
|
+
fastruby/translator/translator.rb 395| plocals->self = self;
|
53
|
+
fastruby/translator/translator.rb 400| "plocals->#{arg} = #{arg};\n"
|
54
|
+
fastruby/translator/translator.rb 403| plocals->block_function_address = LONG2FIX(0);
|
55
|
+
fastruby/translator/translator.rb 404| plocals->block_function_param = LONG2FIX(Qnil);
|
56
|
+
fastruby/translator/translator.rb 405| plocals->call_frame = LONG2FIX(0);
|
57
|
+
fastruby/translator/translator.rb 415| printf(\"plocals->active = Qfalse\\n\");
|
58
|
+
fastruby/translator/translator.rb 416| plocals->active = Qfalse;
|
59
|
+
fastruby/translator/translator.rb 494| "plocals->#{arg} = argv[#{i}];\n"
|
60
|
+
fastruby/translator/translator.rb 516| plocals->#{splat_arg.to_s.gsub("*","")} = rb_ary_new3(0);
|
61
|
+
fastruby/translator/translator.rb 520| plocals->#{splat_arg.to_s.gsub("*","")} = rb_ary_new4(
|
62
|
+
fastruby/translator/translator.rb 537| plocals->#{block_argument.to_s.gsub("&","")} = #{to_c proc_reyield_block_tree.to_fastruby_sexp};
|
63
|
+
fastruby/translator/translator.rb 583| plocals->active = Qtrue;
|
64
|
+
fastruby/translator/translator.rb 584| plocals->targetted = Qfalse;
|
65
|
+
fastruby/translator/translator.rb 585| plocals->pframe = LONG2FIX(&frame);
|
66
|
+
fastruby/translator/translator.rb 586| plocals->call_frame = LONG2FIX(0);
|
67
|
+
fastruby/translator/translator.rb 597| printf(\"plocals->active = Qfalse\\n\");
|
68
|
+
fastruby/translator/translator.rb 598| plocals->active = Qfalse;
|
69
|
+
fastruby/translator/translator.rb 607| if (plocals->targetted == Qfalse) {
|
70
|
+
fastruby/translator/translator.rb 615| return plocals->return_value;
|
71
|
+
fastruby/translator/translator.rb 618| plocals->self = self;
|
72
|
+
fastruby/translator/translator.rb 624| plocals->block_function_address = LONG2FIX(pblock->block_function_address);
|
73
|
+
fastruby/translator/translator.rb 625| plocals->block_function_param = LONG2FIX(pblock->block_function_param);
|
74
|
+
fastruby/translator/translator.rb 627| plocals->block_function_address = LONG2FIX(0);
|
75
|
+
fastruby/translator/translator.rb 628| plocals->block_function_param = LONG2FIX(Qnil);
|
76
|
+
fastruby/translator/translator.rb 639| printf(\"plocals->active = Qfalse\\n\");
|
77
|
+
fastruby/translator/translator.rb 640| plocals->active = Qfalse;
|
78
|
+
fastruby/translator/translator.rb 656| "plocals->"
|
79
|
+
fastruby/translator/translator.rb 721| return "FIX2LONG(plocals->block_function_address) == 0 ? Qfalse : Qtrue"
|
80
|
+
fastruby/translator/translator.rb 935| plocals->pframe = LONG2FIX(&frame);
|
81
|
+
fastruby/translator/translator.rb 936| plocals->targetted = Qfalse;
|
82
|
+
fastruby/translator/translator.rb 946| if (plocals->targetted == Qfalse) {
|
83
|
+
fastruby/translator/translator.rb 950| return plocals->return_value;
|
84
|
+
fastruby/translator/translator.rb 953| plocals->self = self;
|
@@ -0,0 +1,214 @@
|
|
1
|
+
require "fastruby"
|
2
|
+
|
3
|
+
describe FastRuby, "fastruby" do
|
4
|
+
class ::VO1
|
5
|
+
fastruby "
|
6
|
+
def foo(x)
|
7
|
+
yield(*x)
|
8
|
+
end
|
9
|
+
"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should allow pass splat arguments to yield" do
|
13
|
+
::VO1.new.foo([1,2,3]) do |x,y,z|
|
14
|
+
x.should be == 1
|
15
|
+
y.should be == 2
|
16
|
+
z.should be == 3
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class ::VO2
|
21
|
+
fastruby "
|
22
|
+
def foo(x)
|
23
|
+
yield(1,*x)
|
24
|
+
end
|
25
|
+
"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should allow pass normal and splat arguments to yield" do
|
29
|
+
::VO2.new.foo([2,3,4]) do |a,x,y,z|
|
30
|
+
a.should be == 1
|
31
|
+
x.should be == 2
|
32
|
+
y.should be == 3
|
33
|
+
z.should be == 4
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class ::VO3
|
38
|
+
fastruby "
|
39
|
+
def foo(x)
|
40
|
+
yield(1,2,*x)
|
41
|
+
end
|
42
|
+
"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should allow pass two normal args and one splat argument to yield" do
|
46
|
+
::VO3.new.foo([3,4,5]) do |a,b,x,y,z|
|
47
|
+
a.should be == 1
|
48
|
+
b.should be == 2
|
49
|
+
x.should be == 3
|
50
|
+
y.should be == 4
|
51
|
+
z.should be == 5
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should take only the object argument when trying to splat a non-array" do
|
56
|
+
::VO1.new.foo("non-array") do |x|
|
57
|
+
x.should be == "non-array"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class ::VO4
|
62
|
+
|
63
|
+
def bar
|
64
|
+
yield(1,2,3,4)
|
65
|
+
end
|
66
|
+
|
67
|
+
fastruby "
|
68
|
+
def foo
|
69
|
+
bar do |*y|
|
70
|
+
y
|
71
|
+
end
|
72
|
+
end
|
73
|
+
"
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should allow masgn arguments on block passes" do
|
77
|
+
::VO4.new.foo.should be == [1,2,3,4]
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
class ::VO5
|
82
|
+
|
83
|
+
fastruby "
|
84
|
+
def bar
|
85
|
+
yield(1,2,3,4)
|
86
|
+
end
|
87
|
+
|
88
|
+
def foo
|
89
|
+
bar do |*y|
|
90
|
+
y
|
91
|
+
end
|
92
|
+
end
|
93
|
+
"
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should allow masgn arguments on block passes (fastruby call)" do
|
97
|
+
::VO5.new.foo.should be == [1,2,3,4]
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
class ::VO6
|
102
|
+
|
103
|
+
def bar
|
104
|
+
yield(1,2,3,4)
|
105
|
+
end
|
106
|
+
|
107
|
+
fastruby "
|
108
|
+
def foo
|
109
|
+
bar do |a,b,*y|
|
110
|
+
y
|
111
|
+
end
|
112
|
+
end
|
113
|
+
"
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should allow normal arguments with masgn arguments on block passes" do
|
117
|
+
::VO6.new.foo.should be == [3,4]
|
118
|
+
end
|
119
|
+
|
120
|
+
class ::VO7
|
121
|
+
fastruby "
|
122
|
+
def foo
|
123
|
+
pr = proc do |*x|
|
124
|
+
x
|
125
|
+
end
|
126
|
+
pr.call(32)
|
127
|
+
end
|
128
|
+
"
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should allow splat arguments on proc block" do
|
132
|
+
::VO7.new.foo.should be == [32]
|
133
|
+
end
|
134
|
+
|
135
|
+
class ::VO8
|
136
|
+
fastruby "
|
137
|
+
def foo
|
138
|
+
pr = proc do |*x|
|
139
|
+
x
|
140
|
+
end
|
141
|
+
pr.call(32,33,34)
|
142
|
+
end
|
143
|
+
"
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should allow multiple splat arguments on proc block" do
|
147
|
+
::VO8.new.foo.should be == [32,33,34]
|
148
|
+
end
|
149
|
+
|
150
|
+
class ::VO9
|
151
|
+
def bar
|
152
|
+
yield(32)
|
153
|
+
end
|
154
|
+
fastruby "
|
155
|
+
def foo
|
156
|
+
bar do |x|
|
157
|
+
x
|
158
|
+
end
|
159
|
+
end
|
160
|
+
"
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should read single argument on block" do
|
164
|
+
::VO9.new.foo.should be == 32
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
class ::VO10
|
169
|
+
fastruby "
|
170
|
+
def foo
|
171
|
+
pr = proc do |*x|
|
172
|
+
x
|
173
|
+
end
|
174
|
+
pr.call([32])
|
175
|
+
end
|
176
|
+
"
|
177
|
+
end
|
178
|
+
|
179
|
+
it "should allow splat arguments on proc block when the argument is an array" do
|
180
|
+
::VO10.new.foo.should be == [[32]]
|
181
|
+
end
|
182
|
+
|
183
|
+
|
184
|
+
class ::VO11
|
185
|
+
fastruby "
|
186
|
+
def foo
|
187
|
+
pr = proc do |*x|
|
188
|
+
x
|
189
|
+
end
|
190
|
+
pr.call([])
|
191
|
+
end
|
192
|
+
"
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should allow splat arguments on proc block when the argument is an array empty" do
|
196
|
+
::VO11.new.foo.should be == [[]]
|
197
|
+
end
|
198
|
+
|
199
|
+
class ::VO12
|
200
|
+
fastruby "
|
201
|
+
def foo
|
202
|
+
pr = proc do |*x|
|
203
|
+
x
|
204
|
+
end
|
205
|
+
pr.call()
|
206
|
+
end
|
207
|
+
"
|
208
|
+
end
|
209
|
+
|
210
|
+
it "should allow splat arguments on proc block when no arguments are passed" do
|
211
|
+
::VO12.new.foo.should be == []
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require "fastruby"
|
2
|
+
|
3
|
+
describe FastRuby, "fastruby" do
|
4
|
+
class ::VYE1
|
5
|
+
fastruby "
|
6
|
+
def foo(&block)
|
7
|
+
end
|
8
|
+
"
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should allow method receiveing block" do
|
12
|
+
lambda {
|
13
|
+
::VYE1.new.foo do
|
14
|
+
|
15
|
+
end
|
16
|
+
}.should_not raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
class ::VYE2
|
20
|
+
fastruby "
|
21
|
+
def foo(&block)
|
22
|
+
block.call
|
23
|
+
end
|
24
|
+
"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should allow call block" do
|
28
|
+
lambda {
|
29
|
+
executed = 0
|
30
|
+
::VYE2.new.foo do
|
31
|
+
executed = 1
|
32
|
+
end
|
33
|
+
|
34
|
+
executed.should be == 1
|
35
|
+
}.should_not raise_error
|
36
|
+
end
|
37
|
+
|
38
|
+
class ::VYE3
|
39
|
+
fastruby "
|
40
|
+
def foo(&block)
|
41
|
+
block.call(64)
|
42
|
+
end
|
43
|
+
"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should allow call block with argument" do
|
47
|
+
lambda {
|
48
|
+
recv_a = 0
|
49
|
+
::VYE3.new.foo do |a|
|
50
|
+
recv_a = a
|
51
|
+
end
|
52
|
+
|
53
|
+
recv_a.should be == 64
|
54
|
+
}.should_not raise_error
|
55
|
+
end
|
56
|
+
|
57
|
+
class ::VYEE
|
58
|
+
end
|
59
|
+
|
60
|
+
class ::VYE4
|
61
|
+
fastruby "
|
62
|
+
def bar(x)
|
63
|
+
def x.foo(&block)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should allow singleton method receiveing block" do
|
70
|
+
x = ::VYEE.new
|
71
|
+
::VYE4.new.bar(x)
|
72
|
+
x.foo do
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class ::VYE5
|
77
|
+
fastruby "
|
78
|
+
def bar(x)
|
79
|
+
def x.foo(&block)
|
80
|
+
block.call
|
81
|
+
end
|
82
|
+
end
|
83
|
+
"
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should allow singleton method receiveing and call block" do
|
87
|
+
x = ::VYEE.new
|
88
|
+
::VYE5.new.bar(x)
|
89
|
+
|
90
|
+
executed = 0
|
91
|
+
x.foo do
|
92
|
+
executed = 1
|
93
|
+
end
|
94
|
+
|
95
|
+
executed.should be == 1
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,233 @@
|
|
1
|
+
require "fastruby"
|
2
|
+
|
3
|
+
describe FastRuby, "fastruby" do
|
4
|
+
class ::N1
|
5
|
+
fastruby "
|
6
|
+
def bar(cc)
|
7
|
+
cc.call(75)
|
8
|
+
end
|
9
|
+
|
10
|
+
def foo
|
11
|
+
callcc do |cc|
|
12
|
+
bar(cc)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should execute callcc on fastruby" do
|
19
|
+
::N1.new.foo.should be == 75
|
20
|
+
end
|
21
|
+
|
22
|
+
class ::N2
|
23
|
+
def bar(cc)
|
24
|
+
cc.call(76)
|
25
|
+
end
|
26
|
+
|
27
|
+
fastruby "
|
28
|
+
def foo
|
29
|
+
callcc do |cc|
|
30
|
+
bar(cc)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should execute callcc from ruby" do
|
37
|
+
::N2.new.foo.should be == 76
|
38
|
+
end
|
39
|
+
|
40
|
+
class ::N3
|
41
|
+
fastruby "
|
42
|
+
def foo(n_)
|
43
|
+
n = n_
|
44
|
+
|
45
|
+
val = 0
|
46
|
+
cc = nil
|
47
|
+
|
48
|
+
x = callcc{|c| cc = c; nil}
|
49
|
+
|
50
|
+
val = val + x if x
|
51
|
+
n = n - 1
|
52
|
+
|
53
|
+
cc.call(n) if n > 0
|
54
|
+
|
55
|
+
val
|
56
|
+
end
|
57
|
+
"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should execute callcc from ruby using local variables" do
|
61
|
+
::N3.new.foo(4).should be == 6
|
62
|
+
end
|
63
|
+
|
64
|
+
class ::N4
|
65
|
+
fastruby "
|
66
|
+
def foo(n_)
|
67
|
+
$n = n_
|
68
|
+
|
69
|
+
$val = 0
|
70
|
+
c = 0
|
71
|
+
|
72
|
+
|
73
|
+
x = callcc{|c| $cc_n4 = c; nil}
|
74
|
+
|
75
|
+
$val = $val + x if x
|
76
|
+
$n = $n - 1
|
77
|
+
|
78
|
+
$cc_n4.call($n) if $n > 0
|
79
|
+
|
80
|
+
$val
|
81
|
+
end
|
82
|
+
"
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should execute callcc from ruby using global variables" do
|
86
|
+
::N4.new.foo(4).should be == 6
|
87
|
+
end
|
88
|
+
|
89
|
+
class ::N5
|
90
|
+
fastruby "
|
91
|
+
def foo(n_)
|
92
|
+
$n = n_
|
93
|
+
|
94
|
+
$val = 0
|
95
|
+
c = 0
|
96
|
+
u = nil
|
97
|
+
|
98
|
+
x = callcc{|c| $cc_n4 = c; u = 44; nil}
|
99
|
+
|
100
|
+
$val = $val + x if x
|
101
|
+
$n = $n - 1
|
102
|
+
|
103
|
+
$cc_n4.call($n) if $n > 0
|
104
|
+
|
105
|
+
u
|
106
|
+
end
|
107
|
+
"
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should execute callcc loops and preserve local variables" do
|
111
|
+
::N5.new.foo(4).should be == 44
|
112
|
+
end
|
113
|
+
|
114
|
+
class ::N6
|
115
|
+
fastruby "
|
116
|
+
|
117
|
+
def bar
|
118
|
+
a = 5555
|
119
|
+
|
120
|
+
callcc do |cc|
|
121
|
+
$cc = cc
|
122
|
+
end
|
123
|
+
|
124
|
+
a
|
125
|
+
end
|
126
|
+
|
127
|
+
def another_method(n)
|
128
|
+
a = 9999
|
129
|
+
another_method(n-1) if n>0
|
130
|
+
end
|
131
|
+
|
132
|
+
def foo
|
133
|
+
|
134
|
+
$called = nil
|
135
|
+
|
136
|
+
ret = bar
|
137
|
+
another_method(200)
|
138
|
+
|
139
|
+
unless $called
|
140
|
+
$called = 1
|
141
|
+
$cc.call
|
142
|
+
end
|
143
|
+
|
144
|
+
ret
|
145
|
+
end
|
146
|
+
"
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should execute callcc loops and preserve local variables when another method is called after callcc" do
|
150
|
+
::N6.new.foo.should be == 5555
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
it "shouldn't raise LocalJumpError from proc being called on callcc de-initialized stack" do
|
155
|
+
|
156
|
+
fastruby <<ENDSTR
|
157
|
+
|
158
|
+
class ::N7
|
159
|
+
def foo
|
160
|
+
val = nil
|
161
|
+
|
162
|
+
pr = Proc.new do
|
163
|
+
return val
|
164
|
+
end
|
165
|
+
|
166
|
+
val = callcc do |cc|
|
167
|
+
$cc = cc
|
168
|
+
end
|
169
|
+
|
170
|
+
pr.call
|
171
|
+
end
|
172
|
+
|
173
|
+
def bar
|
174
|
+
ret = foo
|
175
|
+
|
176
|
+
if ret.instance_of? Continuation
|
177
|
+
ret.call(4)
|
178
|
+
else
|
179
|
+
$cc.call(ret-1) if ret > 0
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
ENDSTR
|
185
|
+
|
186
|
+
|
187
|
+
n7 = ::N7.new
|
188
|
+
lambda {
|
189
|
+
n7.bar
|
190
|
+
}.should_not raise_error(LocalJumpError)
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should raise LocalJumpError from proc defined on abandoned stack after Continuation#call" do
|
194
|
+
|
195
|
+
fastruby <<ENDSTR
|
196
|
+
class ::N8
|
197
|
+
def bar
|
198
|
+
ret = callcc do |cc|
|
199
|
+
$cc_n8 = cc
|
200
|
+
end
|
201
|
+
|
202
|
+
if ret == 9
|
203
|
+
$pr_n8.call
|
204
|
+
end
|
205
|
+
|
206
|
+
ret
|
207
|
+
end
|
208
|
+
|
209
|
+
def foo3
|
210
|
+
$cc_n8.call(9)
|
211
|
+
end
|
212
|
+
|
213
|
+
def foo2
|
214
|
+
$pr_n8 = Proc.new do
|
215
|
+
return
|
216
|
+
end
|
217
|
+
|
218
|
+
foo3
|
219
|
+
end
|
220
|
+
|
221
|
+
def foo
|
222
|
+
return if bar == 9
|
223
|
+
foo2
|
224
|
+
end
|
225
|
+
end
|
226
|
+
ENDSTR
|
227
|
+
|
228
|
+
n8 = ::N8.new
|
229
|
+
lambda {
|
230
|
+
n8.foo
|
231
|
+
}.should raise_error(LocalJumpError)
|
232
|
+
end
|
233
|
+
end
|