[前][次][番号順一覧][スレッド一覧][生データ]

yarv-diff:411

From: ko1 atdot.net
Date: 10 Nov 2006 09:18:14 +0900
Subject: [yarv-diff:411] r579 - in trunk: . yarvtest

Author: ko1
Date: 2006-11-10 09:18:12 +0900 (Fri, 10 Nov 2006)
New Revision: 579

Modified:
   trunk/ChangeLog
   trunk/class.c
   trunk/compile.c
   trunk/eval_thread.c
   trunk/gc.c
   trunk/iseq.c
   trunk/node.h
   trunk/parse.y
   trunk/vm_dump.c
   trunk/yarvtest/test_block.rb
   trunk/yarvtest/test_class.rb
   trunk/yarvtest/test_syntax.rb
Log:
	* class.c : revert module duplicate inclusion

	* parse.y : catch up current Ruby HEAD

	* node.h : ditto

	* compile.c : ditto

	* gc.c : ditto

	* iseq.c : ditto

	* eval_thread.c : define Continuation (null class)

	* vm_dump.c : fix to output backtrae to stderr

	* yarvtest/test_block.rb : remove unsupported test

	* yarvtest/test_class.rb : add a test about super

	* yarvtest/test_syntax.rb : add a test about case/when



Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2006-11-09 01:27:13 UTC (rev 578)
+++ trunk/ChangeLog	2006-11-10 00:18:12 UTC (rev 579)
@@ -4,6 +4,31 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2006-11-10(Fri) 09:13:46 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* class.c : revert module duplicate inclusion
+
+	* parse.y : catch up current Ruby HEAD
+
+	* node.h : ditto
+
+	* compile.c : ditto
+
+	* gc.c : ditto
+
+	* iseq.c : ditto
+
+	* eval_thread.c : define Continuation (null class)
+
+	* vm_dump.c : fix to output backtrae to stderr
+
+	* yarvtest/test_block.rb : remove unsupported test
+
+	* yarvtest/test_class.rb : add a test about super
+
+	* yarvtest/test_syntax.rb : add a test about case/when
+
+
 2006-11-09(Thu) 10:22:59 +0900  Koichi Sasada  <ko1 atdot.net>
 
 	* call_cfunc.h -> call_cfunc.ci : renamed

Modified: trunk/class.c
===================================================================
--- trunk/class.c	2006-11-09 01:27:13 UTC (rev 578)
+++ trunk/class.c	2006-11-10 00:18:12 UTC (rev 579)
@@ -365,7 +365,7 @@
 void
 rb_include_module(VALUE klass, VALUE module)
 {
-    VALUE c;
+    VALUE p, c;
     int changed = 0;
 
     rb_frozen_class_p(klass);
@@ -380,11 +380,29 @@
     OBJ_INFECT(klass, module);
     c = klass;
     while (module) {
+       int superclass_seen = Qfalse;
+
 	if (RCLASS(klass)->m_tbl == RCLASS(module)->m_tbl)
 	    rb_raise(rb_eArgError, "cyclic include detected");
-	RCLASS(c)->super = include_class_new(module, RCLASS(c)->super);
-	c = RCLASS(c)->super;
+       /* ignore if the module included already in superclasses */
+       for (p = RCLASS(klass)->super; p; p = RCLASS(p)->super) {
+           switch (BUILTIN_TYPE(p)) {
+             case T_ICLASS:
+               if (RCLASS(p)->m_tbl == RCLASS(module)->m_tbl) {
+                   if (!superclass_seen) {
+                       c = p;  /* move insertion point */
+                   }
+                   goto skip;
+               }
+               break;
+             case T_CLASS:
+               superclass_seen = Qtrue;
+               break;
+           }
+       }
+       c = RCLASS(c)->super = include_class_new(module, RCLASS(c)->super);
 	changed = 1;
+      skip:
 	module = RCLASS(module)->super;
     }
     if (changed) rb_clear_cache();

Modified: trunk/compile.c
===================================================================
--- trunk/compile.c	2006-11-09 01:27:13 UTC (rev 578)
+++ trunk/compile.c	2006-11-10 00:18:12 UTC (rev 579)
@@ -1967,7 +1967,7 @@
 	if (opt_p && nd_type(node->nd_head) != NODE_LIT) {
 	    opt_p = Qfalse;
 	}
-	COMPILE(anchor, "element", node->nd_head);
+	COMPILE(anchor, "array element", node->nd_head);
 	node = node->nd_next;
     }
 
@@ -1992,8 +1992,7 @@
 	ADD_INSN1(anchor, line, newarray, INT2FIX(len));
 	APPEND_LIST(ret, anchor);
     }
-
-    return COMPILE_OK;
+    return len;
 }
 
 static VALUE
@@ -2012,6 +2011,33 @@
     return Qfalse;
 }
 
+static VALUE
+when_vals(yarv_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, VALUE special_literals)
+{
+    while (vals) {
+	VALUE lit;
+	NODE* val;
+
+	val = vals->nd_head;
+
+	if (special_literals &&
+	    (lit = case_when_optimizable_literal(val)) != Qfalse) {
+	    rb_ary_push(special_literals, lit);
+	    rb_ary_push(special_literals, (VALUE)(l1) | 1);
+	}
+	else {
+	    special_literals = Qfalse;
+	}
+
+	COMPILE(cond_seq, "when cond", val);
+	ADD_INSN1(cond_seq, nd_line(val), topn, INT2FIX(1));
+	ADD_SEND(cond_seq, nd_line(val), ID2SYM(idEqq), INT2FIX(1));
+	ADD_INSNL(cond_seq, nd_line(val), branchif, l1);
+	vals = vals->nd_next;
+    }
+    return special_literals;
+}
+
 static int
 make_masgn_lhs(yarv_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node)
 {
@@ -2156,7 +2182,10 @@
 		    break;
 		}
 	    default:
-		rb_bug("unknown rhs: %s", node_name(nd_type(rhsn)));
+		COMPILE(ret, "rhs to ary (splat/default)", rhsn);
+		ADD_INSN2(ret, nd_line(rhsn), expandarray, INT2FIX(llen),
+			  INT2FIX(lhs_splat));
+		// rb_bug("unknown rhs: %s", node_name(nd_type(rhsn)));
 	    }
 	}
 	else {
@@ -2468,6 +2497,49 @@
     ADD_SEQ(ret, ensure);
 }
 
+static VALUE
+setup_arg(yarv_iseq_t *iseq, LINK_ANCHOR *args, NODE *node, VALUE *flag)
+{
+    VALUE argc = INT2FIX(0);
+    NODE *argn = node->nd_args;
+    DECL_ANCHOR(arg_block);
+
+    if (argn && nd_type(argn) == NODE_BLOCK_PASS) {
+	COMPILE(arg_block, "block", argn->nd_body);
+	*flag |= VM_CALL_ARGS_BLOCKARG_BIT;
+	argn = argn->nd_head;
+    }
+
+    if (argn) {
+	switch (nd_type(argn)) {
+	  case NODE_SPLAT: {
+	      COMPILE(args, "args(splat)", argn->nd_head);
+	      argc = INT2FIX(1);
+	      *flag |= VM_CALL_ARGS_SPLAT_BIT;
+	      break;
+	  }
+	  case NODE_ARGSCAT: {
+	      argc = INT2FIX(compile_array(iseq, args, argn->nd_head, Qfalse) + 1);
+	      POP_ELEMENT(args);
+	      COMPILE(args, "args(cat: splat)", argn->nd_body);
+	      *flag |= VM_CALL_ARGS_SPLAT_BIT;
+	      break;
+	  }
+	  default: {
+	      argc = INT2FIX(compile_array(iseq, args, argn, Qfalse));
+	      POP_ELEMENT(args);
+	      break;
+	  }
+	}
+    }
+
+    if (*flag & VM_CALL_ARGS_BLOCKARG_BIT) {
+	ADD_SEQ(args, arg_block);
+    }
+    return argc;
+}
+     
+
 /**
   compile each node
 
@@ -2502,6 +2574,7 @@
 
       case NODE_METHOD:{
 	  /* OK */
+	  bp();
 	  COMPILE_ERROR(("BUG: unknown node: NODE_METHOD"));
 	  break;
       }
@@ -2569,6 +2642,10 @@
 	  DECL_ANCHOR(cond_seq);
 	  VALUE special_literals = rb_ary_new();
 
+	  if (node->nd_head == 0) {
+	      COMPILE_(ret, "when", node->nd_body, poped);
+	      break;
+	  }
 	  COMPILE(head, "case base", node->nd_head);
 
 	  node = node->nd_body;
@@ -2593,43 +2670,29 @@
 	      ADD_INSNL(body_seq, nd_line(node), jump, endlabel);
 
 	      vals = node->nd_head;
