mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* vm.c, vm_insnhelper.c: fix escape process with "braek" and "return"
syntax in "lambda". [ ruby-Bugs-19304 ], [ruby-core:17164] * KNOWNBUGS.rb, bootstraptest/test_proc.rb: add/move solved test. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17390 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
e2f37fb9c6
commit
00e4fd42f3
5 changed files with 125 additions and 23 deletions
|
@ -1,3 +1,10 @@
|
||||||
|
Wed Jun 18 04:24:20 2008 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
|
* vm.c, vm_insnhelper.c: fix escape process with "braek" and "return"
|
||||||
|
syntax in "lambda". [ ruby-Bugs-19304 ], [ruby-core:17164]
|
||||||
|
|
||||||
|
* KNOWNBUGS.rb, bootstraptest/test_proc.rb: add/move solved test.
|
||||||
|
|
||||||
Wed Jun 18 01:51:10 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
|
Wed Jun 18 01:51:10 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
|
||||||
|
|
||||||
* ext/tk/lib/multi-tk.rb: cannot access class variable from
|
* ext/tk/lib/multi-tk.rb: cannot access class variable from
|
||||||
|
|
21
KNOWNBUGS.rb
21
KNOWNBUGS.rb
|
@ -3,15 +3,18 @@
|
||||||
# So all tests will cause failure.
|
# So all tests will cause failure.
|
||||||
#
|
#
|
||||||
|
|
||||||
assert_equal %q{[:bar, :foo]}, %q{
|
assert_equal 'A', %q{
|
||||||
def foo
|
class A
|
||||||
klass = Class.new do
|
@@a = 'A'
|
||||||
define_method(:bar) do
|
def a=(x)
|
||||||
return :bar
|
@@a = x
|
||||||
end
|
end
|
||||||
|
def a
|
||||||
|
@@a
|
||||||
end
|
end
|
||||||
[klass.new.bar, :foo]
|
|
||||||
end
|
end
|
||||||
foo
|
|
||||||
}, "[ ruby-Bugs-19304 ]"
|
|
||||||
|
|
||||||
|
B = A.dup
|
||||||
|
B.new.a = 'B'
|
||||||
|
A.new.a
|
||||||
|
}
|
||||||
|
|
|
@ -276,3 +276,91 @@ assert_equal 'ok', %q{
|
||||||
:ng
|
:ng
|
||||||
}.call
|
}.call
|
||||||
}, '[ruby-dev:34646]'
|
}, '[ruby-dev:34646]'
|
||||||
|
|
||||||
|
assert_equal %q{[:bar, :foo]}, %q{
|
||||||
|
def foo
|
||||||
|
klass = Class.new do
|
||||||
|
define_method(:bar) do
|
||||||
|
return :bar
|
||||||
|
end
|
||||||
|
end
|
||||||
|
[klass.new.bar, :foo]
|
||||||
|
end
|
||||||
|
foo
|
||||||
|
}, "[ ruby-Bugs-19304 ]"
|
||||||
|
|
||||||
|
assert_equal 'ok', %q{
|
||||||
|
$x = :ok
|
||||||
|
def def7(x, y)
|
||||||
|
x[y]
|
||||||
|
$x = :ng
|
||||||
|
end
|
||||||
|
def test_def7
|
||||||
|
def7(lambda {|x| x.call}, Proc.new {return})
|
||||||
|
$x = :ng
|
||||||
|
end
|
||||||
|
test_def7
|
||||||
|
$x
|
||||||
|
}, '[ruby-core:17164]'
|
||||||
|
|
||||||
|
assert_equal 'ok', %q{
|
||||||
|
lambda { a = lambda { return }; $x = :ng; a[]; $x = :ok }.call
|
||||||
|
$x
|
||||||
|
}, '[ruby-core:17164]'
|
||||||
|
|
||||||
|
assert_equal 'ok', %q{
|
||||||
|
lambda { a = lambda { break }; $x = :ng; a[]; $x = :ok }.call
|
||||||
|
$x
|
||||||
|
}, '[ruby-core:17164]'
|
||||||
|
|
||||||
|
assert_equal 'ok', %q{
|
||||||
|
def def8
|
||||||
|
$x = :ng
|
||||||
|
lambda { a = Proc.new { return }; a[]}.call
|
||||||
|
$x = :ok
|
||||||
|
end
|
||||||
|
def8
|
||||||
|
$x
|
||||||
|
}, '[ruby-core:17164]'
|
||||||
|
|
||||||
|
|
||||||
|
assert_equal 'ok', %q{
|
||||||
|
def def9
|
||||||
|
lambda {|a| $x = :ok; a[]; $x = :ng }.call(Proc.new { return })
|
||||||
|
$x = :ng
|
||||||
|
end
|
||||||
|
def9
|
||||||
|
$x
|
||||||
|
}, '[ruby-core:17164]'
|
||||||
|
|
||||||
|
assert_equal 'ok', %q{
|
||||||
|
def def10
|
||||||
|
$x = :ng
|
||||||
|
lambda { 1.times { return } }.call
|
||||||
|
$x = :ok
|
||||||
|
end
|
||||||
|
$x = :ok
|
||||||
|
def10
|
||||||
|
$x
|
||||||
|
}, '[ruby-core:17164]'
|
||||||
|
|
||||||
|
assert_equal 'ok', %q{
|
||||||
|
def def11
|
||||||
|
yield
|
||||||
|
end
|
||||||
|
begin
|
||||||
|
lambda { def11 { return } }.call
|
||||||
|
rescue LocalJumpError
|
||||||
|
:ng
|
||||||
|
else
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
}, '[ruby-core:17164]'
|
||||||
|
|
||||||
|
assert_equal 'ok', %q{
|
||||||
|
def def12
|
||||||
|
b = Proc.new { $x = :ng; lambda { return }.call; $x = :ok }.call
|
||||||
|
end
|
||||||
|
def12
|
||||||
|
$x
|
||||||
|
}, '[ruby-core:17164]'
|
||||||
|
|
4
vm.c
4
vm.c
|
@ -525,9 +525,9 @@ vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self,
|
||||||
if (state == TAG_RETURN && proc->is_lambda) {
|
if (state == TAG_RETURN && proc->is_lambda) {
|
||||||
VALUE err = th->errinfo;
|
VALUE err = th->errinfo;
|
||||||
VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
|
VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
|
||||||
VALUE *cdfp = proc->block.dfp;
|
|
||||||
|
|
||||||
if (escape_dfp == cdfp) {
|
if (escape_dfp == cfp->dfp) {
|
||||||
|
printf("ok\n");
|
||||||
state = 0;
|
state = 0;
|
||||||
th->errinfo = Qnil;
|
th->errinfo = Qnil;
|
||||||
th->cfp = cfp;
|
th->cfp = cfp;
|
||||||
|
|
|
@ -1044,7 +1044,8 @@ vm_get_cvar_base(NODE *cref)
|
||||||
{
|
{
|
||||||
VALUE klass;
|
VALUE klass;
|
||||||
|
|
||||||
while (cref && cref->nd_next && (NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON))) {
|
while (cref && cref->nd_next &&
|
||||||
|
(NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON))) {
|
||||||
cref = cref->nd_next;
|
cref = cref->nd_next;
|
||||||
|
|
||||||
if (!cref->nd_next) {
|
if (!cref->nd_next) {
|
||||||
|
@ -1221,7 +1222,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
||||||
if (cfp->dfp == dfp) {
|
if (cfp->dfp == dfp) {
|
||||||
goto search_parent;
|
goto search_parent;
|
||||||
}
|
}
|
||||||
cfp++;
|
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||||
}
|
}
|
||||||
rb_bug("VM (throw): can't find break base.");
|
rb_bug("VM (throw): can't find break base.");
|
||||||
}
|
}
|
||||||
|
@ -1229,7 +1230,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
||||||
if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
|
if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
|
||||||
/* lambda{... break ...} */
|
/* lambda{... break ...} */
|
||||||
is_orphan = 0;
|
is_orphan = 0;
|
||||||
pt = GET_LFP();
|
pt = cfp->dfp;
|
||||||
state = TAG_RETURN;
|
state = TAG_RETURN;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1261,7 +1262,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
||||||
is_orphan = 0;
|
is_orphan = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cfp++;
|
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1284,26 +1285,29 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
||||||
* check orphan:
|
* check orphan:
|
||||||
*/
|
*/
|
||||||
while ((VALUE *) cfp < th->stack + th->stack_size) {
|
while ((VALUE *) cfp < th->stack + th->stack_size) {
|
||||||
if (GET_DFP() == dfp) {
|
if (dfp == cfp->dfp) {
|
||||||
if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
|
if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
|
||||||
/* in lambda */
|
/* in lambda */
|
||||||
is_orphan = 0;
|
is_orphan = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GET_LFP() == dfp && cfp->iseq->type == ISEQ_TYPE_METHOD) {
|
||||||
|
is_orphan = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dfp = GC_GUARDED_PTR_REF(dfp[0]);
|
||||||
}
|
}
|
||||||
if (GET_LFP() == cfp->lfp &&
|
|
||||||
cfp->iseq->type == ISEQ_TYPE_METHOD) {
|
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||||
is_orphan = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cfp++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_orphan) {
|
if (is_orphan) {
|
||||||
vm_localjump_error("unexpected return", throwobj, TAG_RETURN);
|
vm_localjump_error("unexpected return", throwobj, TAG_RETURN);
|
||||||
}
|
}
|
||||||
|
|
||||||
pt = GET_LFP();
|
pt = dfp;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rb_bug("isns(throw): unsupport throw type");
|
rb_bug("isns(throw): unsupport throw type");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue