mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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
This commit is contained in:
parent
df896a0560
commit
bb7a2d40ff
15 changed files with 588 additions and 1059 deletions
11
ChangeLog
11
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.
|
||||
|
|
612
compile.c
612
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;
|
||||
|
@ -779,274 +716,6 @@ set_exception_tbl(rb_iseq_t *iseq)
|
|||
return COMPILE_OK;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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;
|
||||
debugs("set_arguments: %s\n", node_args ? "" : "0");
|
||||
|
||||
iseq->argc = node_arg->nd_frml;
|
||||
node_opt = node_arg->nd_opt;
|
||||
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 (node_aux) {
|
||||
rest_id = node_aux->nd_rest;
|
||||
block_id = (ID)node_aux->nd_body;
|
||||
node_aux = node_aux->nd_next;
|
||||
if (nd_type(node_args) != NODE_ARGS) {
|
||||
rb_bug("set_arguments: NODE_ARGS is expected, but %s", ruby_node_name(nd_type(node_args)));
|
||||
}
|
||||
|
||||
iseq->argc = node_args->nd_frml;
|
||||
debugs(" - argc: %d\n", iseq->argc);
|
||||
|
||||
if (node_aux) {
|
||||
post_start_id = node_aux->nd_pid;
|
||||
post_len = node_aux->nd_plen;
|
||||
node_init = node_aux->nd_next;
|
||||
}
|
||||
}
|
||||
rest_id = node_aux->nd_rest;
|
||||
block_id = (ID)node_aux->nd_body;
|
||||
node_aux = node_aux->nd_next;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
|
|
11
debug.c
11
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)
|
||||
{
|
||||
|
|
5
debug.h
5
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);
|
||||
|
|
77
eval.c
77
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rb_scope_setup_top_local_tbl(ID *tbl)
|
||||
int
|
||||
rb_local_defined(ID id)
|
||||
{
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
if (tbl) {
|
||||
if (th->top_local_tbl) {
|
||||
xfree(th->top_local_tbl);
|
||||
th->top_local_tbl = 0;
|
||||
rb_iseq_t *iseq;
|
||||
|
||||
if (th->base_block && th->base_block->iseq) {
|
||||
int i;
|
||||
iseq = th->base_block->iseq->local_iseq;
|
||||
|
||||
for (i=0; i<iseq->local_table_size; i++) {
|
||||
if (iseq->local_table[i] == id) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
th->top_local_tbl = tbl;
|
||||
}
|
||||
else {
|
||||
th->top_local_tbl = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
rb_scope_base_local_tbl_size(void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
rb_dvar_current(void)
|
||||
{
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
if (th->base_block) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
3
intern.h
3
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);
|
||||
|
|
34
iseq.c
34
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 ? ">" : "");
|
||||
|
|
2
lex.c
2
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) \
|
||||
|
|
26
node.h
26
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))
|
||||
|
|
2
proc.c
2
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 {
|
||||
|
|
83
vm.c
83
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;
|
||||
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 (iseq->arg_rest > 0) {
|
||||
argv[0] = rb_ary_new4(argc, argv);
|
||||
argc = 1;
|
||||
}
|
||||
|
||||
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->argc < argc) {
|
||||
/* simple truncate */
|
||||
argc = iseq->argc;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (argc == 1 && TYPE(argv[0]) == T_ARRAY /* && iseq->arg_rest == 0 */) {
|
||||
VALUE ary = argv[0];
|
||||
argc = RARRAY_LEN(ary);
|
||||
int r = iseq->arg_rest;
|
||||
|
||||
if (argc < r) {
|
||||
/* TODO: check overflow */
|
||||
for (i=0; i<argc; i++) {
|
||||
argv[i] = RARRAY_PTR(ary)[i];
|
||||
for (i=argc; i<r; i++) {
|
||||
argv[i] = Qnil;
|
||||
}
|
||||
argv[r] = rb_ary_new();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
else {
|
||||
argv[r] = rb_ary_new4(argc-r, &argv[r]);
|
||||
}
|
||||
}
|
||||
|
||||
if (argc > iseq->argc) {
|
||||
argc = iseq->argc;
|
||||
argc = iseq->arg_rest + 1;
|
||||
}
|
||||
|
||||
return argc;
|
||||
|
|
42
vm_macro.def
42
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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue