summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-03-04 06:47:45 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-03-04 06:47:45 +0000
commit70bbad3cfd5a692c8e78ccf750eed3f1c7f186db (patch)
tree93678f3b87002b5d2dee2c9069fc7098810ed0b1 /eval.c
parentd29f9e080bc6e578df495c56c4fbee29260273d2 (diff)
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c. * eval.c (rb_exec_recursive): new function. * array.c (rb_ary_join): use rb_exec_recursive(). * array.c (rb_ary_inspect, rb_ary_hash): ditto. * file.c (rb_file_join): ditto. * hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto. * io.c (rb_io_puts): ditto. * object.c (rb_obj_inspect): ditto * struct.c (rb_struct_inspect): ditto. * lib/set.rb (SortedSet::setup): a hack to shut up warning. [ruby-talk:132866] * lib/time.rb (Time::strptime): add new function. inspired by [ruby-talk:132815]. * lib/parsedate.rb (ParseDate::strptime): ditto. * regparse.c: move st_*_strend() functions from st.c. fixed some potential memory leaks. * exception error messages updated. [ruby-core:04497] * ext/socket/socket.c (Init_socket): add bunch of Socket constants. Patch from Sam Roberts <sroberts@uniserve.com>. [ruby-core:04409] * array.c (rb_ary_s_create): no need for negative argc check. [ruby-core:04463] * array.c (rb_ary_unshift_m): ditto. * lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass of StandardError class, not Exception class. [ruby-core:04429] * parse.y (fcall_gen): lvar(arg) will be evaluated as lvar.call(arg) when lvar is a defined local variable. [new] * object.c (rb_class_initialize): call inherited method before calling initializing block. * eval.c (rb_thread_start_1): initialize newly pushed frame. * lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE. fixed: [ruby-core:04444] * eval.c (is_defined): NODE_IASGN is an assignment. * ext/readline/readline.c (Readline.readline): use rl_outstream and rl_instream. [ruby-dev:25699] * ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check [ruby-dev:25675] * misc/ruby-mode.el: [ruby-core:04415] * lib/rdoc/generators/html_generator.rb: [ruby-core:04412] * lib/rdoc/generators/ri_generator.rb: ditto. * struct.c (make_struct): fixed: [ruby-core:04402] * ext/curses/curses.c (window_color_set): [ruby-core:04393] * ext/socket/socket.c (Init_socket): SO_REUSEPORT added. [ruby-talk:130092] * object.c: [ruby-doc:818] * parse.y (open_args): fix too verbose warnings for the space before argument parentheses. [ruby-dev:25492] * parse.y (parser_yylex): ditto. * parse.y (parser_yylex): the first expression in the parentheses should not be a command. [ruby-dev:25492] * lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330] * object.c (Init_Object): remove Object#type. [ruby-core:04335] * st.c (st_foreach): report success/failure by return value. [ruby-Bugs-1396] * parse.y: forgot to initialize parser struct. [ruby-dev:25492] * parse.y (parser_yylex): no tLABEL on EXPR_BEG. [ruby-talk:127711] * document updates - [ruby-core:04296], [ruby-core:04301], [ruby-core:04302], [ruby-core:04307] * dir.c (rb_push_glob): should work for NUL delimited patterns. * dir.c (rb_glob2): should aware of offset in the pattern. * string.c (rb_str_new4): should propagate taintedness. * env.h: rename member names in struct FRAME; last_func -> callee, orig_func -> this_func, last_class -> this_class. * struct.c (rb_struct_set): use original method name, not callee name, to retrieve member slot. [ruby-core:04268] * time.c (time_strftime): protect from format modification from GC finalizers. * object.c (Init_Object): remove rb_obj_id_obsolete() * eval.c (rb_mod_define_method): incomplete subclass check. [ruby-dev:25464] * gc.c (rb_data_object_alloc): klass may be NULL. [ruby-list:40498] * bignum.c (rb_big_rand): should return positive random number. [ruby-dev:25401] * bignum.c (rb_big_rand): do not use rb_big_modulo to generate random bignums. [ruby-dev:25396] * variable.c (rb_autoload): [ruby-dev:25373] * eval.c (svalue_to_avalue): [ruby-dev:25366] * string.c (rb_str_justify): [ruby-dev:25367] * io.c (rb_f_select): [ruby-dev:25312] * ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072] * struct.c (make_struct): [ruby-dev:25249] * dir.c (dir_open_dir): new function. [ruby-dev:25242] * io.c (rb_f_open): add type check for return value from to_open. * lib/pstore.rb (PStore#transaction): Use the empty content when a file is not found. [ruby-dev:24561] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c246
1 files changed, 149 insertions, 97 deletions
diff --git a/eval.c b/eval.c
index ebb16396c9..e23f52e83f 100644
--- a/eval.c
+++ b/eval.c
@@ -174,9 +174,9 @@ rb_secure(level)
int level;
{
if (level <= ruby_safe_level) {
- if (ruby_frame->last_func) {
+ if (ruby_frame->callee) {
rb_raise(rb_eSecurityError, "Insecure operation `%s' at level %d",
- rb_id2name(ruby_frame->last_func), ruby_safe_level);
+ rb_id2name(ruby_frame->callee), ruby_safe_level);
}
else {
rb_raise(rb_eSecurityError, "Insecure operation at level %d", ruby_safe_level);
@@ -196,9 +196,9 @@ rb_check_safe_obj(x)
VALUE x;
{
if (ruby_safe_level > 0 && OBJ_TAINTED(x)){
- if (ruby_frame->last_func) {
+ if (ruby_frame->callee) {
rb_raise(rb_eSecurityError, "Insecure operation - %s",
- rb_id2name(ruby_frame->last_func));
+ rb_id2name(ruby_frame->callee));
}
else {
rb_raise(rb_eSecurityError, "Insecure operation: -r");
@@ -1086,9 +1086,9 @@ error_pos()
{
ruby_set_current_source();
if (ruby_sourcefile) {
- if (ruby_frame->last_func) {
+ if (ruby_frame->callee) {
warn_printf("%s:%d:in `%s'", ruby_sourcefile, ruby_sourceline,
- rb_id2name(ruby_frame->last_func));
+ rb_id2name(ruby_frame->callee));
}
else if (ruby_sourceline == 0) {
warn_printf("%s", ruby_sourcefile);
@@ -1607,9 +1607,9 @@ rb_eval_string_wrap(str, state)
ruby_top_self = rb_obj_clone(ruby_top_self);
rb_extend_object(ruby_top_self, ruby_wrapper);
PUSH_FRAME();
- ruby_frame->last_func = 0;
- ruby_frame->orig_func = 0;
- ruby_frame->last_class = 0;
+ ruby_frame->callee = 0;
+ ruby_frame->this_func = 0;
+ ruby_frame->this_class = 0;
ruby_frame->self = self;
PUSH_CREF(ruby_wrapper);
PUSH_SCOPE();
@@ -1749,9 +1749,9 @@ rb_eval_cmd(cmd, arg, level)
saved_scope = ruby_scope;
ruby_scope = top_scope;
PUSH_FRAME();
- ruby_frame->last_func = 0;
- ruby_frame->orig_func = 0;
- ruby_frame->last_class = 0;
+ ruby_frame->callee = 0;
+ ruby_frame->this_func = 0;
+ ruby_frame->this_class = 0;
ruby_frame->self = ruby_top_self;
PUSH_CREF(ruby_wrapper ? ruby_wrapper : rb_cObject);
@@ -2234,10 +2234,10 @@ is_defined(self, node, buf, noeval)
switch (nd_type(node)) {
case NODE_SUPER:
case NODE_ZSUPER:
- if (ruby_frame->orig_func == 0) return 0;
- else if (ruby_frame->last_class == 0) return 0;
- val = ruby_frame->last_class;
- if (rb_method_boundp(RCLASS(val)->super, ruby_frame->orig_func, 0)) {
+ if (ruby_frame->this_func == 0) return 0;
+ else if (ruby_frame->this_class == 0) return 0;
+ val = ruby_frame->this_class;
+ if (rb_method_boundp(RCLASS(val)->super, ruby_frame->this_func, 0)) {
if (nd_type(node) == NODE_SUPER) {
return arg_defined(self, node->nd_args, buf, "super");
}
@@ -2312,6 +2312,7 @@ is_defined(self, node, buf, noeval)
case NODE_DASGN:
case NODE_DASGN_CURR:
case NODE_GASGN:
+ case NODE_IASGN:
case NODE_CDECL:
case NODE_CVDECL:
case NODE_CVASGN:
@@ -2576,7 +2577,7 @@ svalue_to_avalue(v)
if (RARRAY(tmp)->len == 1) {
top = rb_check_array_type(RARRAY(tmp)->ptr[0]);
if (!NIL_P(top) && RARRAY(top)->len > 1) {
- return v;
+ return tmp;
}
return rb_ary_new3(1, v);
}
@@ -2687,8 +2688,8 @@ rb_eval(self, n)
ruby_current_node = node;
if (trace_func && (node->flags & NODE_NEWLINE)) {
call_trace_func("line", node, self,
- ruby_frame->last_func,
- ruby_frame->last_class);
+ ruby_frame->this_func,
+ ruby_frame->this_class);
}
switch (nd_type(node)) {
case NODE_BLOCK:
@@ -2784,8 +2785,8 @@ rb_eval(self, n)
case NODE_IF:
if (trace_func) {
call_trace_func("line", node, self,
- ruby_frame->last_func,
- ruby_frame->last_class);
+ ruby_frame->this_func,
+ ruby_frame->this_class);
}
if (RTEST(rb_eval(self, node->nd_cond))) {
node = node->nd_body;
@@ -2804,8 +2805,8 @@ rb_eval(self, n)
while (tag) {
if (trace_func) {
call_trace_func("line", tag, self,
- ruby_frame->last_func,
- ruby_frame->last_class);
+ ruby_frame->this_func,
+ ruby_frame->this_class);
}
if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
VALUE v = rb_eval(self, tag->nd_head->nd_head);
@@ -2847,8 +2848,8 @@ rb_eval(self, n)
while (tag) {
if (trace_func) {
call_trace_func("line", tag, self,
- ruby_frame->last_func,
- ruby_frame->last_class);
+ ruby_frame->this_func,
+ ruby_frame->this_class);
}
if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
VALUE v = rb_eval(self, tag->nd_head->nd_head);
@@ -3275,11 +3276,11 @@ rb_eval(self, n)
int argc; VALUE *argv; /* used in SETUP_ARGS */
TMP_PROTECT;
- if (ruby_frame->last_class == 0) {
- if (ruby_frame->orig_func) {
- rb_name_error(ruby_frame->last_func,
+ if (ruby_frame->this_class == 0) {
+ if (ruby_frame->this_func) {
+ rb_name_error(ruby_frame->callee,
"superclass method `%s' disabled",
- rb_id2name(ruby_frame->orig_func));
+ rb_id2name(ruby_frame->this_func));
}
else {
rb_raise(rb_eNoMethodError, "super called outside of method");
@@ -3961,7 +3962,7 @@ module_setup(module, n)
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
if (trace_func) {
- call_trace_func("class", n, ruby_cbase, ruby_frame->last_func, ruby_frame->last_class);
+ call_trace_func("class", n, ruby_cbase, ruby_frame->this_func, ruby_frame->this_class);
}
result = rb_eval(ruby_cbase, node->nd_next);
}
@@ -3973,7 +3974,7 @@ module_setup(module, n)
ruby_frame = frame.tmp;
if (trace_func) {
- call_trace_func("end", n, 0, ruby_frame->last_func, ruby_frame->last_class);
+ call_trace_func("end", n, 0, ruby_frame->this_func, ruby_frame->this_class);
}
if (state) JUMP_TAG(state);
@@ -4372,8 +4373,8 @@ rb_longjmp(tag, mesg)
if (trace_func && tag != TAG_FATAL) {
call_trace_func("raise", ruby_current_node,
ruby_frame->self,
- ruby_frame->last_func,
- ruby_frame->last_class);
+ ruby_frame->this_func,
+ ruby_frame->this_class);
}
if (!prot_tag) {
error_print();
@@ -4592,7 +4593,7 @@ return_jump(retval)
tt->retval = retval;
if (trace_func) {
struct FRAME *f = tt->frame;
- call_trace_func("return", f->node, f->self, f->last_func, f->last_class);
+ call_trace_func("return", f->node, f->self, f->this_func, f->this_class);
}
JUMP_TAG(TAG_RETURN);
}
@@ -4633,12 +4634,6 @@ static VALUE bmcall _((VALUE, VALUE));
static int method_arity _((VALUE));
static VALUE
-kk()
-{
- return rb_proc_new(rb_yield, Qnil);
-}
-
-static VALUE
rb_yield_0(val, self, klass, flags, avalue)
VALUE val, self, klass; /* OK */
int flags, avalue;
@@ -5532,7 +5527,7 @@ call_cfunc(func, recv, len, argc, argv)
argv[11], argv[12], argv[13], argv[14]);
break;
default:
- rb_raise(rb_eArgError, "too many arguments(%d)", len);
+ rb_raise(rb_eArgError, "too many arguments (%d)", len);
break;
}
return Qnil; /* not reached */
@@ -5570,18 +5565,17 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
stack_check();
rb_gc_finalize_deferred();
}
- PUSH_ITER(itr);
- PUSH_FRAME();
-
if (argc < 0) {
argc = -argc-1;
args = rb_ary_concat(rb_ary_new4(argc, argv), splat_value(argv[argc]));
argc = RARRAY(args)->len;
argv = RARRAY(args)->ptr;
}
- ruby_frame->last_func = id;
- ruby_frame->orig_func = oid;
- ruby_frame->last_class = nosuper?0:klass;
+ PUSH_ITER(itr);
+ PUSH_FRAME();
+ ruby_frame->callee = id;
+ ruby_frame->this_func = oid;
+ ruby_frame->this_class = nosuper?0:klass;
ruby_frame->self = recv;
ruby_frame->argc = argc;
@@ -5591,7 +5585,7 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
int len = body->nd_argc;
if (len < -2) {
- rb_bug("bad argc(%d) specified for `%s(%s)'",
+ rb_bug("bad argc (%d) specified for `%s(%s)'",
len, rb_class2name(klass), rb_id2name(id));
}
if (trace_func) {
@@ -5943,16 +5937,16 @@ rb_call_super(argc, argv)
{
VALUE result, self, klass, k;
- if (ruby_frame->last_class == 0) {
- rb_name_error(ruby_frame->last_func, "calling `super' from `%s' is prohibited",
- rb_id2name(ruby_frame->last_func));
+ if (ruby_frame->this_class == 0) {
+ rb_name_error(ruby_frame->callee, "calling `super' from `%s' is prohibited",
+ rb_id2name(ruby_frame->this_func));
}
self = ruby_frame->self;
- klass = ruby_frame->last_class;
+ klass = ruby_frame->this_class;
PUSH_ITER(ruby_iter->iter ? ITER_PRE : ITER_NOT);
- result = rb_call(RCLASS(klass)->super, self, ruby_frame->orig_func, argc, argv, 3);
+ result = rb_call(RCLASS(klass)->super, self, ruby_frame->this_func, argc, argv, 3);
POP_ITER();
return result;
@@ -5968,15 +5962,15 @@ backtrace(lev)
NODE *n;
ary = rb_ary_new();
- if (frame->last_func == ID_ALLOCATOR) {
+ if (frame->this_func == ID_ALLOCATOR) {
frame = frame->prev;
}
if (lev < 0) {
ruby_set_current_source();
- if (frame->last_func) {
+ if (frame->this_func) {
snprintf(buf, BUFSIZ, "%s:%d:in `%s'",
ruby_sourcefile, ruby_sourceline,
- rb_id2name(frame->last_func));
+ rb_id2name(frame->this_func));
}
else if (ruby_sourceline == 0) {
snprintf(buf, BUFSIZ, "%s", ruby_sourcefile);
@@ -5997,10 +5991,10 @@ backtrace(lev)
}
}
while (frame && (n = frame->node)) {
- if (frame->prev && frame->prev->last_func) {
+ if (frame->prev && frame->prev->this_func) {
snprintf(buf, BUFSIZ, "%s:%d:in `%s'",
n->nd_file, nd_line(n),
- rb_id2name(frame->prev->last_func));
+ rb_id2name(frame->prev->this_func));
}
else {
snprintf(buf, BUFSIZ, "%s:%d", n->nd_file, nd_line(n));
@@ -6049,7 +6043,7 @@ rb_f_caller(argc, argv)
if (NIL_P(level)) lev = 1;
else lev = NUM2INT(level);
- if (lev < 0) rb_raise(rb_eArgError, "negative level(%d)", lev);
+ if (lev < 0) rb_raise(rb_eArgError, "negative level (%d)", lev);
return backtrace(lev);
}
@@ -6073,9 +6067,9 @@ make_backtrace()
}
ID
-rb_frame_last_func()
+rb_frame_this_func()
{
- return ruby_frame->last_func;
+ return ruby_frame->this_func;
}
static NODE*
@@ -6313,8 +6307,9 @@ exec_under(func, under, cbase, args)
PUSH_CLASS(under);
PUSH_FRAME();
ruby_frame->self = _frame.prev->self;
- ruby_frame->last_func = _frame.prev->last_func;
- ruby_frame->last_class = _frame.prev->last_class;
+ ruby_frame->callee = _frame.prev->callee;
+ ruby_frame->this_func = _frame.prev->this_func;
+ ruby_frame->this_class = _frame.prev->this_class;
ruby_frame->argc = _frame.prev->argc;
if (cbase) {
PUSH_CREF(cbase);
@@ -6408,8 +6403,8 @@ specific_eval(argc, argv, klass, self)
}
if (argc > 3) {
rb_raise(rb_eArgError, "wrong number of arguments: %s(src) or %s{..}",
- rb_id2name(ruby_frame->last_func),
- rb_id2name(ruby_frame->last_func));
+ rb_id2name(ruby_frame->callee),
+ rb_id2name(ruby_frame->callee));
}
if (argc > 2) line = NUM2INT(argv[2]);
if (argc > 1) {
@@ -6505,10 +6500,10 @@ rb_load(fname, wrap)
VALUE tmp;
int state;
volatile int prohibit_int = rb_prohibit_interrupt;
- volatile ID last_func;
+ volatile ID callee, this_func;
volatile VALUE wrapper = ruby_wrapper;
volatile VALUE self = ruby_top_self;
- NODE *volatile last_node;
+ NODE * volatile last_node;
NODE *saved_cref = ruby_cref;
TMP_PROTECT;
@@ -6539,22 +6534,24 @@ rb_load(fname, wrap)
}
PUSH_ITER(ITER_NOT);
PUSH_FRAME();
- ruby_frame->last_func = 0;
- ruby_frame->last_class = 0;
+ ruby_frame->callee = 0;
+ ruby_frame->this_func = 0;
+ ruby_frame->this_class = 0;
ruby_frame->self = self;
PUSH_SCOPE();
/* default visibility is private at loading toplevel */
SCOPE_SET(SCOPE_PRIVATE);
PUSH_TAG(PROT_NONE);
state = EXEC_TAG();
- last_func = ruby_frame->last_func;
+ callee = ruby_frame->callee;
+ this_func = ruby_frame->this_func;
last_node = ruby_current_node;
if (!ruby_current_node && ruby_sourcefile) {
last_node = NEW_BEGIN(0);
}
ruby_current_node = 0;
if (state == 0) {
- NODE *node;
+ NODE * volatile node;
volatile int critical;
DEFER_INTS;
@@ -6570,7 +6567,8 @@ rb_load(fname, wrap)
eval_node(self, node);
}
}
- ruby_frame->last_func = last_func;
+ ruby_frame->callee = callee;
+ ruby_frame->this_func = this_func;
ruby_current_node = last_node;
ruby_sourcefile = 0;
ruby_set_current_source();
@@ -6840,7 +6838,7 @@ static void
load_failed(fname)
VALUE fname;
{
- rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING(fname)->ptr);
+ rb_raise(rb_eLoadError, "no such file to load -- %s", RSTRING(fname)->ptr);
}
VALUE
@@ -6853,7 +6851,7 @@ rb_require_safe(fname, safe)
int state;
struct {
NODE *node;
- ID func;
+ ID this_func, callee;
int vmode, safe;
} volatile saved;
char *volatile ftptr = 0;
@@ -6862,7 +6860,8 @@ rb_require_safe(fname, safe)
fname = rb_str_new4(fname);
saved.vmode = scope_vmode;
saved.node = ruby_current_node;
- saved.func = ruby_frame->last_func;
+ saved.callee = ruby_frame->callee;
+ saved.this_func = ruby_frame->this_func;
saved.safe = ruby_safe_level;
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
@@ -6894,7 +6893,8 @@ rb_require_safe(fname, safe)
ruby_current_node = 0;
ruby_sourcefile = rb_source_filename(RSTRING(path)->ptr);
ruby_sourceline = 0;
- ruby_frame->last_func = 0;
+ ruby_frame->callee = 0;
+ ruby_frame->this_func = 0;
SCOPE_SET(SCOPE_PUBLIC);
handle = (long)dln_load(RSTRING(path)->ptr);
rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
@@ -6908,7 +6908,8 @@ rb_require_safe(fname, safe)
POP_TAG();
ruby_current_node = saved.node;
ruby_set_current_source();
- ruby_frame->last_func = saved.func;
+ ruby_frame->this_func = saved.this_func;
+ ruby_frame->callee = saved.callee;
SCOPE_SET(saved.vmode);
ruby_safe_level = saved.safe;
if (ftptr) {
@@ -7503,8 +7504,9 @@ call_end_proc(data)
PUSH_FRAME();
ruby_frame->self = ruby_frame->prev->self;
ruby_frame->node = 0;
- ruby_frame->last_func = 0;
- ruby_frame->last_class = 0;
+ ruby_frame->callee = 0;
+ ruby_frame->this_func = 0;
+ ruby_frame->this_class = 0;
proc_invoke(data, rb_ary_new2(0), Qundef, 0);
POP_FRAME();
POP_ITER();
@@ -7986,8 +7988,9 @@ rb_f_binding(self)
data->iter = rb_f_block_given_p();
frame_dup(&data->frame);
if (ruby_frame->prev) {
- data->frame.last_func = ruby_frame->prev->last_func;
- data->frame.last_class = ruby_frame->prev->last_class;
+ data->frame.callee = ruby_frame->prev->callee;
+ data->frame.this_func = ruby_frame->prev->this_func;
+ data->frame.this_class = ruby_frame->prev->this_class;
}
if (data->iter) {
@@ -8228,8 +8231,8 @@ proc_invoke(proc, args, self, klass)
avalue = Qfalse;
args = RARRAY(args)->ptr[0];
}
- if (rb_block_given_p() && ruby_frame->last_func) {
- if (klass != ruby_frame->last_class)
+ if (rb_block_given_p() && ruby_frame->callee) {
+ if (klass != ruby_frame->this_class)
klass = rb_obj_class(proc);
bvar = rb_block_proc();
}
@@ -8242,7 +8245,7 @@ proc_invoke(proc, args, self, klass)
_block = *data;
_block.block_obj = bvar;
if (self != Qundef) _block.frame.self = self;
- if (klass) _block.frame.last_class = klass;
+ if (klass) _block.frame.this_class = klass;
_block.frame.argc = RARRAY(tmp)->len;
if (_block.frame.argc && (ruby_frame->flags & FRAME_DMETH)) {
NEWOBJ(scope, struct SCOPE);
@@ -8378,12 +8381,12 @@ rb_proc_arity(proc)
* call-seq:
* prc.arity -> fixnum
*
- * Returns the number of arguments required by the block. If the block
+ * Returns the number of arguments that would not be ignored. If the block
* is declared to take no arguments, returns 0. If the block is known
* to take exactly n arguments, returns n. If the block has optional
* arguments, return -n-1, where n is the number of mandatory
* arguments. A <code>proc</code> with no argument declarations
- * is handled like a block declaring <code>||</code> as its arguments.
+ * is the same a block declaring <code>||</code> as its arguments.
*
* Proc.new {}.arity #=> 0
* Proc.new {||}.arity #=> 0
@@ -8944,7 +8947,7 @@ method_call(argc, argv, method)
Data_Get_Struct(method, struct METHOD, data);
if (data->recv == Qundef) {
- rb_raise(rb_eTypeError, "you cannot call unbound method; bind first");
+ rb_raise(rb_eTypeError, "can't call unbound method; bind first");
}
PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
PUSH_TAG(PROT_NONE);
@@ -9382,10 +9385,9 @@ rb_mod_define_method(argc, argv, mod)
VALUE rklass = method->rklass;
if (rklass != mod) {
if (FL_TEST(rklass, FL_SINGLETON)) {
- rb_raise(rb_eTypeError, "cannot bind singleton method to a different class");
+ rb_raise(rb_eTypeError, "can't bind singleton method to a different class");
}
- if (RCLASS(mod)->super && RCLASS(rklass)->super &&
- !RTEST(rb_class_inherited_p(mod, rklass))) {
+ if (!RTEST(rb_class_inherited_p(mod, rklass))) {
rb_raise(rb_eTypeError, "bind argument must be a subclass of %s",
rb_class2name(rklass));
}
@@ -9398,9 +9400,9 @@ rb_mod_define_method(argc, argv, mod)
body = proc_clone(body);
RBASIC(body)->flags |= PROC_NOSAFE;
Data_Get_Struct(body, struct BLOCK, block);
- block->frame.last_func = id;
- block->frame.orig_func = id;
- block->frame.last_class = mod;
+ block->frame.callee = id;
+ block->frame.this_func = id;
+ block->frame.this_class = mod;
node = NEW_BMETHOD(body);
}
else {
@@ -9470,8 +9472,6 @@ Init_Proc()
rb_define_method(rb_cProc, "to_proc", proc_to_self, 0);
rb_define_method(rb_cProc, "binding", proc_binding, 0);
- rb_define_global_function("kk", kk, 0);
-
rb_define_global_function("proc", rb_block_proc, 0);
rb_define_global_function("lambda", proc_lambda, 0);
@@ -10114,7 +10114,8 @@ rb_thread_switch(n)
rb_trap_eval(th_cmd, th_sig, th_safe);
break;
case RESTORE_RAISE:
- ruby_frame->last_func = 0;
+ ruby_frame->callee = 0;
+ ruby_frame->this_func = 0;
ruby_current_node = th_raise_node;
rb_raise_jump(th_raise_exception);
break;
@@ -11783,7 +11784,6 @@ rb_thread_start_1()
if ((state = EXEC_TAG()) == 0) {
if (THREAD_SAVE_CONTEXT(th) == 0) {
new_thread.thread = 0;
- curr_thread = th;
th->result = rb_block_pass(rb_thread_yield_0, arg, proc);
}
th = th_save;
@@ -12770,6 +12770,10 @@ thgroup_add(group, thread)
return group;
}
+/* variables for recursive traversals */
+static ID recursive_key;
+static VALUE recursive_tbl;
+
/*
* +Thread+ encapsulates the behavior of a thread of
@@ -12856,6 +12860,7 @@ Init_Thread()
/* allocate main thread */
main_thread = rb_thread_alloc(rb_cThread);
curr_thread = main_thread->prev = main_thread->next = main_thread;
+ recursive_key = rb_intern("__recursive_key__");
}
/*
@@ -12984,3 +12989,50 @@ rb_throw(tag, val)
argv[1] = val;
rb_f_throw(2, argv);
}
+
+VALUE
+rb_exec_recursive(func, obj, arg)
+ VALUE (*func) _((VALUE, VALUE, int));
+ VALUE obj, arg;
+{
+ VALUE list = rb_thread_local_aref(rb_thread_current(), recursive_key);
+ int found = Qfalse;
+
+ if (NIL_P(list) || TYPE(list) != T_NODE) {
+ list = Qnil;
+ }
+ else {
+ NODE *tmp = (NODE*)list;
+
+ while (!NIL_P(tmp)) {
+ if (tmp->nd_cfnc == func && tmp->nd_tval == obj) {
+ found = Qtrue;
+ break;
+ }
+ tmp = tmp->nd_next;
+ }
+ }
+ if (found) {
+ return (*func)(obj, arg, Qtrue);
+ }
+ else {
+ NODE *node = rb_node_newnode(NODE_MEMO, (VALUE)func, obj, list);
+ VALUE result;
+ int state;
+
+ rb_thread_local_aset(rb_thread_current(), recursive_key, (VALUE)node);
+ PUSH_TAG(PROT_NONE);
+ if ((state = EXEC_TAG()) == 0) {
+ result = (*func)(obj, arg, Qfalse);
+ }
+ POP_TAG();
+ if (state) JUMP_TAG(state);
+
+ /* remove pushed tag */
+ list = rb_thread_local_aref(rb_thread_current(), recursive_key);
+ node = (NODE*)list;
+
+ rb_thread_local_aset(rb_thread_current(), recursive_key, (VALUE)node->nd_next);
+ return result;
+ }
+}