-	      if (vals && nd_type(vals) == NODE_ARRAY) {
-		  while (vals) {
-		      VALUE lit;
-		      val = vals->nd_head;
+	      if (vals) {
+		  if (nd_type(vals) == NODE_ARRAY) {
+		      special_literals = when_vals(iseq, cond_seq, vals, l1, special_literals);
+		  }
+		  else if (nd_type(vals) == NODE_SPLAT || nd_type(vals) == NODE_ARGSCAT) {
+		      NODE *val = vals->nd_head;
+		      special_literals = 0;
 
-		      if ((lit = case_when_optimizable_literal(val))
-			  && special_literals) {
-			  rb_ary_push(special_literals, lit);
-			  rb_ary_push(special_literals, (VALUE)(l1) | 1);
+		      if (nd_type(vals) == NODE_ARGSCAT) {
+			  when_vals(iseq, cond_seq, vals->nd_head, l1, 0);
+			  val = vals->nd_body;
 		      }
-		      else {
-			  special_literals = Qfalse;
-		      }
 
-		      if (nd_type(val) == NODE_WHEN) {	// && nd_type(val->nd_head) != NODE_ARRAY){
-			  COMPILE(cond_seq, "when/cond specail?",
-				  val->nd_head);
-			  ADD_INSN1(cond_seq, nd_line(node),
-				    checkincludearray, Qtrue);
-			  /* for stack caching */
-			  ADD_INSN(cond_seq, nd_line(node), putnil);
-			  ADD_INSN(cond_seq, nd_line(node), pop);
-		      }
-		      else {
-			  COMPILE(cond_seq, "when cond", val);
-			  ADD_INSN1(cond_seq, nd_line(node), topn,
-				    INT2FIX(1));
-			  ADD_SEND(cond_seq, nd_line(node), ID2SYM(idEqq),
-				   INT2FIX(1));
-		      }
-		      ADD_INSNL(cond_seq, nd_line(node), branchif, l1) ;
-		      vals = vals->nd_next;
+		      COMPILE(cond_seq, "when/cond splat", val);
+		      ADD_INSN1(cond_seq, nd_line(val), checkincludearray, Qtrue);
+		      ADD_INSNL(cond_seq, nd_line(val), branchif, l1);
 		  }
+		  else {
+		      rb_bug("NODE_CASAE: unknown node (%s)", node_name(nd_type(vals)));
+		  }
 	      }
 	      else {
-		  COMPILE_ERROR(("NODE_CASAE: must be NODE_ARRAY, but %s\n",
-				 node_name(nd_type(vals))));
+		  rb_bug("NODE_CASAE: must be NODE_ARRAY, but 0\n");
 	      }
 
 	      node = node->nd_next;
@@ -2686,21 +2749,32 @@
 	      if (vals && nd_type(vals) == NODE_ARRAY) {
 		  while (vals) {
 		      val = vals->nd_head;
-		      if (nd_type(val) == NODE_WHEN) {
-			  ADD_INSN(ret, nd_line(val), putnil);
-			  COMPILE(ret, "when2/splat", val->nd_head);
-			  ADD_INSN1(ret, nd_line(val), checkincludearray,
-				    Qfalse);
-			  ADD_INSN(ret, nd_line(val), pop);
-			  ADD_INSNL(ret, nd_line(val), branchif, l1) ;
-		      }
-		      else {
-			  COMPILE(ret, "when2", val);
-			  ADD_INSNL(ret, nd_line(val), branchif, l1) ;
-		      }
+		      COMPILE(ret, "when2", val);
+		      ADD_INSNL(ret, nd_line(val), branchif, l1) ;
 		      vals = vals->nd_next;
 		  }
 	      }
+	      else if (nd_type(vals) == NODE_SPLAT || nd_type(vals) == NODE_ARGSCAT) {
+		  NODE *val = vals->nd_head;
+		  
+		  if (nd_type(vals) == NODE_ARGSCAT) {
+		      NODE *vs = vals->nd_head;
+		      val = vals->nd_body;
+
+		      while (vs) {
+			  NODE* val = vs->nd_head;
+			  COMPILE(ret, "when/argscat", val);
+			  ADD_INSNL(ret, nd_line(val), branchif, l1);
+			  vs = vs->nd_next;
+		      }
+		  }
+
+		  ADD_INSN(ret, nd_line(val), putnil);
+		  COMPILE(ret, "when2/splat", val);
+		  ADD_INSN1(ret, nd_line(val), checkincludearray, Qfalse);
+		  ADD_INSN(ret, nd_line(val), pop);
+		  ADD_INSNL(ret, nd_line(val), branchif, l1);
+	      }
 	      else {
 		  rb_bug("err");
 	      }
@@ -3220,15 +3294,20 @@
 	   * send op   # a x a[x]+y
 	   * send []=  # ret
 	   */
+
+	  /*
+	   * nd_recv[nd_args->nd_body] (nd_mid)= nd_args->nd_head;
+	   * NODE_OP_ASGN nd_recv
+	   *              nd_args->nd_head
+	   *              nd_args->nd_body
+	   *              nd_mid
+	   */
+
 	  COMPILE(ret, "NODE_OP_ASGN1 recv", node->nd_recv);
-
-	  compile_array(iseq, args, node->nd_args->nd_next, Qfalse);
+	  argc = compile_array(iseq, args, node->nd_args->nd_body, Qfalse);
 	  POP_ELEMENT(args);
-	  POP_ELEMENT(args);
-	  argc = node->nd_args->nd_alen - 2;
-
 	  ADD_SEQ(ret, args);
-	  ADD_INSN1(ret, nd_line(node), dupn, INT2FIX(argc + 1));
+	  ADD_INSN1(ret, nd_line(node), dupn, INT2FIX(argc+1));
 	  ADD_SEND(ret, nd_line(node), ID2SYM(idAREF), INT2FIX(argc));
 
 	  if (id == 0 || id == 1) {
@@ -3477,31 +3556,8 @@
 	  }
 
 	  /* args */
-	  if (type != NODE_VCALL && node->nd_args) {
-	      if (nd_type(node->nd_args) == NODE_SPLAT) {
-		  COMPILE(args, "args(splat)", node->nd_args->nd_head);
-		  argc = INT2FIX(1);
-		  flag |= VM_CALL_ARGS_SPLAT_BIT;
-	      }
-	      else if (nd_type(node->nd_args) == NODE_ARGSCAT) {
-		  NODE *t = node->nd_args->nd_head;
-		  for (argc = 0; t; argc++, t = t->nd_next) {
-		      /* */
-		  }
-		  argc = INT2FIX(argc + 1);
-
-		  compile_array(iseq, args, node->nd_args->nd_head, Qfalse);
-		  POP_ELEMENT(args);
-
-		  // argc = INT2FIX(LIST_SIZE(args) + 1);
-		  COMPILE(args, "args(cat: splat)", node->nd_args->nd_body);
-
-		  flag |= VM_CALL_ARGS_SPLAT_BIT;
-	      }
-	      else {
-		  compile_array(iseq, args, node->nd_args, Qfalse);
-		  argc = OPERAND_AT(POP_ELEMENT(args), 0);
-	      }
+	  if (nd_type(node) != NODE_VCALL) {
+	      argc = setup_arg(iseq, args, node, &flag);
 	  }
 	  else {
 	      argc = INT2FIX(0);
@@ -3550,31 +3606,7 @@
 	  iseq->compile_data->current_block = Qfalse;
 
 	  if (nd_type(node) == NODE_SUPER) {
-	      /* args */
-	      if (type != NODE_VCALL && node->nd_args) {
-		  if (nd_type(node->nd_args) == NODE_SPLAT) {
-		      COMPILE(args, "args(splat)", node->nd_args->nd_head);
-		      argc = INT2FIX(1);
-		      flag |= VM_CALL_ARGS_SPLAT_BIT;
-		  }
-		  else if (nd_type(node->nd_args) == NODE_ARGSCAT) {
-		      compile_array(iseq, args, node->nd_args->nd_head,
-				    Qfalse);
-		      POP_ELEMENT(args);
-
-		      argc = INT2FIX(LIST_SIZE(args) + 1);
-		      COMPILE(args, "args(cat: splat)",
-			      node->nd_args->nd_body);
-		      flag |= VM_CALL_ARGS_SPLAT_BIT;
-		  }
-		  else {
-		      compile_array(iseq, args, node->nd_args, Qfalse);
-		      argc = OPERAND_AT(POP_ELEMENT(args), 0);
-		  }
-	      }
-	      else {
-		  argc = INT2FIX(0);
-	      }
+	      argc = setup_arg(iseq, args, node, &flag);
 	  }
 	  else {
 	      /* NODE_ZSUPER */
@@ -4025,35 +4057,14 @@
 	  COMPILE_ERROR(("BUG: unknown node: NODE_TO_ARY"));
 	  break;
       }
-      case NODE_SVALUE:{
-	  COMPILE(ret, "svalue head", node->nd_head);
-	  ADD_INSN1(ret, nd_line(node), splatarray, Qtrue);
-	  break;
-      }
       case NODE_BLOCK_ARG:{
 	  iseq->arg_block = node->nd_cnt - 2 + 1;
 	  iseq->arg_simple = 0;
-
 	  break;
       }
       case NODE_BLOCK_PASS:{
-	  VALUE prevblock = iseq->compile_data->current_block;
-	  LABEL *retry_label = NEW_LABEL(nd_line(node));
-	  LABEL *retry_end_l = NEW_LABEL(nd_line(node));
-	  DECL_ANCHOR(current_block);
-
-	  COMPILE(current_block, "block pass proc", node->nd_body);
-
-	  iseq->compile_data->current_block = (VALUE)current_block | 1;
-	  ADD_LABEL(ret, retry_label);
-	  COMPILE_(ret, "iter caller (NODE_BLOCK_PASS)", node->nd_iter,
-		   poped);
-	  ADD_LABEL(ret, retry_end_l);
-
-	  iseq->compile_data->current_block = prevblock;
-	  ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, retry_label, retry_end_l, 0,
-			  retry_label);
-	  break;
+	  /* OK */
+	  COMPILE_ERROR(("BUG: unknown node: NODE_BLOCK_PASS"));
       }
       case NODE_DEFN:{
 	  VALUE iseqval = NEW_ISEQVAL(node->nd_defn,
@@ -4362,8 +4373,8 @@
 	  break;
       }
       case NODE_POSTEXE:{
-	  ADD_INSN1(ret, nd_line(node), postexe,
-		    iseq->compile_data->current_block);
+	  VALUE block = NEW_CHILD_ISEQVAL(node, 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);
 	  }

Modified: trunk/eval_thread.c
===================================================================
--- trunk/eval_thread.c	2006-11-09 01:27:13 UTC (rev 578)
+++ trunk/eval_thread.c	2006-11-10 00:18:12 UTC (rev 579)
@@ -587,6 +587,7 @@
 {
     recursive_key = rb_intern("__recursive_key__");
     rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
+    rb_cCont = rb_define_class("Continuation", rb_cObject);
 }
 
 static VALUE

Modified: trunk/gc.c
===================================================================
--- trunk/gc.c	2006-11-09 01:27:13 UTC (rev 578)
+++ trunk/gc.c	2006-11-10 00:18:12 UTC (rev 579)
@@ -847,6 +847,7 @@
 	  case NODE_RESBODY:
 	  case NODE_CLASS:
 	  case NODE_ARGS:
+	  case NODE_BLOCK_PASS:
 	    gc_mark((VALUE)obj->as.node.u2.node, lev);
 	    /* fall through */
 	  case NODE_BLOCK:	/* 1,3 */
@@ -901,6 +902,7 @@
 	  case NODE_OPT_N:
 	  case NODE_EVSTR:
 	  case NODE_UNDEF:
+	  case NODE_POSTEXE:
 	    ptr = (VALUE)obj->as.node.u2.node;
 	    goto again;
 
@@ -917,12 +919,10 @@
 	  case NODE_COLON2:
 	  case NODE_SPLAT:
 	  case NODE_TO_ARY:
-	  case NODE_SVALUE:
 	    ptr = (VALUE)obj->as.node.u1.node;
 	    goto again;
 
 	  case NODE_SCOPE:	/* 2,3 */
-	  case NODE_BLOCK_PASS:
 	  case NODE_CDECL:
 	    gc_mark((VALUE)obj->as.node.u3.node, lev);
 	    ptr = (VALUE)obj->as.node.u2.node;
@@ -948,7 +948,6 @@
 	  case NODE_ERRINFO:
 	  case NODE_ATTRSET:
 	  case NODE_BLOCK_ARG:
-	  case NODE_POSTEXE:
 	    break;
 	  case NODE_ALLOCA:
 	    mark_locations_array((VALUE*)obj->as.node.u1.value,

Modified: trunk/iseq.c
===================================================================
--- trunk/iseq.c	2006-11-09 01:27:13 UTC (rev 578)
+++ trunk/iseq.c	2006-11-10 00:18:12 UTC (rev 579)
@@ -934,6 +934,8 @@
 	return "NODE_DREGX_ONCE";
     case NODE_ARGS:
 	return "NODE_ARGS";
+    case NODE_POSTARG:
+	return "NODE_POSTARG";
     case NODE_ARGSCAT:
 	return "NODE_ARGSCAT";
     case NODE_ARGSPUSH:
@@ -942,8 +944,6 @@
 	return "NODE_SPLAT";
     case NODE_TO_ARY:
 	return "NODE_TO_ARY";
-    case NODE_SVALUE:
-	return "NODE_SVALUE";
     case NODE_BLOCK_ARG:
 	return "NODE_BLOCK_ARG";
     case NODE_BLOCK_PASS:

Modified: trunk/node.h
===================================================================
--- trunk/node.h	2006-11-09 01:27:13 UTC (rev 578)
+++ trunk/node.h	2006-11-10 00:18:12 UTC (rev 579)
@@ -86,11 +86,11 @@
     NODE_DREGX,
     NODE_DREGX_ONCE,
     NODE_ARGS,
+    NODE_POSTARG,
     NODE_ARGSCAT,
     NODE_ARGSPUSH,
     NODE_SPLAT,
     NODE_TO_ARY,
-    NODE_SVALUE,
     NODE_BLOCK_ARG,
     NODE_BLOCK_PASS,
     NODE_DEFN,
@@ -314,11 +314,11 @@
 #define NEW_SUPER(a) NEW_NODE(NODE_SUPER,0,0,a)
 #define NEW_ZSUPER() NEW_NODE(NODE_ZSUPER,0,0,0)
 #define NEW_ARGS(f,o,r) NEW_NODE(NODE_ARGS,o,r,f)
+#define NEW_POSTARG(r,m) NEW_NODE(NODE_POSTARG,m,0,r)
 #define NEW_ARGSCAT(a,b) NEW_NODE(NODE_ARGSCAT,a,b,0)
 #define NEW_ARGSPUSH(a,b) NEW_NODE(NODE_ARGSPUSH,a,b,0)
 #define NEW_SPLAT(a) NEW_NODE(NODE_SPLAT,a,0,0)
 #define NEW_TO_ARY(a) NEW_NODE(NODE_TO_ARY,a,0,0)
-#define NEW_SVALUE(a) NEW_NODE(NODE_SVALUE,a,0,0)
 #define NEW_BLOCK_ARG(v) NEW_NODE(NODE_BLOCK_ARG,v,0,local_cnt(v))
 #define NEW_BLOCK_PASS(b) NEW_NODE(NODE_BLOCK_PASS,0,b,0)
 #define NEW_ALIAS(n,o) NEW_NODE(NODE_ALIAS,n,o,0)
@@ -340,7 +340,7 @@
 #define NEW_ERRINFO() NEW_NODE(NODE_ERRINFO,0,0,0)
 #define NEW_DEFINED(e) NEW_NODE(NODE_DEFINED,e,0,0)
 #define NEW_PREEXE(b) NEW_SCOPE(b)
-#define NEW_POSTEXE() NEW_NODE(NODE_POSTEXE,0,0,0)
+#define NEW_POSTEXE(b) NEW_NODE(NODE_POSTEXE,0,b,0)
 #define NEW_BMETHOD(b) NEW_NODE(NODE_BMETHOD,0,0,b)
 #define NEW_ATTRASGN(r,m,a) NEW_NODE(NODE_ATTRASGN,r,m,a)
 #define NEW_PRELUDE(p,b) NEW_NODE(NODE_PRELUDE,p,b,0)

Modified: trunk/parse.y
===================================================================
--- trunk/parse.y	2006-11-09 01:27:13 UTC (rev 578)
+++ trunk/parse.y	2006-11-10 00:18:12 UTC (rev 579)
@@ -66,7 +66,6 @@
 enum lex_state_e {
     EXPR_BEG,			/* ignore newline, +/- is a sign. */
     EXPR_END,			/* newline significant, +/- is a operator. */
-    EXPR_END2,			/* newline significant, +/- is a operator. */
     EXPR_ARG,			/* newline significant, +/- is a operator. */
     EXPR_CMDARG,		/* newline significant, +/- is a operator. */
     EXPR_ENDARG,		/* newline significant, +/- is a operator. */
@@ -206,6 +205,8 @@
                      token
 */
 struct parser_params {
+    NODE *heap;
+
     union tmpyystype *parser_yylval;   /* YYSTYPE not defined yet */
     VALUE eofp;
 
@@ -226,15 +227,18 @@
     int parser_toksiz;
     VALUE parser_lex_input;
     VALUE parser_lex_lastline;
-    char *parser_lex_pbeg;
-    char *parser_lex_p;
-    char *parser_lex_pend;
+    const char *parser_lex_pbeg;
+    const char *parser_lex_p;
+    const char *parser_lex_pend;
     int parser_heredoc_end;
     int parser_command_start;
     int parser_lex_gets_ptr;
     VALUE (*parser_lex_gets)(struct parser_params*,VALUE);
     struct local_vars *parser_lvtbl;
     int parser_ruby__end__seen;
+    int line_count;
+    int has_shebang;
+
 #ifndef RIPPER
     /* Ruby core only */
     NODE *parser_eval_tree_begin;
@@ -244,7 +248,7 @@
     /* Ripper only */
     int parser_ruby_sourceline;
     VALUE parser_ruby_sourcefile;
-    char *tokp;
+    const char *tokp;
     VALUE delayed;
     int delayed_line;
     int delayed_col;
@@ -254,12 +258,6 @@
     VALUE parsing_thread;
     int toplevel_p;
 #endif
-    int line_count;
-    int has_shebang;
-
-#ifdef YYMALLOC
-    NODE *heap;
-#endif
 };
 
 #ifdef YYMALLOC
@@ -314,7 +312,7 @@
 static int yylex(void*, void*);
 
 #ifndef RIPPER
-#define yyparse parser_yyparse
+#define yyparse ruby_yyparse
 #define yydebug ruby_yydebug
 
 static NODE *cond_gen(struct parser_params*,NODE*);
@@ -335,11 +333,12 @@
 static void void_stmts_gen(struct parser_params*,NODE*);
 #define void_stmts(node) void_stmts_gen(parser, node)
 static void reduce_nodes(NODE**);
-static void block_dup_check(NODE*);
+static void block_dup_check(NODE*,NODE*);
 
 static NODE *block_append(NODE*,NODE*);
 static NODE *list_append(NODE*,NODE*);
 static NODE *list_concat(NODE*,NODE*);
+static NODE *arg_append(NODE*,NODE*);
 static NODE *arg_concat(NODE*,NODE*);
 static NODE *literal_concat(NODE*,NODE*);
 static NODE *new_evstr(NODE*);
@@ -348,18 +347,14 @@
 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*,VALUE,NODE*,NODE*,NODE*);
-#define new_args(f,o,r,b) new_args_gen(parser, f,o,r,b)
+static NODE *new_args_gen(struct parser_params*,VALUE,NODE*,NODE*,NODE*,NODE*);
+#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)
 
 static NODE *negate_lit(NODE*);
 static NODE *ret_args(NODE*);
 static NODE *arg_blk_pass(NODE*,NODE*);
-static NODE *new_call(NODE*,ID,NODE*);
-static NODE *new_fcall_gen(struct parser_params*,ID,NODE*);
-#define new_fcall(id,args) new_fcall_gen(parser, id, args)
-static NODE *new_super(NODE*);
 static NODE *new_yield(NODE*);
 
 static NODE *gettable_gen(struct parser_params*,ID);
@@ -413,6 +408,7 @@
 static int dvar_curr_gen(struct parser_params*,ID);
 #define dvar_curr(id) dvar_curr_gen(parser, id)
 
+
 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*);
@@ -620,15 +616,17 @@
 %type <node> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
 %type <node> expr_value arg_value primary_value
 %type <node> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
-%type <node> args when_args call_args call_args2 open_args paren_args opt_paren_args
+%type <node> args call_args call_args2 opt_call_args
+%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_rest_arg f_optarg f_opt f_block_arg opt_f_block_arg
-%type <node> assoc_list assocs assoc undef_list backref string_dvar
-%type <node> for_var block_param opt_block_param block_param_def block_param0
-%type <node> opt_bv_decl bv_decls bv_decl lambda f_larglist lambda_body
+%type <node> f_arglist f_args f_rest_arg f_post_arg
+%type <node> f_optarg f_opt f_block_arg opt_f_block_arg
+%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> brace_block cmd_brace_block do_block lhs none fitem
-%type <node> mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node
+%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
 %type <val>  f_arg
@@ -663,7 +661,6 @@
 %token tSTAR		/* * */
 %token tAMPER		/* & */
 %token tLAMBDA		/* -> */
-%token tLAMBDA_ARG	/* -> */
 %token tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG
 %token tSTRING_DBEG tSTRING_DVAR tSTRING_END tLAMBEG
 
@@ -942,16 +939,12 @@
 		    }
 		| keyword_END '{' compstmt '}'
 		    {
-		    /*%%%*/
 			if (in_def || in_single) {
-			    rb_warn("END in method; use at_exit");
-			}
-
-			$$ = NEW_ITER(0, NEW_POSTEXE(), $3);
-		    /*%
-			if (in_def || in_single) {
 			    rb_warn0("END in method; use at_exit");
 			}
+		    /*%%%*/
+			$$ = NEW_POSTEXE($3);
+		    /*%
 		    	$$ = dispatch1(END, $3);
 		    %*/
 		    }
@@ -1002,17 +995,13 @@
 		    	$$ = dispatch3(opassign, $1, $2, $3);
 		    %*/
 		    }
-		| primary_value '[' aref_args ']' tOP_ASGN command_call
+		| primary_value '[' opt_call_args rbracket tOP_ASGN command_call
 		    {
 		    /*%%%*/
-                        NODE *args;
+			NODE *args = $3;
 
 			value_expr($6);
-		        args = NEW_LIST($6);
-			if ($3 && nd_type($3) != NODE_ARRAY)
-			    $3 = NEW_LIST($3);
-			$3 = list_append($3, NEW_NIL());
-			list_concat(args, $3);
+			args = arg_concat($6, $3);
 			if ($5 == tOROP) {
 			    $5 = 0;
 			}
@@ -1090,7 +1079,7 @@
 		| lhs '=' mrhs
 		    {
 		    /*%%%*/
-			$$ = node_assign($1, NEW_SVALUE($3));
+			$$ = node_assign($1, $3);
 		    /*%
 		    	$$ = dispatch2(assign, $1, $3);
 		    %*/
@@ -1098,7 +1087,7 @@
 		| mlhs '=' arg_value
 		    {
 		    /*%%%*/
-			$1->nd_value = ($1->nd_head) ? NEW_TO_ARY($3) : NEW_ARRAY($3);
+			$1->nd_value = $3;
 			$$ = $1;
 		    /*%
 		    	dispatch2(massign, $1, $3);
@@ -1195,7 +1184,7 @@
 		| block_call '.' operation2 command_args
 		    {
 		    /*%%%*/
-			$$ = new_call($1, $3, $4);
+			$$ = NEW_CALL($1, $3, $4);
 		    /*%
 		    	$$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
                         $$ = method_arg($$, $4);
@@ -1204,7 +1193,7 @@
 		| block_call tCOLON2 operation2 command_args
 		    {
 		    /*%%%*/
-			$$ = new_call($1, $3, $4);
+			$$ = NEW_CALL($1, $3, $4);
 		    /*%
 		    	$$ = dispatch3(call, $1, ripper_intern("::"), $3);
                         $$ = method_arg($$, $4);
@@ -1216,7 +1205,7 @@
 		    {
 		    /*%%%*/
 			$<num>$ = dyna_push();
-			$<num>1 = ruby_sourceline;
+			$<num>$ = ruby_sourceline;
 		    /*%
 		    %*/
 		    }
@@ -1239,7 +1228,7 @@
 command		: operation command_args       %prec tLOWEST
 		    {
 		    /*%%%*/
-			$$ = new_fcall($1, $2);
+			$$ = NEW_FCALL($1, $2);
 		        fixpos($$, $2);
 		    /*%
 		        $$ = dispatch2(command, $1, $2);
@@ -1248,12 +1237,8 @@
 		| operation command_args cmd_brace_block
 		    {
 		    /*%%%*/
-			$$ = new_fcall($1, $2);
-			if ($3) {
-		            block_dup_check($$);
-			    $3->nd_iter = $$;
-			    $$ = $3;
-			}
+			$$ = NEW_FCALL($1, $2);
+			block_dup_check($2,$3);
 		        fixpos($$, $2);
 		    /*%
 		        $$ = dispatch2(command, $1, $2);
@@ -1263,7 +1248,7 @@
 		| primary_value '.' operation2 command_args	%prec tLOWEST
 		    {
 		    /*%%%*/
-			$$ = new_call($1, $3, $4);
+			$$ = NEW_CALL($1, $3, $4);
 		        fixpos($$, $1);
 		    /*%
 			$$ = dispatch4(command_call, $1, ripper_id2sym('.'), $3, $4);
@@ -1272,12 +1257,8 @@
 		| primary_value '.' operation2 command_args cmd_brace_block
 		    {
 		    /*%%%*/
-			$$ = new_call($1, $3, $4);
-			if ($5) {
-		            block_dup_check($$);
-			    $5->nd_iter = $$;
-			    $$ = $5;
-			}
+			$$ = NEW_CALL($1, $3, $4);
+			block_dup_check($4,$5);
 		        fixpos($$, $1);
 		    /*%
 			$$ = dispatch4(command_call, $1, ripper_id2sym('.'), $3, $4);
@@ -1287,7 +1268,7 @@
 		| primary_value tCOLON2 operation2 command_args	%prec tLOWEST
 		    {
 		    /*%%%*/
-			$$ = new_call($1, $3, $4);
+			$$ = NEW_CALL($1, $3, $4);
 		        fixpos($$, $1);
 		    /*%
 			$$ = dispatch4(command_call, $1, ripper_intern("::"), $3, $4);
@@ -1296,12 +1277,8 @@
 		| primary_value tCOLON2 operation2 command_args cmd_brace_block
 		    {
 		    /*%%%*/
-			$$ = new_call($1, $3, $4);
-			if ($5) {
-		            block_dup_check($$);
-			    $5->nd_iter = $$;
-			    $$ = $5;
-			}
+			$$ = NEW_CALL($1, $3, $4);
+			block_dup_check($4,$5);
 		        fixpos($$, $1);
 		    /*%
 			$$ = dispatch4(command_call, $1, ripper_intern("::"), $3, $4);
@@ -1311,7 +1288,7 @@
 		| keyword_super command_args
 		    {
 		    /*%%%*/
-			$$ = new_super($2);
+			$$ = NEW_SUPER($2);
 		        fixpos($$, $2);
 		    /*%
 			$$ = dispatch1(super, $2);
@@ -1329,20 +1306,9 @@
 		;
 
 mlhs		: mlhs_basic
-		| tLPAREN mlhs_entry rparen
+		| tLPAREN mlhs rparen
 		    {
 		    /*%%%*/
-			$$ = $2;
-		    /*%
-			$$ = dispatch1(mlhs_paren, $2);
-		    %*/
-		    }
-		;
-
-mlhs_entry	: mlhs_basic
-		| tLPAREN mlhs_entry rparen
-		    {
-		    /*%%%*/
 			$$ = NEW_MASGN(NEW_LIST($2), 0);
 		    /*%
 			$$ = dispatch1(mlhs_paren, $2);
@@ -1374,6 +1340,14 @@
 			$$ = mlhs_add_star($1, $3);
 		    %*/
 		    }
+		| mlhs_head tSTAR mlhs_node ',' mlhs_post
+		    {
+		    /*%%%*/
+			$$ = NEW_MASGN($1, NEW_POSTARG($3,$5));
+		    /*%
+			$$ = mlhs_add_star($1, $3);
+		    %*/
+		    }
 		| mlhs_head tSTAR
 		    {
 		    /*%%%*/
@@ -1382,6 +1356,14 @@
 			$$ = mlhs_add_star($1, Qnil);
 		    %*/
 		    }
+		| mlhs_head tSTAR ',' mlhs_post
+		    {
+		    /*%%%*/
+			$$ = NEW_MASGN($1, NEW_POSTARG(-1,$4));
+		    /*%
+			$$ = mlhs_add_star($1, Qnil);
+		    %*/
+		    }
 		| tSTAR mlhs_node
 		    {
 		    /*%%%*/
@@ -1390,6 +1372,14 @@
 			$$ = mlhs_add_star(mlhs_new(), $2);
 		    %*/
 		    }
+		| tSTAR mlhs_node ',' mlhs_post
+		    {
+		    /*%%%*/
+			$$ = NEW_MASGN(0, NEW_POSTARG($2,$4));
+		    /*%
+			$$ = mlhs_add_star(mlhs_new(), $2);
+		    %*/
+		    }
 		| tSTAR
 		    {
 		    /*%%%*/
@@ -1398,10 +1388,18 @@
 			$$ = mlhs_add_star(mlhs_new(), Qnil);
 		    %*/
 		    }
+		| tSTAR ',' mlhs_head
+		    {
+		    /*%%%*/
+			$$ = NEW_MASGN(0, NEW_POSTARG(-1,$3));
+		    /*%
+			$$ = mlhs_add_star(mlhs_new(), Qnil);
+		    %*/
+		    }
 		;
 
 mlhs_item	: mlhs_node
-		| tLPAREN mlhs_entry rparen
+		| tLPAREN mlhs rparen
 		    {
 		    /*%%%*/
 			$$ = $2;
@@ -1429,6 +1427,24 @@
 		    }
 		;
 
+mlhs_post	: mlhs_item
+		    {
+		    /*%%%*/
+			$$ = NEW_LIST($1);
+		    /*%
+			$$ = mlhs_add(mlhs_new(), $1);
+		    %*/
+		    }
+		| mlhs_post ',' mlhs_item
+		    {
+		    /*%%%*/
+			$$ = list_append($1, $3);
+		    /*%
+			$$ = mlhs_add($1, $3);
+		    %*/
+		    }
+		;
+
 mlhs_node	: variable
 		    {
 		    /*%%%*/
@@ -1437,7 +1453,7 @@
 			$$ = $1;
 		    %*/
 		    }
-		| primary_value '[' aref_args ']'
+		| primary_value '[' opt_call_args rbracket
 		    {
 		    /*%%%*/
 			$$ = aryset($1, $3);
@@ -1511,7 +1527,7 @@
 			$$ = dispatch1(var_field, $1);
 		    %*/
 		    }
-		| primary_value '[' aref_args ']'
+		| primary_value '[' opt_call_args rbracket
 		    {
 		    /*%%%*/
 			$$ = aryset($1, $3);
@@ -1704,12 +1720,16 @@
 		;
 
 reswords	: keyword__LINE__ | keyword__FILE__ | keyword_BEGIN | keyword_END
-		| keyword_alias | keyword_and | keyword_begin | keyword_break | keyword_case | keyword_class | keyword_def
-		| keyword_defined | keyword_do | keyword_else | keyword_elsif | keyword_end | keyword_ensure | keyword_false
-		| keyword_for | keyword_in | keyword_module | keyword_next | keyword_nil | keyword_not
-		| keyword_or | keyword_redo | keyword_rescue | keyword_retry | keyword_return | keyword_self | keyword_super
-		| keyword_then | keyword_true | keyword_undef | keyword_when | keyword_yield
-		| modifier_if | modifier_unless | modifier_while | modifier_until | modifier_rescue
+		| keyword_alias | keyword_and | keyword_begin
+		| keyword_break | keyword_case | keyword_class | keyword_def
+		| keyword_defined | keyword_do | keyword_else | keyword_elsif
+		| keyword_end | keyword_ensure | keyword_false
+		| keyword_for | keyword_in | keyword_module | keyword_next
+		| keyword_nil | keyword_not | keyword_or | keyword_redo
+		| keyword_rescue | keyword_retry | keyword_return | keyword_self
+		| keyword_super | keyword_then | keyword_true | keyword_undef
+		| keyword_when | keyword_yield | keyword_if | keyword_unless
+		| keyword_while | keyword_until
 		;
 
 arg		: lhs '=' arg
@@ -1757,17 +1777,13 @@
 		    	$$ = dispatch3(opassign, $1, $2, $3);
 		    %*/
 		    }
-		| primary_value '[' aref_args ']' tOP_ASGN arg
+		| primary_value '[' opt_call_args rbracket tOP_ASGN arg
 		    {
 		    /*%%%*/
                         NODE *args;
 
 			value_expr($6);
-			args = NEW_LIST($6);
-			if ($3 && nd_type($3) != NODE_ARRAY)
-			    $3 = NEW_LIST($3);
-			$3 = list_append($3, NEW_NIL());
-			list_concat(args, $3);
+			args = arg_concat($6, $3);
 			if ($5 == tOROP) {
 			    $5 = 0;
 			}
@@ -2148,13 +2164,13 @@
 			$$ = dispatch1(defined, $4);
 		    %*/
 		    }
-		| arg '?' arg ':' arg
+		| arg '?' arg opt_nl ':' arg
 		    {
 		    /*%%%*/
-			$$ = NEW_IF(cond($1), $3, $5);
+			$$ = NEW_IF(cond($1), $3, $6);
 		        fixpos($$, $1);
 		    /*%
-			$$ = dispatch3(ifop, $1, $3, $5);
+			$$ = dispatch3(ifop, $1, $3, $6);
 		    %*/
 		    }
 		| primary
@@ -2175,27 +2191,16 @@
 		;
 
 aref_args	: none
-		| command opt_nl
-		    {
-		    /*%%%*/
-		        rb_warn("parenthesize argument(s) for future version");
-			$$ = NEW_LIST($1);
-		    /*%
-		        rb_warn0("parenthesize argument(s) for future version");
-			$$ = arg_add(arg_new(), $1);
-		    %*/
-		    }
 		| args trailer
 		    {
 			$$ = $1;
 		    }
-		| args ',' tSTAR arg opt_nl
+		| args ',' assocs trailer
 		    {
 		    /*%%%*/
-			value_expr($4);
-			$$ = arg_concat($1, $4);
+			$$ = list_append($1, NEW_HASH($3));
 		    /*%
-			$$ = arg_add_star($1, $4);
+			$$ = arg_add_assocs($1, $3);
 		    %*/
 		    }
 		| assocs trailer
@@ -2206,66 +2211,32 @@
 			$$ = arg_add_assocs(arg_new(), $1);
 		    %*/
 		    }
-		| tSTAR arg opt_nl
-		    {
-		    /*%%%*/
-			value_expr($2);
-			$$ = newline_node(NEW_SPLAT($2));
-		    /*%
-			$$ = arg_add_star(arg_new(), $2);
-		    %*/
-		    }
 		;
 
-paren_args	: '(' none ')'
+paren_args	: '(' opt_call_args rparen
 		    {
 		    /*%%%*/
 			$$ = $2;
 		    /*%
-			$$ = dispatch1(arg_paren, arg_new());
+			$$ = dispatch1(arg_paren, escape_Qundef($2));
 		    %*/
 		    }
-		| '(' call_args rparen
-		    {
-		    /*%%%*/
-			$$ = $2;
-		    /*%
-			$$ = dispatch1(arg_paren, $2);
-		    %*/
-		    }
-		| '(' block_call rparen
-		    {
-		    /*%%%*/
-		        rb_warn("parenthesize argument for future version");
-			$$ = NEW_LIST($2);
-		    /*%
-		        rb_warn0("parenthesize argument for future version");
-			$$ = dispatch1(arg_paren, arg_add(arg_new(), $2));
-		    %*/
-		    }
-		| '(' args ',' block_call rparen
-		    {
-		    /*%%%*/
-		        rb_warn("parenthesize argument for future version");
-			$$ = list_append($2, $4);
-		    /*%
-		        rb_warn0("parenthesize argument for future version");
-			$$ = dispatch1(arg_paren, arg_add($2, $4));
-		    %*/
-		    }
 		;
 
 opt_paren_args	: none
 		| paren_args
 		;
 
+opt_call_args   : none
+		| call_args
+		;
+
 call_args	: command
 		    {
-		    /*%%%*/
 		        rb_warn("parenthesize argument(s) for future version");
+		    /*%%%*/
 			$$ = NEW_LIST($1);
 		    /*%
-		        rb_warn0("parenthesize argument(s) for future version");
 			$$ = arg_add(arg_new(), $1);
 		    %*/
 		    }
@@ -2277,15 +2248,6 @@
 			$$ = arg_add_optblock($1, $2);
 		    %*/
 		    }
-		| args ',' tSTAR arg_value opt_block_arg
-		    {
-		    /*%%%*/
-			$$ = arg_concat($1, $4);
-			$$ = arg_blk_pass($$, $5);
-		    /*%
-			arg_add_optblock(arg_add_star($1, $4), $5);
-		    %*/
-		    }
 		| assocs opt_block_arg
 		    {
 		    /*%%%*/
@@ -2296,44 +2258,15 @@
 			$$ = arg_add_optblock($$, $2);
 		    %*/
 		    }
-		| assocs ',' tSTAR arg_value opt_block_arg
-		    {
-		    /*%%%*/
-			$$ = arg_concat(NEW_LIST(NEW_HASH($1)), $4);
-			$$ = arg_blk_pass($$, $5);
-		    /*%
-			$$ = arg_add_star(arg_add_assocs(arg_new(), $1), $4);
-			$$ = arg_add_optblock($$, $5);
-		    %*/
-		    }
 		| args ',' assocs opt_block_arg
 		    {
 		    /*%%%*/
-			$$ = list_append($1, NEW_HASH($3));
+			$$ = arg_append($1, NEW_HASH($3));
 			$$ = arg_blk_pass($$, $4);
 		    /*%
 			$$ = arg_add_optblock(arg_add_assocs($1, $3), $4);
 		    %*/
 		    }
-		| args ',' assocs ',' tSTAR arg opt_block_arg
-		    {
-		    /*%%%*/
-			value_expr($6);
-			$$ = arg_concat(list_append($1, NEW_HASH($3)), $6);
-			$$ = arg_blk_pass($$, $7);
-		    /*%
-			$$ = arg_add_star(arg_add_assocs($1, $3), $6);
-			$$ = arg_add_optblock($$, $7);
-		    %*/
-		    }
-		| tSTAR arg_value opt_block_arg
-		    {
-		    /*%%%*/
-			$$ = arg_blk_pass(NEW_SPLAT($2), $3);
-		    /*%
-			$$ = arg_add_optblock(arg_add_star(arg_new(), $2), $3);
-		    %*/
-		    }
 		| block_arg
 		    /*%c%*/
 		    /*%c
@@ -2359,26 +2292,6 @@
 			$$ = arg_add_block(arg_add(arg_new(), $1), $3);
 		    %*/
                     }
-		| arg_value ',' tSTAR arg_value opt_block_arg
-		    {
-		    /*%%%*/
-			$$ = arg_concat(NEW_LIST($1), $4);
-			$$ = arg_blk_pass($$, $5);
-		    /*%
-			$$ = arg_add_star(arg_add(arg_new(), $1), $4);
-			$$ = arg_add_optblock($$, $5);
-		    %*/
-		    }
-		| arg_value ',' args ',' tSTAR arg_value opt_block_arg
-		    {
-		    /*%%%*/
-			$$ = arg_concat(list_concat(NEW_LIST($1),$3), $6);
-			$$ = arg_blk_pass($$, $7);
-		    /*%
-			$$ = arg_add_star(arg_prepend($3, $1), $6);
-			$$ = arg_add_optblock($$, $7);
-		    %*/
-		    }
 		| assocs opt_block_arg
 		    {
 		    /*%%%*/
@@ -2388,20 +2301,10 @@
 			$$ = arg_add_optblock(arg_add_assocs(arg_new(), $1), $2);
 		    %*/
 		    }
-		| assocs ',' tSTAR arg_value opt_block_arg
-		    {
-		    /*%%%*/
-			$$ = arg_concat(NEW_LIST(NEW_HASH($1)), $4);
-			$$ = arg_blk_pass($$, $5);
-		    /*%
-			$$ = arg_add_star(arg_add_assocs(arg_new(), $1), $4);
-			$$ = arg_add_optblock($$, $4);
-		    %*/
-		    }
 		| arg_value ',' assocs opt_block_arg
 		    {
 		    /*%%%*/
-			$$ = list_append(NEW_LIST($1), NEW_HASH($3));
+			$$ = arg_append(NEW_LIST($1), NEW_HASH($3));
 			$$ = arg_blk_pass($$, $4);
 		    /*%
 			$$ = arg_add_assocs(arg_add(arg_new(), $1), $3);
@@ -2411,43 +2314,13 @@
 		| arg_value ',' args ',' assocs opt_block_arg
 		    {
 		    /*%%%*/
-			$$ = list_append(list_concat(NEW_LIST($1),$3), NEW_HASH($5));
+			$$ = arg_append(list_concat(NEW_LIST($1),$3), NEW_HASH($5));
 			$$ = arg_blk_pass($$, $6);
 		    /*%
 			$$ = arg_add_assocs(arg_prepend($3, $1), $5);
 			$$ = arg_add_optblock($$, $6);
 		    %*/
 		    }
-		| arg_value ',' assocs ',' tSTAR arg_value opt_block_arg
-		    {
-		    /*%%%*/
-			$$ = arg_concat(list_append(NEW_LIST($1), NEW_HASH($3)), $6);
-			$$ = arg_blk_pass($$, $7);
-		    /*%
-			$$ = arg_add_assocs(arg_add(arg_new(), $1), $3);
-			$$ = arg_add_star($$, $6);
-			$$ = arg_add_optblock($$, $7);
-		    %*/
-		    }
-		| arg_value ',' args ',' assocs ',' tSTAR arg_value opt_block_arg
-		    {
-		    /*%%%*/
-			$$ = arg_concat(list_append(list_concat(NEW_LIST($1), $3), NEW_HASH($5)), $8);
-			$$ = arg_blk_pass($$, $9);
-		    /*%
-			$$ = arg_add_assocs(arg_prepend($3, $1), $5);
-			$$ = arg_add_star($$, $8);
-			$$ = arg_add_optblock($$, $9);
-		    %*/
-		    }
-		| tSTAR arg_value opt_block_arg
-		    {
-		    /*%%%*/
-			$$ = arg_blk_pass(NEW_SPLAT($2), $3);
-		    /*%
-			$$ = arg_add_optblock(arg_add_star(arg_new(), $2), $3);
-		    %*/
-		    }
 		| block_arg
 		;
 
@@ -2509,14 +2382,30 @@
 			$$ = arg_add(arg_new(), $1);
 		    %*/
 		    }
+		| tSTAR arg_value
+		    {
+		    /*%%%*/
+			$$ = NEW_SPLAT($2);
+		    /*%
+			$$ = arg_add_star(arg_new(), $2);
+		    %*/
+		    }
 		| args ',' arg_value
 		    {
 		    /*%%%*/
-			$$ = list_append($1, $3);
+			$$ = arg_append($1, $3);
 		    /*%
 			$$ = arg_add($1, $3);
 		    %*/
 		    }
+		| args ',' tSTAR arg_value
+		    {
+		    /*%%%*/
+			$$ = arg_concat($1, $4);
+		    /*%
+			$$ = arg_add_star($1, $4);
+		    %*/
+		    }
 		;
 
 mrhs		: args ',' arg_value
@@ -2698,7 +2587,7 @@
 		| method_call brace_block
 		    {
 		    /*%%%*/
-		        block_dup_check($$);
+			block_dup_check($1->nd_args, $2);
 			$2->nd_iter = $1;
 			$$ = $2;
 		        fixpos($$, $1);
@@ -2783,30 +2672,14 @@
 			$$ = dispatch2(case, $2, $4);
 		    %*/
 		    }
-		| keyword_case expr_value opt_terms keyword_else compstmt keyword_end
-		    {
-		    /*%%%*/
-			$$ = block_append($2, $5);
-		    /*%
-		    	$$ = dispatch2(case, $2, dispatch1(else, $5));
-		    %*/
-		    }
 		| keyword_case opt_terms case_body keyword_end
 		    {
 		    /*%%%*/
-			$$ = $3;
+			$$ = NEW_CASE(0, $3);
 		    /*%
 			$$ = dispatch2(case, Qnil, $3);
 		    %*/
 		    }
-		| keyword_case opt_terms keyword_else compstmt keyword_end
-		    {
-		    /*%%%*/
-			$$ = $4;
-		    /*%
-			$$ = dispatch2(case, Qnil, dispatch1(else, $4));
-		    %*/
-		    }
 		| keyword_for for_var keyword_in {COND_PUSH(1);} expr_value do {COND_POP();}
 		  compstmt
 		  keyword_end
@@ -3007,11 +2880,6 @@
 		    /*%c
 		    { $$ = Qnil; }
 		    %*/
-		| ':'
-		    /*%c%*/
-		    /*%c
-		    { $$ = Qnil; }
-		    %*/
 		| keyword_then
 		| term keyword_then
 		    /*%c%*/
@@ -3025,11 +2893,6 @@
 		    /*%c
 		    { $$ = Qnil; }
 		    %*/
-		| ':'
-		    /*%c%*/
-		    /*%c
-		    { $$ = Qnil; }
-		    %*/
 		| keyword_do_cond
 		;
 
@@ -3062,15 +2925,31 @@
 		| mlhs
 		;
 
-block_param0	: mlhs_item
+bparam_item	: bvar
+		| tLPAREN block_param rparen
 		    {
 		    /*%%%*/
+			if (nd_type($2) != NODE_MASGN) {
+			    $$ = NEW_MASGN(NEW_LIST($2), 0);
+			}
+			else {
+			    $$ = $2;
+			}
+		    /*%
+			$$ = dispatch1(mlhs_paren, $2);
+		    %*/
+		    }
+		;
+
+bparam_list	: bparam_item
+		    {
+		    /*%%%*/
 			$$ = NEW_LIST($1);
 		    /*%
 			$$ = mlhs_add(mlhs_new(), $1);
 		    %*/
 		    }
-		| block_param0 ',' mlhs_item
+		| bparam_list ',' bparam_item
 		    {
 		    /*%%%*/
 			$$ = list_append($1, $3);
@@ -3080,10 +2959,10 @@
 		    }
 		;
 
-block_param	: block_param0
+block_param	: bparam_list
 		    {
 		    /*%%%*/
-			if ($1->nd_alen == 1) {
+                        if ($1->nd_alen == 1 && nd_type($1->nd_head) != NODE_MASGN) {
 			    $$ = $1->nd_head;
 			    rb_gc_force_recycle((VALUE)$1);
 			}
@@ -3094,7 +2973,7 @@
 			$$ = blockvar_new($1);
 		    %*/
 		    }
-		| block_param0 ','
+		| bparam_list ','
 		    {
 		    /*%%%*/
 			$$ = NEW_MASGN($1, 0);
@@ -3102,7 +2981,7 @@
 			$$ = blockvar_new($1);
 		    %*/
 		    }
-		| block_param0 ',' tAMPER lhs
+		| bparam_list ',' tAMPER bvar
 		    {
 		    /*%%%*/
 			$$ = NEW_BLOCK_PARAM($4, NEW_MASGN($1, 0));
@@ -3110,16 +2989,25 @@
 			$$ = blockvar_add_block(blockvar_new($1), $4);
 		    %*/
 		    }
-		| block_param0 ',' tSTAR lhs ',' tAMPER lhs
+		| 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);
 		    %*/
 		    }
