mirror of
https://github.com/ruby/ruby.git
synced 2025-09-15 16:44:01 +02:00
* eval.c (rb_call0): argument update propagation. [ruby-dev:28044]
* env.h: remove argc member from struct FRAME. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@9920 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
fdbf3a76a1
commit
8a3d25a790
7 changed files with 119 additions and 113 deletions
|
@ -1,3 +1,9 @@
|
|||
Mon Feb 13 18:08:12 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* eval.c (rb_call0): argument update propagation. [ruby-dev:28044]
|
||||
|
||||
* env.h: remove argc member from struct FRAME.
|
||||
|
||||
Mon Feb 13 13:27:00 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* eval.c (eval): should push class from binding if supplied.
|
||||
|
|
5
env.h
5
env.h
|
@ -16,7 +16,6 @@
|
|||
extern struct FRAME {
|
||||
VALUE self;
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
ID last_func;
|
||||
ID orig_func;
|
||||
VALUE last_class;
|
||||
|
@ -30,8 +29,8 @@ extern struct FRAME {
|
|||
|
||||
void rb_gc_mark_frame _((struct FRAME *));
|
||||
|
||||
#define FRAME_ALLOCA 0
|
||||
#define FRAME_MALLOC 1
|
||||
#define FRAME_DMETH 1
|
||||
#define FRAME_FUNC 2
|
||||
|
||||
extern struct SCOPE {
|
||||
struct RBasic super;
|
||||
|
|
148
eval.c
148
eval.c
|
@ -764,8 +764,7 @@ static unsigned long frame_unique = 0;
|
|||
_frame.node = ruby_current_node; \
|
||||
_frame.iter = ruby_iter->iter; \
|
||||
_frame.argc = 0; \
|
||||
_frame.argv = 0; \
|
||||
_frame.flags = FRAME_ALLOCA; \
|
||||
_frame.flags = 0; \
|
||||
_frame.uniq = frame_unique++; \
|
||||
ruby_frame = &_frame
|
||||
|
||||
|
@ -844,6 +843,8 @@ struct RVarmap *ruby_dyna_vars;
|
|||
|
||||
#define DVAR_DONT_RECYCLE FL_USER2
|
||||
|
||||
#define DMETHOD_P() (ruby_frame->prev ? (ruby_frame->prev->flags & FRAME_DMETH) : 0)
|
||||
|
||||
static struct RVarmap*
|
||||
new_dvar(id, value, prev)
|
||||
ID id;
|
||||
|
@ -1181,9 +1182,9 @@ error_pos()
|
|||
{
|
||||
ruby_set_current_source();
|
||||
if (ruby_sourcefile) {
|
||||
if (ruby_frame->last_func) {
|
||||
if (ruby_frame->orig_func) {
|
||||
warn_printf("%s:%d:in `%s'", ruby_sourcefile, ruby_sourceline,
|
||||
rb_id2name(ruby_frame->last_func));
|
||||
rb_id2name(ruby_frame->orig_func));
|
||||
}
|
||||
else if (ruby_sourceline == 0) {
|
||||
warn_printf("%s", ruby_sourcefile);
|
||||
|
@ -3467,7 +3468,17 @@ rb_eval(self, n)
|
|||
}
|
||||
if (nd_type(node) == NODE_ZSUPER) {
|
||||
argc = ruby_frame->argc;
|
||||
argv = ruby_frame->argv;
|
||||
if (argc && DMETHOD_P()) {
|
||||
if (TYPE(RBASIC(ruby_scope)->klass) != T_ARRAY ||
|
||||
RARRAY(RBASIC(ruby_scope)->klass)->len != argc) {
|
||||
rb_raise(rb_eRuntimeError,
|
||||
"super: specify arguments explicitly");
|
||||
}
|
||||
argv = RARRAY(RBASIC(ruby_scope)->klass)->ptr;
|
||||
}
|
||||
else {
|
||||
argv = ruby_scope->local_vars + 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BEGIN_CALLARGS;
|
||||
|
@ -3842,13 +3853,6 @@ rb_eval(self, n)
|
|||
result = node->nd_lit;
|
||||
break;
|
||||
|
||||
case NODE_ATTRSET:
|
||||
if (ruby_frame->argc != 1)
|
||||
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)",
|
||||
ruby_frame->argc);
|
||||
result = rb_ivar_set(self, node->nd_vid, ruby_frame->argv[0]);
|
||||
break;
|
||||
|
||||
case NODE_DEFN:
|
||||
if (node->nd_defn) {
|
||||
NODE *body, *defn;
|
||||
|
@ -5702,6 +5706,18 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
|
|||
stack_check();
|
||||
rb_gc_finalize_deferred();
|
||||
}
|
||||
if (argc < 0) {
|
||||
VALUE tmp;
|
||||
VALUE *nargv;
|
||||
|
||||
argc = -argc-1;
|
||||
tmp = splat_value(argv[argc]);
|
||||
nargv = TMP_ALLOC(argc + RARRAY(tmp)->len);
|
||||
MEMCPY(nargv, argv, VALUE, argc);
|
||||
MEMCPY(nargv+argc, RARRAY(tmp)->ptr, VALUE, RARRAY(tmp)->len);
|
||||
argc += RARRAY(tmp)->len;
|
||||
argv = nargv;
|
||||
}
|
||||
PUSH_ITER(itr);
|
||||
PUSH_FRAME();
|
||||
|
||||
|
@ -5710,7 +5726,7 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
|
|||
ruby_frame->last_class = (flags & NOEX_NOSUPER)?0:klass;
|
||||
ruby_frame->self = recv;
|
||||
ruby_frame->argc = argc;
|
||||
ruby_frame->argv = argv;
|
||||
ruby_frame->flags = 0;
|
||||
|
||||
switch (nd_type(body)) {
|
||||
case NODE_CFUNC:
|
||||
|
@ -5751,9 +5767,13 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
|
|||
break;
|
||||
|
||||
case NODE_ATTRSET:
|
||||
/* for re-scoped/renamed method */
|
||||
if (argc != 1)
|
||||
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
|
||||
result = rb_ivar_set(recv, body->nd_vid, argv[0]);
|
||||
break;
|
||||
|
||||
case NODE_ZSUPER:
|
||||
result = rb_eval(recv, body);
|
||||
result = rb_call_super(argc, argv);
|
||||
break;
|
||||
|
||||
case NODE_DMETHOD:
|
||||
|
@ -5761,6 +5781,7 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
|
|||
break;
|
||||
|
||||
case NODE_BMETHOD:
|
||||
ruby_frame->flags |= FRAME_DMETH;
|
||||
result = proc_invoke(body->nd_cval, rb_ary_new4(argc, argv), recv, klass);
|
||||
break;
|
||||
|
||||
|
@ -5801,7 +5822,7 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
|
|||
PUSH_TAG(PROT_FUNC);
|
||||
if ((state = EXEC_TAG()) == 0) {
|
||||
NODE *node = 0;
|
||||
int i;
|
||||
int i, nopt = 0;
|
||||
|
||||
if (nd_type(body) == NODE_ARGS) {
|
||||
node = body;
|
||||
|
@ -5821,27 +5842,26 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
|
|||
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
|
||||
argc, i);
|
||||
}
|
||||
if ((long)node->nd_rest == -1) {
|
||||
int opt = i;
|
||||
if (!node->nd_rest) {
|
||||
NODE *optnode = node->nd_opt;
|
||||
|
||||
nopt = i;
|
||||
while (optnode) {
|
||||
opt++;
|
||||
nopt++;
|
||||
optnode = optnode->nd_next;
|
||||
}
|
||||
if (opt < argc) {
|
||||
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
|
||||
argc, opt);
|
||||
if (nopt < argc) {
|
||||
rb_raise(rb_eArgError,
|
||||
"wrong number of arguments (%d for %d)",
|
||||
argc, nopt);
|
||||
}
|
||||
ruby_frame->argc = opt;
|
||||
ruby_frame->argv = local_vars+2;
|
||||
}
|
||||
|
||||
if (local_vars) {
|
||||
if (i > 0) {
|
||||
/* +2 for $_ and $~ */
|
||||
MEMCPY(local_vars+2, argv, VALUE, i);
|
||||
}
|
||||
}
|
||||
argv += i; argc -= i;
|
||||
if (node->nd_opt) {
|
||||
NODE *opt = node->nd_opt;
|
||||
|
@ -5854,20 +5874,22 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
|
|||
if (opt) {
|
||||
rb_eval(recv, opt);
|
||||
}
|
||||
i = nopt;
|
||||
}
|
||||
local_vars = ruby_scope->local_vars;
|
||||
if ((long)node->nd_rest >= 0) {
|
||||
if (node->nd_rest) {
|
||||
VALUE v;
|
||||
|
||||
if (argc > 0)
|
||||
if (argc > 0) {
|
||||
v = rb_ary_new4(argc,argv);
|
||||
else
|
||||
i = -i - 1;
|
||||
}
|
||||
else {
|
||||
v = rb_ary_new2(0);
|
||||
ruby_scope->local_vars[node->nd_rest] = v;
|
||||
}
|
||||
assign(recv, node->nd_rest, v, 1);
|
||||
}
|
||||
ruby_frame->argc = i;
|
||||
}
|
||||
|
||||
if (event_hooks) {
|
||||
EXEC_EVENT_HOOK(RUBY_EVENT_CALL, b2, recv, id, klass);
|
||||
}
|
||||
|
@ -6154,10 +6176,10 @@ backtrace(lev)
|
|||
}
|
||||
if (lev < 0) {
|
||||
ruby_set_current_source();
|
||||
if (frame->last_func) {
|
||||
if (frame->orig_func) {
|
||||
snprintf(buf, BUFSIZ, "%s:%d:in `%s'",
|
||||
ruby_sourcefile, ruby_sourceline,
|
||||
rb_id2name(frame->last_func));
|
||||
rb_id2name(frame->orig_func));
|
||||
}
|
||||
else if (ruby_sourceline == 0) {
|
||||
snprintf(buf, BUFSIZ, "%s", ruby_sourcefile);
|
||||
|
@ -6178,11 +6200,11 @@ backtrace(lev)
|
|||
}
|
||||
}
|
||||
for (; frame && (n = frame->node); frame = frame->prev) {
|
||||
if (frame->prev && frame->prev->last_func) {
|
||||
if (frame->prev && frame->prev->orig_func) {
|
||||
if (frame->prev->node == n) continue;
|
||||
snprintf(buf, BUFSIZ, "%s:%d:in `%s'",
|
||||
n->nd_file, nd_line(n),
|
||||
rb_id2name(frame->prev->last_func));
|
||||
rb_id2name(frame->prev->orig_func));
|
||||
}
|
||||
else {
|
||||
snprintf(buf, BUFSIZ, "%s:%d", n->nd_file, nd_line(n));
|
||||
|
@ -6498,7 +6520,6 @@ exec_under(func, under, cbase, args)
|
|||
ruby_frame->orig_func = f->orig_func;
|
||||
ruby_frame->last_class = f->last_class;
|
||||
ruby_frame->argc = f->argc;
|
||||
ruby_frame->argv = f->argv;
|
||||
if (cbase) {
|
||||
PUSH_CREF(cbase);
|
||||
}
|
||||
|
@ -8053,12 +8074,8 @@ frame_free(frame)
|
|||
{
|
||||
struct FRAME *tmp;
|
||||
|
||||
if (frame->argc > 0 && (frame->flags & FRAME_MALLOC))
|
||||
free(frame->argv);
|
||||
frame = frame->prev;
|
||||
while (frame) {
|
||||
if (frame->argc > 0 && (frame->flags & FRAME_MALLOC))
|
||||
free(frame->argv);
|
||||
tmp = frame;
|
||||
frame = frame->prev;
|
||||
free(tmp);
|
||||
|
@ -8083,16 +8100,9 @@ static void
|
|||
frame_dup(frame)
|
||||
struct FRAME *frame;
|
||||
{
|
||||
VALUE *argv;
|
||||
struct FRAME *tmp;
|
||||
|
||||
for (;;) {
|
||||
if (frame->argc > 0) {
|
||||
argv = ALLOC_N(VALUE, frame->argc);
|
||||
MEMCPY(argv, frame->argv, VALUE, frame->argc);
|
||||
frame->argv = argv;
|
||||
frame->flags |= FRAME_MALLOC;
|
||||
}
|
||||
frame->tmp = 0; /* should not preserve tmp */
|
||||
if (!frame->prev) break;
|
||||
tmp = ALLOC(struct FRAME);
|
||||
|
@ -8425,11 +8435,15 @@ proc_invoke(proc, args, self, klass)
|
|||
if (self != Qundef) _block.frame.self = self;
|
||||
if (klass) _block.frame.last_class = klass;
|
||||
_block.frame.argc = RARRAY(tmp)->len;
|
||||
_block.frame.argv = ALLOCA_N(VALUE, RARRAY(tmp)->len);
|
||||
MEMCPY(_block.frame.argv, RARRAY(tmp)->ptr, VALUE, RARRAY(tmp)->len);
|
||||
_block.frame.flags = FRAME_ALLOCA;
|
||||
if (_block.frame.argc && (ruby_frame->flags & FRAME_DMETH)) {
|
||||
NEWOBJ(scope, struct SCOPE);
|
||||
OBJSETUP(scope, tmp, T_SCOPE);
|
||||
scope->local_tbl = _block.scope->local_tbl;
|
||||
scope->local_vars = _block.scope->local_vars;
|
||||
_block.scope = scope;
|
||||
}
|
||||
/* modify current frame */
|
||||
ruby_block = &_block;
|
||||
|
||||
PUSH_ITER(ITER_CUR);
|
||||
ruby_frame->iter = ITER_CUR;
|
||||
PUSH_TAG(pcall ? PROT_LAMBDA : PROT_NONE);
|
||||
|
@ -9240,15 +9254,17 @@ method_arity(method)
|
|||
return proc_arity(body->nd_cval);
|
||||
case NODE_DMETHOD:
|
||||
return method_arity(body->nd_cval);
|
||||
default:
|
||||
case NODE_SCOPE:
|
||||
body = body->nd_next; /* skip NODE_SCOPE */
|
||||
if (nd_type(body) == NODE_BLOCK)
|
||||
body = body->nd_head;
|
||||
if (!body) return INT2FIX(0);
|
||||
n = body->nd_cnt;
|
||||
if (body->nd_opt || body->nd_rest != -1)
|
||||
if (body->nd_opt || body->nd_rest)
|
||||
n = -n-1;
|
||||
return INT2FIX(n);
|
||||
default:
|
||||
rb_raise(rb_eArgError, "invalid node 0x%x", nd_type(body));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9941,26 +9957,6 @@ timeofday()
|
|||
|
||||
#define STACK(addr) (th->stk_pos<(VALUE*)(addr) && (VALUE*)(addr)<th->stk_pos+th->stk_len)
|
||||
#define ADJ(addr) (void*)(STACK(addr)?(((VALUE*)(addr)-th->stk_pos)+th->stk_ptr):(VALUE*)(addr))
|
||||
#ifdef C_ALLOCA
|
||||
# define MARK_FRAME_ADJ(f) rb_gc_mark_frame(f)
|
||||
#else
|
||||
# define MARK_FRAME_ADJ(f) mark_frame_adj(f, th)
|
||||
static void
|
||||
mark_frame_adj(frame, th)
|
||||
struct FRAME *frame;
|
||||
rb_thread_t th;
|
||||
{
|
||||
if (frame->flags & FRAME_MALLOC) {
|
||||
rb_gc_mark_locations(frame->argv, frame->argv+frame->argc);
|
||||
}
|
||||
else {
|
||||
VALUE *start = ADJ(frame->argv);
|
||||
rb_gc_mark_locations(start, start+frame->argc);
|
||||
}
|
||||
rb_gc_mark((VALUE)frame->node);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
thread_mark(th)
|
||||
rb_thread_t th;
|
||||
|
@ -10003,13 +9999,13 @@ thread_mark(th)
|
|||
frame = th->frame;
|
||||
while (frame && frame != top_frame) {
|
||||
frame = ADJ(frame);
|
||||
MARK_FRAME_ADJ(frame);
|
||||
rb_gc_mark_frame(frame);
|
||||
if (frame->tmp) {
|
||||
struct FRAME *tmp = frame->tmp;
|
||||
|
||||
while (tmp && tmp != top_frame) {
|
||||
tmp = ADJ(tmp);
|
||||
MARK_FRAME_ADJ(tmp);
|
||||
rb_gc_mark_frame(tmp);
|
||||
tmp = tmp->prev;
|
||||
}
|
||||
}
|
||||
|
@ -10018,7 +10014,7 @@ thread_mark(th)
|
|||
block = th->block;
|
||||
while (block) {
|
||||
block = ADJ(block);
|
||||
MARK_FRAME_ADJ(&block->frame);
|
||||
rb_gc_mark_frame(&block->frame);
|
||||
block = block->prev;
|
||||
}
|
||||
}
|
||||
|
|
3
gc.c
3
gc.c
|
@ -816,6 +816,7 @@ gc_mark_children(ptr, lev)
|
|||
case NODE_MODULE:
|
||||
case NODE_ALIAS:
|
||||
case NODE_VALIAS:
|
||||
case NODE_ARGS:
|
||||
gc_mark((VALUE)obj->as.node.u1.node, lev);
|
||||
/* fall through */
|
||||
case NODE_METHOD: /* 2 */
|
||||
|
@ -845,7 +846,6 @@ gc_mark_children(ptr, lev)
|
|||
case NODE_NEXT:
|
||||
case NODE_YIELD:
|
||||
case NODE_COLON2:
|
||||
case NODE_ARGS:
|
||||
case NODE_SPLAT:
|
||||
case NODE_TO_ARY:
|
||||
case NODE_SVALUE:
|
||||
|
@ -1265,7 +1265,6 @@ void
|
|||
rb_gc_mark_frame(frame)
|
||||
struct FRAME *frame;
|
||||
{
|
||||
mark_locations_array(frame->argv, frame->argc);
|
||||
gc_mark((VALUE)frame->node, 0);
|
||||
}
|
||||
|
||||
|
|
2
node.h
2
node.h
|
@ -199,7 +199,7 @@ typedef struct RNode {
|
|||
#define nd_lit u1.value
|
||||
|
||||
#define nd_frml u1.node
|
||||
#define nd_rest u2.argc
|
||||
#define nd_rest u2.node
|
||||
#define nd_opt u1.node
|
||||
|
||||
#define nd_recv u1.node
|
||||
|
|
28
parse.y
28
parse.y
|
@ -275,12 +275,12 @@ static void top_local_setup();
|
|||
%type <node> args when_args call_args call_args2 open_args paren_args opt_paren_args
|
||||
%type <node> command_args aref_args opt_block_arg block_arg var_ref var_lhs
|
||||
%type <node> mrhs superclass block_call block_command
|
||||
%type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
|
||||
%type <node> f_arglist f_args f_optarg f_opt f_rest_arg f_block_arg opt_f_block_arg
|
||||
%type <node> assoc_list assocs assoc undef_list backref string_dvar
|
||||
%type <node> block_var opt_block_var brace_block cmd_brace_block do_block lhs none fitem
|
||||
%type <node> mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node
|
||||
%type <id> fsym variable sym symbol operation operation2 operation3
|
||||
%type <id> cname fname op f_rest_arg
|
||||
%type <id> cname fname op
|
||||
%type <num> f_norm_arg f_arg
|
||||
%token tUPLUS /* unary+ */
|
||||
%token tUMINUS /* unary- */
|
||||
|
@ -2249,7 +2249,7 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
|
|||
}
|
||||
| f_arg ',' f_optarg opt_f_block_arg
|
||||
{
|
||||
$$ = block_append(NEW_ARGS($1, $3, -1), $4);
|
||||
$$ = block_append(NEW_ARGS($1, $3, 0), $4);
|
||||
}
|
||||
| f_arg ',' f_rest_arg opt_f_block_arg
|
||||
{
|
||||
|
@ -2257,7 +2257,7 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
|
|||
}
|
||||
| f_arg opt_f_block_arg
|
||||
{
|
||||
$$ = block_append(NEW_ARGS($1, 0, -1), $2);
|
||||
$$ = block_append(NEW_ARGS($1, 0, 0), $2);
|
||||
}
|
||||
| f_optarg ',' f_rest_arg opt_f_block_arg
|
||||
{
|
||||
|
@ -2265,7 +2265,7 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
|
|||
}
|
||||
| f_optarg opt_f_block_arg
|
||||
{
|
||||
$$ = block_append(NEW_ARGS(0, $1, -1), $2);
|
||||
$$ = block_append(NEW_ARGS(0, $1, 0), $2);
|
||||
}
|
||||
| f_rest_arg opt_f_block_arg
|
||||
{
|
||||
|
@ -2273,11 +2273,11 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
|
|||
}
|
||||
| f_block_arg
|
||||
{
|
||||
$$ = block_append(NEW_ARGS(0, 0, -1), $1);
|
||||
$$ = block_append(NEW_ARGS(0, 0, 0), $1);
|
||||
}
|
||||
| /* none */
|
||||
{
|
||||
$$ = NEW_ARGS(0, 0, -1);
|
||||
$$ = NEW_ARGS(0, 0, 0);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -2344,13 +2344,19 @@ f_rest_arg : restarg_mark tIDENTIFIER
|
|||
{
|
||||
if (!is_local_id($2))
|
||||
yyerror("rest argument must be local variable");
|
||||
else if (local_id($2))
|
||||
yyerror("duplicate rest argument name");
|
||||
$$ = local_cnt($2);
|
||||
if (dyna_in_block()) {
|
||||
rb_dvar_push($2, Qnil);
|
||||
}
|
||||
$$ = assignable($2, 0);
|
||||
}
|
||||
| restarg_mark
|
||||
{
|
||||
$$ = -2;
|
||||
if (dyna_in_block()) {
|
||||
$$ = NEW_DASGN_CURR(internal_id(), 0);
|
||||
}
|
||||
else {
|
||||
$$ = NEW_NODE(NODE_LASGN,0,0,local_append(0));
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ class DRbService
|
|||
@@ruby += " -d" if $DEBUG
|
||||
def self.add_service_command(nm)
|
||||
dir = File.dirname(File.expand_path(__FILE__))
|
||||
DRb::ExtServManager.command[nm] = "#{@@ruby} -d #{dir}/#{nm}"
|
||||
DRb::ExtServManager.command[nm] = "#{@@ruby} #{dir}/#{nm}"
|
||||
end
|
||||
|
||||
%w(ut_drb.rb ut_array.rb ut_port.rb ut_large.rb ut_safe1.rb ut_eval.rb).each do |nm|
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue