mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* eval.c (proc_invoke): prepare to pass a block from "call" method
to a Proc generated by Method#to_proc. [ruby-dev:25031] * eval.c (rb_yield_0): actually passes a block given to "call". * object.c (convert_type): use rb_respond_to() again. this fix is based on [ruby-dev:25021] * eval.c (rb_respond_to): funcall respond_to? if it's redefined. [ruby-dev:25021] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7446 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
da4884e2d4
commit
405a50a594
4 changed files with 63 additions and 28 deletions
13
ChangeLog
13
ChangeLog
|
@ -20,6 +20,19 @@ Fri Dec 3 01:55:24 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
|
||||||
|
|
||||||
* ext/tk/sample/demos-jp/widget: ditto.
|
* ext/tk/sample/demos-jp/widget: ditto.
|
||||||
|
|
||||||
|
Fri Dec 3 00:21:05 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
|
* eval.c (proc_invoke): prepare to pass a block from "call" method
|
||||||
|
to a Proc generated by Method#to_proc. [ruby-dev:25031]
|
||||||
|
|
||||||
|
* eval.c (rb_yield_0): actually passes a block given to "call".
|
||||||
|
|
||||||
|
* object.c (convert_type): use rb_respond_to() again. this fix is
|
||||||
|
based on [ruby-dev:25021]
|
||||||
|
|
||||||
|
* eval.c (rb_respond_to): funcall respond_to? if it's redefined.
|
||||||
|
[ruby-dev:25021]
|
||||||
|
|
||||||
Thu Dec 2 15:13:53 2004 Michael Neumann <mneumann@ruby-lang.org>
|
Thu Dec 2 15:13:53 2004 Michael Neumann <mneumann@ruby-lang.org>
|
||||||
|
|
||||||
* test/xmlrpc/test_parser.rb, test/xmlrpc/data/*.expected: Expected
|
* test/xmlrpc/test_parser.rb, test/xmlrpc/data/*.expected: Expected
|
||||||
|
|
54
eval.c
54
eval.c
|
@ -312,7 +312,7 @@ rb_clear_cache_by_class(klass)
|
||||||
|
|
||||||
static ID init, eqq, each, aref, aset, match, missing;
|
static ID init, eqq, each, aref, aset, match, missing;
|
||||||
static ID added, singleton_added;
|
static ID added, singleton_added;
|
||||||
static ID __id__, __send__;
|
static ID __id__, __send__, respond_to;
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_add_method(klass, mid, node, noex)
|
rb_add_method(klass, mid, node, noex)
|
||||||
|
@ -1006,7 +1006,8 @@ static VALUE rb_yield_0 _((VALUE, VALUE, VALUE, int, int));
|
||||||
|
|
||||||
#define YIELD_LAMBDA_CALL 1
|
#define YIELD_LAMBDA_CALL 1
|
||||||
#define YIELD_PROC_CALL 2
|
#define YIELD_PROC_CALL 2
|
||||||
#define YIELD_PUBLIC_DEF 4
|
#define YIELD_PROC_BLOCK 4
|
||||||
|
#define YIELD_PUBLIC_DEF 8
|
||||||
#define YIELD_FUNC_AVALUE 1
|
#define YIELD_FUNC_AVALUE 1
|
||||||
#define YIELD_FUNC_SVALUE 2
|
#define YIELD_FUNC_SVALUE 2
|
||||||
|
|
||||||
|
@ -3922,17 +3923,25 @@ module_setup(module, n)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NODE *basic_respond_to = 0;
|
||||||
|
|
||||||
int
|
int
|
||||||
rb_respond_to(obj, id)
|
rb_respond_to(obj, id)
|
||||||
VALUE obj;
|
VALUE obj;
|
||||||
ID id;
|
ID id;
|
||||||
{
|
{
|
||||||
if (rb_method_boundp(CLASS_OF(obj), id, 0)) {
|
VALUE klass = CLASS_OF(obj);
|
||||||
|
if (rb_method_node(klass, respond_to) == basic_respond_to &&
|
||||||
|
rb_method_boundp(klass, id, 0)) {
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
return rb_funcall(obj, respond_to, 1, ID2SYM(id));
|
||||||
|
}
|
||||||
return Qfalse;
|
return Qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* obj.respond_to?(symbol, include_private=false) => true or false
|
* obj.respond_to?(symbol, include_private=false) => true or false
|
||||||
|
@ -4712,7 +4721,21 @@ rb_yield_0(val, self, klass, flags, avalue)
|
||||||
if (val == Qundef && node->nd_state != YIELD_FUNC_SVALUE)
|
if (val == Qundef && node->nd_state != YIELD_FUNC_SVALUE)
|
||||||
val = Qnil;
|
val = Qnil;
|
||||||
}
|
}
|
||||||
result = (*node->nd_cfnc)(val, node->nd_tval, self);
|
if ((flags&YIELD_PROC_BLOCK) && RTEST(block->block_obj)) {
|
||||||
|
struct BLOCK *data, _block;
|
||||||
|
Data_Get_Struct(block->block_obj, struct BLOCK, data);
|
||||||
|
_block = *data;
|
||||||
|
_block.outer = ruby_block;
|
||||||
|
_block.uniq = block_unique++;
|
||||||
|
ruby_block = &_block;
|
||||||
|
PUSH_ITER(ITER_PRE);
|
||||||
|
ruby_frame->iter = ITER_CUR;
|
||||||
|
result = (*node->nd_cfnc)(val, node->nd_tval, self);
|
||||||
|
POP_ITER();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = (*node->nd_cfnc)(val, node->nd_tval, self);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = rb_eval(self, node);
|
result = rb_eval(self, node);
|
||||||
|
@ -7585,7 +7608,10 @@ Init_eval()
|
||||||
rb_define_global_function("loop", rb_f_loop, 0);
|
rb_define_global_function("loop", rb_f_loop, 0);
|
||||||
|
|
||||||
rb_define_method(rb_mKernel, "respond_to?", rb_obj_respond_to, -1);
|
rb_define_method(rb_mKernel, "respond_to?", rb_obj_respond_to, -1);
|
||||||
|
respond_to = rb_intern("respond_to?");
|
||||||
|
basic_respond_to = rb_method_node(rb_cObject, respond_to);
|
||||||
|
rb_global_variable((VALUE*)&basic_respond_to);
|
||||||
|
|
||||||
rb_define_global_function("raise", rb_f_raise, -1);
|
rb_define_global_function("raise", rb_f_raise, -1);
|
||||||
rb_define_global_function("fail", rb_f_raise, -1);
|
rb_define_global_function("fail", rb_f_raise, -1);
|
||||||
|
|
||||||
|
@ -8164,18 +8190,19 @@ proc_invoke(proc, args, self, klass)
|
||||||
volatile int pcall, avalue = Qtrue;
|
volatile int pcall, avalue = Qtrue;
|
||||||
VALUE bvar = Qnil;
|
VALUE bvar = Qnil;
|
||||||
|
|
||||||
if (rb_block_given_p() && ruby_frame->last_func) {
|
|
||||||
if (klass != ruby_frame->last_class)
|
|
||||||
klass = rb_obj_class(proc);
|
|
||||||
bvar = rb_block_proc();
|
|
||||||
}
|
|
||||||
|
|
||||||
Data_Get_Struct(proc, struct BLOCK, data);
|
Data_Get_Struct(proc, struct BLOCK, data);
|
||||||
pcall = (data->flags & BLOCK_LAMBDA) ? YIELD_LAMBDA_CALL : 0;
|
pcall = (data->flags & BLOCK_LAMBDA) ? YIELD_LAMBDA_CALL : 0;
|
||||||
if (!pcall && RARRAY(args)->len == 1) {
|
if (!pcall && RARRAY(args)->len == 1) {
|
||||||
avalue = Qfalse;
|
avalue = Qfalse;
|
||||||
args = RARRAY(args)->ptr[0];
|
args = RARRAY(args)->ptr[0];
|
||||||
}
|
}
|
||||||
|
if (rb_block_given_p() && ruby_frame->last_func) {
|
||||||
|
if (klass != ruby_frame->last_class)
|
||||||
|
klass = rb_obj_class(proc);
|
||||||
|
bvar = rb_block_proc();
|
||||||
|
pcall |= YIELD_PROC_BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PUSH_VARS();
|
PUSH_VARS();
|
||||||
ruby_wrapper = data->wrapper;
|
ruby_wrapper = data->wrapper;
|
||||||
|
@ -8190,7 +8217,7 @@ proc_invoke(proc, args, self, klass)
|
||||||
|
|
||||||
PUSH_ITER(ITER_CUR);
|
PUSH_ITER(ITER_CUR);
|
||||||
ruby_frame->iter = ITER_CUR;
|
ruby_frame->iter = ITER_CUR;
|
||||||
PUSH_TAG(pcall ? PROT_LAMBDA : PROT_NONE);
|
PUSH_TAG((pcall&YIELD_LAMBDA_CALL) ? PROT_LAMBDA : PROT_NONE);
|
||||||
state = EXEC_TAG();
|
state = EXEC_TAG();
|
||||||
if (state == 0) {
|
if (state == 0) {
|
||||||
proc_set_safe_level(proc);
|
proc_set_safe_level(proc);
|
||||||
|
@ -8519,7 +8546,6 @@ block_pass(self, node)
|
||||||
orphan = block_orphan(data);
|
orphan = block_orphan(data);
|
||||||
|
|
||||||
/* PUSH BLOCK from data */
|
/* PUSH BLOCK from data */
|
||||||
old_block = ruby_block;
|
|
||||||
_block = *data;
|
_block = *data;
|
||||||
_block.outer = ruby_block;
|
_block.outer = ruby_block;
|
||||||
_block.uniq = block_unique++;
|
_block.uniq = block_unique++;
|
||||||
|
@ -8547,7 +8573,7 @@ block_pass(self, node)
|
||||||
}
|
}
|
||||||
POP_TAG();
|
POP_TAG();
|
||||||
POP_ITER();
|
POP_ITER();
|
||||||
ruby_block = old_block;
|
ruby_block = _block.outer;
|
||||||
if (proc_safe_level_p(proc)) ruby_safe_level = safe;
|
if (proc_safe_level_p(proc)) ruby_safe_level = safe;
|
||||||
|
|
||||||
switch (state) {/* escape from orphan block */
|
switch (state) {/* escape from orphan block */
|
||||||
|
|
|
@ -59,21 +59,17 @@ class OpenStruct
|
||||||
@table = @table.dup
|
@table = @table.dup
|
||||||
end
|
end
|
||||||
|
|
||||||
module Marshaler
|
def marshal_dump
|
||||||
def marshal_dump
|
@table
|
||||||
table = @table
|
end
|
||||||
OpenStruct.new.instance_eval{@table=table; self}
|
def marshal_load(x)
|
||||||
end
|
@table = x
|
||||||
def marshal_load(x)
|
@table.each_key{|key| new_ostruct_member(key)}
|
||||||
@table = x.instance_variable_get("@table")
|
|
||||||
@table.each_key{|key| new_ostruct_member(key)}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_ostruct_member(name)
|
def new_ostruct_member(name)
|
||||||
unless self.respond_to?(name)
|
unless self.respond_to?(name)
|
||||||
self.instance_eval %{
|
self.instance_eval %{
|
||||||
extend OpenStruct::Marshaler
|
|
||||||
def #{name}; @table[:#{name}]; end
|
def #{name}; @table[:#{name}]; end
|
||||||
def #{name}=(x); @table[:#{name}] = x; end
|
def #{name}=(x); @table[:#{name}] = x; end
|
||||||
}
|
}
|
||||||
|
|
8
object.c
8
object.c
|
@ -2056,9 +2056,10 @@ convert_type(val, tname, method, raise)
|
||||||
const char *tname, *method;
|
const char *tname, *method;
|
||||||
int raise;
|
int raise;
|
||||||
{
|
{
|
||||||
VALUE result = rb_funcall_rescue(val, rb_intern(method), 0);
|
ID m;
|
||||||
|
|
||||||
if (result == Qundef) {
|
m = rb_intern(method);
|
||||||
|
if (!rb_respond_to(val, m)) {
|
||||||
if (raise) {
|
if (raise) {
|
||||||
rb_raise(rb_eTypeError, "cannot convert %s into %s",
|
rb_raise(rb_eTypeError, "cannot convert %s into %s",
|
||||||
NIL_P(val) ? "nil" :
|
NIL_P(val) ? "nil" :
|
||||||
|
@ -2068,11 +2069,10 @@ convert_type(val, tname, method, raise)
|
||||||
tname);
|
tname);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ruby_errinfo = Qnil;
|
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return rb_funcall(val, m, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
|
|
Loading…
Add table
Reference in a new issue