-		| block_param0 ',' tSTAR ',' tAMPER lhs
+		| bparam_list ',' tSTAR ',' tAMPER bvar
 		    {
 		    /*%%%*/
 			$$ = NEW_BLOCK_PARAM($6, NEW_MASGN($1, -1));
@@ -3128,32 +3016,57 @@
 			$$ = blockvar_add_block($$, $6);
 		    %*/
 		    }
-		| block_param0 ',' tSTAR lhs
+		| bparam_list ',' tSTAR  ',' bparam_list ',' tAMPER bvar
 		    {
 		    /*%%%*/
+			$$ = NEW_BLOCK_PARAM($8, NEW_MASGN($1, NEW_POSTARG(-1,$5)));
+		    /*%
+			$$ = blockvar_add_star(blockvar_new($1), Qnil);
+			$$ = blockvar_add_block($$, $8);
+		    %*/
+		    }
+		| bparam_list ',' tSTAR bvar
+		    {
+		    /*%%%*/
 			$$ = NEW_MASGN($1, $4);
 		    /*%
 			$$ = blockvar_add_star(blockvar_new($1), $4);
 		    %*/
 		    }
-		| block_param0 ',' tSTAR
+		| bparam_list ',' tSTAR bvar ',' bparam_list
 		    {
 		    /*%%%*/
+			$$ = NEW_MASGN($1, NEW_POSTARG($4,$6));
+		    /*%
+			$$ = blockvar_add_star(blockvar_new($1), $4);
+		    %*/
+		    }
+		| bparam_list ',' tSTAR
+		    {
+		    /*%%%*/
 			$$ = NEW_MASGN($1, -1);
 		    /*%
 			$$ = blockvar_add_star(blockvar_new($1), Qnil);
 		    %*/
 		    }
