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

yarv-diff:85

From: ko1 atdot.net
Date: 15 Aug 2005 23:33:22 -0000
Subject: [yarv-diff:85] r241 - in trunk: . rb yarvtest

Author: ko1
Date: 2005-08-16 08:33:21 +0900 (Tue, 16 Aug 2005)
New Revision: 241

Added:
   trunk/rb/parse.rb
   trunk/yarvtest/test_yield.rb
Modified:
   trunk/ChangeLog
   trunk/common.mk
   trunk/compile.c
   trunk/eval.c
   trunk/insns.def
   trunk/test.rb
   trunk/test1.rb
   trunk/vm.c
   trunk/yarvcore.c
   trunk/yarvtest/test_method.rb
Log:
	* eval.c : fix to support rb_yield_0 with multiple values

	* common.mk : add parse, run1p ruelse

	* compile.c : support yield with ARGSCAT/SPLAT

	* vm.c, insns.def : fix yield arguments to do compatible behaviour

	* yarvtest/test_yield.rb : added for above



Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2005-08-15 21:01:19 UTC (rev 240)
+++ trunk/ChangeLog	2005-08-15 23:33:21 UTC (rev 241)
@@ -4,6 +4,19 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2005-08-16(Tue) 08:29:47 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* eval.c : fix to support rb_yield_0 with multiple values
+
+	* common.mk : add parse, run1p ruelse
+
+	* compile.c : support yield with ARGSCAT/SPLAT
+
+	* vm.c, insns.def : fix yield arguments to do compatible behaviour
+
+	* yarvtest/test_yield.rb : added for above
+
+
 2005-08-16(Tue) 06:00:17 +0900  Koichi Sasada  <ko1 atdot.net>
 
 	* insns.def : fix to set klass_nest_stack on singleton
@@ -11,6 +24,7 @@
 
 	* yarvtest/test_method.rb : add a test for above
 
+
 2005-08-16(Tue) 05:34:48 +0900  Koichi Sasada  <ko1 atdot.net>
 
 	* test1.rb : added.  gdb and run1 rule run this script

Modified: trunk/common.mk
===================================================================
--- trunk/common.mk	2005-08-15 21:01:19 UTC (rev 240)
+++ trunk/common.mk	2005-08-15 23:33:21 UTC (rev 241)
@@ -400,6 +400,13 @@
 run1: all
 	$(MINIRUBY) $(srcdir)/test1.rb
 
+parse: all
+	$(MINIRUBY) $(srcdir)/rb/parse.rb $(srcdir)/test1.rb
+
+run1p: all
+	$(MINIRUBY) $(srcdir)/rb/parse.rb $(srcdir)/test1.rb
+	$(MINIRUBY) $(srcdir)/test1.rb
+
 benchmark: all
 	$(BASERUBY) -I$(srcdir) $(srcdir)/benchmark/run_rite.rb $(OPT) $(ITEMS) --yarv-program=$(MINIRUBY) --ruby-program=$(BASERUBY)
 

Modified: trunk/compile.c
===================================================================
--- trunk/compile.c	2005-08-15 21:01:19 UTC (rev 240)
+++ trunk/compile.c	2005-08-15 23:33:21 UTC (rev 241)
@@ -3045,6 +3045,7 @@
   case NODE_YIELD:{
     DECL_ANCHOR(args);
     int argc;
+    unsigned long flag = 0;
     
     if(iseqobj->type == ISEQ_TYPE_TOP ||
        iseqobj->type == ISEQ_TYPE_CLASS){
@@ -3059,15 +3060,32 @@
         debugs("argc: %d\n", argc);
       }
       else{
-        COMPILE(args, "nd_head(1)", node->nd_head);
-        argc = 1;
+        if(nd_type(node->nd_head) == NODE_ARGSCAT){
+          flag |= VM_CALL_ARGS_SPLAT_BIT;
+          
+          compile_array(self, iseqobj, args, node->nd_head->nd_head, Qfalse);
+          POP_ELEMENT(args);
+          argc = LIST_SIZE(args) + 1;
+
+          COMPILE(args, "args(cat: splat)", node->nd_head->nd_body);
+        }
+        else if(nd_type(node->nd_head) == NODE_SPLAT){
+          flag |= VM_CALL_ARGS_SPLAT_BIT;
+
+          argc = 1;
+          COMPILE(args, "splat", node->nd_head->nd_head);
+        }
+        else{
+          COMPILE(args, "nd_head(1)", node->nd_head);
+          argc = 1;
+        }
       }
     }
     else{
       argc = 0;
     }
     ADD_SEQ  (ret, args);
