diff options
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | compile.c | 616 | ||||
-rw-r--r-- | debug.c | 11 | ||||
-rw-r--r-- | debug.h | 5 | ||||
-rw-r--r-- | eval.c | 73 | ||||
-rw-r--r-- | intern.h | 3 | ||||
-rw-r--r-- | iseq.c | 34 | ||||
-rw-r--r-- | lex.c | 2 | ||||
-rw-r--r-- | node.h | 26 | ||||
-rw-r--r-- | parse.y | 680 | ||||
-rw-r--r-- | proc.c | 2 | ||||
-rw-r--r-- | vm.c | 83 | ||||
-rw-r--r-- | vm_macro.def | 42 | ||||
-rw-r--r-- | yarvcore.c | 2 | ||||
-rw-r--r-- | yarvcore.h | 3 |
15 files changed, 561 insertions, 1032 deletions
@@ -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. @@ -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); @@ -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) { @@ -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); @@ -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 @@ -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); @@ -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 ? ">" : ""); @@ -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) \ @@ -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)) @@ -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); } @@ -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 { @@ -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; |