From 930610eac6c9b5463be3e0d269a3bd3d6243d19d Mon Sep 17 00:00:00 2001
From: Yusuke Endoh <mame@tsg.ne.jp>
Date: Mon, 17 Oct 2011 22:18:40 +0900
Subject: [PATCH 2/5] * use struct rb_args_info instead of NODEs.

---
 compile.c |   60 ++++++++++++++++++++----------------------------------------
 gc.c      |   18 +++++++++++++++++-
 node.c    |   53 ++++++++---------------------------------------------
 node.h    |   17 ++++++++++++++++-
 parse.y   |   31 +++++++++++++++----------------
 5 files changed, 76 insertions(+), 103 deletions(-)

diff --git a/compile.c b/compile.c
index 81d87be..89e7059 100644
--- a/compile.c
+++ b/compile.c
@@ -1067,52 +1067,34 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args)
     debugs("iseq_set_arguments: %s\n", node_args ? "" : "0");
 
     if (node_args) {
-	NODE *node_aux = node_args->nd_next;
-	NODE *node_opt = node_args->nd_opt;
+	struct rb_args_info *args = node_args->nd_ainfo;
 	ID rest_id = 0;
 	int last_comma = 0;
 	ID block_id = 0;
-	NODE *node_init = 0;
 
 	if (nd_type(node_args) != NODE_ARGS) {
 	    rb_bug("iseq_set_arguments: NODE_ARGS is expected, but %s",
 		   ruby_node_name(nd_type(node_args)));
 	}
 
-	/*
-         * new argument information:
-         *   NODE_ARGS     [m: int,  o: NODE_OPT_ARG, ->]
-         *   NODE_ARGS_AUX [r: ID,   b: ID,           ->]
-         *   NODE_ARGS_AUX [Pst: id, Plen: int,       init: NODE*]
-         *  optarg information:
-         *   NODE_OPT_ARGS [idx,     expr,            next ->]
-	 *  init arg:
-	 *   NODE_AND(m_init, p_init)
-	 *  if "r" is 1, it's means "{|x,|}" type block parameter.
-	 */
 
-	iseq->argc = (int)node_args->nd_frml;
+	iseq->argc = (int)args->pre_args_num;
 	debugs("  - argc: %d\n", iseq->argc);
 
-	if (node_aux) {
-	    rest_id = node_aux->nd_rest;
-	    if (rest_id == 1) {
-		last_comma = 1;
-		rest_id = 0;
-	    }
-	    block_id = (ID)node_aux->nd_body;
-	    node_aux = node_aux->nd_next;
-
-	    if (node_aux) {
-		ID post_start_id = node_aux->nd_pid;
-		iseq->arg_post_start = get_dyna_var_idx_at_raw(iseq, post_start_id);
-		iseq->arg_post_len = (int)node_aux->nd_plen;
-		node_init = node_aux->nd_next;
-	    }
+	rest_id = args->rest_arg;
+	if (rest_id == 1) {
+	    last_comma = 1;
+	    rest_id = 0;
 	}
+	block_id = args->block_arg;
 
-	if (node_opt) {
-	    NODE *node = node_opt;
+	if (args->first_post_arg) {
+	    iseq->arg_post_start = get_dyna_var_idx_at_raw(iseq, args->first_post_arg);
+	    iseq->arg_post_len = args->post_args_num;
+	}
+
+	if (args->opt_args) {
+	    NODE *node = args->opt_args;
 	    LABEL *label;
 	    VALUE labels = rb_ary_tmp_new(1);
 	    int i = 0, j;
@@ -1144,13 +1126,11 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args)
 	    iseq->arg_opts = 0;
 	}
 
-	if (node_init) {
-	    if (node_init->nd_1st) { /* m_init */
-		COMPILE_POPED(optargs, "init arguments (m)", node_init->nd_1st);
-	    }
-	    if (node_init->nd_2nd) { /* p_init */
-		COMPILE_POPED(optargs, "init arguments (p)", node_init->nd_2nd);
-	    }
+	if (args->pre_init) { /* m_init */
+	    COMPILE_POPED(optargs, "init arguments (m)", args->pre_init);
+	}
+	if (args->post_init) { /* p_init */
+	    COMPILE_POPED(optargs, "init arguments (p)", args->post_init);
 	}
 
 	if (rest_id) {
diff --git a/gc.c b/gc.c
index ccd7441..60f6b27 100644
--- a/gc.c
+++ b/gc.c
@@ -1710,7 +1710,6 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
 	  case NODE_CALL:
 	  case NODE_DEFS:
 	  case NODE_OP_ASGN1:
-	  case NODE_ARGS:
 	    gc_mark(objspace, (VALUE)obj->as.node.u1.node, lev);
 	    /* fall through */
 	  case NODE_SUPER:	/* 3 */
@@ -1778,6 +1777,18 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
 	    ptr = (VALUE)obj->as.node.u2.node;
 	    goto again;
 
+	  case NODE_ARGS:	/* custom */
+	    {
+		struct rb_args_info *args = obj->as.node.u3.args;
+		if (args) {
+		    if (args->pre_init)  gc_mark(objspace, (VALUE)args->pre_init, lev);
+		    if (args->post_init) gc_mark(objspace, (VALUE)args->post_init, lev);
+		    if (args->opt_args)  gc_mark(objspace, (VALUE)args->opt_args, lev);
+		}
+	    }
+	    ptr = (VALUE)obj->as.node.u2.node;
+	    goto again;
+
 	  case NODE_ZARRAY:	/* - */
 	  case NODE_ZSUPER:
 	  case NODE_VCALL:
@@ -2371,6 +2382,11 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
 		xfree(RANY(obj)->as.node.u1.tbl);
 	    }
 	    break;
+	  case NODE_ARGS:
+	    if (RANY(obj)->as.node.u3.args) {
+		xfree(RANY(obj)->as.node.u3.args);
+	    }
+	    break;
 	  case NODE_ALLOCA:
 	    xfree(RANY(obj)->as.node.u1.node);
 	    break;
diff --git a/node.c b/node.c
index 5912bc4..eca8981 100644
--- a/node.c
+++ b/node.c
@@ -837,55 +837,18 @@ dump_node(VALUE buf, VALUE indent, int comment, NODE *node)
 	F_NODE(nd_2nd, "post arguments");
 	break;
 
-      case NODE_ARGS_AUX:
-	ANN("method parameters (cont'd)");
-	F_CUSTOM1(nd_rest, "rest argument", {
-	    if (node->nd_rest == 1) A("nil (with last comma)");
-	    else A_ID(node->nd_rest);
-	});
-	F_CUSTOM1(nd_body, "block argument", { A_ID((ID)node->nd_body); });
-	LAST_NODE;
-	F_CUSTOM2(nd_next, "aux info 2", {
-	    node = node->nd_next;
-	    next_indent = "|    ";
-	    if (!node) {
-		D_NULL_NODE;
-	    }
-	    else {
-		D_NODE_HEADER(node);
-		ANN("method parameters (cont'd)");
-		F_ID(nd_pid, "first post argument");
-		F_LONG(nd_plen, "post argument length");
-		LAST_NODE;
-		F_CUSTOM2(nd_next, "aux info 3", {
-		    node = node->nd_next;
-		    next_indent = "|   ";
-		    if (!node) {
-			D_NULL_NODE;
-		    }
-		    else {
-			D_NODE_HEADER(node);
-			ANN("method parameters (cont'd)");
-			ANN("\"init arguments (m)\" evaluates multiple assignments before rest argument");
-			ANN("\"init arguments (p)\" evaluates multiple assignments after rest argument");
-			ANN("example: def foo((m1, m2), *r, (p1, p2))");
-			F_NODE(nd_1st, "init arguments (m)");
-			LAST_NODE;
-			F_NODE(nd_2nd, "init arguments (p)");
-		    }
-		});
-	    }
-	});
-	break;
-
       case NODE_ARGS:
 	ANN("method parameters");
 	ANN("format: def method_name(.., [nd_opt=some], *[nd_rest], [nd_pid], .., &[nd_body])");
 	ANN("example: def foo(a, b, opt1=1, opt2=2, *rest, y, z, &blk); end");
-	F_LONG(nd_frml, "argc");
-	F_NODE(nd_next, "aux info 1");
-	LAST_NODE;
-	F_NODE(nd_opt, "optional arguments");
+	F_LONG(nd_ainfo->pre_args_num, "count of mandatory (pre-)arguments");
+	F_NODE(nd_ainfo->pre_init, "initialization of (pre-)arguments");
+	F_LONG(nd_ainfo->post_args_num, "count of mandatory post-arguments");
+	F_NODE(nd_ainfo->post_init, "initialization of post-arguments");
+	F_ID(nd_ainfo->first_post_arg, "first post argument");
+	F_ID(nd_ainfo->rest_arg, "rest argument");
+	F_ID(nd_ainfo->block_arg, "block argument");
+	F_NODE(nd_ainfo->opt_args, "optional arguments");
 	break;
 
       case NODE_SCOPE:
diff --git a/node.h b/node.h
index 7c360cd..873c52c 100644
--- a/node.h
+++ b/node.h
@@ -253,6 +253,7 @@ typedef struct RNode {
 	ID id;
 	long state;
 	struct rb_global_entry *entry;
+	struct rb_args_info *args;
 	long cnt;
 	VALUE value;
     } u3;
@@ -321,6 +322,7 @@ typedef struct RNode {
 #define nd_recv  u1.node
 #define nd_mid   u2.id
 #define nd_args  u3.node
+#define nd_ainfo u3.args
 
 #define nd_noex  u3.id
 #define nd_defn  u3.node
@@ -415,7 +417,6 @@ typedef struct RNode {
 #define NEW_VCALL(m) NEW_NODE(NODE_VCALL,0,m,0)
 #define NEW_SUPER(a) NEW_NODE(NODE_SUPER,0,0,a)
 #define NEW_ZSUPER() NEW_NODE(NODE_ZSUPER,0,0,0)
-#define NEW_ARGS(m,o) NEW_NODE(NODE_ARGS,o,m,0)
 #define NEW_ARGS_AUX(r,b) NEW_NODE(NODE_ARGS_AUX,r,b,0)
 #define NEW_OPT_ARG(i,v) NEW_NODE(NODE_OPT_ARG,i,v,0)
 #define NEW_POSTARG(i,v) NEW_NODE(NODE_POSTARG,i,v,0)
@@ -483,6 +484,20 @@ VALUE rb_gvar_set(struct rb_global_entry *, VALUE);
 VALUE rb_gvar_defined(struct rb_global_entry *);
 const struct kwtable *rb_reserved_word(const char *, unsigned int);
 
+struct rb_args_info {
+    long pre_args_num;  /* count of mandatory pre-arguments */
+    NODE *pre_init;
+
+    long post_args_num; /* count of mandatory post-arguments */
+    NODE *post_init;
+    ID first_post_arg;
+
+    ID rest_arg;
+    ID block_arg;
+
+    NODE *opt_args;
+};
+
 struct parser_params;
 void *rb_parser_malloc(struct parser_params *, size_t);
 void *rb_parser_realloc(struct parser_params *, void *, size_t);
diff --git a/parse.y b/parse.y
index 69f3dcc..4a05e0f 100644
--- a/parse.y
+++ b/parse.y
@@ -9069,25 +9069,24 @@ static NODE*
 new_args_gen(struct parser_params *parser, NODE *m, NODE *o, ID r, NODE *p, ID b)
 {
     int saved_line = ruby_sourceline;
-    NODE *node;
-    NODE *i1, *i2 = 0;
+    struct rb_args_info *args;
 
-    node = NEW_ARGS(m ? m->nd_plen : 0, o);
-    i1 = m ? m->nd_next : 0;
-    node->nd_next = NEW_ARGS_AUX(r, b);
+    args = ALLOC(struct rb_args_info);
+
+    args->pre_args_num   = m ? m->nd_plen : 0;
+    args->pre_init       = m ? m->nd_next : 0;
+
+    args->post_args_num  = p ? p->nd_plen : 0;
+    args->post_init      = p ? p->nd_next : 0;
+    args->first_post_arg = p ? p->nd_pid : 0;
+
+    args->rest_arg       = r;
+    args->block_arg      = b;
+
+    args->opt_args       = o;
 
-    if (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;
+    return NEW_NODE(NODE_ARGS, 0, 0, args);
 }
 #endif /* !RIPPER */
 
-- 
1.7.5.4