-    ADD_INSN2(ret, nd_line(node), yield, I2F(argc), I2F(0));
+    ADD_INSN2(ret, nd_line(node), yield, I2F(argc), I2F(flag));
 
     if(poped){
       ADD_INSN(ret, nd_line(node), pop);

Modified: trunk/eval.c
===================================================================
--- trunk/eval.c	2005-08-15 21:01:19 UTC (rev 240)
+++ trunk/eval.c	2005-08-15 23:33:21 UTC (rev 241)
@@ -3198,7 +3198,15 @@
                            RARRAY(val)->len, RARRAY(val)->ptr);
   }
   else{
-    return th_invoke_yield(GET_THREAD(), 1, &val);
+    int argc = 1;
+    VALUE *argv = &val;
+
+    if(argc == 1 && CLASS_OF(argv[0]) == rb_cValues){
+      argc = RARRAY(argv[0])->len;
+      argv = RARRAY(argv[0])->ptr;
+    }
+
+    return th_invoke_yield(GET_THREAD(), argc, argv);
   }
 }
 

Modified: trunk/insns.def
===================================================================
--- trunk/insns.def	2005-08-15 21:01:19 UTC (rev 240)
+++ trunk/insns.def	2005-08-15 23:33:21 UTC (rev 241)
@@ -1223,10 +1223,37 @@
   iseq = block->iseq;
   
   if(BUILTIN_TYPE(iseq) != T_NODE){
-    if(argc > iseq->argc){
+
+    if(flag & VM_CALL_ARGS_SPLAT_BIT){
+      VALUE ary = TOPN(0);
+      if(CLASS_OF(ary) != rb_cArray){
+        /* not a [BUG] */
+      }
+      else{
+        VALUE *ptr = RARRAY(ary)->ptr;
+        VALUE *dst = GET_SP() - 1;
+        int i, len = RARRAY(ary)->len;
+        for(i=0; i<len; i++){
+          dst[i] = ptr[i];
+        }
+        argc += i-1;
+        INC_SP(i-1);
+      }
+    }
+
+    if(iseq->argc == 1 &&
+       argc > 1){
+      /* TODO: for backward compatibility */
+      
+      INC_SP(1-argc);
+      *(GET_SP()-1) = rb_ary_new4(argc, GET_SP()-1);
+      argc = 1;
+    }
+    else if(argc > iseq->argc){
       INC_SP(iseq->argc - argc);
-      argc -= num - iseq->argc;
+      argc -= argc - iseq->argc;
     }
+    
     th_set_env(th, iseq,
                FRAME_MAGIC_BLOCK, block->self, (VALUE)block->dfp,
                iseq->iseq_encoded, GET_SP(), block->lfp,

Added: trunk/rb/parse.rb
===================================================================
--- trunk/rb/parse.rb	2005-08-15 21:01:19 UTC (rev 240)
+++ trunk/rb/parse.rb	2005-08-15 23:33:21 UTC (rev 241)
@@ -0,0 +1,5 @@
+$file = ARGV[0]
+$str  = ARGF.read
+puts $str
+$parsed = YARVCore::parse($str, $file, 1)
+puts $parsed.disasm

Modified: trunk/test.rb
===================================================================
--- trunk/test.rb	2005-08-15 21:01:19 UTC (rev 240)
+++ trunk/test.rb	2005-08-15 23:33:21 UTC (rev 241)
@@ -1,5 +1,14 @@
 $prog = <<'__EOP__'
+def iter args
+  yield [1, 2]
+end
 
+iter([1]){|e|
+  p e
+}
+
+
+__END__
 1.times{|e|
   begin
   rescue => err

Modified: trunk/test1.rb
===================================================================
--- trunk/test1.rb	2005-08-15 21:01:19 UTC (rev 240)
+++ trunk/test1.rb	2005-08-15 23:33:21 UTC (rev 241)
@@ -0,0 +1,30 @@
+def iter args
+  yield *args
+end
+
+iter([]){|a, b|
+  p [a, b]
+}
+iter([1]){|a, b|
+  p [a, b]
+}
+iter([1, 2]){|a, b|
+  p [a, b]
+}
+iter([1, 2, 3]){|a, b|
+  p [a, b]
+}
+
+iter([]){|a|
+  p [a]
+}
+iter([1]){|a|
+  p [a]
+}
+iter([1, 2]){|a|
+  p [a]
+}
+iter([1, 2, 3]){|a|
+  p [a]
+}
+

Modified: trunk/vm.c
===================================================================
--- trunk/vm.c	2005-08-15 21:01:19 UTC (rev 240)
+++ trunk/vm.c	2005-08-15 23:33:21 UTC (rev 241)
@@ -358,7 +358,9 @@
 }
 
 
-VALUE th_invoke_yield(yarv_thread_t *th, int argc, VALUE *argv){
+VALUE
+th_invoke_yield(yarv_thread_t *th, int argc, VALUE *argv)
+{
   yarv_control_frame_t *cfp = th->cfp;
   yarv_block_t *block = GC_GUARDED_PTR_REF(cfp->lfp[0]);
   VALUE val;
@@ -368,6 +370,21 @@
   }
   else{
     if(BUILTIN_TYPE(block->iseq) != T_NODE){
+
+      if(block->iseq->argc == 1){
+        if(argc > 1){
+          argv[0] = rb_ary_new4(argc, argv);
+          argc = 1;
+        }
+      }
+      else{
+        if(argc == 1 && !IMMEDIATE_P(argv[0]) &&
+           BUILTIN_TYPE(argv[0]) == T_ARRAY){
+          argc = RARRAY(argv[0])->len;
+          argv = RARRAY(argv[0])->ptr;
+        }
+      }
+
       th_set_finish_env(th);
       th_set_env(th, block->iseq, FRAME_MAGIC_BLOCK,
                  block->self, GC_GUARDED_PTR(block->dfp),

Modified: trunk/yarvcore.c
===================================================================
--- trunk/yarvcore.c	2005-08-15 21:01:19 UTC (rev 240)
+++ trunk/yarvcore.c	2005-08-15 23:33:21 UTC (rev 241)
@@ -214,7 +214,7 @@
 static VALUE compile_string(VALUE str, VALUE file, VALUE line){
   NODE *node;
   node = rb_compile_string(StringValueCStr(file), str, NUM2INT(line));
-  
+
   if(ruby_nerrs > 0){
     ruby_nerrs = 0;
     rb_exc_raise(ruby_errinfo);
@@ -254,12 +254,14 @@
 }
 
 static VALUE yarvcore_parse(VALUE self, VALUE str, VALUE file, VALUE line){
-  VALUE node = compile_string(str, file, line);
+  VALUE node;
   VALUE argv[5];
   VALUE iseq;
   
+  node = compile_string(str, file, line);
+  
   argv[0] = node;
-  argv[1] = rb_str_new2("main");
+  argv[1] = rb_str_new2("<main>");
   argv[2] = file;
   argv[3] = Qfalse;
   argv[4] = ISEQ_TYPE_TOP;

Modified: trunk/yarvtest/test_method.rb
===================================================================
--- trunk/yarvtest/test_method.rb	2005-08-15 21:01:19 UTC (rev 240)
+++ trunk/yarvtest/test_method.rb	2005-08-15 23:33:21 UTC (rev 241)
@@ -1,6 +1,4 @@
 require 'yarvtest/yarvtest'
-
-
 class TestMethod < YarvTestBase
   
   def test_simple_method

Added: trunk/yarvtest/test_yield.rb
===================================================================
--- trunk/yarvtest/test_yield.rb	2005-08-15 21:01:19 UTC (rev 240)
+++ trunk/yarvtest/test_yield.rb	2005-08-15 23:33:21 UTC (rev 241)
@@ -0,0 +1,145 @@
+require 'yarvtest/yarvtest'
+class TestYield < YarvTestBase
+  def test_simple
+    ae %q{
+      def iter
+        yield
+      end
+      iter{
+        1
+      }
+    }
+  end
+
+  def test_hash_each
+    ae %q{
+      h = {:a => 1}
+      a = []
+      h.each{|k, v|
+        a << [k, v]
+      }
+      h.each{|kv|
+        a << kv
+      }
+      a
+    }
+  end
+
+  def test_ary_each
+    ae %q{
+      ans = []
+      ary = [1,2,3]
+      ary.each{|a, b, c, d|
+        ans << [a, b, c, d]
+      }
+      ary.each{|a, b, c|
+        ans << [a, b, c]
+      }
+      ary.each{|a, b|
+        ans << [a, b]
+      }
+      ary.each{|a|
+        ans << [a]
+      }
+      ans
+    }
+  end
+
+  def test_iter
+    ae %q{
+      def iter *args
+        yield *args
+      end
+      
+      ans = []
+      ary = [1,2,3]
+      ary.each{|a, b, c, d|
+        ans << [a, b, c, d]
+      }
+      ary.each{|a, b, c|
+        ans << [a, b, c]
+      }
+      ary.each{|a, b|
+        ans << [a, b]
+      }
+      ary.each{|a|
+        ans << [a]
+      }
+      ans
+    }
+  end
+
+  def test_iter2
+    ae %q{
+      def iter args
+        yield *args
+      end
+      ans = []
+      iter([]){|a, b|
+        ans << [a, b]
+      }
+      iter([1]){|a, b|
+        ans << [a, b]
+      }
+      iter([1, 2]){|a, b|
+        ans << [a, b]
+      }
+      iter([1, 2, 3]){|a, b|
+        ans << [a, b]
+      }
+      ans
+    }
+    ae %q{
+      def iter args
+        yield *args
+      end
+      ans = []
+      
+      iter([]){|a|
+        ans << a
+      }
+      iter([1]){|a|
+        ans << a
+      }
+      iter([1, 2]){|a|
+        ans << a
+      }
+      iter([1, 2, 3]){|a|
+        ans << a
+      }
+      ans
+    }
+  end
+
+  def test_argscat
+    ae %q{
+      def iter
+        yield 1, *[2, 3]
+      end
+
+      iter{|a, b, c|
+        [a, b, c]
+      }
+    }
+    ae %q{
+      def iter
+        yield 1, *[]
+      end
+
+      iter{|a, b, c|
+        [a, b, c]
+      }
+    }
+    ae %q{
+      def iter
+        yield 1, *2
+      end
+
+      iter{|a, b, c|
+        [a, b, c]
+      }
+    }
+  end
+end
+
+


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

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