-		| tSTAR lhs ',' tAMPER lhs
+		| bparam_list ',' tSTAR ',' bparam_list
 		    {
 		    /*%%%*/
+			$$ = NEW_MASGN($1, NEW_MASGN($1, NEW_POSTARG(-1,$5)));
+		    /*%
+			$$ = blockvar_add_star(blockvar_new($1), Qnil);
+		    %*/
+		    }
+		| tSTAR bvar ',' tAMPER bvar
+		    {
+		    /*%%%*/
 			$$ = NEW_BLOCK_PARAM($5, NEW_MASGN(0, $2));
 		    /*%
 			$$ = blockvar_add_star(blockvar_new(Qnil), $2);
 			$$ = blockvar_add_block($$, $5);
 		    %*/
 		    }
-		| tSTAR ',' tAMPER lhs
+		| tSTAR ',' tAMPER bvar
 		    {
 		    /*%%%*/
 			$$ = NEW_BLOCK_PARAM($4, NEW_MASGN(0, -1));
@@ -3162,7 +3075,7 @@
 			$$ = blockvar_add_block($$, $4);
 		    %*/
 		    }
-		| tSTAR lhs
+		| tSTAR bvar
 		    {
 		    /*%%%*/
 			$$ = NEW_MASGN(0, $2);
@@ -3170,6 +3083,23 @@
 			$$ = blockvar_add_star(blockvar_new(Qnil), $2);
 		    %*/
 		    }
