summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--eval.c54
-rw-r--r--lib/ostruct.rb16
-rw-r--r--object.c8
4 files changed, 63 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index 7b27b59..cc9a1b2 100644
--- a/ChangeLog
+++ b/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.
+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>
* test/xmlrpc/test_parser.rb, test/xmlrpc/data/*.expected: Expected
diff --git a/eval.c b/eval.c
index 5c702b2..54a37e4 100644
--- a/eval.c
+++ b/eval.c
@@ -312,7 +312,7 @@ rb_clear_cache_by_class(klass)
static ID init, eqq, each, aref, aset, match, missing;
static ID added, singleton_added;
-static ID __id__, __send__;
+static ID __id__, __send__, respond_to;
void
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_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_SVALUE 2
@@ -3922,17 +3923,25 @@ module_setup(module, n)
return result;
}
+static NODE *basic_respond_to = 0;
+
int
rb_respond_to(obj, id)
VALUE obj;
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;
}
+ else{
+ return rb_funcall(obj, respond_to, 1, ID2SYM(id));
+ }
return Qfalse;
}
+
/*
* call-seq:
* 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)
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 {
result = rb_eval(self, node);
@@ -7585,7 +7608,10 @@ Init_eval()
rb_define_global_function("loop", rb_f_loop, 0);
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("fail", rb_f_raise, -1);
@@ -8164,18 +8190,19 @@ proc_invoke(proc, args, self, klass)
volatile int pcall, avalue = Qtrue;
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);
pcall = (data->flags & BLOCK_LAMBDA) ? YIELD_LAMBDA_CALL : 0;
if (!pcall && RARRAY(args)->len == 1) {
avalue = Qfalse;
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();
ruby_wrapper = data->wrapper;
@@ -8190,7 +8217,7 @@ proc_invoke(proc, args, self, klass)
PUSH_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();
if (state == 0) {
proc_set_safe_level(proc);
@@ -8519,7 +8546,6 @@ block_pass(self, node)
orphan = block_orphan(data);
/* PUSH BLOCK from data */
- old_block = ruby_block;
_block = *data;
_block.outer = ruby_block;
_block.uniq = block_unique++;
@@ -8547,7 +8573,7 @@ block_pass(self, node)
}
POP_TAG();
POP_ITER();
- ruby_block = old_block;
+ ruby_block = _block.outer;
if (proc_safe_level_p(proc)) ruby_safe_level = safe;
switch (state) {/* escape from orphan block */
diff --git a/lib/ostruct.rb b/lib/ostruct.rb
index 7f46682..b30ae64 100644
--- a/lib/ostruct.rb
+++ b/lib/ostruct.rb
@@ -59,21 +59,17 @@ class OpenStruct
@table = @table.dup
end
- module Marshaler
- def marshal_dump
- table = @table
- OpenStruct.new.instance_eval{@table=table; self}
- end
- def marshal_load(x)
- @table = x.instance_variable_get("@table")
- @table.each_key{|key| new_ostruct_member(key)}
- end
+ def marshal_dump
+ @table
+ end
+ def marshal_load(x)
+ @table = x
+ @table.each_key{|key| new_ostruct_member(key)}
end
def new_ostruct_member(name)
unless self.respond_to?(name)
self.instance_eval %{
- extend OpenStruct::Marshaler
def #{name}; @table[:#{name}]; end
def #{name}=(x); @table[:#{name}] = x; end
}
diff --git a/object.c b/object.c
index a196e3b..3d77c36 100644
--- a/object.c
+++ b/object.c
@@ -2056,9 +2056,10 @@ convert_type(val, tname, method, raise)
const char *tname, *method;
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) {
rb_raise(rb_eTypeError, "cannot convert %s into %s",
NIL_P(val) ? "nil" :
@@ -2068,11 +2069,10 @@ convert_type(val, tname, method, raise)
tname);
}
else {
- ruby_errinfo = Qnil;
return Qnil;
}
}
- return result;
+ return rb_funcall(val, m, 0);
}
VALUE