diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-12-03 04:56:25 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-12-03 04:56:25 +0000 |
commit | 405a50a5948fecb6ba44efb250a86052f4a406c8 (patch) | |
tree | df3be019a29fca68dc14bd106d074d8f18c21875 | |
parent | da4884e2d4ea78b39cfdea0a747f2b700ccedfbc (diff) | |
download | ruby-405a50a5948fecb6ba44efb250a86052f4a406c8.tar.gz |
* 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
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | eval.c | 54 | ||||
-rw-r--r-- | lib/ostruct.rb | 16 | ||||
-rw-r--r-- | object.c | 8 |
4 files changed, 63 insertions, 28 deletions
@@ -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 @@ -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 7f4668283b..b30ae640c5 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 } @@ -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 |