+		| tSTAR bvar ',' bparam_list
+		    {
+		    /*%%%*/
+			$$ = NEW_MASGN(0, NEW_POSTARG($2,$4));
+		    /*%
+			$$ = blockvar_add_star(blockvar_new(Qnil), $2);
+		    %*/
+		    }
+		| tSTAR bvar ',' bparam_list ',' tAMPER bvar
+		    {
+		    /*%%%*/
+			$$ = NEW_BLOCK_PARAM($7, NEW_MASGN(0, NEW_POSTARG($2,$4)));
+		    /*%
+			$$ = blockvar_add_star(blockvar_new(Qnil), Qnil);
+			$$ = blockvar_add_block($$, $7);
+		    %*/
+		    }
 		| tSTAR
 		    {
 		    /*%%%*/
@@ -3178,9 +3108,26 @@
 			$$ = blockvar_add_star(blockvar_new(Qnil), Qnil);
 		    %*/
 		    }
-		| tAMPER lhs
+		| tSTAR ',' bparam_list
 		    {
 		    /*%%%*/
+			$$ = NEW_MASGN(0, NEW_POSTARG(-1,$3));
+		    /*%
+			$$ = blockvar_add_star(blockvar_new(Qnil), Qnil);
+		    %*/
+		    }
+		| tSTAR ',' bparam_list ',' tAMPER bvar
+		    {
+		    /*%%%*/
+			$$ = NEW_BLOCK_PARAM($6, NEW_MASGN(0, NEW_POSTARG(-1,$3)));
+		    /*%
+			$$ = blockvar_add_star(blockvar_new(Qnil), Qnil);
+			$$ = blockvar_add_block($$, $6);
+		    %*/
+		    }
+		| tAMPER bvar
+		    {
+		    /*%%%*/
 			$$ = NEW_BLOCK_PARAM($2, (NODE*)1);
 		    /*%
 			$$ = blockvar_add_block(blockvar_new(Qnil), $2);
@@ -3236,7 +3183,7 @@
 		    }
 		;
 
-bv_decls	: bv_decl
+bv_decls	: bvar
 		    {
 		    /*%%%*/
 			$$ = $1;
@@ -3244,7 +3191,7 @@
 			$$ = FIXME;
 		    %*/
 		    }
