[#41918] [Feature #3647] Array#sample(n, replace=false) — Kenta Murata <redmine@...>

Feature #3647: Array#sample(n, replace=false)

11 messages 2010/08/03

[#41966] [Bug #3673] PTY.getpty with IO.pipe doesn't finish on FreeBSD — Yui NARUSE <redmine@...>

Bug #3673: PTY.getpty with IO.pipe doesn't finish on FreeBSD

9 messages 2010/08/10

[#41969] [Feature #3675] String#prepend, String#>> — Sora Harakami <redmine@...>

Feature #3675: String#prepend, String#>>

15 messages 2010/08/10
[#41976] Re: [Feature #3675] String#prepend, String#>> — Yukihiro Matsumoto <matz@...> 2010/08/10

まつもと ゆきひろです

[#41974] Re: [ruby-cvs:36157] Ruby:r28955 (trunk): * complex.c (nucomp_to_[ifr]): don't allow complex with in-exact — Yukihiro Matsumoto <matz@...>

まつもと ゆきひろです

7 messages 2010/08/10

[#42003] WEBrickに関するセキュリティ修正 (CVE-2010-0541) — Hideki Yamane <henrich@...>

12 messages 2010/08/11

[#42090] Math::atan2(0, 0) on ruby 1.9.2 — KUBO Takehiro <kubo@...>

久保です。

18 messages 2010/08/22
[#42092] Re: Math::atan2(0, 0) on ruby 1.9.2 — Kenta Murata <muraken@...> 2010/08/22

=1B$B$`$i$?$G$9!#=1B(B

[#42166] Ruby'sライセンスの、BSDLとのデュアルライセンスへの変更 — "NARUSE, Yui" <naruse@...>

Ruby's ライセンスは BSDL と Ruby's のデュアルライセンスになります。

14 messages 2010/08/31

[ruby-dev:42134] Re: [Feature:trunk] argument delegation

From: Yusuke ENDOH <mame@...>
Date: 2010-08-25 12:07:14 UTC
List: ruby-dev #42134
遠藤です。

2010年8月25日3:23 SASADA Koichi <ko1@atdot.net>:
>  できれば,VM_CALL_ARGS_BLOCKTRGH_BIT を増やすんじゃなく
> て,VM_CALL_ARGS_BLOCKARG_BIT だけど,blockiseq かなんかの値を特殊にし
> ておくとか,そういう実装にしてもらえるといいんじゃないかと思います.
>
> (命令オペランドのバリエーションが減った方が色々うれしい)

コメントありがとうございます。でも、見かけ上バリエーションを増やさない
ところで、VM_CALL_ARGS_BLOCKTRGH_BIT に結構異なる 2 つの意味を突っ込む
ことになる (スタックに Proc を載せる・載せないの違いがあるので、細々条
件判定が必要になる) ので、大して嬉しくないと思います。メンテナンス性も
下がりますので、元のパッチの方がいいと思います。

一応 blockiseq に -1 が入ってたら BLOCKTRGH 扱いにするパッチも書いてみ
ましたが、かなり本質的でないコードでいっぱいになりました。
# 今 trunk が壊れてるようなので、test-all はできてません。


diff --git a/compile.c b/compile.c
index 2fd804c..1c04640 100644
--- a/compile.c
+++ b/compile.c
@@ -1411,11 +1411,18 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
 		      case TS_ISEQ:	/* iseq */
 			{
 			    VALUE v = operands[j];
-			    rb_iseq_t *block = 0;
+			    VALUE block = 0;
 			    if (v) {
-				GetISeqPtr(v, block);
+				if (v == Qundef) {
+				    block = (VALUE)-1;
+				}
+				else {
+				    rb_iseq_t *blk;
+				    GetISeqPtr(v, blk);
+				    block = (VALUE)blk;
+				}
 			    }
-			    generated_iseq[pos + 1 + j] = (VALUE)block;
+			    generated_iseq[pos + 1 + j] = block;
 			    break;
 			}
 		      case TS_VALUE:	/* VALUE */
@@ -2853,7 +2860,7 @@ add_ensure_iseq(LINK_ANCHOR *ret, rb_iseq_t
*iseq, int is_return)
 }

 static VALUE
-setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args, NODE *argn, unsigned long *flag)
+setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args, NODE *argn, VALUE
*blockiseq, unsigned long *flag)
 {
     VALUE argc = INT2FIX(0);
     int nsplat = 0;
@@ -2863,7 +2870,13 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args,
NODE *argn, unsigned long *flag)
     INIT_ANCHOR(arg_block);
     INIT_ANCHOR(args_splat);
     if (argn && nd_type(argn) == NODE_BLOCK_PASS) {
-	COMPILE(arg_block, "block", argn->nd_body);
+	if ((VALUE)argn->nd_body != (VALUE)-1) {
+	    COMPILE(arg_block, "block", argn->nd_body);
+	}
+	else {
+	    arg_block = 0;
+	    if (blockiseq) *blockiseq = Qundef;
+	}
 	*flag |= VM_CALL_ARGS_BLOCKARG_BIT;
 	argn = argn->nd_head;
     }
@@ -2932,7 +2945,7 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args,
NODE *argn, unsigned long *flag)
 	ADD_SEQ(args, args_splat);
     }

-    if (*flag & VM_CALL_ARGS_BLOCKARG_BIT) {
+    if ((*flag & VM_CALL_ARGS_BLOCKARG_BIT) && arg_block) {
 	ADD_SEQ(args, arg_block);
     }
     return argc;
@@ -3776,7 +3789,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR
*ret, NODE * node, int poped)
 	    boff = 1;
 	  default:
 	    INIT_ANCHOR(args);
-	    argc = setup_args(iseq, args, node->nd_args->nd_head, &flag);
+	    argc = setup_args(iseq, args, node->nd_args->nd_head, 0, &flag);
 	    ADD_SEQ(ret, args);
 	}
 	ADD_INSN1(ret, nd_line(node), dupn, FIXNUM_INC(argc, 1 + boff));
@@ -4083,7 +4096,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR
*ret, NODE * node, int poped)

 	/* args */
 	if (nd_type(node) != NODE_VCALL) {
-	    argc = setup_args(iseq, args, node->nd_args, &flag);
+	    argc = setup_args(iseq, args, node->nd_args, &parent_block, &flag);
 	}
 	else {
 	    argc = INT2FIX(0);
@@ -4121,7 +4134,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR
*ret, NODE * node, int poped)
 	INIT_ANCHOR(args);
 	iseq->compile_data->current_block = Qfalse;
 	if (nd_type(node) == NODE_SUPER) {
-	    argc = setup_args(iseq, args, node->nd_args, &flag);
+	    argc = setup_args(iseq, args, node->nd_args, &parent_block, &flag);
 	}
 	else {
 	    /* NODE_ZSUPER */
@@ -4294,7 +4307,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR
*ret, NODE * node, int poped)
 	}

 	if (node->nd_head) {
-	    argc = setup_args(iseq, args, node->nd_head, &flag);
+	    argc = setup_args(iseq, args, node->nd_head, 0, &flag);
 	}
 	else {
 	    argc = INT2FIX(0);
@@ -4906,7 +4919,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR
*ret, NODE * node, int poped)

 	INIT_ANCHOR(recv);
 	INIT_ANCHOR(args);
-	argc = setup_args(iseq, args, node->nd_args, &flag);
+	argc = setup_args(iseq, args, node->nd_args, 0, &flag);

 	if (node->nd_recv == (NODE *) 1) {
 	    flag |= VM_CALL_FCALL_BIT;
diff --git a/insns.def b/insns.def
index fcd97ae..10b99be 100644
--- a/insns.def
+++ b/insns.def
@@ -989,7 +989,7 @@ DEFINE_INSN
 send
 (ID op_id, rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag, IC ic)
 (...)
-(VALUE val) // inc += - (int)(op_argc + ((op_flag &
VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0));
+(VALUE val) // inc += - (int)(op_argc + (((op_flag &
VM_CALL_ARGS_BLOCKARG_BIT) && (VALUE)blockiseq != (VALUE)-1) ? 1 :
0));
 {
     const rb_method_entry_t *me;
     VALUE recv, klass;
@@ -1017,7 +1017,7 @@ DEFINE_INSN
 invokesuper
 (rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag)
 (...)
-(VALUE val) // inc += - (int)(op_argc + ((op_flag &
VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0));
+(VALUE val) // inc += - (int)(op_argc + (((op_flag &
VM_CALL_ARGS_BLOCKARG_BIT) && (VALUE)blockiseq != (VALUE)-1) ? 1 :
0));
 {
     rb_block_t *blockptr = !(op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ?
GET_BLOCK_PTR() : 0;
     int num = caller_setup_args(th, GET_CFP(), op_flag,
diff --git a/node.c b/node.c
index 65bc541..85574b4 100644
--- a/node.c
+++ b/node.c
@@ -621,7 +621,12 @@ dump_node(VALUE buf, VALUE indent, int comment, NODE *node)
 	ANN("example: foo(x, &blk)");
 	F_NODE(nd_head, "other arguments");
 	LAST_NODE;
-	F_NODE(nd_body, "block argument");
+	if ((VALUE)node->nd_body != (VALUE)-1) {
+	    F_NODE(nd_body, "block argument");
+	}
+	else {
+	    F_MSG(nd_body, "block argument", "-1 (anonymous)");
+	}
 	break;

       case NODE_DEFN:
diff --git a/parse.y b/parse.y
index e085088..b0b946b 100644
--- a/parse.y
+++ b/parse.y
@@ -2459,6 +2459,14 @@ block_arg	: tAMPER arg_value
 			$$ = $2;
 		    %*/
 		    }
+		| tAMPER
+		    {
+		    /*%%%*/
+			$$ = NEW_BLOCK_PASS(-1);
+		    /*%
+			$$ = dispatch0(anonymous_block_arg);
+		    %*/
+		    }
 		;

 opt_block_arg	: ',' block_arg
diff --git a/tool/instruction.rb b/tool/instruction.rb
index 4fd2127..4ce219f 100755
--- a/tool/instruction.rb
+++ b/tool/instruction.rb
@@ -66,13 +66,12 @@ class RubyVM
         ret = "int inc = 0;\n"

         @opes.each_with_index{|(t, v), i|
-          if t == 'rb_num_t' && ((re = /\b#{v}\b/n) =~ @sp_inc ||
-                                 @defopes.any?{|t, val| re =~ val})
+          if ((re = /\b#{v}\b/n) =~ @sp_inc || @defopes.any?{|t, val|
re =~ val})
             ret << "        int #{v} = FIX2INT(opes[#{i}]);\n"
           end
         }
         @defopes.each_with_index{|((t, var), val), i|
-          if t == 'rb_num_t' && val != '*' && /\b#{var}\b/ =~ @sp_inc
+          if val != '*' && /\b#{var}\b/ =~ @sp_inc
             ret << "        #{t} #{var} = #{val};\n"
           end
         }
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 985a2fb..f6418b7 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -240,25 +240,31 @@ caller_setup_args(const rb_thread_t *th,
rb_control_frame_t *cfp, VALUE flag,

     if (block) {
 	if (flag & VM_CALL_ARGS_BLOCKARG_BIT) {
-	    rb_proc_t *po;
-	    VALUE proc;
-
-	    proc = *(--cfp->sp);
-
-	    if (proc != Qnil) {
-		if (!rb_obj_is_proc(proc)) {
-		    VALUE b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
-		    if (NIL_P(b) || !rb_obj_is_proc(b)) {
-			rb_raise(rb_eTypeError,
-				 "wrong argument type %s (expected Proc)",
-				 rb_obj_classname(proc));
+	    if ((VALUE)blockiseq != (VALUE)-1) {
+		rb_proc_t *po;
+		VALUE proc;
+
+		proc = *(--cfp->sp);
+
+		if (proc != Qnil) {
+		    if (!rb_obj_is_proc(proc)) {
+			VALUE b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
+			if (NIL_P(b) || !rb_obj_is_proc(b)) {
+			    rb_raise(rb_eTypeError,
+				    "wrong argument type %s (expected Proc)",
+				    rb_obj_classname(proc));
+			}
+			proc = b;
 		    }
-		    proc = b;
+		    GetProcPtr(proc, po);
+		    blockptr = &po->block;
+		    RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp)->proc = proc;
+		    *block = blockptr;
 		}
-		GetProcPtr(proc, po);
-		blockptr = &po->block;
-		RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp)->proc = proc;
-		*block = blockptr;
+	    }
+	    else {
+		rb_control_frame_t *reg_cfp = cfp;
+		*block = GET_BLOCK_PTR();
 	    }
 	}
 	else if (blockiseq) {

-- 
Yusuke Endoh <mame@tsg.ne.jp>

In This Thread