aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--compile.c111
-rw-r--r--sample/test.rb3
-rw-r--r--test/ruby/test_lambda.rb28
4 files changed, 98 insertions, 53 deletions
diff --git a/ChangeLog b/ChangeLog
index 348826991a..c1c74ec2c0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Fri Jan 5 12:03:07 2007 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c (iseq_compile_each, set_block_local_tbl) :
+ support NODE_LAMBDA (partly).
+
+ * sample/test.rb : restore test of NODE_LAMBDA
+
+ * test/ruby/test_lambda.rb : ditto
+
Fri Jan 5 12:31:23 2007 GOTOU Yuuzou <gotoyuzo@notwork.org>
* thread_pthread.ci (native_sleep): fix tv_nsec overflow.
diff --git a/compile.c b/compile.c
index 025e655457..131eb7f8e6 100644
--- a/compile.c
+++ b/compile.c
@@ -964,48 +964,74 @@ set_block_local_tbl(yarv_iseq_t *iseq, NODE * node, LINK_ANCHOR *anchor)
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;
- }
- }
+ 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;
+ /* 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;
- }
+ 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:
+ case NODE_DASGN_CURR:
break;
- /* for 1.x compatibility */
- default:{
- /* first param, current level */
- set_block_initializer(iseq, nargs, anchor, iseq->local_size);
- 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_tbl) {
+ /* copy from old local tbl and delete it */
+ for (i=1; i<iseq->local_size; i++) {
+ local_tbl[argc + i - 1] = iseq->local_tbl[i];
+ }
+ ruby_xfree(iseq->local_tbl);
+ }
+ iseq->local_tbl = 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;
+ }
}
}
@@ -4480,6 +4506,17 @@ iseq_compile_each(yarv_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
COMPILE_(ret, "body", node->nd_body, poped);
break;
}
+ case NODE_LAMBDA:{
+ VALUE block = NEW_CHILD_ISEQVAL(node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK);
+ VALUE argc = INT2FIX(0);
+ ADD_INSN (ret, nd_line(node), putself);
+ ADD_SEND_R(ret, nd_line(node), ID2SYM(idLambda), argc,
+ block, INT2FIX(VM_CALL_FCALL_BIT));
+ if (poped) {
+ ADD_INSN(ret, nd_line(node), pop);
+ }
+ break;
+ }
default:
COMPILE_ERROR(("BUG: unknown node (default): %s", node_name(type)));
return Qnil;
diff --git a/sample/test.rb b/sample/test.rb
index 0968fa5015..cf2e3a2493 100644
--- a/sample/test.rb
+++ b/sample/test.rb
@@ -1101,8 +1101,7 @@ def proc_return1
end
test_ok(proc_return1() == 43)
def proc_return2
- #! ->{return 42}.call+1
- lambda{return 42}.call+1
+ ->{return 42}.call+1
end
test_ok(proc_return2() == 43)
def proc_return3
diff --git a/test/ruby/test_lambda.rb b/test/ruby/test_lambda.rb
index 5687722c31..b4f0dac658 100644
--- a/test/ruby/test_lambda.rb
+++ b/test/ruby/test_lambda.rb
@@ -1,14 +1,6 @@
require 'test/unit'
class TestLambdaParameters < Test::Unit::TestCase
- def test_not_supported
- flunk("YARV doesn't support NODE_LAMBDA")
- end
-end
-
-__END__
-
-class TestLambdaParametersBackup
def test_call_simple
assert_equal(1, ->(a){ a }.call(1))
assert_equal([1,2], ->(a,b){ [a,b] }.call(1,2))
@@ -18,6 +10,20 @@ class TestLambdaParametersBackup
assert_raises(ArgumentError) { ->(a,b){ }.call(1,2,3) }
end
+ def test_lambda_as_iterator
+ a = 0
+ 2.times(&->(_){ a += 1 })
+ assert_equal(a, 2)
+ end
+
+ def test_message
+ flunk("YARV doesn't support some argument types for Proc object created by '->' syntax")
+ end
+end
+
+__END__
+
+class TestLambdaParameters
def test_call_rest_args
assert_equal([1,2], ->(*a){ a }.call(1,2))
assert_equal([1,2,[]], ->(a,b,*c){ [a,b,c] }.call(1,2))
@@ -52,10 +58,4 @@ class TestLambdaParametersBackup
def foo
assert_equal(nil, ->(&b){ b }.call)
end
-
- def test_lambda_as_iterator
- a = 0
- 2.times(&->(_){ a += 1 })
- assert_equal(a, 2)
- end
end