-		| bv_decls ',' bv_decl
+		| bv_decls ',' bvar
 		    {
 		    /*%%%*/
 			$$ = block_append($1, $3);
@@ -3254,7 +3201,7 @@
 		    }
 		;
 
-bv_decl		:  tIDENTIFIER
+bvar		:  tIDENTIFIER
 		    {
 		    /*%%%*/
                         $$ = new_bv($1, NEW_NIL());
@@ -3350,7 +3297,7 @@
 block_call	: command do_block
 		    {
 		    /*%%%*/
-		        block_dup_check($1);
+			block_dup_check($1->nd_args, $2);
 			$2->nd_iter = $1;
 			$$ = $2;
 		        fixpos($$, $1);
@@ -3361,7 +3308,7 @@
 		| block_call '.' operation2 opt_paren_args
 		    {
 		    /*%%%*/
-			$$ = new_call($1, $3, $4);
+			$$ = NEW_CALL($1, $3, $4);
 		    /*%
 			$$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
 			$$ = method_optarg($$, $4);
@@ -3370,7 +3317,7 @@
 		| block_call tCOLON2 operation2 opt_paren_args
 		    {
 		    /*%%%*/
-			$$ = new_call($1, $3, $4);
+			$$ = NEW_CALL($1, $3, $4);
 		    /*%
 			$$ = dispatch3(call, $1, ripper_intern("::"), $3);
 			$$ = method_optarg($$, $4);
@@ -3381,7 +3328,7 @@
 method_call	: operation paren_args
 		    {
 		    /*%%%*/
-			$$ = new_fcall($1, $2);
+			$$ = NEW_FCALL($1, $2);
 		        fixpos($$, $2);
 		    /*%
 		        $$ = method_arg(dispatch1(fcall, $1), $2);
@@ -3390,7 +3337,7 @@
 		| primary_value '.' operation2 opt_paren_args
 		    {
 		    /*%%%*/
-			$$ = new_call($1, $3, $4);
+			$$ = NEW_CALL($1, $3, $4);
 		        fixpos($$, $1);
 		    /*%
 			$$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
@@ -3400,7 +3347,7 @@
 		| primary_value tCOLON2 operation2 paren_args
 		    {
 		    /*%%%*/
-			$$ = new_call($1, $3, $4);
+			$$ = NEW_CALL($1, $3, $4);
 		        fixpos($$, $1);
 		    /*%
 			$$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
@@ -3410,42 +3357,52 @@
 		| primary_value tCOLON2 operation3
 		    {
 		    /*%%%*/
-			$$ = new_call($1, $3, 0);
+			$$ = NEW_CALL($1, $3, 0);
 		    /*%
 			$$ = dispatch3(call, $1, ripper_intern("::"), $3);
 		    %*/
 		    }
-		| keyword_super paren_args
+		| primary_value '.' paren_args
 		    {
 		    /*%%%*/
-			$$ = new_super($2);
+			$$ = NEW_CALL($1, rb_intern("call"), $3);
+			fixpos($$, $1);
 		    /*%
-			$$ = dispatch1(super, $2);
+			$$ = dispatch3(call, dispatch1(paren, $1),
+				       ripper_id2sym('.'), rb_intern("call"));
+			$$ = method_optarg($$, $3);
 		    %*/
 		    }
-		| keyword_super
+		| primary_value tCOLON2 paren_args
 		    {
 		    /*%%%*/
-			$$ = NEW_ZSUPER();
+			$$ = NEW_CALL($1, rb_intern("call"), $3);
+			fixpos($$, $1);
 		    /*%
-			$$ = dispatch0(zsuper);
+			$$ = dispatch3(call, dispatch1(paren, $1),
+				       ripper_id2sym('.'), rb_intern("call"));
+			$$ = method_optarg($$, $3);
 		    %*/
 		    }
-		| tLPAREN compstmt ')' paren_args
+		| keyword_super paren_args
 		    {
 		    /*%%%*/
-			if (!$2) $2 = NEW_NIL();
-			$$ = new_call($2, rb_intern("call"), $4);
-		        fixpos($$, $2);
+			$$ = NEW_SUPER($2);
 		    /*%
-			$$ = dispatch3(call, dispatch1(paren, $2),
-		                       ripper_id2sym('.'), rb_intern("call"));
-			$$ = method_optarg($$, $4);
+			$$ = dispatch1(super, $2);
 		    %*/
 		    }
-		| primary_value '[' aref_args ']'
+		| keyword_super
 		    {
 		    /*%%%*/
+			$$ = NEW_ZSUPER();
+		    /*%
+			$$ = dispatch0(zsuper);
+		    %*/
+		    }
+		| primary_value '[' opt_call_args rbracket
+		    {
+		    /*%%%*/
 			if ($1 && nd_type($1) == NODE_SELF)
 			    $$ = NEW_FCALL(tAREF, $3);
 			else
@@ -3509,19 +3466,9 @@
 			$$ = dispatch2(do_block, escape_Qundef($3), $5);
 		    %*/
 		    }
-		| tLAMBDA_ARG
-		  lambda
-		    {
-		    /*%%%*/
-			$$ = $2;
-			nd_set_type($$, NODE_ITER);
-		    /*%
-			$$ = dispatch2(do_block, Qnil, $2);
-		    %*/
-		    }
 		;
 
-case_body	: keyword_when when_args then
+case_body	: keyword_when args then
 		  compstmt
 		  cases
 		    {
@@ -3532,24 +3479,6 @@
 		    %*/
 		    }
 		;
-when_args	: args
-		| args ',' tSTAR arg_value
-		    {
-		    /*%%%*/
-			$$ = list_append($1, NEW_WHEN($4, 0, 0));
-		    /*%
-			$$ = arg_add_star($1, $4);
-		    %*/
-		    }
-		| tSTAR arg_value
-		    {
-		    /*%%%*/
-			$$ = NEW_LIST(NEW_WHEN($2, 0, 0));
-		    /*%
-			$$ = arg_add_star(arg_new(), $2);
-		    %*/
-		    }
-		;
 
 cases		: opt_else
 		| case_body
@@ -3932,12 +3861,19 @@
 			    yyerror("empty symbol literal");
 			}
 			else {
+			    VALUE lit;
+
 			    switch (nd_type($$)) {
 			      case NODE_DSTR:
 				nd_set_type($$, NODE_DSYM);
 				break;
 			      case NODE_STR:
-				if (strlen(RSTRING_PTR($$->nd_lit)) == RSTRING_LEN($$->nd_lit)) {
+				lit = $$->nd_lit;
+				if (RSTRING_LEN(lit) == 0) {
+				    yyerror("empty symbol literal");
+				    break;
+				}
+				if (strlen(RSTRING_PTR(lit)) == RSTRING_LEN(lit)) {
 				    $$->nd_lit = ID2SYM(rb_intern(RSTRING_PTR($$->nd_lit)));
 				    nd_set_type($$, NODE_LIT);
 				    break;
@@ -4061,73 +3997,121 @@
 f_args		: f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
 		    {
 		    /*%%%*/
-			$$ = new_args($1, $3, $5, $6);
+			$$ = new_args($1, $3, $5, 0, $6);
 		    /*%
-			$$ = dispatch4(params, $1, $3, $5, escape_Qundef($6));
+			$$ = dispatch5(params, $1, $3, $5, Qnil, escape_Qundef($6));
 		    %*/
 		    }
+		| f_arg ',' f_optarg ',' f_rest_arg ',' f_post_arg opt_f_block_arg
+		    {
+		    /*%%%*/
+			$$ = new_args($1, $3, $5, $7, $8);
+		    /*%
+			$$ = dispatch5(params, $1, $3, $5, $7, escape_Qundef($8));
+		    %*/
+		    }
 		| f_arg ',' f_optarg opt_f_block_arg
 		    {
 		    /*%%%*/
-			$$ = new_args($1, $3, 0, $4);
+			$$ = new_args($1, $3, 0, 0, $4);
 		    /*%
-			$$ = dispatch4(params, $1, $3, Qnil, escape_Qundef($4));
+			$$ = dispatch5(params, $1, $3, Qnil, Qnil, escape_Qundef($4));
 		    %*/
 		    }
+		| f_arg ',' f_optarg ',' f_post_arg opt_f_block_arg
+		    {
+		    /*%%%*/
+			$$ = new_args($1, $3, 0, $5, $6);
+		    /*%
+			$$ = dispatch5(params, $1, $3, Qnil, $5, escape_Qundef($6));
+		    %*/
+		    }
 		| f_arg ',' f_rest_arg opt_f_block_arg
 		    {
 		    /*%%%*/
-			$$ = new_args($1, 0, $3, $4);
+			$$ = new_args($1, 0, $3, 0, $4);
 		    /*%
-			$$ = dispatch4(params, $1, Qnil, $3, escape_Qundef($4));
+			$$ = dispatch5(params, $1, Qnil, $3, Qnil, escape_Qundef($4));
 		    %*/
 		    }
+		| f_arg ',' f_rest_arg ',' f_post_arg opt_f_block_arg
+		    {
+		    /*%%%*/
+			$$ = new_args($1, 0, $3, $5, $6);
+		    /*%
+			$$ = dispatch5(params, $1, Qnil, $3, $5, escape_Qundef($6));
+		    %*/
+		    }
 		| f_arg opt_f_block_arg
 		    {
 		    /*%%%*/
-			$$ = new_args($1, 0, 0, $2);
+			$$ = new_args($1, 0, 0, 0, $2);
 		    /*%
-			$$ = dispatch4(params, $1, Qnil, Qnil, escape_Qundef($2));
+			$$ = dispatch5(params, $1, Qnil, Qnil, Qnil, escape_Qundef($2));
 		    %*/
 		    }
 		| f_optarg ',' f_rest_arg opt_f_block_arg
 		    {
 		    /*%%%*/
-			$$ = new_args(0, $1, $3, $4);
+			$$ = new_args(0, $1, $3, 0, $4);
 		    /*%
-			$$ = dispatch4(params, Qnil, $1, $3, escape_Qundef($4));
+			$$ = dispatch5(params, Qnil, $1, $3, Qnil, escape_Qundef($4));
 		    %*/
 		    }
+		| f_optarg ',' f_rest_arg ',' f_post_arg opt_f_block_arg
+		    {
+		    /*%%%*/
+			$$ = new_args(0, $1, $3, $5, $6);
+		    /*%
+			$$ = dispatch5(params, Qnil, $1, $3, $5, escape_Qundef($6));
+		    %*/
+		    }
 		| f_optarg opt_f_block_arg
 		    {
 		    /*%%%*/
-			$$ = new_args(0, $1, 0, $2);
+			$$ = new_args(0, $1, 0, 0, $2);
 		    /*%
-			$$ = dispatch4(params, Qnil, $1, Qnil, escape_Qundef($2));
+			$$ = dispatch5(params, Qnil, $1, Qnil, Qnil, escape_Qundef($2));
 		    %*/
 		    }
+		| f_optarg ',' f_post_arg opt_f_block_arg
+		    {
+		    /*%%%*/
+			$$ = new_args(0, $1, 0, $3, $4);
+		    /*%
+			$$ = dispatch5(params, Qnil, $1, Qnil, $3, escape_Qundef($4));
+		    %*/
+		    }
 		| f_rest_arg opt_f_block_arg
 		    {
 		    /*%%%*/
-			$$ = new_args(0, 0, $1, $2);
+			$$ = new_args(0, 0, $1, 0, $2);
 		    /*%
-			$$ = dispatch4(params, Qnil, Qnil, $1, escape_Qundef($2));
+			$$ = dispatch5(params, Qnil, Qnil, $1, Qnil, escape_Qundef($2));
 		    %*/
 		    }
+		| f_rest_arg ',' f_post_arg opt_f_block_arg
+		    {
+		    /*%%%*/
+			$$ = new_args(0, 0, $1, $3, $4);
+		    /*%
+			$$ = dispatch5(params, Qnil, Qnil, $1, $3, escape_Qundef($4));
+		    %*/
+		    }
 		| f_block_arg
 		    {
 		    /*%%%*/
-			$$ = new_args(0, 0, 0, $1);
+			$$ = new_args(0, 0, 0, 0, $1);
 		    /*%
-			$$ = dispatch4(params, Qnil, Qnil, Qnil, $1);
+			$$ = dispatch5(params, Qnil, Qnil, Qnil, Qnil, $1);
 		    %*/
 		    }
 		| /* none */
 		    {
 		    /*%%%*/
-			$$ = new_args(0, 0, 0, 0);
+			$$ = new_args(0, 0, 0, 0, 0);
 		    /*%
-			$$ = dispatch4(params, Qnil, Qnil, Qnil, Qnil);
+			$$ = dispatch5(params, Qnil, Qnil, Qnil, Qnil, Qnil);
 		    %*/
 		    }
 		;
@@ -4198,7 +4182,7 @@
 			VALUE arg = ID2SYM($3);
 			$$ = $1;
 			if (rb_ary_includes($$, arg)) {
-			    yyerror("duplicated argument arg");
+			    yyerror("duplicated argument name");
 			}
 			rb_ary_push($$, arg);
 		    /*%
@@ -4207,6 +4191,24 @@
 		    }
 		;
 
+f_post_arg	: f_norm_arg
+		    {
+		    /*%%%*/
+			$$ = NEW_LIST(assignable($1, 0));
+		    /*%
+			$$ = mlhs_add(mlhs_new(), $1);
+		    %*/
+		    }
+		| f_post_arg ',' f_norm_arg
+		    {
+		    /*%%%*/
+			$$ = list_append($1, assignable($3, 0));
+		    /*%
+		        $$ = mlhs_add($1, $3);
+		    %*/
+		    }
+		;
+
 f_opt		: tIDENTIFIER '=' arg_value
 		    {
 		    /*%%%*/
@@ -4310,13 +4312,8 @@
 singleton	: var_ref
 		    {
 		    /*%%%*/
-			if (nd_type($1) == NODE_SELF) {
-			    $$ = NEW_SELF();
-			}
-			else {
 			    $$ = $1;
 		            value_expr($$);
-			}
 		    /*%
 			$$ = $1;
 		    %*/
@@ -4442,6 +4439,9 @@
 rparen		: opt_nl ')'
 		;
 
+rbracket	: opt_nl ']'
+		;
+
 trailer		: /* none */
 		| '\n'
 		| ','
@@ -4531,7 +4531,7 @@
 ripper_dispatch_delayed_token(struct parser_params *parser, int t)
 {
     int saved_line = ruby_sourceline;
-    char *saved_tokp = parser->tokp;
+    const char *saved_tokp = parser->tokp;
 
     ruby_sourceline = parser->delayed_line;
     parser->tokp = lex_pbeg + parser->delayed_col;
@@ -4562,7 +4562,8 @@
 parser_yyerror(struct parser_params *parser, const char *msg)
 {
 #ifndef RIPPER
-    char *p, *pe, *buf;
+    const char *p, *pe;
+    char *buf;
     int len, i;
 
     rb_compile_error("%s", msg);
@@ -4581,17 +4582,18 @@
 
     len = pe - p;
     if (len > 4) {
+	char *p2;
 	buf = ALLOCA_N(char, len+2);
 	MEMCPY(buf, p, char, len);
 	buf[len] = '\0';
 	rb_compile_error_append("%s", buf);
 
 	i = lex_p - p;
-	p = buf; pe = p + len;
+	p2 = buf; pe = buf + len;
 
-	while (p < pe) {
-	    if (*p != '\t') *p = ' ';
-	    p++;
+	while (p2 < pe) {
+	    if (*p2 != '\t') *p2 = ' ';
+	    p2++;
 	}
 	buf[i] = '^';
 	buf[i+1] = '\0';
@@ -4654,8 +4656,6 @@
 }
 #endif /* !RIPPER */
 
-static VALUE lex_get_str(struct parser_params *, VALUE);
-
 static VALUE
 lex_get_str(struct parser_params *parser, VALUE s)
 {
@@ -4853,9 +4853,9 @@
 }
 
 static void
-parser_tokadd(struct parser_params *parser, char c)
+parser_tokadd(struct parser_params *parser, int c)
 {
-    tokenbuf[tokidx++] = c;
+    tokenbuf[tokidx++] = (char)c;
     if (tokidx >= toksiz) {
 	toksiz *= 2;
 	REALLOC_N(tokenbuf, char, toksiz);
@@ -5053,7 +5053,7 @@
 
     int kcode   = 0;
     int options = 0;
-    int c, opt, kc, found;
+    int c, opt, kc;
 
     newtok();
     while (c = nextc(), ISALPHA(c)) {
@@ -5241,10 +5241,17 @@
     }
     pushback(c);
     if (tokadd_string(func, term, paren, &quote->nd_nest) == -1) {
+       if (func & STR_FUNC_REGEXP) {
+           ruby_sourceline = nd_line(quote);
+           rb_compile_error(PARSER_ARG  "unterminated regexp meets end of file");
+           return tREGEXP_END;
+       }
+       else {
 	ruby_sourceline = nd_line(quote);
 	rb_compile_error(PARSER_ARG  "unterminated string meets end of file");
 	return tSTRING_END;
     }
+    }
 
     tokfix();
     set_yylval_str(rb_str_new(tok(), toklen()));
@@ -5351,7 +5358,7 @@
 parser_whole_match_p(struct parser_params *parser,
     const char *eos, int len, int indent)
 {
-    char *p = lex_pbeg;
+    const char *p = lex_pbeg;
     int n;
 
     if (indent) {
@@ -5367,7 +5374,7 @@
 parser_here_document(struct parser_params *parser, NODE *here)
 {
     int c, func, indent = 0;
-    char *eos, *p, *pend;
+    const char *eos, *p, *pend;
     long len;
     VALUE str = 0;
 
@@ -5841,7 +5848,6 @@
 	c = nextc();
 	if (c == '<' &&
 	    lex_state != EXPR_END &&
-	    lex_state != EXPR_END2 &&
 	    lex_state != EXPR_DOT &&
 	    lex_state != EXPR_ENDARG &&
 	    lex_state != EXPR_CLASS &&
@@ -5921,7 +5927,6 @@
 
       case '?':
 	if (lex_state == EXPR_END ||
-	    lex_state == EXPR_END2 ||
 	    lex_state == EXPR_ENDARG) {
 	    lex_state = EXPR_VALUE;
 	    return '?';
@@ -6095,18 +6100,9 @@
 	    return tOP_ASGN;
 	}
 	if (c == '>') {
-	    enum lex_state_e state = lex_state;
 	    lex_state = EXPR_ARG;
-	    switch (state) {
-	      case EXPR_CMDARG:
-	      case EXPR_ENDARG:
-	      case EXPR_ARG:
-	      case EXPR_END:
-		return tLAMBDA_ARG;
-	      default:
 		return tLAMBDA;
 	    }
-	}
 	if (IS_BEG() ||
 	    (IS_ARG() && space_seen && !ISSPACE(c))) {
 	    if (IS_ARG()) arg_ambiguous();
@@ -6375,7 +6371,7 @@
 	    lex_state = EXPR_DOT;
 	    return tCOLON2;
 	}
-	if (lex_state == EXPR_END || lex_state == EXPR_END2 ||
+	if (lex_state == EXPR_END || 
 	    lex_state == EXPR_ENDARG || ISSPACE(c)) {
 	    pushback(c);
 	    lex_state = EXPR_BEG;
@@ -6437,10 +6433,6 @@
 	return '^';
 
       case ';':
-	if (lex_state != EXPR_END2 && peek(';')) {
-	    lex_state = EXPR_END2;
-	    return keyword_end;
-	}
 	lex_state = EXPR_BEG;
 	command_start = Qtrue;
 	return ';';
@@ -6514,7 +6506,7 @@
 	    --paren_nest;
 	    return tLAMBEG;
 	}
-	if (IS_ARG() || lex_state == EXPR_END || lex_state == EXPR_END2)
+	if (IS_ARG() || lex_state == EXPR_END)
 	    c = '{';          /* block (primary) */
 	else if (lex_state == EXPR_ENDARG)
 	    c = tLBRACE_ARG;  /* block (expr) */
@@ -6577,13 +6569,13 @@
 		return tSTRING_BEG;
 
 	      case 'W':
-		lex_strterm = NEW_STRTERM(str_dquote | STR_FUNC_QWORDS, term, paren);
+		lex_strterm = NEW_STRTERM(str_dword, term, paren);
 		do {c = nextc();} while (ISSPACE(c));
 		pushback(c);
 		return tWORDS_BEG;
 
 	      case 'w':
-		lex_strterm = NEW_STRTERM(str_squote | STR_FUNC_QWORDS, term, paren);
+		lex_strterm = NEW_STRTERM(str_sword, term, paren);
 		do {c = nextc();} while (ISSPACE(c));
 		pushback(c);
 		return tQWORDS_BEG;
@@ -6843,6 +6835,7 @@
 		    lex_state = kw->state;
 		    if (state == EXPR_FNAME) {
                         set_yylval_id(rb_intern(kw->name));
+			return kw->id[0];
 		    }
 		    if (kw->id[0] == keyword_do) {
 			if (lpar_beg && lpar_beg == paren_nest) {
@@ -6948,13 +6941,13 @@
     return n;
 }
 
-static enum node_type
+enum node_type
 nodetype(NODE *node)			/* for debug */
 {
     return (enum node_type)nd_type(node);
 }
 
-static int
+int
 nodeline(NODE *node)
 {
     return nd_line(node);
@@ -6984,7 +6977,7 @@
 {
     int line = ruby_sourceline;
     ruby_sourceline = nd_line(node);
-    rb_warning(mesg);
+    rb_warning("%s", mesg);
     ruby_sourceline = line;
 }
 
@@ -6993,7 +6986,7 @@
 {
     int line = ruby_sourceline;
     ruby_sourceline = nd_line(node);
-    rb_warn(mesg);
+    rb_warn("%s", mesg);
     ruby_sourceline = line;
 }
 
@@ -7352,10 +7345,10 @@
 }
 
 static void
-block_dup_check(NODE *node)
+block_dup_check(NODE *node1, NODE *node2)
 {
-    if (node && nd_type(node) == NODE_BLOCK_PASS) {
-	compile_error(PARSER_ARG "both block arg and actual block given");
+    if (node2 && node1 && nd_type(node1) == NODE_BLOCK_PASS) {
+	compile_error("both block arg and actual block given");
     }
 }
 
@@ -7394,17 +7387,39 @@
 arg_concat(NODE *node1, NODE *node2)
 {
     if (!node2) return node1;
+    if (nd_type(node1) == NODE_BLOCK_PASS) {
+	node1->nd_iter = arg_concat(node1->nd_iter, node2);
+	return node1;
+    }
     return NEW_ARGSCAT(node1, node2);
 }
 
 static NODE *
-arg_add(NODE *node1, NODE *node2)
+arg_append(NODE *node1, NODE *node2)
 {
     if (!node1) return NEW_LIST(node2);
-    if (nd_type(node1) == NODE_ARRAY) {
+    switch (nd_type(node1))  {
+      case NODE_ARRAY:
 	return list_append(node1, node2);
+      case NODE_BLOCK_PASS:
+	node1->nd_head = arg_append(node1->nd_head, node2);
+	return node1;
+      default:
+	return NEW_ARGSPUSH(node1, node2);
     }
-    else {
+}
+
+static NODE *
+arg_add(NODE *node1, NODE *node2)
+{
+    if (!node1) return NEW_LIST(node2);
+    switch (nd_type(node1))  {
+      case NODE_ARRAY:
+	return list_append(node1, node2);
+      case NODE_BLOCK_PASS:
+	node1->nd_head = arg_add(node1->nd_head, node2);
+	return node1;
+      default:
 	return NEW_ARGSPUSH(node1, node2);
     }
 }
@@ -7882,9 +7897,6 @@
 		nd_set_type(node, NODE_VALUES);
 	    }
 	}
-	else if (nd_type(node) == NODE_SPLAT) {
-	    node = NEW_SVALUE(node);
-	}
     }
     return node;
 }
@@ -7939,32 +7951,13 @@
     return node1;
 }
 
-static NODE*
-arg_prepend(NODE *node1, NODE *node2)
-{
-    switch (nd_type(node2)) {
-      case NODE_ARRAY:
-	return list_concat(NEW_LIST(node1), node2);
-
-      case NODE_SPLAT:
-	return arg_concat(node1, node2->nd_head);
-
-      case NODE_BLOCK_PASS:
-	node2->nd_body = arg_prepend(node1, node2->nd_body);
-	return node2;
-
-      default:
-	rb_bug("unknown nodetype(%d) for arg_prepend", nd_type(node2));
-    }
-    return 0;			/* not reached */
-}
-
 static int
 arg_dup_check(ID vid, VALUE m, VALUE list, NODE *node)
 {
     VALUE sym;
 
     if (!vid) return 0;
+    if (is_junk_id(vid)) return 0;
     sym = ID2SYM(vid);
     if ((m && rb_ary_includes(m, sym)) || rb_ary_includes(list, sym)) {
 	ruby_sourceline = nd_line(node);
@@ -7975,21 +7968,21 @@
 }
 
 static NODE*
-new_args_gen(struct parser_params *parser, VALUE m, NODE *o, NODE *r, NODE *b)
+new_args_gen(struct parser_params *parser, VALUE m, NODE *o, NODE *r, NODE *p, NODE *b)
 {
     int saved_line = ruby_sourceline;
-    NODE *tmp;
+    NODE *node;
     VALUE list;
 
     list = rb_ary_new();
-    tmp = o;
-    while (tmp) {
-	if (!tmp->nd_head) break;
-	if (arg_dup_check(tmp->nd_head->nd_vid, m, list, tmp)) {
+    node = o;
+    while (node) {
+	if (!node->nd_head) break;
+	if (arg_dup_check(node->nd_head->nd_vid, m, list, node)) {
 	    yyerror("duplicated optional argument name");
 	    return 0;	
 	}
-	tmp = tmp->nd_next;
+	node = node->nd_next;
     }
     if (RTEST(r)) {
 	if (arg_dup_check(r->nd_vid, m, list, r)) {
@@ -7997,46 +7990,30 @@
 	    return 0;
 	}
     }
+    if (p) {
+	node = p;
+	while (node) {
+	    if (!node->nd_head) break;
+	    if (arg_dup_check(node->nd_head->nd_vid, m, list, node)) {
+		yyerror("duplicated argument name");
+		return 0;
+	    }
+	    node = node->nd_next;
+	}
+	r = NEW_POSTARG(r, p);
+    }
+    node = NEW_ARGS(m, o, r);
     if (b) {
 	if (arg_dup_check(b->nd_vid, m, list, b)) {
 	    yyerror("duplicated block argument name");
 	    return 0;
 	}
+	node = block_append(node, b);
     }
     ruby_sourceline = saved_line;
-    return block_append(NEW_ARGS(m, o, r), b);
+    return node;
 }
 
-static NODE*
-new_call(NODE *r,ID m, NODE *a)
-{
-    if (a && nd_type(a) == NODE_BLOCK_PASS) {
-	a->nd_iter = NEW_CALL(r,m,a->nd_head);
-	return a;
-    }
-    return NEW_CALL(r,m,a);
-}
-
-static NODE*
-new_fcall_gen(struct parser_params *parser, ID m, NODE *a)
-{
-    if (a && nd_type(a) == NODE_BLOCK_PASS) {
-	a->nd_iter = NEW_FCALL(m,a->nd_head);
-	return a;
-    }
-    return NEW_FCALL(m, a);
-}
-
-static NODE*
-new_super(NODE *a)
-{
-    if (a && nd_type(a) == NODE_BLOCK_PASS) {
-	a->nd_iter = NEW_SUPER(a->nd_head);
-	return a;
-    }
-    return NEW_SUPER(a);
-}
-
 static void
 local_push_gen(struct parser_params *parser, int inherit_dvars)
 {
@@ -8560,11 +8537,12 @@
 {
     return rb_intern2(name, strlen(name));
 }
-#include "debug.h"
+
 VALUE
 rb_id2sym(ID id)
 {
     VALUE data;
+
     while (!st_lookup(global_symbols.id_sym, id, &data)) {
 	rb_id2name(id);
     }
@@ -8752,6 +8730,7 @@
 #else
     rb_gc_mark(p->parser_ruby_sourcefile);
     rb_gc_mark(p->delayed);
+    rb_gc_mark(p->value);
     rb_gc_mark(p->result);
     rb_gc_mark(p->parsing_thread);
 #endif
@@ -9011,7 +8990,7 @@
     {modifier_until,	"until"},
     {modifier_rescue,	"rescue"},
     {keyword_alias,	"alias"},
-    {keyword_defined,	"defined"},
+    {keyword_defined,	"defined?"},
     {keyword_BEGIN,	"BEGIN"},
     {keyword_END,	"END"},
     {keyword__LINE__,	"__LINE__"},
@@ -9304,7 +9283,7 @@
 {
     StringValue(msg);
     if (obj == Qundef) {
-        rb_raise(rb_eArgError, RSTRING_PTR(msg));
+        rb_raise(rb_eArgError, "%s", RSTRING_PTR(msg));
     }
     return Qnil;
 }
@@ -9346,3 +9325,4 @@
     rb_intern("&&");
 }
 #endif /* RIPPER */
+

Modified: trunk/vm_dump.c
===================================================================
--- trunk/vm_dump.c	2006-11-09 01:27:13 UTC (rev 578)
+++ trunk/vm_dump.c	2006-11-10 00:18:12 UTC (rev 579)
@@ -586,11 +586,11 @@
 	int n = backtrace(trace, MAX_NATIVE_TRACE);
 	int i;
 
-	printf("-- backtrace of native function call (Use addr2line) --\n");
+	fprintf(stderr, "-- backtrace of native function call (Use addr2line) --\n");
 	for (i=0; i<n; i++) {
-	    printf("%p\n", trace[i]);
+	    fprintf(stderr, "%p\n", trace[i]);
 	}
-	printf("-------------------------------------------------------\n");
+	fprintf(stderr, "-------------------------------------------------------\n");
     }
 #endif
 }

Modified: trunk/yarvtest/test_block.rb
===================================================================
--- trunk/yarvtest/test_block.rb	2006-11-09 01:27:13 UTC (rev 578)
+++ trunk/yarvtest/test_block.rb	2006-11-10 00:18:12 UTC (rev 579)
@@ -83,7 +83,7 @@
       iter{|a, $b, @c, d|
         [a, $b]
       } + [a, $b, @c]
-    }
+    } if false # 1.9 doesn't support expr block parameters
   end
 
   def test_param3

Modified: trunk/yarvtest/test_class.rb
===================================================================
--- trunk/yarvtest/test_class.rb	2006-11-09 01:27:13 UTC (rev 578)
+++ trunk/yarvtest/test_class.rb	2006-11-10 00:18:12 UTC (rev 579)
@@ -214,6 +214,21 @@
         :top
       }
     }
+    ae %q{
+      class C0
+        def m a, &b
+          [a, b]
+        end
+      end
+      
+      class C1 < C0
+        def m a, &b
+          super a, &b
+        end
+      end
+      
+      C1.new.m(10)
+    }
   end
 
   def test_zsuper_from_define_method

Modified: trunk/yarvtest/test_syntax.rb
===================================================================
--- trunk/yarvtest/test_syntax.rb	2006-11-09 01:27:13 UTC (rev 578)
+++ trunk/yarvtest/test_syntax.rb	2006-11-10 00:18:12 UTC (rev 579)
@@ -258,7 +258,8 @@
         :ng2
       else
         :elseng
-      end)
+      end
+    )
 
     ae %q(
       case
@@ -270,7 +271,8 @@
         :ng2
       else
         :elseng
-      end)
+      end
+    )
       
     ae %q(
       case
@@ -287,6 +289,24 @@
       when 1
       end
     }
+
+    ae %q{
+      r = nil
+      ary = []
+      case
+      when false
+        r = :ng1
+      when false, false
+        r = :ng2
+      when *ary
+        r = :ng3
+      when false, *ary
+        r = :ng4
+      when true, *ary
+        r = :ok
+      end
+      r
+    }
   end
 
   def test_when_splat


--
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧][生データ]