Project

General

Profile

Feature #5454 » 0004-rough-implementation-of-keyword-arguments.patch

mame (Yusuke Endoh), 10/18/2011 01:21 AM

View differences:

compile.c
iseq->arg_post_len = args->post_args_num;
}
if (args->kw_args) {
rb_notimplement();
}
if (args->opt_args) {
NODE *node = args->opt_args;
LABEL *label;
......
iseq->arg_opts = 0;
}
if (args->kw_args) {
NODE *node = args->kw_args;
VALUE keywords = rb_ary_tmp_new(1);
int i = 0, j;
while (node) {
rb_ary_push(keywords, INT2FIX(node->nd_body->nd_head->nd_vid));
COMPILE_POPED(optargs, "kwarg", node->nd_body);
node = node->nd_next;
i += 1;
}
iseq->arg_keywords = i;
iseq->arg_keyword_table = ALLOC_N(ID, i);
iseq->arg_keyword_vars = ALLOC_N(int, i);
for (j = 0; j < i; j++) {
ID id = FIX2INT(RARRAY_PTR(keywords)[j]);
iseq->arg_keyword_table[j] = id;
iseq->arg_keyword_vars[j] = get_dyna_var_idx_at_raw(iseq, id);
}
rb_ary_clear(keywords);
}
else {
iseq->arg_keywords = 0;
}
if (args->pre_init) { /* m_init */
COMPILE_POPED(optargs, "init arguments (m)", args->pre_init);
}
......
}
if (iseq->arg_opts != 0 || iseq->arg_post_len != 0 ||
iseq->arg_rest != -1 || iseq->arg_block != -1) {
iseq->arg_rest != -1 || iseq->arg_block != -1 ||
iseq->arg_keywords != 0) {
iseq->arg_simple = 0;
/* set arg_size: size of arguments */
node.c
F_NODE(nd_next, "next");
break;
case NODE_KW_ARG:
ANN("keyword arguments");
ANN("format: def method_name([nd_body=some], [nd_next..])");
ANN("example: def foo(a:1, b:2); end");
F_NODE(nd_body, "body");
LAST_NODE;
F_NODE(nd_next, "next");
break;
case NODE_POSTARG:
ANN("post arguments");
ANN("format: *[nd_1st], [nd_2nd..] = ..");
......
F_ID(nd_ainfo->rest_arg, "rest argument");
F_ID(nd_ainfo->block_arg, "block argument");
F_NODE(nd_ainfo->opt_args, "optional arguments");
LAST_NODE;
F_NODE(nd_ainfo->kw_args, "keyword arguments");
break;
case NODE_SCOPE:
parse.y
f_kw : tLABEL arg_value
{
NODE *lasgn;
arg_var(formal_argument(get_id($1)));
$$ = assignable($1, $2);
lasgn = assignable($1, $2);
$$ = NEW_OP_ASGN_OR(gettable(lasgn->nd_vid), lasgn);
/*%%%*/
$$ = NEW_KW_ARG(0, $$);
/*%
......
f_block_kw : tLABEL primary_value
{
NODE *lasgn;
arg_var(formal_argument(get_id($1)));
$$ = assignable($1, $2);
lasgn = assignable($1, $2);
$$ = NEW_OP_ASGN_OR(gettable(lasgn->nd_vid), lasgn);
/*%%%*/
$$ = NEW_KW_ARG(0, $$);
/*%
vm_core.h
int arg_post_start;
int arg_size;
VALUE *arg_opt_table;
int arg_keywords;
ID *arg_keyword_table;
int *arg_keyword_vars;
size_t stack_max; /* for stack overflow check */
vm_insnhelper.c
th->mark_stack_len = argc + iseq->arg_size;
if (iseq->arg_keywords && argc > 0 && TYPE(argv[argc-1]) == T_HASH) {
VALUE hash = argv[argc-1];
int i;
argc--;
for (i = 0; i < iseq->arg_keywords; i++) {
VALUE val = rb_hash_aref(hash, ID2SYM(iseq->arg_keyword_table[i]));
orig_argv[iseq->arg_keyword_vars[i]] = val;
}
}
/* mandatory */
if (argc < (m + iseq->arg_post_len)) { /* check with post arg */
argument_error(iseq, argc, m + iseq->arg_post_len);
......
iseq->local_size, iseq->arg_size);
/* clear local variables */
for (i = 0; i < iseq->local_size - iseq->arg_size; i++) {
sp += iseq->arg_keywords;
for (i = iseq->arg_keywords; i < iseq->local_size - iseq->arg_size; i++) {
*sp++ = Qnil;
}
......
sp -= rsp - p_rsp;
/* clear local variables */
for (i = 0; i < iseq->local_size - iseq->arg_size; i++) {
sp += iseq->arg_keywords;
for (i = iseq->arg_keywords; i < iseq->local_size - iseq->arg_size; i++) {
*sp++ = Qnil;
}
(4-4/6)