aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-03-21 11:15:15 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-03-21 11:15:15 +0000
commitbb7a2d40ff6190f819feb3d9eef0caaffec1a3f9 (patch)
treee50ce2d744f47f485bc2d1a4bb7eae57f5a9ed87
parentdf896a05608e4041c36488c60218f06ca74830b9 (diff)
downloadruby-bb7a2d40ff6190f819feb3d9eef0caaffec1a3f9.tar.gz
* compile.c, parse.y, eval.c, intern.h, iseq.c, lex.c, node.h,
proc.c, vm.c, vm_macro.def, vm_macro.def, yarvcore.c, yarvcore.h, debug.c, debug.h: merge half-baked-1.9 changes. The biggest change is to change node structure around NODE_SCOPE, NODE_ARGS. Every scope (method/class/block) has own NODE_SCOPE node and NODE_ARGS represents more details of arguments information. I'll write a document about detail of node structure. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12117 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog11
-rw-r--r--compile.c616
-rw-r--r--debug.c11
-rw-r--r--debug.h5
-rw-r--r--eval.c73
-rw-r--r--intern.h3
-rw-r--r--iseq.c34
-rw-r--r--lex.c2
-rw-r--r--node.h26
-rw-r--r--parse.y680
-rw-r--r--proc.c2
-rw-r--r--vm.c83
-rw-r--r--vm_macro.def42
-rw-r--r--yarvcore.c2
-rw-r--r--yarvcore.h3
15 files changed, 561 insertions, 1032 deletions
diff --git a/ChangeLog b/ChangeLog
index 3138fb64ba..3adc39ab8a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Wed Mar 21 20:05:07 2007 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, parse.y, eval.c, intern.h, iseq.c, lex.c, node.h,
+ proc.c, vm.c, vm_macro.def, vm_macro.def, yarvcore.c, yarvcore.h,
+ debug.c, debug.h: merge half-baked-1.9 changes. The biggest change
+ is to change node structure around NODE_SCOPE, NODE_ARGS. Every
+ scope (method/class/block) has own NODE_SCOPE node and NODE_ARGS
+ represents more details of arguments information. I'll write a
+ document about detail of node structure.
+
+
Wed Mar 21 17:04:30 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* bignum.c (rb_big2str0): round up for the most significant digit.
diff --git a/compile.c b/compile.c
index 8ccdb33d21..c2d8559bd3 100644
--- a/compile.c
+++ b/compile.c
@@ -108,8 +108,8 @@ static int set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
static int set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
static int set_exception_table(rb_iseq_t *iseq);
-static int set_localtbl(rb_iseq_t *iseq, ID *tbl);
-static int set_localtbl_eval(rb_iseq_t *iseq, ID *tbl);
+static int set_local_table(rb_iseq_t *iseq, ID *tbl);
+static int set_local_table_eval(rb_iseq_t *iseq, ID *tbl);
static int set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE * node);
static NODE *set_block_local_tbl(rb_iseq_t *iseq, NODE * node,
LINK_ANCHOR *anchor);
@@ -138,118 +138,56 @@ iseq_add_mark_object_compile_time(rb_iseq_t *iseq, VALUE v)
#endif
VALUE
-rb_iseq_compile(VALUE self, NODE *narg)
+rb_iseq_compile(VALUE self, NODE *node)
{
- DECL_ANCHOR(list_anchor);
+ DECL_ANCHOR(ret);
rb_iseq_t *iseq;
- NODE *node = (NODE *) narg;
GetISeqPtr(self, iseq);
- debugs("[compile step 1 (traverse each node)]\n");
+ if (nd_type(node) == NODE_SCOPE) {
+ /* iseq type of top, method, class, block */
+ set_local_table(iseq, node->nd_tbl);
+ set_arguments(iseq, ret, node->nd_args);
- iseq->node = node;
-
- if (iseq->type == ISEQ_TYPE_BLOCK) {
- node = set_block_local_tbl(iseq, node, list_anchor);
- }
-
- if (node && nd_type(node) == NODE_SCOPE) {
- /* with node scope */
- NODE *sn_body = node->nd_next; /* sn: scope node */
- NODE *ndargs = 0;
-
- if (iseq->type != ISEQ_TYPE_BLOCK) {
- set_localtbl(iseq, ((NODE *) node)->nd_tbl);
- }
-
- if (sn_body) {
- switch (nd_type(sn_body)) {
- case NODE_BLOCK:
- if (nd_type(sn_body->nd_head) == NODE_ARGS) {
- /* some method attribute process */
- ndargs = sn_body->nd_head;
- set_arguments(iseq, list_anchor, ndargs);
-
- /* with sn_body->nd_head */
- if (iseq->type == ISEQ_TYPE_METHOD) {
- COMPILE(list_anchor, "normal method",
- sn_body->nd_next);
- }
- else if (iseq->type == ISEQ_TYPE_CLASS) {
- COMPILE(list_anchor, "class/module",
- sn_body->nd_next);
- }
- else {
- rb_bug("must be class or method");
- }
- }
- else {
- /* normal block */
- if (iseq->type == ISEQ_TYPE_CLASS) {
- COMPILE(list_anchor, "class/module", sn_body);
- }
- else if (iseq->type == ISEQ_TYPE_BLOCK) {
- COMPILE(list_anchor, "normal block", sn_body);
- }
- else {
- rb_bug("must be class or block");
- }
- }
- break;
- case NODE_ARGS:
- /* empty method */
- /* some method attribute process */
- debugs("empty method\n");
-
- set_arguments(iseq, list_anchor, sn_body);
- ADD_INSN(list_anchor, nd_line(sn_body), putnil);
- break;
-
- default:
- COMPILE(list_anchor, "other scope", sn_body);
- break;
- }
- }
- else {
- /* sn_body == 0 */
- ADD_INSN(list_anchor, 0, putnil);
- }
- }
- else {
if (iseq->type == ISEQ_TYPE_BLOCK) {
- VALUE tmp;
+ VALUE tmp; /* required by ADD_LABEL */
LABEL *start = iseq->compile_data->start_label = NEW_LABEL(0);
LABEL *end = iseq->compile_data->end_label = NEW_LABEL(0);
- ADD_LABEL(list_anchor, iseq->compile_data->start_label);
- COMPILE(list_anchor, "block body", node);
- ADD_LABEL(list_anchor, iseq->compile_data->end_label);
+ ADD_LABEL(ret, iseq->compile_data->start_label);
+ COMPILE(ret, "block body", node->nd_body);
+ ADD_LABEL(ret, iseq->compile_data->end_label);
/* wide range catch handler must put at last */
ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, 0, start);
ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, 0, end);
}
- else if (iseq->type == ISEQ_TYPE_TOP) {
- set_localtbl(iseq, GET_THREAD()->top_local_tbl);
- COMPILE(list_anchor, "top level node", node);
+ else {
+ COMPILE(ret, "scoped node", node->nd_body);
}
- else if (iseq->type == ISEQ_TYPE_EVAL) {
- set_localtbl_eval(iseq, GET_THREAD()->top_local_tbl);
- COMPILE(list_anchor, "eval node", node);
+ }
+ else {
+ if (iseq->type == ISEQ_TYPE_METHOD ||
+ iseq->type == ISEQ_TYPE_CLASS ||
+ iseq->type == ISEQ_TYPE_BLOCK ||
+ iseq->type == ISEQ_TYPE_EVAL ||
+ iseq->type == ISEQ_TYPE_TOP) {
+ dpn(node);
+ rb_bug("compile/should not be reached: %s:%d", __FILE__, __LINE__);
}
else if (iseq->type == ISEQ_TYPE_RESCUE) {
set_exception_tbl(iseq);
- COMPILE(list_anchor, "rescue", node);
+ COMPILE(ret, "rescue", node);
}
else if (iseq->type == ISEQ_TYPE_ENSURE) {
set_exception_tbl(iseq);
- COMPILE_POPED(list_anchor, "ensure", node);
+ COMPILE_POPED(ret, "ensure", node);
}
else if (iseq->type == ISEQ_TYPE_DEFINED_GUARD) {
- COMPILE(list_anchor, "defined guard", node);
+ COMPILE(ret, "defined guard", node);
}
else if (node == 0) {
- COMPILE(list_anchor, "nil", node);
+ COMPILE(ret, "nil", node);
}
else {
rb_bug("unknown scope");
@@ -259,14 +197,14 @@ rb_iseq_compile(VALUE self, NODE *narg)
GC_CHECK();
if (iseq->type == ISEQ_TYPE_RESCUE || iseq->type == ISEQ_TYPE_ENSURE) {
- ADD_INSN2(list_anchor, 0, getdynamic, INT2FIX(1), INT2FIX(0));
- ADD_INSN1(list_anchor, 0, throw, INT2FIX(0) /* continue throw */ );
+ ADD_INSN2(ret, 0, getdynamic, INT2FIX(1), INT2FIX(0));
+ ADD_INSN1(ret, 0, throw, INT2FIX(0) /* continue throw */ );
}
else {
- ADD_INSN(list_anchor, iseq->compile_data->last_line, leave);
+ ADD_INSN(ret, iseq->compile_data->last_line, leave);
}
- return iseq_setup(iseq, list_anchor);
+ return iseq_setup(iseq, ret);
}
VALUE th_eval(void *);
@@ -323,7 +261,6 @@ compile_data_alloc(rb_iseq_t *iseq, size_t size)
sizeof(struct
iseq_compile_data_storage));
storage = iseq->compile_data->storage_current = storage->next;
-
storage->next = 0;
storage->pos = 0;
storage->size = alloc_size;
@@ -780,274 +717,6 @@ set_exception_tbl(rb_iseq_t *iseq)
}
static int
-search_block_local_variables(NODE * node, VALUE local_vars)
-{
- switch (nd_type(node)) {
- case NODE_DASGN_CURR:{
- rb_ary_push(local_vars, ID2SYM(node->nd_vid));
- break;
- }
- case NODE_MASGN:{
- NODE *narg = node->nd_head;
- while (narg) {
- search_block_local_variables(narg->nd_head, local_vars);
- narg = narg->nd_next;
- }
- if (node->nd_args != 0 && (long)node->nd_args != -1) {
- search_block_local_variables(node->nd_args, local_vars);
- break;
- }
- }
- default:
- break;
- }
- return COMPILE_OK;
-}
-
-static NODE *
-search_block_local_parameters(rb_iseq_t *iseq, NODE * lnode)
-{
- NODE *node = lnode;
- NODE *nelem;
- VALUE local_vars = rb_ary_new();
- VALUE param_vars = rb_ary_new();
-
- /* search args */
- if (node->nd_var && (VALUE)node->nd_var != 1) {
- switch (nd_type(node->nd_var)) {
- case NODE_DASGN_CURR:
- iseq->argc = 1;
- rb_ary_push(param_vars, ID2SYM(node->nd_var->nd_vid));
- debugi("block 1arg", node->nd_var->nd_vid);
- break;
- case NODE_MASGN:{
- int i;
- nelem = node->nd_var->nd_head;
- if (nelem != 0) {
- iseq->argc = node->nd_var->nd_head->nd_alen;
- for (i = 0; i < iseq->argc; i++, nelem = nelem->nd_next) {
- if (nd_type(nelem->nd_head) == NODE_DASGN_CURR) {
- rb_ary_push(param_vars,
- ID2SYM(nelem->nd_head->nd_vid));
- debugi("block arg", nelem->nd_head->nd_vid);
- }
- else {
- char buff[0x20];
- ID id;
- int idx = iseq->argc - RARRAY_LEN(param_vars);
- snprintf(buff, 0x20, "#blp%d", idx);
- id = rb_intern(buff);
- rb_ary_push(param_vars, ID2SYM(id));
- debugi("block arg (auto)", id);
- search_block_local_variables(nelem->nd_head,
- local_vars);
- }
- }
- }
- if (node->nd_var->nd_args) {
- NODE *sn = node->nd_var->nd_args;
- if ((long)sn != -1) {
- if (nd_type(sn) == NODE_DASGN_CURR) {
- rb_ary_push(param_vars, ID2SYM(sn->nd_vid));
- }
- else {
- rb_ary_push(param_vars,
- ID2SYM(rb_intern("#blp_splat")));
- debugi("block/splat (auto)",
- rb_intern("#blp_splat"));
- }
- }
- }
- break;
- }
- default:
- rb_ary_push(param_vars, ID2SYM(rb_intern("#blp")));
- debugi("block 1arg (auto)", rb_intern("#blp"));
- iseq->argc = 1;
- break;
- }
- }
- else {
- iseq->argc = 0;
- }
-
- node = node->nd_body;
-
- /* other block local variables 2 */
- if (node && nd_type(node) == NODE_BLOCK) {
- nelem = node->nd_head;
- if (nelem && nd_type(nelem) == NODE_DASGN_CURR) {
- while (nelem && nd_type(nelem) == NODE_DASGN_CURR) {
- if (!rb_ary_includes(local_vars, ID2SYM(nelem->nd_vid))) {
- debugi("block initialized variable", nelem->nd_vid);
- rb_ary_push(local_vars, ID2SYM(nelem->nd_vid));
- }
- nelem = nelem->nd_value;
- }
- if (nelem == 0) {
- node = node->nd_next;
- }
- }
- }
-
- /* translate to block inlining code */
- if (iseq->special_block_builder != 0) {
- node = ((NODE * (*)(rb_iseq_t *, NODE *, NODE *, VALUE, VALUE))
- iseq->special_block_builder) (iseq, node, lnode->nd_var,
- param_vars, local_vars);
- }
-
- rb_ary_concat(param_vars, local_vars);
- local_vars = param_vars;
-
- {
- int i, size = RARRAY_LEN(local_vars);
-
- if (size > 0) {
- iseq->local_table = ALLOC_N(ID, size);
- for (i = 0; i < size; i++) {
- iseq->local_table[i] = SYM2ID(RARRAY_PTR(local_vars)[i]);
- debugi("block local variable", iseq->local_table[i]);
- }
- }
- iseq->local_table_size = iseq->local_size = size;
- }
- return node;
-}
-
-static int
-set_block_initializer(rb_iseq_t *iseq, NODE * node, LINK_ANCHOR *anchor, int didx)
-{
- DECL_ANCHOR(anc);
- LINK_ELEMENT *elem;
-
- COMPILE_POPED(anc, "set_block_local_tbl#masgn/other", node);
-
- if (nd_type(node) == NODE_ATTRASGN) {
- INSN *iobj = (INSN *)anc->last->prev;
- iobj->operands[1] = INT2FIX(FIX2INT(iobj->operands[1]) + 1);
- INSERT_ELEM_PREV((void *)iobj,
- (void *)new_insn_body(iseq, nd_line(node),
- BIN(getdynamic), 2,
- INT2FIX(didx), INT2FIX(0)));
- }
- else {
- ADD_INSN2(anchor, nd_line(node), getdynamic,
- INT2FIX(didx), INT2FIX(0));
- elem = FIRST_ELEMENT(anc);
- if (elem->type == ISEQ_ELEMENT_INSN &&
- ((INSN *)elem)->insn_id == BIN(putnil)) {
- SHIFT_ELEMENT(anc);
- }
- }
- APPEND_LIST(anchor, anc);
-
- return COMPILE_OK;
-}
-
-static NODE *
-set_block_local_tbl(rb_iseq_t *iseq, NODE * node, LINK_ANCHOR *anchor)
-{
- NODE *rnode;
-
- /* argument check */
- if (iseq->type != ISEQ_TYPE_BLOCK) {
- rb_bug("set_block_local_tbl: unexpected iseq type");
- }
-
- rnode = search_block_local_parameters(iseq, node);
-
- if ((VALUE)node->nd_var == 1) {
- /* TODO */
- }
- else if (node->nd_var) {
- NODE *nargs = node->nd_var;
- switch (nd_type(nargs)) {
- case NODE_MASGN:{
- NODE *massign = nargs;
- int i = 0;
- if (nargs->nd_head != 0) {
- NODE *lhsn = massign->nd_head;
-
- while (lhsn) {
- if (nd_type(lhsn->nd_head) != NODE_DASGN_CURR) {
- /* idx-th param, current level */
- set_block_initializer(iseq, lhsn->nd_head,
- anchor, iseq->local_size - i);
- }
- i++;
- lhsn = lhsn->nd_next;
- }
- }
-
- /* check rest */
- if (massign->nd_args != 0 && (long)massign->nd_args != -1) {
- iseq->argc++;
- iseq->arg_rest = i + 1;
-
- if (nd_type(massign->nd_args) != NODE_DASGN_CURR) {
- set_block_initializer(iseq, massign->nd_args,
- anchor, iseq->local_size - i);
- }
- }
- else if (i == 1) {
- iseq->arg_rest = -1;
- }
- break;
- }
-
- case NODE_DASGN_CURR:
- break;
-
- case NODE_ARGS:{
- /* make parameters */
- VALUE a = nargs->nd_frml;
- int i;
- int argc = a ? RARRAY_LEN(a) : 0;
- int local_size = argc + iseq->local_size - 1;
- ID *local_tbl = local_size > 0 ? ALLOC_N(ID, local_size) : 0;
-
- for (i=0; i<argc; i++) {
- ID id = SYM2ID(RARRAY_PTR(a)[i]);
- debugi("NODE_ARGS param", id);
- local_tbl[i] = id;
- }
-
- if (iseq->local_table) {
- /* copy from old local tbl and delete it */
- for (i=1; i<iseq->local_size; i++) {
- local_tbl[argc + i - 1] = iseq->local_table[i];
- }
- ruby_xfree(iseq->local_table);
- }
- iseq->local_table = local_tbl;
- iseq->local_size = local_size;
- iseq->argc = argc;
- break;
- }
- default:{
- /* for 1.x compatibility */
- /* first param, current level */
- set_block_initializer(iseq, nargs, anchor, iseq->local_size);
- break;
- }
- }
- }
-
- if (iseq->arg_opts || iseq->arg_rest || iseq->arg_block) {
- iseq->arg_simple = 0;
- }
- else {
- iseq->arg_simple = 1;
- }
-
- if (nd_type(node) == NODE_FOR) {
- iseq->compile_data->for_iseq = 1;
- }
- return rnode;
-}
-
-static int
get_dyna_var_idx_at_raw(rb_iseq_t *iseq, ID id)
{
int i;
@@ -1066,6 +735,7 @@ get_local_var_idx(rb_iseq_t *iseq, ID id)
int idx = get_dyna_var_idx_at_raw(iseq->local_iseq, id);
if (idx == -1) {
+ dpi(id);
rb_bug("get_local_var_idx: -1");
}
@@ -1091,141 +761,69 @@ get_dyna_var_idx(rb_iseq_t *iseq, ID id, int *level, int *ls)
return -1;
}
-#if 1
-
static int
-set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_arg)
+set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args)
{
- NODE *node_aux = node_arg->nd_next;
- NODE *node_opt = 0;
- ID rest_id = 0;
- ID block_id = 0;
- ID post_start_id = 0;
- int post_len = 0;
- NODE *node_init = 0;
- int d = iseq->local_size - iseq->local_table_size;
-
- iseq->argc = node_arg->nd_frml;
- node_opt = node_arg->nd_opt;
-
- if (node_aux) {
- rest_id = node_aux->nd_rest;
- block_id = (ID)node_aux->nd_body;
- node_aux = node_aux->nd_next;
-
- if (node_aux) {
- post_start_id = node_aux->nd_pid;
- post_len = node_aux->nd_plen;
- node_init = node_aux->nd_next;
+ debugs("set_arguments: %s\n", node_args ? "" : "0");
+
+ if (node_args) {
+ NODE *node_aux = node_args->nd_next;
+ int mandatory_len = 0;
+ NODE *node_opt = node_args->nd_opt;
+ ID rest_id = 0;
+ ID block_id = 0;
+ ID post_start_id = 0;
+ int post_len = 0;
+ NODE *node_init = 0;
+ int d = iseq->local_size - iseq->local_table_size;
+
+ if (nd_type(node_args) != NODE_ARGS) {
+ rb_bug("set_arguments: NODE_ARGS is expected, but %s", ruby_node_name(nd_type(node_args)));
}
- }
-
- if (node_init) {
- COMPILE(optargs, "arguments", node_init);
- }
-
- if (node_opt) {
- NODE *node = node_opt;
- LABEL *label;
- VALUE labels = rb_ary_new();
- int i = 0, j;
-
- while (node) {
- label = NEW_LABEL(nd_line(node));
- rb_ary_push(labels, (VALUE)label | 1);
- ADD_LABEL(optargs, label);
- COMPILE_POPED(optargs, "optarg", node->nd_body);
- node = node->nd_next;
- i += 1;
- }
- /* last label */
- label = NEW_LABEL(nd_line(node_arg));
- rb_ary_push(labels, (VALUE)label | 1);
- ADD_LABEL(optargs, label);
- i += 1;
-
- iseq->arg_opts = i;
- iseq->arg_opt_tbl = ALLOC_N(VALUE, i);
- MEMCPY(iseq->arg_opt_tbl, RARRAY_PTR(labels), VALUE, i);
- for (j = 0; j < i; j++) {
- iseq->arg_opt_tbl[j] &= ~1;
- }
- }
- else {
- iseq->arg_opts = 0;
- }
+ iseq->argc = node_args->nd_frml;
+ debugs(" - argc: %d\n", iseq->argc);
- if ((long)rest_id == -1) {
- iseq->arg_rest = get_dyna_var_idx_at_raw(iseq, 0 /* dummy var */) + d;
- }
- else if (rest_id) {
- iseq->arg_rest = get_dyna_var_idx_at_raw(iseq, rest_id) + d;
- }
- if (iseq->arg_rest == -1) {
- rb_bug("arg_rest: -1");
- }
-
- if (block_id) {
- iseq->arg_block = get_dyna_var_idx_at_raw(iseq, block_id) + d;
- }
-
- if (iseq->arg_rest != 0 || iseq->arg_opts != 0 || iseq->arg_block != 0) {
- iseq->arg_simple = 0;
- }
- else {
- iseq->arg_simple = 1;
- }
-
- return COMPILE_OK;
-}
-
-#else
-
-static int
-set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE * node)
-{
- int i, j;
-
- if (node) {
- /* normal method */
- if (node->nd_frml) {
- iseq->argc = RARRAY_LEN(node->nd_frml);
- }
- else {
- iseq->argc = 0;
+ if (node_aux) {
+ rest_id = node_aux->nd_rest;
+ block_id = (ID)node_aux->nd_body;
+ node_aux = node_aux->nd_next;
+
+ if (node_aux) {
+ post_start_id = node_aux->nd_pid;
+ post_len = node_aux->nd_plen;
+ node_init = node_aux->nd_next;
+ }
}
- if (node->nd_rest) {
- iseq->arg_rest = node->nd_rest->nd_cnt - 2 + 1;
+ if (node_init) {
+ COMPILE_POPED(optargs, "init arguments", node_init);
}
- /* optional initializer */
- if (node->nd_opt) {
- NODE *optarg = node->nd_opt;
+ if (node_opt) {
+ NODE *node = node_opt;
LABEL *label;
VALUE labels = rb_ary_new();
- i = 0;
- while (optarg) {
+ int i = 0, j;
+
+ while (node) {
label = NEW_LABEL(nd_line(node));
rb_ary_push(labels, (VALUE)label | 1);
ADD_LABEL(optargs, label);
- COMPILE_POPED(optargs, "optarg", optarg->nd_head);
-
- optarg = optarg->nd_next;
+ COMPILE_POPED(optargs, "optarg", node->nd_body);
+ node = node->nd_next;
i += 1;
}
+
/* last label */
- label = NEW_LABEL(nd_line(node));
+ label = NEW_LABEL(nd_line(node_args));
rb_ary_push(labels, (VALUE)label | 1);
ADD_LABEL(optargs, label);
i += 1;
iseq->arg_opts = i;
iseq->arg_opt_tbl = ALLOC_N(VALUE, i);
-
MEMCPY(iseq->arg_opt_tbl, RARRAY_PTR(labels), VALUE, i);
-
for (j = 0; j < i; j++) {
iseq->arg_opt_tbl[j] &= ~1;
}
@@ -1233,30 +831,37 @@ set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE * node)
else {
iseq->arg_opts = 0;
}
- }
- else {
- iseq->argc = 0;
- iseq->arg_rest = 0;
- iseq->arg_opts = 0;
- }
- if (iseq->arg_rest != 0 || iseq->arg_opts != 0) {
- iseq->arg_simple = 0;
- }
- else {
- iseq->arg_simple = 1;
+ if (rest_id) {
+ iseq->arg_rest = get_dyna_var_idx_at_raw(iseq, rest_id) + d;
+
+ if (iseq->arg_rest == -1) {
+ rb_bug("arg_rest: -1");
+ }
+ }
+
+ if (block_id) {
+ iseq->arg_block = get_dyna_var_idx_at_raw(iseq, block_id) + d;
+ }
+
+ if (iseq->arg_opts != 0 || iseq->arg_rest != -1 || iseq->arg_block != -1) {
+ iseq->arg_simple = 0;
+ }
+ else {
+ iseq->arg_simple = 1;
+ }
}
return COMPILE_OK;
}
-#endif
static int
-set_localtbl(rb_iseq_t *iseq, ID *tbl)
+set_local_table(rb_iseq_t *iseq, ID *tbl)
{
int size;
if (tbl) {
- size = *tbl - 2 /* $~, $_ */;
+ size = *tbl;
+ tbl++;
}
else {
size = 0;
@@ -1264,17 +869,23 @@ set_localtbl(rb_iseq_t *iseq, ID *tbl)
if (size > 0) {
iseq->local_table = (ID *)ALLOC_N(ID *, size);
- MEMCPY(iseq->local_table, tbl + 3 /* size, $~, $_ */, ID *, size);
+ MEMCPY(iseq->local_table, tbl, ID *, size);
}
- iseq->local_table_size = size;
- iseq->local_size = size + 1 /* svar */;
+ iseq->local_size = iseq->local_table_size = size;
+
+ if (iseq->type == ISEQ_TYPE_METHOD ||
+ iseq->type == ISEQ_TYPE_CLASS ||
+ iseq->type == ISEQ_TYPE_TOP) {
+ iseq->local_size += 1 /* svar */;
+ }
+ debugs("set_local_table: %d, %d\n", iseq->local_size, iseq->local_table_size);
return COMPILE_OK;
}
static int
-set_localtbl_eval(rb_iseq_t *iseq, ID *tbl)
+set_local_table_eval(rb_iseq_t *iseq, ID *tbl)
{
int size;
if (tbl) {
@@ -3058,7 +2669,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
COMPILE(ret, "iter caller (for)", node->nd_iter);
iseq->compile_data->current_block =
- NEW_CHILD_ISEQVAL(node, make_name_for_block(iseq),
+ NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq),
ISEQ_TYPE_BLOCK);
mid = idEach;
@@ -3070,7 +2681,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
}
else {
iseq->compile_data->current_block =
- NEW_CHILD_ISEQVAL(node, make_name_for_block(iseq),
+ NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq),
ISEQ_TYPE_BLOCK);
COMPILE_(ret, "iter caller", node->nd_iter, poped);
}
@@ -3364,7 +2975,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
}
case NODE_MASGN:{
- compile_massign(iseq, ret, node->nd_value, /* rhsn */
+ compile_massign(iseq, ret,
+ node->nd_value, /* rhsn */
node->nd_args, /* splat */
node->nd_head, /* lhsn */
0);
@@ -3379,7 +2991,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
int idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id);
debugs("lvar: %s idx: %d\n", rb_id2name(id), idx);
- COMPILE(ret, "lvalue", node->nd_value);
+ COMPILE(ret, "rvalue", node->nd_value);
if (!poped) {
ADD_INSN(ret, nd_line(node), dup);
@@ -3397,16 +3009,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
if (!poped) {
ADD_INSN(ret, nd_line(node), dup);
}
- idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls);
- if (nd_type(node) == NODE_DASGN_CURR &&
- lv > 0 &&
- iseq->type == ISEQ_TYPE_BLOCK &&
- iseq->compile_data->for_iseq != 1) {
- dpi(node->nd_vid);
- rb_bug("NODE_DASGN_CURR, but lv == %d (line: %d)", lv,
- nd_line(node));
- }
+ idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls);
if (idx < 0) {
debugi("unknown id", node->nd_vid);
@@ -4531,7 +4135,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
break;
}
case NODE_POSTEXE:{
- VALUE block = NEW_CHILD_ISEQVAL(node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK);
+ VALUE block = NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK);
ADD_INSN1(ret, nd_line(node), postexe, block);
if (!poped) {
ADD_INSN(ret, nd_line(node), putnil);
@@ -4624,7 +4228,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
}
case NODE_LAMBDA:{
/* compile same as lambda{...} */
- VALUE block = NEW_CHILD_ISEQVAL(node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK);
+ VALUE block = NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK);
VALUE argc = INT2FIX(0);
ADD_CALL_RECEIVER(ret, nd_line(node));
ADD_CALL_WITH_BLOCK(ret, nd_line(node), ID2SYM(idLambda), argc, block);
diff --git a/debug.c b/debug.c
index 3e8b143caa..7dca05b5db 100644
--- a/debug.c
+++ b/debug.c
@@ -54,6 +54,17 @@ ruby_debug_id(int level, int debug_level, char *header, ID id)
return id;
}
+NODE *
+ruby_debug_node(int level, int debug_level, char *header, NODE *node)
+{
+ if (level < debug_level) {
+ fprintf(stderr, "DBG> %s: %s\n", header, ruby_node_name(nd_type(node)));
+ fflush(stderr);
+ }
+ return node;
+}
+
+
void
ruby_debug_gc_check_func(void)
{
diff --git a/debug.h b/debug.h
index 5f9fb27c52..b25fa6ddce 100644
--- a/debug.h
+++ b/debug.h
@@ -14,14 +14,17 @@
#define _DEBUG_H_INCLUDED_
#include <ruby.h>
+#include <node.h>
#define dpv(h,v) ruby_debug_value(-1, 0, h, v)
#define dp(v) ruby_debug_value(-1, 0, "", v)
-#define dpi(i) ruby_debug_id (-1, 0, "", i)
+#define dpi(i) ruby_debug_id(-1, 0, "", i)
#define bp() ruby_debug_breakpoint()
+#define dpn(n) ruby_debug_node(-1, 0, "", n)
VALUE ruby_debug_value(int level, int debug_level, char *header, VALUE v);
ID ruby_debug_id(int level, int debug_level, char *header, ID id);
+NODE *ruby_debug_node(int level, int debug_level, char *header, NODE *node);
void ruby_debug_indent(int level, int debug_level, int indent_level);
void ruby_debug_breakpoint(void);
void ruby_debug_gc_check_func(void);
diff --git a/eval.c b/eval.c
index cfd0fbfb42..a96f9b8d9d 100644
--- a/eval.c
+++ b/eval.c
@@ -1942,6 +1942,7 @@ eval(VALUE self, VALUE src, VALUE scope, char *file, int line)
th->parse_in_eval--;
th_set_eval_stack(th, iseqval);
th->base_block = 0;
+
if (0) { /* for debug */
extern VALUE ruby_iseq_disasm(VALUE);
printf("%s\n", RSTRING_PTR(ruby_iseq_disasm(iseqval)));
@@ -2803,7 +2804,11 @@ rb_f_local_variables(void)
for (i = 0; i < cfp->iseq->local_table_size; i++) {
ID lid = cfp->iseq->local_table[i];
if (lid) {
- rb_ary_push(ary, rb_str_new2(rb_id2name(lid)));
+ const char *vname = rb_id2name(lid);
+ /* should skip temporary variable */
+ if (vname) {
+ rb_ary_push(ary, rb_str_new2(vname));
+ }
}
}
}
@@ -2984,7 +2989,7 @@ Init_eval(void)
/* for parser */
-VALUE
+int
rb_dvar_defined(ID id)
{
rb_thread_t *th = GET_THREAD();
@@ -2996,72 +3001,34 @@ rb_dvar_defined(ID id)
iseq->type == ISEQ_TYPE_EVAL) {
int i;
- /* printf("local size: %d\n", iseq->local_size); */
for (i = 0; i < iseq->local_table_size; i++) {
- /* printf("id (%4d): %s\n", i, rb_id2name(iseq->local_tbl[i])); */
if (iseq->local_table[i] == id) {
- return Qtrue;
+ return 1;
}
}
iseq = iseq->parent_iseq;
}
}
- return Qfalse;
-}
-
-void
-rb_scope_setup_top_local_tbl(ID *tbl)
-{
- rb_thread_t *th = GET_THREAD();
- if (tbl) {
- if (th->top_local_tbl) {
- xfree(th->top_local_tbl);
- th->top_local_tbl = 0;
- }
- th->top_local_tbl = tbl;
- }
- else {
- th->top_local_tbl = 0;
- }
+ return 0;
}
int
-rb_scope_base_local_tbl_size(void)
+rb_local_defined(ID id)
{
rb_thread_t *th = GET_THREAD();
- if (th->base_block) {
- return th->base_block->iseq->local_iseq->local_size +
- 2 /* $_, $~ */ - 1 /* svar */ ;
- }
- else {
- return 0;
- }
-}
+ rb_iseq_t *iseq;
-ID
-rb_scope_base_local_tbl_id(int i)
-{
- rb_thread_t *th = GET_THREAD();
- switch (i) {
- case 0:
- return rb_intern("$_");
- case 1:
- return rb_intern("$~");
- default:
- return th->base_block->iseq->local_iseq->local_table[i-2];
- }
-}
+ if (th->base_block && th->base_block->iseq) {
+ int i;
+ iseq = th->base_block->iseq->local_iseq;
-int
-rb_dvar_current(void)
-{
- rb_thread_t *th = GET_THREAD();
- if (th->base_block) {
- return 1;
- }
- else {
- return 0;
+ for (i=0; i<iseq->local_table_size; i++) {
+ if (iseq->local_table[i] == id) {
+ return 1;
+ }
+ }
}
+ return 0;
}
int
diff --git a/intern.h b/intern.h
index 0d9fa12476..1f4c2d3085 100644
--- a/intern.h
+++ b/intern.h
@@ -217,9 +217,6 @@ void rb_clear_cache_by_class(VALUE);
void rb_alias(VALUE, ID, ID);
void rb_attr(VALUE,ID,int,int,int);
int rb_method_boundp(VALUE, ID, int);
-VALUE rb_dvar_defined(ID);
-VALUE rb_dvar_curr(ID);
-VALUE rb_dvar_ref(ID);
void rb_dvar_asgn(ID, VALUE);
void rb_dvar_push(ID, VALUE);
VALUE *rb_svar(int);
diff --git a/iseq.c b/iseq.c
index 06ca48f613..4a2bed7c5a 100644
--- a/iseq.c
+++ b/iseq.c
@@ -116,8 +116,8 @@ prepare_iseq_build(rb_iseq_t *iseq,
RBASIC(iseq->iseq_mark_ary)->klass = 0;
iseq->type = type;
- iseq->arg_rest = 0;
- iseq->arg_block = 0;
+ iseq->arg_rest = -1;
+ iseq->arg_block = -1;
iseq->klass = 0;
iseq->special_block_builder = GC_GUARDED_PTR_REF(block_opt);
iseq->cached_special_block_builder = 0;
@@ -545,10 +545,10 @@ insn_operand_intern(rb_iseq_t *iseq,
{
rb_iseq_t *ip = iseq->local_iseq;
int lidx = ip->local_size - op;
- ID id = ip->local_table[lidx];
+ const char *name = rb_id2name(ip->local_table[lidx]);
- if (id) {
- ret = rb_str_new2(rb_id2name(id));
+ if (name) {
+ ret = rb_str_new2(name);
}
else {
ret = rb_str_new2("*");
@@ -558,12 +558,17 @@ insn_operand_intern(rb_iseq_t *iseq,
case TS_DINDEX:{
if (insn == BIN(getdynamic) || insn == BIN(setdynamic)) {
rb_iseq_t *ip = iseq;
- int level = *pnop;
- int i;
+ int level = *pnop, i;
+ const char *name;
for (i = 0; i < level; i++) {
ip = ip->parent_iseq;
}
- ret = rb_str_new2(rb_id2name(ip->local_table[ip->local_size - op]));
+ name = rb_id2name(ip->local_table[ip->local_size - op]);
+
+ if (!name) {
+ name = "*";
+ }
+ ret = rb_str_new2(name);
}
else {
ret = rb_inspect(INT2FIX(op));
@@ -704,7 +709,7 @@ ruby_iseq_disasm(VALUE self)
VALUE str = rb_str_new(0, 0);
VALUE child = rb_ary_new();
unsigned long size;
- int i;
+ int i, d = iseqdat->local_size - iseqdat->local_table_size;
ID *tbl;
char buff[0x200];
@@ -744,8 +749,11 @@ ruby_iseq_disasm(VALUE self)
if (tbl) {
snprintf(buff, sizeof(buff),
- "local scope table (size: %d, argc: %d)\n",
- iseqdat->local_size, iseqdat->argc);
+ "local table (size: %d, argc: %d "
+ "[opts: %d, rest: %d, block: %d] %s)\n",
+ iseqdat->local_size, iseqdat->argc,
+ iseqdat->arg_opts, iseqdat->arg_rest, iseqdat->arg_block,
+ iseqdat->arg_simple ? "s" : "c");
rb_str_cat2(str, buff);
for (i = 0; i < iseqdat->local_table_size; i++) {
@@ -766,8 +774,8 @@ ruby_iseq_disasm(VALUE self)
snprintf(argi, sizeof(argi), "%s%s%s%s", /* arg, opts, rest, block */
iseqdat->argc > i ? "Arg" : "",
opti,
- iseqdat->arg_rest - 1 == i ? "Rest" : "",
- iseqdat->arg_block - 1 == i ? "Block" : "");
+ iseqdat->arg_rest - d == i ? "Rest" : "",
+ iseqdat->arg_block - d == i ? "Block" : "");
snprintf(info, sizeof(info), "%s%s%s%s", name ? name : "?",
*argi ? "<" : "", argi, *argi ? ">" : "");
diff --git a/lex.c b/lex.c
index 5412455357..035873da11 100644
--- a/lex.c
+++ b/lex.c
@@ -1,4 +1,4 @@
-/* C code produced by gperf version 3.0.1 */
+/* C code produced by gperf version 3.0.2 */
/* Command-line: gperf -C -p -j1 -i 1 -g -o -t -N rb_reserved_word -k'1,3,$' keywords */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
diff --git a/node.h b/node.h
index c21158f9da..14ba0ad38e 100644
--- a/node.h
+++ b/node.h
@@ -203,7 +203,6 @@ typedef struct RNode {
#define nd_tbl u1.tbl
#define nd_var u1.node
-#define nd_ibdy u2.node
#define nd_iter u3.node
#define nd_value u2.node
@@ -249,12 +248,11 @@ typedef struct RNode {
#define NEW_METHOD(n,x,v) NEW_NODE(NODE_METHOD,x,n,v)
#define NEW_FBODY(n,i) NEW_NODE(NODE_FBODY,i,n,0)
-#define NEW_DEFN(i,a,d,p) NEW_NODE(NODE_DEFN,p,i,NEW_RFUNC(a,d))
-#define NEW_DEFS(r,i,a,d) NEW_NODE(NODE_DEFS,r,i,NEW_RFUNC(a,d))
+#define NEW_DEFN(i,a,d,p) NEW_NODE(NODE_DEFN,0,i,NEW_SCOPE(a,d))
+#define NEW_DEFS(r,i,a,d) NEW_NODE(NODE_DEFS,r,i,NEW_SCOPE(a,d))
#define NEW_CFUNC(f,c) NEW_NODE(NODE_CFUNC,f,c,0)
#define NEW_IFUNC(f,c) NEW_NODE(NODE_IFUNC,f,c,0)
-#define NEW_RFUNC(b1,b2) NEW_SCOPE(block_append(b1,b2))
-#define NEW_SCOPE(b) NEW_NODE(NODE_SCOPE,local_tbl(),0,(b))
+#define NEW_SCOPE(a,b) NEW_NODE(NODE_SCOPE,local_tbl(),b,a)
#define NEW_BLOCK(a) NEW_NODE(NODE_BLOCK,a,0,0)
#define NEW_IF(c,t,e) NEW_NODE(NODE_IF,c,t,e)
#define NEW_UNLESS(c,t,e) NEW_IF(c,e,t)
@@ -264,8 +262,8 @@ typedef struct RNode {
#define NEW_WHILE(c,b,n) NEW_NODE(NODE_WHILE,c,b,n)
#define NEW_UNTIL(c,b,n) NEW_NODE(NODE_UNTIL,c,b,n)
#define NEW_FOR(v,i,b) NEW_NODE(NODE_FOR,v,b,i)
-#define NEW_ITER(v,i,b) NEW_NODE(NODE_ITER,v,b,i)
-#define NEW_LAMBDA(a,b) NEW_NODE(NODE_LAMBDA,a,b,0)
+#define NEW_ITER(a,b) NEW_NODE(NODE_ITER,0,NEW_SCOPE(a,b),0)
+#define NEW_LAMBDA(a) NEW_NODE(NODE_LAMBDA,a,0,0)
#define NEW_BREAK(s) NEW_NODE(NODE_BREAK,s,0,0)
#define NEW_NEXT(s) NEW_NODE(NODE_NEXT,s,0,0)
#define NEW_REDO() NEW_NODE(NODE_REDO,0,0,0)
@@ -283,7 +281,7 @@ typedef struct RNode {
#define NEW_NOT(a) NEW_NODE(NODE_NOT,0,a,0)
#define NEW_MASGN(l,r) NEW_NODE(NODE_MASGN,l,0,r)
#define NEW_GASGN(v,val) NEW_NODE(NODE_GASGN,v,val,rb_global_entry(v))
-#define NEW_LASGN(v,val) NEW_NODE(NODE_LASGN,v,val,local_cnt(v))
+#define NEW_LASGN(v,val) NEW_NODE(NODE_LASGN,v,val,0)
#define NEW_DASGN(v,val) NEW_NODE(NODE_DASGN,v,val,0)
#define NEW_DASGN_CURR(v,val) NEW_NODE(NODE_DASGN_CURR,v,val,0)
#define NEW_IASGN(v,val) NEW_NODE(NODE_IASGN,v,val,0)
@@ -297,13 +295,13 @@ typedef struct RNode {
#define NEW_OP_ASGN_OR(i,val) NEW_NODE(NODE_OP_ASGN_OR,i,val,0)
#define NEW_OP_ASGN_AND(i,val) NEW_NODE(NODE_OP_ASGN_AND,i,val,0)
#define NEW_GVAR(v) NEW_NODE(NODE_GVAR,v,0,rb_global_entry(v))
-#define NEW_LVAR(v) NEW_NODE(NODE_LVAR,v,0,local_cnt(v))
+#define NEW_LVAR(v) NEW_NODE(NODE_LVAR,v,0,0)
#define NEW_DVAR(v) NEW_NODE(NODE_DVAR,v,0,0)
#define NEW_IVAR(v) NEW_NODE(NODE_IVAR,v,0,0)
#define NEW_CONST(v) NEW_NODE(NODE_CONST,v,0,0)
#define NEW_CVAR(v) NEW_NODE(NODE_CVAR,v,0,0)
-#define NEW_NTH_REF(n) NEW_NODE(NODE_NTH_REF,0,n,local_cnt('~'))
-#define NEW_BACK_REF(n) NEW_NODE(NODE_BACK_REF,0,n,local_cnt('~'))
+#define NEW_NTH_REF(n) NEW_NODE(NODE_NTH_REF,0,n,0)
+#define NEW_BACK_REF(n) NEW_NODE(NODE_BACK_REF,0,n,0)
#define NEW_MATCH(c) NEW_NODE(NODE_MATCH,c,0,0)
#define NEW_MATCH2(n1,n2) NEW_NODE(NODE_MATCH2,n1,n2,0)
#define NEW_MATCH3(r,n2) NEW_NODE(NODE_MATCH3,r,n2,0)
@@ -332,9 +330,9 @@ typedef struct RNode {
#define NEW_ALIAS(n,o) NEW_NODE(NODE_ALIAS,n,o,0)
#define NEW_VALIAS(n,o) NEW_NODE(NODE_VALIAS,n,o,0)
#define NEW_UNDEF(i) NEW_NODE(NODE_UNDEF,0,i,0)
-#define NEW_CLASS(n,b,s) NEW_NODE(NODE_CLASS,n,NEW_SCOPE(b),(s))
-#define NEW_SCLASS(r,b) NEW_NODE(NODE_SCLASS,r,NEW_SCOPE(b),0)
-#define NEW_MODULE(n,b) NEW_NODE(NODE_MODULE,n,NEW_SCOPE(b),0)
+#define NEW_CLASS(n,b,s) NEW_NODE(NODE_CLASS,n,NEW_SCOPE(0,b),(s))
+#define NEW_SCLASS(r,b) NEW_NODE(NODE_SCLASS,r,NEW_SCOPE(0,b),0)
+#define NEW_MODULE(n,b) NEW_NODE(NODE_MODULE,n,NEW_SCOPE(0,b),0)
#define NEW_COLON2(c,i) NEW_NODE(NODE_COLON2,c,i,0)
#define NEW_COLON3(i) NEW_NODE(NODE_COLON3,0,i,0)
#define NEW_CREF(c) (NEW_NODE(NODE_CREF,0,0,c))
diff --git a/parse.y b/parse.y
index d883b7c725..65980830fb 100644
--- a/parse.y
+++ b/parse.y
@@ -114,8 +114,8 @@ struct vtable {
};
struct local_vars {
- struct vtable *tbl;
- struct vtable *dvars;
+ struct vtable *args;
+ struct vtable *vars;
struct local_vars *prev;
};
@@ -124,6 +124,7 @@ struct local_vars {
#define DVARS_SPECIAL_P(tbl) (!POINTER_P(tbl))
#define POINTER_P(val) ((unsigned long)(val) & ~3UL)
+#ifndef RIPPER
static int
vtable_size(struct vtable *tbl)
{
@@ -192,6 +193,7 @@ vtable_included(struct vtable * tbl, ID id)
}
return 0;
}
+#endif
/*
Structure of Lexer Buffer:
@@ -345,7 +347,7 @@ static NODE *evstr2dstr(NODE*);
static NODE *call_op_gen(struct parser_params*,NODE*,ID,int,NODE*);
#define call_op(recv,id,narg,arg1) call_op_gen(parser, recv,id,narg,arg1)
-static NODE *new_args_gen(struct parser_params*,int,NODE*,ID,NODE*,ID);
+static NODE *new_args_gen(struct parser_params*,NODE*,NODE*,ID,NODE*,ID);
#define new_args(f,o,r,p,b) new_args_gen(parser, f,o,r,p,b)
static void shadowing_lvar_gen(struct parser_params*,ID);
#define shadowing_lvar(name) shadowing_lvar_gen(parser, name)
@@ -359,8 +361,8 @@ static NODE *gettable_gen(struct parser_params*,ID);
#define gettable(id) gettable_gen(parser,id)
static NODE *assignable_gen(struct parser_params*,ID,NODE*);
#define assignable(id,node) assignable_gen(parser, id, node)
-static NODE *new_bv_gen(struct parser_params*,ID,NODE*);
-#define new_bv(id,node) new_bv_gen(parser, id, node)
+static void new_bv_gen(struct parser_params*,ID);
+#define new_bv(id) new_bv_gen(parser, id)
static NODE *aryset_gen(struct parser_params*,NODE*,NODE*);
#define aryset(node1,node2) aryset_gen(parser, node1, node2)
static NODE *attrset_gen(struct parser_params*,NODE*,ID);
@@ -377,16 +379,14 @@ static void local_push_gen(struct parser_params*,int);
#define local_push(top) local_push_gen(parser,top)
static void local_pop_gen(struct parser_params*);
#define local_pop() local_pop_gen(parser)
-static int local_append_gen(struct parser_params*, ID);
-#define local_append(id) local_append_gen(parser, id)
-static int local_cnt_gen(struct parser_params*, ID);
-#define local_cnt(id) local_cnt_gen(parser, id)
+static int local_var_gen(struct parser_params*, ID);
+#define local_var(id) local_var_gen(parser, id);
+static int arg_var_gen(struct parser_params*, ID);
+#define arg_var(id) arg_var_gen(parser, id)
static int local_id_gen(struct parser_params*, ID);
#define local_id(id) local_id_gen(parser, id)
static ID *local_tbl_gen(struct parser_params*);
#define local_tbl() local_tbl_gen(parser)
-static ID *dyna_tbl_gen(struct parser_params*);
-#define dyna_tbl() dyna_tbl_gen(parser)
static ID internal_id(void);
static void dyna_push_gen(struct parser_params*);
@@ -395,20 +395,16 @@ static void dyna_pop_gen(struct parser_params*);
#define dyna_pop() dyna_pop_gen(parser)
static int dyna_in_block_gen(struct parser_params*);
#define dyna_in_block() dyna_in_block_gen(parser)
-static NODE *dyna_init_gen(struct parser_params*, NODE*, int);
-#define dyna_init(node, pre) dyna_init_gen(parser, node, pre)
-static void dyna_var_gen(struct parser_params*,ID);
-#define dyna_var(id) dyna_var_gen(parser, id)
+#define dyna_var(id) local_var(id)
static int dvar_defined_gen(struct parser_params*,ID);
#define dvar_defined(id) dvar_defined_gen(parser, id)
static int dvar_curr_gen(struct parser_params*,ID);
#define dvar_curr(id) dvar_curr_gen(parser, id)
+extern int rb_dvar_defined(ID);
+extern int rb_local_defined(ID);
+extern int rb_parse_in_eval(void);
-static void top_local_init_gen(struct parser_params*);
-#define top_local_init() top_local_init_gen(parser)
-static void top_local_setup_gen(struct parser_params*);
-#define top_local_setup() top_local_setup_gen(parser)
#else
#define remove_begin(node) (node)
#endif /* !RIPPER */
@@ -523,8 +519,6 @@ static void ripper_compile_error(struct parser_params*, const char *fmt, ...);
# define PARSER_ARG
#endif
-#define NEW_BLOCK_PARAM(b, v) NEW_NODE(NODE_BLOCK_PASS, 0, b, v)
-
/* Older versions of Yacc set YYMAXDEPTH to a very low value by default (150,
for instance). This is too low for Ruby to parse some files, such as
date/format.rb, therefore bump the value up to at least Bison's default. */
@@ -616,16 +610,15 @@ static void ripper_compile_error(struct parser_params*, const char *fmt, ...);
%type <node> 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_post_arg
-%type <node> f_optarg f_opt
+%type <node> f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_head f_margs
%type <node> assoc_list assocs assoc undef_list backref string_dvar for_var
-%type <node> block_param opt_block_param block_param_def bparam_list bparam_item
-%type <node> opt_bv_decl bv_decls bvar lambda f_larglist lambda_body
+%type <node> block_param opt_block_param block_param_def f_opt
+%type <node> bv_decls opt_bv_decl bvar
+%type <node> lambda f_larglist lambda_body
%type <node> brace_block cmd_brace_block do_block lhs none fitem
%type <node> mlhs mlhs_head mlhs_basic mlhs_item mlhs_node mlhs_post
%type <id> fsym variable sym symbol operation operation2 operation3
-%type <id> cname fname op f_norm_arg f_rest_arg f_block_arg opt_f_block_arg
-%type <val> f_arg
+%type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg
/*%%%*/
/*%
%type <val> program reswords then do dot_or_colon
@@ -694,7 +687,7 @@ static void ripper_compile_error(struct parser_params*, const char *fmt, ...);
program : {
/*%%%*/
lex_state = EXPR_BEG;
- top_local_init();
+ local_push(compile_for_eval);
/*%
lex_state = EXPR_BEG;
%*/
@@ -713,8 +706,8 @@ program : {
void_expr(node->nd_head);
}
}
- ruby_eval_tree = block_append(ruby_eval_tree, $2);
- top_local_setup();
+ ruby_eval_tree = NEW_SCOPE(0, block_append(ruby_eval_tree, $2));
+ local_pop();
/*%
$$ = $2;
parser->result = dispatch1(program, $$);
@@ -938,7 +931,8 @@ stmt : keyword_alias fitem {lex_state = EXPR_FNAME;} fitem
rb_warn0("END in method; use at_exit");
}
/*%%%*/
- $$ = NEW_POSTEXE($3);
+ $$ = NEW_POSTEXE(NEW_NODE(
+ NODE_SCOPE, 0 /* tbl */, $3 /* body */, 0 /* args */));
/*%
$$ = dispatch1(END, $3);
%*/
@@ -1205,18 +1199,16 @@ cmd_brace_block : tLBRACE_ARG
/*%
%*/
}
- opt_block_param {$<num>$ = vtable_size(lvtbl->dvars);}
+ opt_block_param
compstmt
'}'
{
/*%%%*/
- $3->nd_body = block_append($3->nd_body,
- dyna_init($5, $<num>4));
- $$ = $3;
+ $$ = NEW_ITER($3,$4);
nd_set_line($$, $<num>2);
dyna_pop();
/*%
- $$ = dispatch2(brace_block, escape_Qundef($3), $5);
+ $$ = dispatch2(brace_block, escape_Qundef($3), $4);
%*/
}
;
@@ -2677,12 +2669,27 @@ primary : literal
$$ = dispatch2(case, Qnil, $3);
%*/
}
- | keyword_for for_var keyword_in {COND_PUSH(1);} expr_value do {COND_POP();}
+ | keyword_for for_var keyword_in
+ {COND_PUSH(1);}
+ expr_value do
+ {COND_POP();}
compstmt
keyword_end
{
/*%%%*/
- $$ = NEW_FOR($2, $5, $8);
+ ID id = internal_id();
+ ID *tbl = ALLOC_N(ID, 2);
+ NODE *args = NEW_ARGS(1 /* m */, 0 /* o */);
+ NODE *init;
+ NODE *scope = NEW_NODE(NODE_SCOPE, tbl, $8, args);
+ tbl[0] = 1; tbl[1] = id;
+
+ init = node_assign($2, NEW_DVAR(id));
+ args->nd_next = NEW_ARGS_AUX(0, 0);
+ args->nd_next->nd_next = NEW_ARGS_AUX(0, 0);
+ args->nd_next->nd_next->nd_next = init;
+
+ $$ = NEW_FOR(0, $5, scope);
fixpos($$, $2);
/*%
$$ = dispatch3(for, $2, $5, $8);
@@ -2922,23 +2929,25 @@ for_var : lhs
| mlhs
;
-bparam_item : bvar
- | tLPAREN block_param rparen
+f_marg : f_norm_arg
{
/*%%%*/
- if (nd_type($2) != NODE_MASGN) {
- $$ = NEW_MASGN(NEW_LIST($2), 0);
- }
- else {
- $$ = $2;
- }
+ $$ = assignable($1, 0);
+ /*%
+ $$ = dispatch1(mlhs_paren, $1);
+ %*/
+ }
+ | tLPAREN f_margs rparen
+ {
+ /*%%%*/
+ $$ = $2;
/*%
$$ = dispatch1(mlhs_paren, $2);
%*/
}
;
-bparam_list : bparam_item
+f_marg_head : f_marg
{
/*%%%*/
$$ = NEW_LIST($1);
@@ -2946,206 +2955,164 @@ bparam_list : bparam_item
$$ = mlhs_add(mlhs_new(), $1);
%*/
}
- | bparam_list ',' bparam_item
+ | f_marg_head ',' f_marg
{
/*%%%*/
$$ = list_append($1, $3);
/*%
- $$ = mlhs_add($1, $3);
+ $$ = mlhs_add($1, $3);
%*/
}
;
-block_param : bparam_list
- {
- /*%%%*/
- if ($1->nd_alen == 1 && nd_type($1->nd_head) != NODE_MASGN) {
- $$ = $1->nd_head;
- rb_gc_force_recycle((VALUE)$1);
- }
- else {
- $$ = NEW_MASGN($1, 0);
- }
- /*%
- $$ = blockvar_new($1);
- %*/
- }
- | bparam_list ','
+f_margs : f_marg_head
{
/*%%%*/
$$ = NEW_MASGN($1, 0);
/*%
- $$ = blockvar_new($1);
- %*/
- }
- | bparam_list ',' tAMPER bvar
- {
- /*%%%*/
- $$ = NEW_BLOCK_PARAM($4, NEW_MASGN($1, 0));
- /*%
- $$ = blockvar_add_block(blockvar_new($1), $4);
- %*/
- }
- | bparam_list ',' tSTAR bvar ',' bparam_list ',' tAMPER bvar
- {
- /*%%%*/
- $$ = NEW_BLOCK_PARAM($9, NEW_MASGN($1, NEW_POSTARG($4,$6)));
- /*%
- $$ = blockvar_add_star(blockvar_new($1), $4);
- $$ = blockvar_add_block($$, $9);
- %*/
- }
- | bparam_list ',' tSTAR bvar ',' tAMPER bvar
- {
- /*%%%*/
- $$ = NEW_BLOCK_PARAM($7, NEW_MASGN($1, $4));
- /*%
- $$ = blockvar_add_star(blockvar_new($1), $4);
- $$ = blockvar_add_block($$, $7);
+ $$ = $1;
%*/
}
- | bparam_list ',' tSTAR ',' tAMPER bvar
+ | f_marg_head ',' tSTAR f_norm_arg
{
/*%%%*/
- $$ = NEW_BLOCK_PARAM($6, NEW_MASGN($1, -1));
+ $$ = NEW_MASGN($1, assignable($4, 0));
/*%
- $$ = blockvar_add_star(blockvar_new($1), Qnil);
- $$ = blockvar_add_block($$, $6);
+ $$ = mlhs_add_star($1, $4);
%*/
}
- | bparam_list ',' tSTAR ',' bparam_list ',' tAMPER bvar
+ | f_marg_head ',' tSTAR f_norm_arg ',' f_marg
{
/*%%%*/
- $$ = NEW_BLOCK_PARAM($8, NEW_MASGN($1, NEW_POSTARG(-1,$5)));
+ $$ = NEW_MASGN($1, NEW_POSTARG($4,$6));
/*%
- $$ = blockvar_add_star(blockvar_new($1), Qnil);
- $$ = blockvar_add_block($$, $8);
+ $$ = mlhs_add_star($1, $4);
%*/
}
- | bparam_list ',' tSTAR bvar
+ | f_marg_head ',' tSTAR
{
/*%%%*/
- $$ = NEW_MASGN($1, $4);
+ $$ = NEW_MASGN($1, -1);
/*%
- $$ = blockvar_add_star(blockvar_new($1), $4);
+ $$ = mlhs_add_star($1, Qnil);
%*/
}
- | bparam_list ',' tSTAR bvar ',' bparam_list
+ | f_marg_head ',' tSTAR ',' f_marg
{
/*%%%*/
- $$ = NEW_MASGN($1, NEW_POSTARG($4,$6));
+ $$ = NEW_MASGN($1, NEW_POSTARG(-1,$5));
/*%
- $$ = blockvar_add_star(blockvar_new($1), $4);
+ $$ = mlhs_add_star($1, $5);
%*/
}
- | bparam_list ',' tSTAR
+ | tSTAR f_norm_arg
{
/*%%%*/
- $$ = NEW_MASGN($1, -1);
+ $$ = NEW_MASGN(0, assignable($2, 0));
/*%
- $$ = blockvar_add_star(blockvar_new($1), Qnil);
+ $$ = mlhs_add_star(mlhs_new(), $2);
%*/
}
- | bparam_list ',' tSTAR ',' bparam_list
+ | tSTAR f_norm_arg ',' f_marg
{
/*%%%*/
- $$ = NEW_MASGN($1, NEW_MASGN($1, NEW_POSTARG(-1,$5)));
+ $$ = NEW_MASGN(0, NEW_POSTARG(assignable($2, 0), $4));
/*%
- $$ = blockvar_add_star(blockvar_new($1), Qnil);
+ #if 0
+ TODO: Check me
+ #endif
+ $$ = mlhs_add_star($2, $4);
%*/
}
- | tSTAR bvar ',' tAMPER bvar
+ | tSTAR
{
/*%%%*/
- $$ = NEW_BLOCK_PARAM($5, NEW_MASGN(0, $2));
+ $$ = NEW_MASGN(0, -1);
/*%
- $$ = blockvar_add_star(blockvar_new(Qnil), $2);
- $$ = blockvar_add_block($$, $5);
+ $$ = mlhs_add_star(mlhs_new(), Qnil);
%*/
}
- | tSTAR ',' tAMPER bvar
+ | tSTAR ',' f_marg
{
/*%%%*/
- $$ = NEW_BLOCK_PARAM($4, NEW_MASGN(0, -1));
+ $$ = NEW_MASGN(0, NEW_POSTARG(-1, $3));
/*%
- $$ = blockvar_add_star(blockvar_new(Qnil), Qnil);
- $$ = blockvar_add_block($$, $4);
+ $$ = mlhs_add_star(mlhs_new(), Qnil);
%*/
}
- | tSTAR bvar
+ ;
+
+block_param : f_arg ',' f_rest_arg opt_f_block_arg
{
/*%%%*/
- $$ = NEW_MASGN(0, $2);
+ $$ = new_args($1, 0, $3, 0, $4);
/*%
- $$ = blockvar_add_star(blockvar_new(Qnil), $2);
+ $$ = dispatch5(params, $1, Qnil, $3, Qnil, escape_Qundef($4));
%*/
}
- | tSTAR bvar ',' bparam_list
+ | f_arg ','
{
/*%%%*/
- $$ = NEW_MASGN(0, NEW_POSTARG($2,$4));
+ ID id = internal_id();
+ arg_var(id);
+ $$ = new_args($1, 0, id, 0, 0);
/*%
- $$ = blockvar_add_star(blockvar_new(Qnil), $2);
+ #if 0
+ TODO: check me (anonymous rest)
+ #endif
+ $$ = dispatch5(params, $1, Qnil, Qnil, Qnil, 0);
%*/
}
- | tSTAR bvar ',' bparam_list ',' tAMPER bvar
+ | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
{
/*%%%*/
- $$ = NEW_BLOCK_PARAM($7, NEW_MASGN(0, NEW_POSTARG($2,$4)));
+ $$ = new_args($1, 0, $3, $5, $6);
/*%
- $$ = blockvar_add_star(blockvar_new(Qnil), Qnil);
- $$ = blockvar_add_block($$, $7);
+ $$ = dispatch5(params, $1, Qnil, $3, $5, escape_Qundef($6));
%*/
}
- | tSTAR
+ | f_arg opt_f_block_arg
{
/*%%%*/
- $$ = NEW_MASGN(0, -1);
+ $$ = new_args($1, 0, 0, 0, $2);
/*%
- $$ = blockvar_add_star(blockvar_new(Qnil), Qnil);
+ $$ = dispatch5(params, $1, Qnil, Qnil, Qnil, escape_Qundef($2));
%*/
}
- | tSTAR ',' bparam_list
+ | f_rest_arg opt_f_block_arg
{
/*%%%*/
- $$ = NEW_MASGN(0, NEW_POSTARG(-1,$3));
+ $$ = new_args(0, 0, $1, 0, $2);
/*%
- $$ = blockvar_add_star(blockvar_new(Qnil), Qnil);
+ $$ = dispatch5(params, Qnil, Qnil, $1, Qnil, escape_Qundef($2));
%*/
}
- | tSTAR ',' bparam_list ',' tAMPER bvar
+ | f_rest_arg ',' f_arg opt_f_block_arg
{
/*%%%*/
- $$ = NEW_BLOCK_PARAM($6, NEW_MASGN(0, NEW_POSTARG(-1,$3)));
+ $$ = new_args(0, 0, $1, $3, $4);
/*%
- $$ = blockvar_add_star(blockvar_new(Qnil), Qnil);
- $$ = blockvar_add_block($$, $6);
+ $$ = dispatch5(params, Qnil, Qnil, $1, $3, escape_Qundef($4));
%*/
}
- | tAMPER bvar
+ | f_block_arg
{
/*%%%*/
- $$ = NEW_BLOCK_PARAM($2, (NODE*)1);
+ $$ = new_args(0, 0, 0, 0, $1);
/*%
- $$ = blockvar_add_block(blockvar_new(Qnil), $2);
+ $$ = dispatch5(params, Qnil, Qnil, Qnil, Qnil, $1);
%*/
}
;
opt_block_param : none
- {
- /*%%%*/
- $$ = NEW_ITER(0, 0, 0);
- /*%
- %*/
- }
| block_param_def
;
block_param_def : '|' opt_bv_decl '|'
{
/*%%%*/
- $$ = NEW_ITER((NODE*)1, 0, $2);
+ $$ = 0;
/*%
$$ = blockvar_new(mlhs_new());
%*/
@@ -3153,7 +3120,7 @@ block_param_def : '|' opt_bv_decl '|'
| tOROP
{
/*%%%*/
- $$ = NEW_ITER((NODE*)1, 0, 0);
+ $$ = 0;
/*%
$$ = blockvar_new(mlhs_new());
%*/
@@ -3161,9 +3128,9 @@ block_param_def : '|' opt_bv_decl '|'
| '|' block_param opt_bv_decl '|'
{
/*%%%*/
- $$ = NEW_ITER($2, 0, $3);
+ $$ = $2;
/*%
- $$ = blockvar_new($2);
+ $$ = blockvar_new(escape_Qundef($2));
%*/
}
;
@@ -3173,37 +3140,36 @@ opt_bv_decl : none
| ';' bv_decls
{
/*%%%*/
- $$ = $2;
+ $$ = 0;
/*%
- $$ = FIXME;
+ $$ = $2;
%*/
}
;
bv_decls : bvar
+ /*%c%*/
+ /*%c
{
- /*%%%*/
- $$ = $1;
- /*%
- $$ = FIXME;
- %*/
+ $$ = mlhs_new();
+ $$ = mlhs_add($$, $1);
}
+ %*/
| bv_decls ',' bvar
+ /*%c%*/
+ /*%c
{
- /*%%%*/
- $$ = block_append($1, $3);
- /*%
- $$ = FIXME;
- %*/
+ $$ = mlhs_add($$, $3);
}
+ %*/
;
-bvar : tIDENTIFIER
+bvar : f_norm_arg
{
/*%%%*/
- $$ = new_bv($1, NEW_NIL());
+ new_bv($1);
/*%
- $$ = FIXME;
+ $$ = dispatch0(new_blockvars)
%*/
}
;
@@ -3221,7 +3187,7 @@ lambda : {
{
/*%%%*/
$$ = $2;
- $$->nd_body = block_append($$->nd_body, $3);
+ $$->nd_body = NEW_SCOPE($2->nd_head, $3);
dyna_pop();
lpar_beg = $<num>1;
/*%
@@ -3233,7 +3199,7 @@ lambda : {
f_larglist : '(' f_args opt_bv_decl rparen
{
/*%%%*/
- $$ = NEW_LAMBDA($2, $3);
+ $$ = NEW_LAMBDA($2);
/*%
$$ = dispatch1(paren, $2);
%*/
@@ -3241,7 +3207,7 @@ f_larglist : '(' f_args opt_bv_decl rparen
| f_args opt_bv_decl
{
/*%%%*/
- $$ = NEW_LAMBDA($1, $2);
+ $$ = NEW_LAMBDA($1);
/*%
$$ = $1;
%*/
@@ -3266,19 +3232,12 @@ do_block : keyword_do_block
/*% %*/
}
opt_block_param
- {
- /*%%%*/
- $<num>$ = vtable_size(lvtbl->dvars);
- /*% %*/
- }
compstmt
keyword_end
{
/*%%%*/
- $3->nd_body = block_append($3->nd_body,
- dyna_init($5, $<num>4));
- $$ = $3;
- nd_set_line($$, $<num>2);
+ $$ = NEW_ITER($3,$4);
+ nd_set_line($$, $<num>1);
dyna_pop();
/*%
$$ = dispatch2(do_block, escape_Qundef($3), $5);
@@ -3414,22 +3373,14 @@ brace_block : '{'
/*% %*/
}
opt_block_param
- {
- /*%%%*/
- $<num>$ = vtable_size(lvtbl->dvars);
- /*%
- %*/
- }
compstmt '}'
{
/*%%%*/
- $3->nd_body = block_append($3->nd_body,
- dyna_init($5, $<num>4));
- $$ = $3;
+ $$ = NEW_ITER($3,$4);
nd_set_line($$, $<num>2);
dyna_pop();
/*%
- $$ = dispatch2(brace_block, escape_Qundef($3), $5);
+ $$ = dispatch2(brace_block, escape_Qundef($3), $4);
%*/
}
| keyword_do
@@ -3440,18 +3391,10 @@ brace_block : '{'
/*% %*/
}
opt_block_param
- {
- /*%%%*/
- $<num>$ = vtable_size(lvtbl->dvars);
- /*%
- %*/
- }
compstmt keyword_end
{
/*%%%*/
- $3->nd_body = block_append($3->nd_body,
- dyna_init($5, $<num>4));
- $$ = $3;
+ $$ = NEW_ITER($3,$4);
nd_set_line($$, $<num>2);
dyna_pop();
/*%
@@ -3994,7 +3937,7 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
$$ = dispatch5(params, $1, $3, $5, Qnil, escape_Qundef($6));
%*/
}
- | f_arg ',' f_optarg ',' f_rest_arg ',' f_post_arg opt_f_block_arg
+ | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
{
/*%%%*/
$$ = new_args($1, $3, $5, $7, $8);
@@ -4010,7 +3953,7 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
$$ = dispatch5(params, $1, $3, Qnil, Qnil, escape_Qundef($4));
%*/
}
- | f_arg ',' f_optarg ',' f_post_arg opt_f_block_arg
+ | f_arg ',' f_optarg ',' f_arg opt_f_block_arg
{
/*%%%*/
$$ = new_args($1, $3, 0, $5, $6);
@@ -4026,7 +3969,7 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
$$ = dispatch5(params, $1, Qnil, $3, Qnil, escape_Qundef($4));
%*/
}
- | f_arg ',' f_rest_arg ',' f_post_arg opt_f_block_arg
+ | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
{
/*%%%*/
$$ = new_args($1, 0, $3, $5, $6);
@@ -4050,7 +3993,7 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
$$ = dispatch5(params, Qnil, $1, $3, Qnil, escape_Qundef($4));
%*/
}
- | f_optarg ',' f_rest_arg ',' f_post_arg opt_f_block_arg
+ | f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
{
/*%%%*/
$$ = new_args(0, $1, $3, $5, $6);
@@ -4066,7 +4009,7 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
$$ = dispatch5(params, Qnil, $1, Qnil, Qnil, escape_Qundef($2));
%*/
}
- | f_optarg ',' f_post_arg opt_f_block_arg
+ | f_optarg ',' f_arg opt_f_block_arg
{
/*%%%*/
$$ = new_args(0, $1, 0, $3, $4);
@@ -4082,7 +4025,7 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
$$ = dispatch5(params, Qnil, Qnil, $1, Qnil, escape_Qundef($2));
%*/
}
- | f_rest_arg ',' f_post_arg opt_f_block_arg
+ | f_rest_arg ',' f_arg opt_f_block_arg
{
/*%%%*/
$$ = new_args(0, 0, $1, $3, $4);
@@ -4112,6 +4055,7 @@ f_norm_arg : tCONSTANT
{
/*%%%*/
yyerror("formal argument cannot be a constant");
+ $$ = 0;
/*%
$$ = dispatch1(param_error, $1);
%*/
@@ -4120,6 +4064,7 @@ f_norm_arg : tCONSTANT
{
/*%%%*/
yyerror("formal argument cannot be an instance variable");
+ $$ = 0;
/*%
$$ = dispatch1(param_error, $1);
%*/
@@ -4128,6 +4073,7 @@ f_norm_arg : tCONSTANT
{
/*%%%*/
yyerror("formal argument cannot be a global variable");
+ $$ = 0;
/*%
$$ = dispatch1(param_error, $1);
%*/
@@ -4136,59 +4082,61 @@ f_norm_arg : tCONSTANT
{
/*%%%*/
yyerror("formal argument cannot be a class variable");
+ $$ = 0;
/*%
$$ = dispatch1(param_error, $1);
%*/
}
| tIDENTIFIER
{
- /*%%%*/
- if (!is_local_id($1))
- yyerror("formal argument must be local variable");
- shadowing_lvar($1);
$$ = $1;
- /*%
- $$ = $1;
- %*/
}
;
-f_arg : f_norm_arg
+f_arg_item : f_norm_arg
{
/*%%%*/
- $$ = 1;
+ if (!is_local_id($1))
+ yyerror("formal argument must be local variable");
+ shadowing_lvar($1);
+ arg_var($1);
+ $$ = NEW_ARGS_AUX($1, 1);
/*%
$$ = rb_ary_new();
%*/
}
- | f_arg ',' f_norm_arg
+ | tLPAREN f_margs rparen
{
/*%%%*/
- $$ = $1 + 1;
+ ID tid = internal_id();
+ arg_var(tid);
+ $2->nd_value = NEW_DVAR(tid);
+ $$ = NEW_ARGS_AUX(tid, 1);
+ $$->nd_next = $2;
/*%
- rb_ary_push($$, $3);
+ $$ = dispatch1(mlhs_paren, $2);
%*/
}
;
-f_post_arg : f_norm_arg
+f_arg : f_arg_item
+ /*%c%*/
+ /*%c
{
- /*%%%*/
- $$ = NEW_ARGS_AUX($1, 1);
- /*%
- $$ = mlhs_add(mlhs_new(), $1);
- %*/
+ $$ = rb_ary_new3(1, $1);
}
- | f_post_arg ',' f_norm_arg
+ c%*/
+ | f_arg ',' f_arg_item
{
/*%%%*/
- $1->nd_alen++;
- $$ = $1;
+ $$->nd_plen++;
+ $$->nd_next = block_append($$->nd_next, $3->nd_next);
+ rb_gc_force_recycle((VALUE)$3);
/*%
- $$ = mlhs_add($1, $3);
+ rb_ary_push($$, $3);
%*/
}
- ;
+ ;
f_opt : tIDENTIFIER '=' arg_value
{
@@ -4196,6 +4144,7 @@ f_opt : tIDENTIFIER '=' arg_value
if (!is_local_id($1))
yyerror("formal argument must be local variable");
shadowing_lvar($1);
+ arg_var($1);
$$ = NEW_OPT_ARG(0, assignable($1, $3));
/*%
$$ = rb_assoc_new($1, $3);
@@ -4237,6 +4186,7 @@ f_rest_arg : restarg_mark tIDENTIFIER
if (!is_local_id($2))
yyerror("rest argument must be local variable");
shadowing_lvar($2);
+ arg_var($2);
$$ = $2;
/*%
$$ = dispatch1(restparam, $2);
@@ -4245,13 +4195,8 @@ f_rest_arg : restarg_mark tIDENTIFIER
| restarg_mark
{
/*%%%*/
- if (dyna_in_block()) {
- $$ = internal_id();
- }
- else {
- local_append(0);
- $$ = -1;
- }
+ $$ = internal_id();
+ arg_var($$);
/*%
$$ = dispatch1(restparam, Qnil);
%*/
@@ -4270,6 +4215,7 @@ f_block_arg : blkarg_mark tIDENTIFIER
else if (!dyna_in_block() && local_id($2))
yyerror("duplicated block argument name");
shadowing_lvar($2);
+ arg_var($2);
$$ = $2;
/*%
$$ = $2;
@@ -4473,7 +4419,6 @@ static int parser_here_document(struct parser_params*,NODE*);
#ifdef RIPPER
/* FIXME */
-# define local_cnt(x) 3
# define local_id(x) 1
# define dyna_in_block() 1
#endif /* RIPPER */
@@ -4630,7 +4575,9 @@ yycompile(struct parser_params *parser, const char *f, int line)
lex_strterm = 0;
if (ruby_eval_tree_begin) {
- return NEW_PRELUDE(ruby_eval_tree_begin, ruby_eval_tree);
+ NODE *scope = ruby_eval_tree;
+ scope->nd_body = NEW_PRELUDE(ruby_eval_tree_begin, scope->nd_body);
+ return scope;
}
else {
return ruby_eval_tree;
@@ -4678,8 +4625,6 @@ rb_compile_string(const char *f, VALUE s, int line)
return rb_parser_compile_string(vparser, f, s, line);
}
-int rb_parse_in_eval(void);
-
NODE*
rb_parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line)
{
@@ -6617,8 +6562,6 @@ parser_yylex(struct parser_params *parser)
c = '_';
/* fall through */
case '~': /* $~: match-data */
- (void)local_cnt(c);
- /* fall through */
case '*': /* $*: argv */
case '$': /* $$: pid */
case '?': /* $?: last status */
@@ -7162,8 +7105,6 @@ call_op_gen(struct parser_params *parser, NODE *recv, ID id, int narg, NODE *arg
static NODE*
match_op_gen(struct parser_params *parser, NODE *node1, NODE *node2)
{
- local_cnt('~');
-
value_expr(node1);
value_expr(node2);
if (node1) {
@@ -7261,19 +7202,27 @@ assignable_gen(struct parser_params *parser, ID id, NODE *val)
yyerror("Can't assign to __LINE__");
}
else if (is_local_id(id)) {
- if (dvar_curr(id)) {
- return NEW_DASGN_CURR(id, val);
- }
- else if (dvar_defined(id)) {
- return NEW_DASGN(id, val);
+ if (dyna_in_block()) {
+ if (dvar_curr(id)) {
+ return NEW_DASGN_CURR(id, val);
+ }
+ else if (dvar_defined(id)) {
+ return NEW_DASGN(id, val);
+ }
+ else if (local_id(id)) {
+ return NEW_LASGN(id, val);
+ }
+ else{
+ dyna_var(id);
+ return NEW_DASGN_CURR(id, val);
+ }
}
- else if (local_id(id) || !dyna_in_block()) {
+ else {
+ if (!local_id(id)) {
+ local_var(id);
+ }
return NEW_LASGN(id, val);
}
- else{
- dyna_var(id);
- return NEW_DASGN_CURR(id, val);
- }
}
else if (is_global_id(id)) {
return NEW_GASGN(id, val);
@@ -7305,27 +7254,25 @@ shadowing_lvar_gen(struct parser_params *parser, ID name)
else if (dvar_defined(name) || local_id(name)) {
rb_warningS("shadowing outer local variable - %s", rb_id2name(name));
}
- dyna_var(name);
}
else {
if (local_id(name)) {
yyerror("duplicated argument name");
}
- local_cnt(name);
}
}
-static NODE*
-new_bv_gen(struct parser_params *parser, ID name, NODE *val)
+static void
+new_bv_gen(struct parser_params *parser, ID name)
{
+ if (!name) return;
if (!is_local_id(name)) {
compile_error(PARSER_ARG "invalid local variable - %s",
rb_id2name(name));
- return 0;
+ return;
}
shadowing_lvar(name);
dyna_var(name);
- return NEW_DASGN_CURR(name, val);
}
static NODE *
@@ -7787,8 +7734,6 @@ cond0(struct parser_params *parser, NODE *node)
case NODE_DREGX:
case NODE_DREGX_ONCE:
warning_unless_e_option(node, "regex literal in condition");
- local_cnt('_');
- local_cnt('~');
return NEW_MATCH2(node, NEW_GVAR(rb_intern("$_")));
case NODE_AND:
@@ -7803,7 +7748,6 @@ cond0(struct parser_params *parser, NODE *node)
node->nd_end = range_op(parser, node->nd_end);
if (nd_type(node) == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
else if (nd_type(node) == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
- node->nd_cnt = local_append(internal_id());
if (!e_option_supplied()) {
int b = literal_node(node->nd_beg);
int e = literal_node(node->nd_end);
@@ -7821,8 +7765,6 @@ cond0(struct parser_params *parser, NODE *node)
if (TYPE(node->nd_lit) == T_REGEXP) {
warn_unless_e_option(node, "regex literal in condition");
nd_set_type(node, NODE_MATCH);
- local_cnt('_');
- local_cnt('~');
}
else {
parser_warning(node, "literal in condition");
@@ -7962,14 +7904,24 @@ arg_dup_check(ID vid, VALUE m, VALUE list, NODE *node)
}
static NODE*
-new_args_gen(struct parser_params *parser, int m, NODE *o, ID r, NODE *p, ID b)
+new_args_gen(struct parser_params *parser, NODE *m, NODE *o, ID r, NODE *p, ID b)
{
int saved_line = ruby_sourceline;
- NODE *node = NEW_ARGS(m, o);
+ NODE *node;
+ NODE *i1, *i2 = 0;
+ node = NEW_ARGS(m ? m->nd_plen : 0, o);
+ i1 = m ? m->nd_next : 0;
node->nd_next = NEW_ARGS_AUX(r, b);
if (p) {
- node->nd_next->nd_next = p;
+ i2 = p->nd_next;
+ node->nd_next->nd_next = NEW_ARGS_AUX(p->nd_pid, p->nd_plen);
+ }
+ else if (i1) {
+ node->nd_next->nd_next = NEW_ARGS_AUX(0, 0);
+ }
+ if (i1 || i2) {
+ node->nd_next->nd_next->nd_next = NEW_NODE(NODE_AND, i1, i2, 0);
}
ruby_sourceline = saved_line;
return node;
@@ -7982,8 +7934,8 @@ local_push_gen(struct parser_params *parser, int inherit_dvars)
local = ALLOC(struct local_vars);
local->prev = lvtbl;
- local->tbl = 0;
- local->dvars = inherit_dvars ? DVARS_INHERIT : DVARS_TOPSCOPE;
+ local->args = vtable_alloc(0);
+ local->vars = vtable_alloc(inherit_dvars ? DVARS_INHERIT : DVARS_TOPSCOPE);
lvtbl = local;
}
@@ -7991,171 +7943,147 @@ static void
local_pop_gen(struct parser_params *parser)
{
struct local_vars *local = lvtbl->prev;
- vtable_free(lvtbl->tbl);
- vtable_free(lvtbl->dvars);
+ vtable_free(lvtbl->args);
+ vtable_free(lvtbl->vars);
xfree(lvtbl);
lvtbl = local;
}
static ID*
-vtable_to_tbl(struct vtable *src)
+vtable_tblcpy(ID *buf, struct vtable *src)
{
int i, cnt = vtable_size(src);
if (cnt > 0) {
- ID *tbl = ALLOC_N(ID, cnt + 1);
- tbl[0] = cnt;
+ buf[0] = cnt;
for (i = 0; i < cnt; i++) {
- tbl[i+1] = src->tbl[i];
+ buf[i] = src->tbl[i];
}
- return tbl;
+ return buf;
}
return 0;
}
static ID*
-local_tbl_gen(struct parser_params *parser)
+vtable_to_tbl(struct vtable *src)
{
- return vtable_to_tbl(lvtbl->tbl);
+ int cnt = vtable_size(src);
+ ID *buf;
+
+ if (cnt <= 0) return 0;
+ buf = ALLOC_N(ID, cnt + 1);
+ vtable_tblcpy(buf+1, src);
+ return buf;
}
static ID*
-dyna_tbl_gen(struct parser_params *parser)
+local_tbl_gen(struct parser_params *parser)
{
- return vtable_to_tbl(lvtbl->dvars);
+ int cnt = vtable_size(lvtbl->args) + vtable_size(lvtbl->vars);
+ ID *buf;
+
+ if (cnt <= 0) return 0;
+ buf = ALLOC_N(ID, cnt + 1);
+ vtable_tblcpy(buf+1, lvtbl->args);
+ vtable_tblcpy(buf+vtable_size(lvtbl->args)+1, lvtbl->vars);
+ buf[0] = cnt;
+ return buf;
}
+#include "debug.h"
static int
-local_append_gen(struct parser_params *parser, ID id)
+arg_var_gen(struct parser_params *parser, ID id)
{
- if (lvtbl->tbl == 0) {
- lvtbl->tbl = vtable_alloc(0);
- vtable_add(lvtbl->tbl, '_');
- vtable_add(lvtbl->tbl, '~');
- if (id == '_') return 0;
- if (id == '~') return 1;
- }
- vtable_add(lvtbl->tbl, id);
- return vtable_size(lvtbl->tbl) - 1;
+ vtable_add(lvtbl->args, id);
+ return vtable_size(lvtbl->args) - 1;
}
static int
-local_cnt_gen(struct parser_params *parser, ID id)
+local_var_gen(struct parser_params *parser, ID id)
{
- int cnt, max;
- if (id == 0) return vtable_size(lvtbl->tbl);
-
- for (cnt=0, max=vtable_size(lvtbl->tbl); cnt<max;cnt++) {
- if (lvtbl->tbl->tbl[cnt] == id) {
- return cnt;
- }
- }
- return local_append(id);
+ vtable_add(lvtbl->vars, id);
+ return vtable_size(lvtbl->vars) - 1;
}
static int
local_id_gen(struct parser_params *parser, ID id)
{
- if (lvtbl == 0) return Qfalse;
- return vtable_included(lvtbl->tbl, id);
-}
+ struct vtable *vars, *args;
-extern int rb_dvar_current(void);
-extern int rb_scope_base_local_tbl_size(void);
-extern ID rb_scope_base_local_tbl_id(int i);
-extern void rb_scope_setup_top_local_tbl(ID *tbl);
-
-static void
-top_local_init_gen(struct parser_params *parser)
-{
- int i, cnt;
+ vars = lvtbl->vars;
+ args = lvtbl->args;
- local_push(rb_dvar_current());
- if (cnt = rb_scope_base_local_tbl_size()) {
- if (lvtbl->tbl == 0) {
- lvtbl->tbl = vtable_alloc(0);
- }
- for (i = 0; i < cnt; i++) {
- vtable_add(lvtbl->tbl, rb_scope_base_local_tbl_id(i));
- }
+ while (vars && POINTER_P(vars->prev)) {
+ vars = vars->prev;
+ args = args->prev;
}
-}
-static void
-top_local_setup_gen(struct parser_params *parser)
-{
- if (lvtbl->dvars != 0) {
- /* eval */
- rb_scope_setup_top_local_tbl(dyna_tbl());
+ if (vars && vars->prev == DVARS_INHERIT) {
+ return rb_local_defined(id);
}
else {
- rb_scope_setup_top_local_tbl(local_tbl());
+ return (vtable_included(args, id) ||
+ vtable_included(vars, id));
}
- local_pop();
-}
-
-static void
-dyna_var_gen(struct parser_params *parser, ID id)
-{
- if (!POINTER_P(lvtbl->dvars)) {
- lvtbl->dvars = vtable_alloc(lvtbl->dvars);
- }
- vtable_add(lvtbl->dvars, id);
}
static void
dyna_push_gen(struct parser_params *parser)
{
- lvtbl->dvars = vtable_alloc(lvtbl->dvars);
+ lvtbl->args = vtable_alloc(lvtbl->args);
+ lvtbl->vars = vtable_alloc(lvtbl->vars);
}
static void
dyna_pop_gen(struct parser_params *parser)
{
- struct vtable *tmp = lvtbl->dvars;
- lvtbl->dvars = lvtbl->dvars->prev;
+ struct vtable *tmp;
+
+ tmp = lvtbl->args;
+ lvtbl->args = lvtbl->args->prev;
+ vtable_free(tmp);
+ tmp = lvtbl->vars;
+ lvtbl->vars = lvtbl->vars->prev;
vtable_free(tmp);
}
static int
dyna_in_block_gen(struct parser_params *parser)
{
- return lvtbl->dvars != DVARS_TOPSCOPE;
-}
-
-static NODE *
-dyna_init_gen(struct parser_params *parser, NODE *node, int pre_cnt)
-{
- NODE *var;
- int post_cnt = vtable_size(lvtbl->dvars);
-
- if (!node || pre_cnt == post_cnt) return node;
- for (var = 0; post_cnt != pre_cnt; post_cnt--) {
- var = NEW_DASGN_CURR(lvtbl->dvars->tbl[post_cnt-1], var);
- }
- return block_append(var, node);
+ return lvtbl->vars->prev != DVARS_TOPSCOPE;
}
static int
dvar_defined_gen(struct parser_params *parser, ID id)
{
- struct vtable *dvars = lvtbl->dvars;
- while(POINTER_P(dvars)){
- if(vtable_included(dvars, id)){
- return 1;
- }
- dvars = dvars->prev;
+ struct vtable *vars, *args;
+
+ args = lvtbl->args;
+ vars = lvtbl->vars;
+
+ while (POINTER_P(vars)) {
+ if (vtable_included(args, id)) {
+ return 1;
+ }
+ if (vtable_included(vars, id)) {
+ return 1;
+ }
+ args = args->prev;
+ vars = vars->prev;
}
- if(dvars == DVARS_INHERIT){
+
+ if (vars == DVARS_INHERIT) {
return rb_dvar_defined(id);
}
+
return 0;
}
static int
dvar_curr_gen(struct parser_params *parser, ID id)
{
- return vtable_included(lvtbl->dvars, id);
+ return (vtable_included(lvtbl->args, id) ||
+ vtable_included(lvtbl->vars, id));
}
void
@@ -8167,25 +8095,35 @@ NODE*
rb_parser_append_print(NODE *node)
{
NODE *prelude = 0;
-
+ NODE *scope = node;
+ node = node->nd_body;
+
if (node && (nd_type(node) == NODE_PRELUDE)) {
prelude = node;
node = node->nd_body;
}
+
node = block_append(node,
NEW_FCALL(rb_intern("print"),
NEW_ARRAY(NEW_GVAR(rb_intern("$_")))));
if (prelude) {
prelude->nd_body = node;
- return prelude;
+ scope->nd_body = prelude;
}
- return node;
+ else {
+ scope->nd_body = node;
+ }
+
+ return scope;
}
NODE *
rb_parser_while_loop(NODE *node, int chop, int split)
{
NODE *prelude = 0;
+ NODE *scope = node;
+
+ node = node->nd_body;
if (node && (nd_type(node) == NODE_PRELUDE)) {
prelude = node;
@@ -8201,12 +8139,18 @@ rb_parser_while_loop(NODE *node, int chop, int split)
node = block_append(NEW_CALL(NEW_GVAR(rb_intern("$_")),
rb_intern("chop!"), 0), node);
}
+
node = NEW_OPT_N(node);
+
if (prelude) {
prelude->nd_body = node;
- return prelude;
+ scope->nd_body = prelude;
}
- return node;
+ else {
+ scope->nd_body = node;
+ }
+
+ return scope;
}
static const struct {
@@ -8696,7 +8640,7 @@ parser_free(void *ptr)
xfree(p->parser_tokenbuf);
}
for (local = p->parser_lvtbl; local; local = prev) {
- if (local->tbl) xfree(local->tbl);
+ if (local->vars) xfree(local->vars);
prev = local->prev;
xfree(local);
}
diff --git a/proc.c b/proc.c
index dbfefe601d..54e3c946f0 100644
--- a/proc.c
+++ b/proc.c
@@ -1163,7 +1163,7 @@ rb_node_arity(NODE* body)
case RUBY_VM_METHOD_NODE:{
rb_iseq_t *iseq;
GetISeqPtr((VALUE)body->nd_body, iseq);
- if (iseq->arg_rest == 0 && iseq->arg_opts == 0) {
+ if (iseq->arg_rest == -1 && iseq->arg_opts == 0) {
return iseq->argc;
}
else {
diff --git a/vm.c b/vm.c
index 959f8116f8..37f0d8cd6e 100644
--- a/vm.c
+++ b/vm.c
@@ -678,7 +678,7 @@ th_yield_with_cfunc(rb_thread_t *th, rb_block_t *block,
static inline int
th_yield_setup_args(rb_iseq_t *iseq, int argc, VALUE *argv)
{
- int i;
+ int i, arg_n = iseq->argc + (iseq->arg_rest == -1 ? 0 : 1);
if (0) { /* for debug */
int i;
@@ -686,6 +686,7 @@ th_yield_setup_args(rb_iseq_t *iseq, int argc, VALUE *argv)
for(i=0; i<argc; i++){
dp(argv[i]);
}
+
printf(" argc: %d\n", argc);
printf("iseq argc: %d\n", iseq->argc);
printf("iseq rest: %d\n", iseq->arg_rest);
@@ -693,61 +694,49 @@ th_yield_setup_args(rb_iseq_t *iseq, int argc, VALUE *argv)
GET_THREAD()->cfp->sp -= argc;
}
- if (iseq->argc == 1 && iseq->arg_rest != -1) {
- if (argc > 1) {
- argv[0] = rb_ary_new4(argc, argv);
- argc = 1;
- }
- else if (iseq->arg_rest > 0) {
- argv[0] = rb_ary_new4(argc, argv);
- argc = 1;
+ if (argc == 1 && TYPE(argv[0]) == T_ARRAY && arg_n != 1) {
+ VALUE ary = argv[0];
+ argc = RARRAY_LEN(ary);
+
+ /* TODO: check overflow */
+
+ for (i=0; i<argc; i++) {
+ argv[i] = RARRAY_PTR(ary)[i];
}
}
- else {
- if (argc == 1 && TYPE(argv[0]) == T_ARRAY /* && iseq->arg_rest == 0 */) {
- VALUE ary = argv[0];
- argc = RARRAY_LEN(ary);
- /* TODO: check overflow */
- for (i=0; i<argc; i++) {
- argv[i] = RARRAY_PTR(ary)[i];
+ if (iseq->arg_rest == -1) {
+ if (iseq->argc == 1) {
+ if (argc != 1) {
+ /* yield 1, 2, 3 for iter{|a| ...}
+ *
+ * ruby 1.8 warns on this timing.
+ * rb_warn("multiple values for a block parameter (%d for %d)", argc, iseq->argc);
+ */
+ argv[0] = rb_ary_new4(argc, argv);
+ argc = 1;
}
}
- if (iseq->arg_rest != 0) {
- if (iseq->arg_rest == -1) {
- /* */
- }
- else {
- int rest = iseq->arg_rest - 1;
- if (argc <= rest) {
- /* param: a, b, c, *r
- * args : x, y
- * =>
- * : x, y, nil, []
- */
- for (i=argc; i<rest; i++) {
- argv[i] = Qnil; /* initialize */
- }
- argv[rest] = rb_ary_new();
- argc = rest + 1;
- }
- else {
- /* param: a, *r
- * args : x, y, z
- * =>
- * : x, [y, z]
- */
- /* TODO: check overflow */
- argv[rest] = rb_ary_new4(argc - rest, &argv[rest]);
- argc = rest + 1;
- }
- }
+ if (iseq->argc < argc) {
+ /* simple truncate */
+ argc = iseq->argc;
}
}
+ else {
+ int r = iseq->arg_rest;
- if (argc > iseq->argc) {
- argc = iseq->argc;
+ if (argc < r) {
+ /* TODO: check overflow */
+ for (i=argc; i<r; i++) {
+ argv[i] = Qnil;
+ }
+ argv[r] = rb_ary_new();
+ }
+ else {
+ argv[r] = rb_ary_new4(argc-r, &argv[r]);
+ }
+ argc = iseq->arg_rest + 1;
}
return argc;
diff --git a/vm_macro.def b/vm_macro.def
index 3d6c66402c..9a2d6eb12d 100644
--- a/vm_macro.def
+++ b/vm_macro.def
@@ -90,8 +90,8 @@ MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num)
/* simple (only mandatory) arguments */
if (niseq->arg_simple) {
if (niseq->argc != num) {
- rb_raise(rb_eArgError, "wrong number of arguments (%lu for %d)",
- (unsigned long)num, niseq->argc);
+ rb_raise(rb_eArgError, "%d - wrong number of arguments (%lu for %d)",
+ 0, (unsigned long)num, niseq->argc);
}
}
else {
@@ -101,14 +101,14 @@ MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num)
int opts = niseq->arg_opts - 1;
if (num < iseq_argc ||
- (niseq->arg_rest == 0 && num > iseq_argc + opts)) {
+ (niseq->arg_rest == -1 && num > iseq_argc + opts)) {
if (0) {
printf("num: %lu, iseq_argc: %d, opts: %d\n",
(unsigned long)num, iseq_argc, opts);
}
rb_raise(rb_eArgError,
- "wrong number of arguments (%lu for %d)",
- (unsigned long)num, iseq_argc);
+ "%d - wrong number of arguments (%lu for %d)",
+ 1, (unsigned long)num, iseq_argc);
}
if (0) printf("num: %lu, opts: %d, iseq_argc: %d\n",
@@ -126,46 +126,46 @@ MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num)
}
/* rest argument */
- if (niseq->arg_rest != 0) {
- int rest = niseq->arg_rest - 1;
+ if (niseq->arg_rest != -1) {
+ int rest = niseq->arg_rest - 1 /* spec val */;
int pack_size = num - rest;
if (0) {
printf("num: %lu, rest: %d, ps: %d\n",
- (unsigned long)num, niseq->arg_rest, pack_size);
+ (unsigned long)num, rest, pack_size);
}
if (pack_size < 0) {
rb_raise(rb_eArgError,
- "wrong number of arguments (%lu for %d)",
- (unsigned long)num, rest - niseq->arg_opts);
+ "%d - wrong number of arguments (%lu for %d)",
+ 2, (unsigned long)num, rest - niseq->arg_opts);
}
/*
- * def m(x,y,z,*a) =>
- * x, y, z, a, b, c <SP> => x, y, z, [a,b,c], <SP>
+ * def m(x, y, z, *a) (rest: 3) =>
+ * x, y, z, a, b, c <SP> (num: 6, pack_size = 3)
+ * => x, y, z, [a,b,c] <SP> (num: 4)
*/
- rsp[1 + rest] = rb_ary_new4(pack_size, &rsp[1 + rest]);
- sp = &rsp[2 + rest];
+ rsp[rest + 1] = rb_ary_new4(pack_size, &rsp[rest + 1]);
+ sp = &rsp[rest + 1 + 1];
num = rest + 1;
- clear_local_size = niseq->local_size - rest - 1;
+ clear_local_size = niseq->local_size - (rest + 1);
}
/* block argument */
- if (niseq->arg_block != 0) {
+ if (niseq->arg_block != -1) {
VALUE arg_block_val = Qnil;
- if (!((niseq->arg_rest && num == niseq->arg_rest) ||
- (niseq->arg_opts
- && num == niseq->argc + niseq->arg_opts - 1)
+ if (!((num == niseq->arg_rest) ||
+ (niseq->arg_opts && num == niseq->argc + niseq->arg_opts - 1)
|| num == niseq->argc)) {
if (0) printf("num: %d, rest: %d, opts: %d, argc: %d\n",
num, niseq->arg_rest, niseq->arg_opts, niseq->argc);
rb_raise(rb_eArgError,
- "wrong number of arguments (%lu for %d)",
- (unsigned long)num, niseq->argc);
+ "%d - wrong number of arguments (%lu for %d)",
+ 3, (unsigned long)num, niseq->argc);
}
if (blockptr) {
diff --git a/yarvcore.c b/yarvcore.c
index b8f06ab6d8..75a37b6952 100644
--- a/yarvcore.c
+++ b/yarvcore.c
@@ -16,6 +16,7 @@
#include "yarvcore.h"
#include "gc.h"
+
VALUE rb_cVM;
VALUE rb_cThread;
@@ -216,7 +217,6 @@ thread_free(void *ptr)
if (ptr) {
th = ptr;
FREE_UNLESS_NULL(th->stack);
- FREE_UNLESS_NULL(th->top_local_tbl);
if (th->local_storage) {
st_free_table(th->local_storage);
diff --git a/yarvcore.h b/yarvcore.h
index 189ae86cb0..7eb6a8abb6 100644
--- a/yarvcore.h
+++ b/yarvcore.h
@@ -401,9 +401,6 @@ struct rb_thread_struct
/* for rb_iterate */
rb_block_t *passed_block;
- /* passed via parse.y, eval.c (rb_scope_setup_local_tbl) */
- ID *top_local_tbl;
-
/* for load(true) */
VALUE top_self;
VALUE top_wrapper;