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

yarv-diff:142

From: ko1 atdot.net
Date: 3 Dec 2005 11:37:47 -0000
Subject: [yarv-diff:142] r301 - in trunk: . benchmark lib rb yarvtest

Author: ko1
Date: 2005-12-03 20:37:46 +0900 (Sat, 03 Dec 2005)
New Revision: 301

Added:
   trunk/blockinlining.c
   trunk/yarvtest/test_syntax.rb
Removed:
   trunk/yarvsubst.c
   trunk/yarvtest/test_syn.rb
Modified:
   trunk/ChangeLog
   trunk/benchmark/bm_loop_times.rb
   trunk/benchmark/bmx_temp.rb
   trunk/common.mk
   trunk/compile.c
   trunk/compile.h
   trunk/disasm.c
   trunk/eval_thread.c
   trunk/gc.c
   trunk/insns.def
   trunk/lib/cgi.rb
   trunk/node.h
   trunk/numeric.c
   trunk/opt_operand.def
   trunk/range.c
   trunk/rb/insns2vm.rb
   trunk/test.rb
   trunk/vm.c
   trunk/vm_macro.def
   trunk/yarvcore.c
   trunk/yarvcore.h
   trunk/yarvtest/yarvtest.rb
Log:
	* blockinlining.c, common.mk : add blockinlining.c

	* yarvcore.c, yarvcore.h, blockinlining.c, compile.c, compile.h,
	gc.c, node.h, numeric.c, range.c :
	support block inlining for Integer#times, Range#each

	* compile.c : fix to set block redo/next point at last,
	and fix NODE_OP_ASGN1

	* compile.c, vm.c : add specialized instruction "opt_le"

	* disasm.c : fix to show block, and to show catch type as string
	and change node_name logic

	* eval_thread.c : fix function type declaration

	* insns.def : add instruction "putundef", "opt_checkenv"
	to support block inlining and add stack check routine

	* lib/cgi.rb : add global variable $CGI_DONTINPUT

	* opt_operand.def : add some operand unification rules

	* rb/insns2vm.rb : fix operand unification logic for BLOCKISEQ

	* vm.c : fix exception handling routine (collect stack operations)

	* vm_macro.def : fix macro_eval_invoke_bmethod

	* yarvsubst.c : removed

	* yarvtest/test_syn.rb : rename to yarvtest/test_syntax.rb

	* yarvtest/yarvtest.rb : remove tempfile explicitly



Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/ChangeLog	2005-12-03 11:37:46 UTC (rev 301)
@@ -4,6 +4,44 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2005-12-03(Sat) 20:24:07 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* blockinlining.c, common.mk : add blockinlining.c
+
+	* yarvcore.c, yarvcore.h, blockinlining.c, compile.c, compile.h,
+	gc.c, node.h, numeric.c, range.c :
+	support block inlining for Integer#times, Range#each
+
+	* compile.c : fix to set block redo/next point at last,
+	and fix NODE_OP_ASGN1
+
+	* compile.c, vm.c : add specialized instruction "opt_le"
+
+	* disasm.c : fix to show block, and to show catch type as string
+	and change node_name logic
+
+	* eval_thread.c : fix function type declaration
+
+	* insns.def : add instruction "putundef", "opt_checkenv"
+	to support block inlining and add stack check routine
+
+	* lib/cgi.rb : add global variable $CGI_DONTINPUT
+
+	* opt_operand.def : add some operand unification rules
+
+	* rb/insns2vm.rb : fix operand unification logic for BLOCKISEQ
+
+	* vm.c : fix exception handling routine (collect stack operations)
+
+	* vm_macro.def : fix macro_eval_invoke_bmethod
+
+	* yarvsubst.c : removed
+
+	* yarvtest/test_syn.rb : rename to yarvtest/test_syntax.rb
+
+	* yarvtest/yarvtest.rb : remove tempfile explicitly
+
+
 2005-11-30(Wed) 01:13:57 +0900  Koichi Sasada  <ko1 atdot.net>
 
 	* common.mk : add vm_opts.h rule

Modified: trunk/benchmark/bm_loop_times.rb
===================================================================
--- trunk/benchmark/bm_loop_times.rb	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/benchmark/bm_loop_times.rb	2005-12-03 11:37:46 UTC (rev 301)
@@ -1,2 +1 @@
-30000000.times{|i|
-}
+30000000.times{|e|}

Modified: trunk/benchmark/bmx_temp.rb
===================================================================
--- trunk/benchmark/bmx_temp.rb	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/benchmark/bmx_temp.rb	2005-12-03 11:37:46 UTC (rev 301)
@@ -1,17 +1,14 @@
 
-
-
-__END__
-class Integer
-  def times_
-    i=0
-    while i<self
-      yield(i)
-      i = i.succ
-    end
+class Range
+  def map_
+    r = []
+    self.each{|e|
+      r << yield(e)
+    }
+    r
   end
 end
 
-10000000.times{}
-
-
+(1..5000000).map{|e|
+  e
+}

Added: trunk/blockinlining.c
===================================================================
--- trunk/blockinlining.c	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/blockinlining.c	2005-12-03 11:37:46 UTC (rev 301)
@@ -0,0 +1,43 @@
+#include "ruby.h"
+#include "node.h"
+#include "yarvcore.h"
+
+VALUE yarv_new_iseqval(VALUE node, VALUE name, VALUE file,
+                       VALUE parent, VALUE type, VALUE opt);
+
+VALUE
+yarv_iseq_special_block(yarv_iseq_t * iseq, ID id)
+{
+  VALUE parent = Qfalse;
+  VALUE iseqval;
+
+  if(iseq->argc > 1 ||
+     iseq->arg_simple == 0){
+    /* argument check */
+    return 0;
+  }
+  
+  if(iseq->cached_special_block_type){
+    if(iseq->cached_special_block_type == id){
+      return iseq->cached_special_block;
+    }
+    else{
+      return 0;
+    }
+  }
+  else{
+    iseq->cached_special_block_type = 1;
+  }
+  if(iseq->parent_iseq){
+    parent = iseq->parent_iseq->self;
+  }
+  iseqval = yarv_new_iseqval((VALUE)iseq->node, iseq->name,
+                             iseq->file_name, parent, iseq->type, ID2SYM(id));
+  if(0){
+    printf("%s\n", RSTRING(iseq_disasm(iseqval))->ptr);
+  }
+  iseq->cached_special_block      = iseqval;
+  iseq->cached_special_block_type = id;
+  return iseqval;
+}
+

Modified: trunk/common.mk
===================================================================
--- trunk/common.mk	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/common.mk	2005-12-03 11:37:46 UTC (rev 301)
@@ -60,13 +60,13 @@
 		util.$(OBJEXT) \
 		variable.$(OBJEXT) \
 		version.$(OBJEXT) \
+		blockinlining.$(OBJEXT) \
 		compile.$(OBJEXT) \
 		debug.$(OBJEXT) \
 		disasm.$(OBJEXT) \
 		vm.$(OBJEXT) \
 		vm_dump.$(OBJEXT) \
 		yarvcore.$(OBJEXT) \
-		yarvsubst.$(OBJEXT) \
 		thread.$(OBJEXT) \
 		$(MISSING)
 
@@ -382,7 +382,7 @@
 yarvcore.$(OBJEXT): {$(VPATH)}yarvcore.c {$(VPATH)}yarvcore.h \
         {$(VPATH)}yarv_version.h {$(VPATH)}debug.h rev.inc
 debug.$(OBJEXT): {$(VPATH)}debug.h
-yarvsubst.$(OBJEXT): {$(VPATH)}yarv.h
+blockinlining.$(OBJEXT): {$(VPATH)}yarv.h {$(VPATH)}yarvcore.h 
 
 
 BASERUBY = ruby

Modified: trunk/compile.c
===================================================================
--- trunk/compile.c	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/compile.c	2005-12-03 11:37:46 UTC (rev 301)
@@ -211,12 +211,13 @@
       
       iseq->rewind_frame_size = iseq->local_size + REWIND_DSIZE();
 
-      ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, 0, 0, start);
-      ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, 0, 0, end);
-
       ADD_LABEL(list_anchor, iseq->compile_data->start_label);
       COMPILE(list_anchor, "block body", node);
       ADD_LABEL(list_anchor, iseq->compile_data->end_label);
+
+      /* wide range catch handler must put at last */
+      ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, 0, 0, start);
+      ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, 0, 0, end);
     }
     else if(iseq->type == ISEQ_TYPE_TOP){
       set_localtbl(iseq, GET_THREAD()->top_local_tbl);
@@ -656,6 +657,9 @@
       else if(mid == idLT){
         iobj = new_insn_body(iseq, line_no, BIN(opt_lt), 0);
       }
+      else if(mid == idLE){
+        iobj = new_insn_body(iseq, line_no, BIN(opt_le), 0);
+      }
       else if(mid == idLTLT){
         iobj = new_insn_body(iseq, line_no, BIN(opt_ltlt), 0);
       }
@@ -692,9 +696,9 @@
 
 static VALUE
 new_child_iseq(yarv_iseq_t *iseq, NODE *node,
-               VALUE name, VALUE parent, VALUE type)
+               VALUE name, VALUE parent, VALUE type, VALUE opt)
 {
-  VALUE args[5];
+  VALUE args[6];
   VALUE ret;
   
   debugs("[new_child_iseq]> ---------------------------------------\n");
@@ -703,8 +707,9 @@
   args[2] = iseq_filename(iseq->self);
   args[3] = parent;
   args[4] = type;
+  args[5] = opt;
   
-  ret = rb_class_new_instance(5, args, cYarvISeq);
+  ret = rb_class_new_instance(6, args, cYarvISeq);
   
   debugs("[new_child_iseq]< ---------------------------------------\n");
   iseq_add_mark_object(iseq, ret);
@@ -813,6 +818,160 @@
   return COMPILE_OK;
 }
 
+static NODE *
+new_block(NODE *head, NODE *tail)
+{
+  head = NEW_BLOCK(head);
+  tail = NEW_BLOCK(tail);
+  head->nd_next = tail;
+  return head;
+}
+
+static NODE *
+new_ary(NODE *head, NODE *tail)
+{
+  head = NEW_ARRAY(head);
+  head->nd_next = tail;
+  return head;
+}
+
+static NODE*
+make_special_block_body(yarv_iseq_t *iseq, NODE *node, 
+                        VALUE param_vars, VALUE local_vars)
+{
+  if(iseq->special_block_type == idTimes &&
+     iseq->argc < 2 && iseq->arg_simple){
+    /* Special Block for Integer#times
+       {|e, _self|
+          _e = e
+          while(e < _self)
+            e = _e
+          redo_point:
+            BODY
+          next_point:
+            _e = _e.succ
+          end
+       }
+
+       {|e, _self|
+          while(e < _self)
+            BODY
+          next_point:
+            e = e.succ
+          end
+       }
+     */
+    ID _self = rb_intern("#_self");
+    if(iseq->argc == 0){
+      ID e = rb_intern("#e");
+      rb_ary_push(param_vars, ID2SYM(e));
+      rb_ary_push(param_vars, ID2SYM(_self));
+      iseq->argc+=2;
+
+      node =
+        NEW_WHILE(
+          NEW_CALL(NEW_DVAR(e), idLT, new_ary(NEW_DVAR(_self), 0)),
+          new_block(NEW_OPTBLOCK(node),
+                    NEW_DASGN(e, NEW_CALL(NEW_DVAR(e), idSucc, 0))),
+          Qundef);
+    }
+    else{
+      ID _e = rb_intern("#_e");
+      ID  e = SYM2ID(rb_ary_entry(param_vars, 0));
+      rb_ary_push(param_vars, ID2SYM(_self));
+      rb_ary_push(local_vars, ID2SYM(_e));
+      iseq->argc++;
+      
+      node =
+        new_block(
+          NEW_DASGN(_e, NEW_DVAR(e)),
+          NEW_WHILE(
+            NEW_CALL(NEW_DVAR(_e), idLT, new_ary(NEW_DVAR(_self), 0)),
+            new_block(
+              NEW_DASGN(e, NEW_DVAR(_e)),
+              new_block(NEW_OPTBLOCK(node),
+                        NEW_DASGN(_e, NEW_CALL(NEW_DVAR(_e), idSucc, 0)))),
+            Qundef));
+    }
+  }
+  else if((iseq->special_block_type == idRangeEachLT ||
+           iseq->special_block_type == idRangeEachLE) &&
+          iseq->argc < 2 && iseq->arg_simple){
+    /* Special Block for Range#each
+       {|e, _last|
+          _e = e
+          while _e < _last
+            e = _e
+          next_point:
+            BODY
+          redo_point:
+            _e = _e.succ
+          end
+       }
+       {|e, _last|
+          while e < _last
+            BODY
+          redo_point:
+            e = e.succ
+          end
+       }
+     */
+    ID _last = rb_intern("#_last");
+    ID mid = iseq->special_block_type == idRangeEachLT ? idLT : idLE;
+
+    if(iseq->argc == 0){
+      ID e = rb_intern("#e");
+      rb_ary_push(param_vars, ID2SYM(e));
+      rb_ary_push(param_vars, ID2SYM(_last));
+      iseq->argc+=2;
+
+      node =
+        NEW_WHILE(
+          NEW_CALL(NEW_DVAR(e), mid, new_ary(NEW_DVAR(_last), 0)),
+          new_block(NEW_OPTBLOCK(node),
+                    NEW_DASGN(e, NEW_CALL(NEW_DVAR(e), idSucc, 0))),
+          1);
+    }
+    else{
+      ID _e = rb_intern("#_e");
+      ID  e = SYM2ID(rb_ary_entry(param_vars, 0));
+      rb_ary_push(param_vars, ID2SYM(_last));
+      rb_ary_push(local_vars, ID2SYM(_e));
+      iseq->argc++;
+
+      node =
+        new_block(
+          NEW_DASGN(_e, NEW_DVAR(e)),
+          NEW_WHILE(
+            NEW_CALL(NEW_DVAR(_e), mid, new_ary(NEW_DVAR(_last), 0)),
+            new_block(
+              NEW_DASGN(e, NEW_DVAR(_e)),
+              new_block(NEW_OPTBLOCK(node),
+                        NEW_DASGN(_e, NEW_CALL(NEW_DVAR(_e), idSucc, 0)))),
+            1));
+    }
+  }
+#if 0
+  else if(){
+    /* Special Block for Array#each
+       {|e, _self|
+          _i = 0
+          _j = 0
+          while(_j = _i; _i = _i.succ; e = _self[_i]; _j < _self.length)
+            BODY
+          end
+       }
+     */
+    nn = new_block(...);
+  }
+#endif
+  else{
+    rb_bug("Unsupport special block type: %s",
+           rb_id2name(iseq->special_block_type));
+  }
+  return node;
+}
+
 static int
 search_block_local_variables(NODE *node, VALUE local_vars)
 {
@@ -844,7 +1003,7 @@
   int i;
   NODE *nelem;
   VALUE local_vars = rb_ary_new();
-  VALUE vars = rb_ary_new();
+  VALUE param_vars = rb_ary_new();
   
   /* search args */
   if(node->nd_var &&
@@ -852,7 +1011,7 @@
     switch(nd_type(node->nd_var)){
     case NODE_DASGN_CURR:
       iseq->argc = 1;
-      rb_ary_push(vars, ID2SYM(node->nd_var->nd_vid));
+      rb_ary_push(param_vars, ID2SYM(node->nd_var->nd_vid));
       debugi("block 1arg", node->nd_var->nd_vid);
       break;
     case NODE_MASGN:{
@@ -862,16 +1021,16 @@
         iseq->argc = node->nd_var->nd_head->nd_alen;
         for(i=0; i<iseq->argc; i++, nelem = nelem->nd_next){
           if(nd_type(nelem->nd_head) == NODE_DASGN_CURR){
-            rb_ary_push(vars, ID2SYM(nelem->nd_head->nd_vid));
+            rb_ary_push(param_vars, ID2SYM(nelem->nd_head->nd_vid));
             debugi("block arg", nelem->nd_head->nd_vid);
           }
           else{
             char buff[0x20];
             ID   id;
-            int  idx = iseq->argc - RARRAY(vars)->len;
+            int  idx = iseq->argc - RARRAY(param_vars)->len;
             snprintf(buff, 0x20, "#blp%d", idx);
             id = rb_intern(buff);
-            rb_ary_push(vars, ID2SYM(id));
+            rb_ary_push(param_vars, ID2SYM(id));
             debugi("block arg (auto)", id);
             search_block_local_variables(nelem->nd_head, local_vars);
           }
@@ -881,10 +1040,10 @@
         NODE *sn = node->nd_var->nd_args;
         if((int)sn != -1){
           if(nd_type(sn) == NODE_DASGN_CURR){
-            rb_ary_push(vars, ID2SYM(sn->nd_vid));
+            rb_ary_push(param_vars, ID2SYM(sn->nd_vid));
           }
           else{
-            rb_ary_push(vars, ID2SYM(rb_intern("#blp_splat")));
+            rb_ary_push(param_vars, ID2SYM(rb_intern("#blp_splat")));
             debugi("block/splat (auto)", rb_intern("#blp_splat"));
           }
         }
@@ -892,7 +1051,7 @@
       break;
     }
     default:
-      rb_ary_push(vars, ID2SYM(rb_intern("#blp")));
+      rb_ary_push(param_vars, ID2SYM(rb_intern("#blp")));
       debugi("block 1arg (auto)", rb_intern("#blp"));
       iseq->argc = 1;
       break;
@@ -901,17 +1060,17 @@
   else{
     iseq->argc = 0;
   }
-  rb_ary_concat(vars, local_vars);
+
   node = node->nd_body;
-  
+
   /* other block local variables 2 */
   if(node && nd_type(node) == NODE_BLOCK){
     nelem = node->nd_head;
     if(nelem && nd_type(nelem) == NODE_DASGN_CURR){
       while(nelem && nd_type(nelem) == NODE_DASGN_CURR){
-        if(!rb_ary_includes(vars, ID2SYM(nelem->nd_vid))){
+        if(!rb_ary_includes(local_vars, ID2SYM(nelem->nd_vid))){
           debugi("block initialized variable", nelem->nd_vid);
-          rb_ary_push(vars, ID2SYM(nelem->nd_vid));
+          rb_ary_push(local_vars, ID2SYM(nelem->nd_vid));
         }
         nelem = nelem->nd_value;
       }
@@ -921,14 +1080,30 @@
     }
   }
 
+  if(iseq->arg_opts ||
+     iseq->arg_rest){
+    iseq->arg_simple = 0;
+  }
+  else{
+    iseq->arg_simple = 1;
+  }
+
+  if(iseq->special_block_type != 0){
+    node = make_special_block_body(iseq, node,
+                                   param_vars, local_vars);
+  }
+
+  rb_ary_concat(param_vars, local_vars);
+  local_vars = param_vars;
+
   {
-    int i, size = RARRAY(vars)->len;
+    int i, size = RARRAY(local_vars)->len;
     
     if(size > 0){
       iseq->local_tbl = ALLOC_N(ID, size);
       for(i=0; i<size; i++){
-        iseq->local_tbl[i] = SYM2ID(RARRAY(vars)->ptr[i]);
-        debugi("block param", iseq->local_tbl[i]);
+        iseq->local_tbl[i] = SYM2ID(RARRAY(local_vars)->ptr[i]);
+        debugi("block local variable", iseq->local_tbl[i]);
       }
     }
     iseq->local_size = size;
@@ -962,7 +1137,7 @@
   if(iseq->type != ISEQ_TYPE_BLOCK){
     rb_bug("set_block_local_tbl: unexpected iseq type");
   }
-  
+
   rnode = search_block_local_parameters(iseq, node);
 
   if((VALUE)node->nd_var == 1){
@@ -2517,6 +2692,7 @@
         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);
@@ -2570,8 +2746,8 @@
 
     ADD_LABEL(ret, redo_label);
     COMPILE_ (ret, "while body", node->nd_body, 1);
-
     ADD_LABEL(ret, next_label); /* next */
+    
     if(type == NODE_WHILE){
       compile_branch_condition(self, iseq, ret,
                                node->nd_cond, redo_label, end_label);
@@ -2590,18 +2766,26 @@
 
     ADD_LABEL(ret, end_label);
     if(!poped){
-      ADD_INSN(ret, nd_line(node), putnil);
+      if(node->nd_state == Qundef){
+        ADD_INSN(ret, nd_line(node), putundef);
+      }
+      else{
+        ADD_INSN(ret, nd_line(node), putnil);
+      }
     }
     ADD_LABEL(ret, break_label); /* braek */
     
-    ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, redo_label, break_label, 0, 0, break_label);
-    ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, redo_label, break_label,  0, 0, next_label);
-    ADD_CATCH_ENTRY(CATCH_TYPE_REDO, redo_label, break_label,  0, 0, redo_label);
+    ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, redo_label, break_label,
+                    0, 0, break_label);
+    ADD_CATCH_ENTRY(CATCH_TYPE_NEXT,  redo_label, break_label,
+                    0, 0, iseq->compile_data->start_label);
+    ADD_CATCH_ENTRY(CATCH_TYPE_REDO,  redo_label, break_label,
+                    0, 0, iseq->compile_data->redo_label);
     
-    iseq->compile_data->start_label = prev_start_label;
-    iseq->compile_data->end_label   = prev_end_label;
-    iseq->compile_data->redo_label  = prev_redo_label;
-    iseq->compile_data->loopval_popped = prev_loopval_popped;
+    iseq->compile_data->start_label       = prev_start_label;
+    iseq->compile_data->end_label         = prev_end_label;
+    iseq->compile_data->redo_label        = prev_redo_label;
+    iseq->compile_data->loopval_popped    = prev_loopval_popped;
     iseq->compile_data->ensure_node_stack = enlp;
     break;
   }
@@ -2771,6 +2955,7 @@
     COMPILE(ret, "rescue head", node->nd_head);
     ADD_LABEL(ret, lend);
     if(node->nd_else){
+      ADD_INSN(ret, nd_line(node), pop);
       COMPILE(ret, "rescue else", node->nd_else);
     }
     ADD_INSN (ret, nd_line(node), nop);
@@ -2920,6 +3105,8 @@
        lv > 0 &&
        iseq->type != ISEQ_TYPE_RESCUE &&
        iseq->compile_data->for_iseq != 1){
+      
+      dpi(node->nd_vid);
       rb_bug("NODE_DASGN_CURR, but lv == %d (line: %d)", lv, nd_line(node));
     }
     
@@ -3015,20 +3202,31 @@
       LABEL * lfin  = NEW_LABEL(nd_line(node));
       
       if(id == 0){
+        /* or */
         ADD_INSN (ret, nd_line(node), dup);
         ADD_INSNL(ret, nd_line(node), if, label);
         ADD_INSN (ret, nd_line(node), pop);
       }
       else{
+        /* and */
         ADD_INSNL(ret, nd_line(node), unless, label);
       }
+      
       COMPILE  (ret, "NODE_OP_ASGN1 args->head: ", node->nd_args->nd_head);
       ADD_SEND (ret, nd_line(node), ID2SYM(idASET), I2F(argc+1));
       ADD_INSNL(ret, nd_line(node), jump, lfin);
       ADD_LABEL(ret, label);
-      if(id == 1){ /* and */
-        ADD_INSN (ret, nd_line(node), putnil);
+      if(id == 0){ /* or */
+        ADD_INSN(ret, nd_line(node), swap);
+        ADD_INSN(ret, nd_line(node), pop);
+        ADD_INSN(ret, nd_line(node), swap);
+        ADD_INSN(ret, nd_line(node), pop);
       }
+      else if(id == 1){ /* and */
+        ADD_INSN(ret, nd_line(node), pop);
+        ADD_INSN(ret, nd_line(node), pop);
+        ADD_INSN(ret, nd_line(node), putnil);
+      }
       ADD_LABEL(ret, lfin);
     }
     else{
@@ -4060,6 +4258,20 @@
     }
     break;
   }
+  case NODE_OPTBLOCK:{
+    /* for optimize */
+    LABEL *redo_label = NEW_LABEL(0);
+    LABEL *next_label = NEW_LABEL(0);
+
+    iseq->compile_data->start_label = next_label;
+    iseq->compile_data->redo_label  = redo_label;
+    
+    ADD_LABEL    (ret, redo_label);
+    COMPILE_POPED(ret, "optblock body", node->nd_head);
+    ADD_LABEL    (ret, next_label);
+    ADD_INSN     (ret, 0, opt_checkenv);
+    break;
+  }
   default:
     COMPILE_ERROR(("BUG: unknown node: %s", node_name(type)));
     return Qnil;

Modified: trunk/compile.h
===================================================================
--- trunk/compile.h	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/compile.h	2005-12-03 11:37:46 UTC (rev 301)
@@ -97,11 +97,14 @@
   (((yarv_iseq_t*)DATA_PTR(iseq))->file_name)
 
 #define NEW_ISEQVAL(node, name, type)       \
-  new_child_iseq(iseq, node, name, 0, type)
+  new_child_iseq(iseq, node, name, 0, type, Qfalse)
 
 #define NEW_CHILD_ISEQVAL(node, name, type)       \
-  new_child_iseq(iseq, node, name, iseq->self, type)
+  new_child_iseq(iseq, node, name, iseq->self, type, Qfalse)
 
+#define NEW_SPECIAQL_BLOCK_ISEQVAL(iseq, sym) \
+  new_child_iseq(iseq, iseq->node, iseq->name, iseq->parent_iseq, iseq->type, sym)
+
 /* add instructions */
 #define ADD_SEQ(seq1, seq2) \
   APPEND_LIST(seq1, seq2)

Modified: trunk/disasm.c
===================================================================
--- trunk/disasm.c	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/disasm.c	2005-12-03 11:37:46 UTC (rev 301)
@@ -77,10 +77,17 @@
   case 'B': /* block */
     {
       yarv_iseq_t *block = (yarv_iseq_t *)op;
-      ret = block->name;
+      if(block){
+        ret = block->name;
+        if(child){
+          rb_ary_push(child, block->self);
+        }
+      }
+      else{
+        ret = rb_str_new2("nil");
+      }
       break;
     }
-    
   case 'G':
     {
       struct global_entry *entry = (struct global_entry*)op;
@@ -160,6 +167,21 @@
   return len;
 }
 
+static char *
+catch_type(int type){
+  switch(type){
+  case CATCH_TYPE_RESCUE: return "rs";
+  case CATCH_TYPE_ENSURE: return "en";
+  case CATCH_TYPE_RETRY:  return "rd";
+  case CATCH_TYPE_BREAK:  return "br";
+  case CATCH_TYPE_REDO:   return "rd";
+  case CATCH_TYPE_NEXT:   return "nx";
+  default:
+    rb_bug("unknown catch type (%d)", type);
+    return 0;
+  }
+}
+
 /**
  * Disassemble yarv instruction sequence
  *
@@ -194,8 +216,9 @@
   }
   for(i=0; i<iseqdat->catch_table_size; i++){
     struct catch_table_entry *entry = &iseqdat->catch_table[i];
-    sprintf(buff, "|type: %02d, st: %04d, ed: %04d, sp: %04d, cont: %04d\n",
-            (int)entry->type, (int)entry->start, (int)entry->end, (int)entry->sp, (int)entry->cont);
+    sprintf(buff, "|type: %2s, st: %04d, ed: %04d, sp: %04d, cont: %04d\n",
+            catch_type((int)entry->type), (int)entry->start,
+            (int)entry->end, (int)entry->sp, (int)entry->cont);
     rb_str_cat2(str, buff);
     if(entry->iseq){
       rb_str_concat(str, iseq_disasm(entry->iseq));
@@ -268,119 +291,119 @@
   return str;
 }
 
-/*
-  node.h
-  $Date: 2004/05/07 08:44:14 $
- */
-static char *node_names[] = {
-    "NODE_METHOD",
-    "NODE_FBODY",
-    "NODE_CFUNC",
-    "NODE_SCOPE",
-    "NODE_BLOCK",
-    "NODE_IF",
-    "NODE_CASE",
-    "NODE_WHEN",
-    "NODE_OPT_N",
-    "NODE_WHILE",
-    "NODE_UNTIL",
-    "NODE_ITER",
-    "NODE_FOR",
-    "NODE_BREAK",
-    "NODE_NEXT",
-    "NODE_REDO",
-    "NODE_RETRY",
-    "NODE_BEGIN",
-    "NODE_RESCUE",
-    "NODE_RESBODY",
-    "NODE_ENSURE",
-    "NODE_AND",
-    "NODE_OR",
-    "NODE_NOT",
-    "NODE_MASGN",
-    "NODE_LASGN",
-    "NODE_DASGN",
-    "NODE_DASGN_CURR",
-    "NODE_GASGN",
-    "NODE_IASGN",
-    "NODE_CDECL",
-    "NODE_CVASGN",
-    "NODE_CVDECL",
-    "NODE_OP_ASGN1",
-    "NODE_OP_ASGN2",
-    "NODE_OP_ASGN_AND",
-    "NODE_OP_ASGN_OR",
-    "NODE_CALL",
-    "NODE_FCALL",
-    "NODE_VCALL",
-    "NODE_SUPER",
-    "NODE_ZSUPER",
-    "NODE_ARRAY",
-    "NODE_ZARRAY",
-    "NODE_VALUES",
-    "NODE_HASH",
-    "NODE_RETURN",
-    "NODE_YIELD",
-    "NODE_LVAR",
-    "NODE_DVAR",
-    "NODE_GVAR",
-    "NODE_IVAR",
-    "NODE_CONST",
-    "NODE_CVAR",
-    "NODE_NTH_REF",
-    "NODE_BACK_REF",
-    "NODE_MATCH",
-    "NODE_MATCH2",
-    "NODE_MATCH3",
-    "NODE_LIT",
-    "NODE_STR",
-    "NODE_DSTR",
-    "NODE_XSTR",
-    "NODE_DXSTR",
-    "NODE_EVSTR",
-    "NODE_DREGX",
-    "NODE_DREGX_ONCE",
-    "NODE_ARGS",
-    "NODE_ARGSCAT",
-    "NODE_ARGSPUSH",
-    "NODE_SPLAT",
-    "NODE_TO_ARY",
-    "NODE_SVALUE",
-    "NODE_BLOCK_ARG",
-    "NODE_BLOCK_PASS",
-    "NODE_DEFN",
-    "NODE_DEFS",
-    "NODE_ALIAS",
-    "NODE_VALIAS",
-    "NODE_UNDEF",
-    "NODE_CLASS",
-    "NODE_MODULE",
-    "NODE_SCLASS",
-    "NODE_COLON2",
-    "NODE_COLON3",
-    "NODE_CREF",
-    "NODE_DOT2",
-    "NODE_DOT3",
-    "NODE_FLIP2",
-    "NODE_FLIP3",
-    "NODE_ATTRSET",
-    "NODE_SELF",
-    "NODE_NIL",
-    "NODE_TRUE",
-    "NODE_FALSE",
-    "NODE_ERRINFO",
-    "NODE_DEFINED",
-    "NODE_POSTEXE",
-    "NODE_ALLOCA",
-    "NODE_BMETHOD",
-    "NODE_MEMO",
-    "NODE_IFUNC",
-    "NODE_DSYM",
-    "NODE_ATTRASGN",
-    "NODE_LAST"
-};
-
 char* node_name(int node){
-  return node_names[node];
+  switch(node){
+  case NODE_METHOD     : return "NODE_METHOD";
+  case NODE_FBODY      : return "NODE_FBODY";
+  case NODE_CFUNC      : return "NODE_CFUNC";
+  case NODE_SCOPE      : return "NODE_SCOPE";
+  case NODE_BLOCK      : return "NODE_BLOCK";
+  case NODE_IF         : return "NODE_IF";
+  case NODE_CASE       : return "NODE_CASE";
+  case NODE_WHEN       : return "NODE_WHEN";
+  case NODE_OPT_N      : return "NODE_OPT_N";
+  case NODE_WHILE      : return "NODE_WHILE";
+  case NODE_UNTIL      : return "NODE_UNTIL";
+  case NODE_ITER       : return "NODE_ITER";
+  case NODE_FOR        : return "NODE_FOR";
+  case NODE_BREAK      : return "NODE_BREAK";
+  case NODE_NEXT       : return "NODE_NEXT";
+  case NODE_REDO       : return "NODE_REDO";
+  case NODE_RETRY      : return "NODE_RETRY";
+  case NODE_BEGIN      : return "NODE_BEGIN";
+  case NODE_RESCUE     : return "NODE_RESCUE";
+  case NODE_RESBODY    : return "NODE_RESBODY";
+  case NODE_ENSURE     : return "NODE_ENSURE";
+  case NODE_AND        : return "NODE_AND";
+  case NODE_OR         : return "NODE_OR";
+  case NODE_NOT        : return "NODE_NOT";
+  case NODE_MASGN      : return "NODE_MASGN";
+  case NODE_LASGN      : return "NODE_LASGN";
+  case NODE_DASGN      : return "NODE_DASGN";
+  case NODE_DASGN_CURR : return "NODE_DASGN_CURR";
+  case NODE_GASGN      : return "NODE_GASGN";
+  case NODE_IASGN      : return "NODE_IASGN";
+  case NODE_CDECL      : return "NODE_CDECL";
+  case NODE_CVASGN     : return "NODE_CVASGN";
+  case NODE_CVDECL     : return "NODE_CVDECL";
+  case NODE_OP_ASGN1   : return "NODE_OP_ASGN1";
+  case NODE_OP_ASGN2   : return "NODE_OP_ASGN2";
+  case NODE_OP_ASGN_AND: return "NODE_OP_ASGN_AND";
+  case NODE_OP_ASGN_OR : return "NODE_OP_ASGN_OR";
+  case NODE_CALL       : return "NODE_CALL";
+  case NODE_FCALL      : return "NODE_FCALL";
+  case NODE_VCALL      : return "NODE_VCALL";
+  case NODE_SUPER      : return "NODE_SUPER";
+  case NODE_ZSUPER     : return "NODE_ZSUPER";
+  case NODE_ARRAY      : return "NODE_ARRAY";
+  case NODE_ZARRAY     : return "NODE_ZARRAY";
+  case NODE_VALUES     : return "NODE_VALUES";
+  case NODE_HASH       : return "NODE_HASH";
+  case NODE_RETURN     : return "NODE_RETURN";
+  case NODE_YIELD      : return "NODE_YIELD";
+  case NODE_LVAR       : return "NODE_LVAR";
+  case NODE_DVAR       : return "NODE_DVAR";
+  case NODE_GVAR       : return "NODE_GVAR";
+  case NODE_IVAR       : return "NODE_IVAR";
+  case NODE_CONST      : return "NODE_CONST";
+  case NODE_CVAR       : return "NODE_CVAR";
+  case NODE_NTH_REF    : return "NODE_NTH_REF";
+  case NODE_BACK_REF   : return "NODE_BACK_REF";
+  case NODE_MATCH      : return "NODE_MATCH";
+  case NODE_MATCH2     : return "NODE_MATCH2";
+  case NODE_MATCH3     : return "NODE_MATCH3";
+  case NODE_LIT        : return "NODE_LIT";
+  case NODE_STR        : return "NODE_STR";
+  case NODE_DSTR       : return "NODE_DSTR";
+  case NODE_XSTR       : return "NODE_XSTR";
+  case NODE_DXSTR      : return "NODE_DXSTR";
+  case NODE_EVSTR      : return "NODE_EVSTR";
+  case NODE_DREGX      : return "NODE_DREGX";
+  case NODE_DREGX_ONCE : return "NODE_DREGX_ONCE";
+  case NODE_ARGS       : return "NODE_ARGS";
+  case NODE_ARGSCAT    : return "NODE_ARGSCAT";
+  case NODE_ARGSPUSH   : return "NODE_ARGSPUSH";
+  case NODE_SPLAT      : 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 : return "NODE_BLOCK_PASS";
+  case NODE_DEFN       : return "NODE_DEFN";
+  case NODE_DEFS       : return "NODE_DEFS";
+  case NODE_ALIAS      : return "NODE_ALIAS";
+  case NODE_VALIAS     : return "NODE_VALIAS";
+  case NODE_UNDEF      : return "NODE_UNDEF";
+  case NODE_CLASS      : return "NODE_CLASS";
+  case NODE_MODULE     : return "NODE_MODULE";
+  case NODE_SCLASS     : return "NODE_SCLASS";
+  case NODE_COLON2     : return "NODE_COLON2";
+  case NODE_COLON3     : return "NODE_COLON3";
+  case NODE_CREF       : return "NODE_CREF";
+  case NODE_DOT2       : return "NODE_DOT2";
+  case NODE_DOT3       : return "NODE_DOT3";
+  case NODE_FLIP2      : return "NODE_FLIP2";
+  case NODE_FLIP3      : return "NODE_FLIP3";
+  case NODE_ATTRSET    : return "NODE_ATTRSET";
+  case NODE_SELF       : return "NODE_SELF";
+  case NODE_NIL        : return "NODE_NIL";
+  case NODE_TRUE       : return "NODE_TRUE";
+  case NODE_FALSE      : return "NODE_FALSE";
+  case NODE_ERRINFO    : return "NODE_ERRINFO";
+  case NODE_DEFINED    : return "NODE_DEFINED";
+  case NODE_POSTEXE    : return "NODE_POSTEXE";
+  case NODE_ALLOCA     : return "NODE_ALLOCA";
+  case NODE_BMETHOD    : return "NODE_BMETHOD";
+  case NODE_MEMO       : return "NODE_MEMO";
+  case NODE_IFUNC      : return "NODE_IFUNC";
+  case NODE_DSYM       : return "NODE_DSYM";
+  case NODE_ATTRASGN   : return "NODE_ATTRASGN";
+  case NODE_PRELUDE    : return "NODE_PRELUDE";
+  case NODE_LAMBDA     : return "NODE_LAMBDA";
+  case NODE_OPTBLOCK   : return "NODE_OPTBLOCK";
+  case NODE_LAST       : return "NODE_LAST";
+  default:
+    rb_bug("unknown node (%d)", node);
+    return 0;
+  }
 }
 

Modified: trunk/eval_thread.c
===================================================================
--- trunk/eval_thread.c	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/eval_thread.c	2005-12-03 11:37:46 UTC (rev 301)
@@ -2435,9 +2435,7 @@
 }
 
 VALUE
-rb_exec_recursive(func, obj, arg)
-    VALUE (*func)(ANYARGS);	/* VALUE obj, VALUE arg, int flag */
-    VALUE obj, arg;
+rb_exec_recursive(VALUE (*func)(VALUE, VALUE, int), VALUE obj, VALUE arg)
 {
     if (recursive_check(obj)) {
 	return (*func)(obj, arg, Qtrue);

Modified: trunk/gc.c
===================================================================
--- trunk/gc.c	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/gc.c	2005-12-03 11:37:46 UTC (rev 301)
@@ -757,6 +757,7 @@
 	    gc_mark((VALUE)obj->as.node.u2.node, lev);
 	    /* fall through */
 	  case NODE_BLOCK:	/* 1,3 */
+	  case NODE_OPTBLOCK:
 	  case NODE_ARRAY:
 	  case NODE_DSTR:
 	  case NODE_DXSTR:

Modified: trunk/insns.def
===================================================================
--- trunk/insns.def	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/insns.def	2005-12-03 11:37:46 UTC (rev 301)
@@ -379,6 +379,20 @@
 
 /**
   @c put
+  @e put Qundef.  DO NOT USE in NORMAL RUBY PROGRAM
+  @j put Qundef.
+ */
+DEFINE_INSN
+putundef
+()
+()
+(VALUE val)
+{
+  val = Qundef;
+}
+
+/**
+  @c put
   @e put some object.
      i.e. Fixnum, true, false, nil, and so on.
   @j IuWFNguBi.e. Fixnum, true, false, nil, and so on.
@@ -1470,7 +1484,7 @@
     /* unreachable */
   }
   else{
-    val = thread_invoke_yield_cfunc(th, block, num, STACK_ADDR_FROM_TOP(num));
+    val = th_invoke_yield_cfunc(th, block, num, STACK_ADDR_FROM_TOP(num));
     POPN(num);
   }
 }
@@ -1486,6 +1500,12 @@
 (VALUE val)
 (VALUE val)
 {
+#if IGNORE_OPTIMIZE
+  if(reg_cfp->sp != reg_cfp->bp){
+    rb_bug("stack error (sp: %p, bp: %p)",
+           reg_cfp->sp, reg_cfp->bp);
+  }
+#endif
   YARV_CHECK_INTS();
   POP_CONTROL_STACK_FRAME(th);
   RESTORE_REGS();
@@ -1726,6 +1746,27 @@
   }
 }
 
+/**
+  @c optimize
+  @e check environment
+  @j check environment
+ */
+DEFINE_INSN
+opt_checkenv
+()
+()
+()
+{
+  if(GET_CFP()->bp != GET_DFP() + 1){
+    int i;
+    VALUE *new_dfp = GET_CFP()->bp - 1;
+    /* TODO: copy env and clean stack at creating env? */
+    *new_dfp = *GET_DFP();
+    SET_DFP(new_dfp);
+  }
+}
+
+
 /** simple functions */
 
 
@@ -2156,6 +2197,39 @@
   }
 }
 
+/**
+  @c optimize
+  @e optimized X<=Y.
+  @j K X<=YB
+ */
+DEFINE_INSN
+opt_le
+()
+(VALUE recv, VALUE obj)
+(VALUE val)
+{
+  if(FIXNUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED(FIXNUM_LT)){
+    long a = FIX2LONG(recv), b = FIX2LONG(obj);
+    
+    if (a <= b){
+      val = Qtrue;
+    }
+    else{
+      val = Qfalse;
+    }
+  }
+  else{
+    /* other */
+#ifdef YARV_AOT_COMPILED
+    val = rb_funcall(recv, idLE, 1, obj);
+#else
+    PUSH(recv); PUSH(obj);
+    tmp_id = idLE;
+    goto LABEL_IS_SC(start_init_in_send_for_opt_1);
+    /* TODO */
+#endif
+  }
+}
 
 /**
   @c optimize

Modified: trunk/lib/cgi.rb
===================================================================
--- trunk/lib/cgi.rb	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/lib/cgi.rb	2005-12-03 11:37:46 UTC (rev 301)
@@ -1081,7 +1081,8 @@
     def read_from_cmdline
       require "shellwords"
 
-      string = unless ARGV.empty?
+      string =
+      unless ARGV.empty? && !$CGI_DONTINPUT
         ARGV.join(' ')
       else
         if STDIN.tty?

Modified: trunk/node.h
===================================================================
--- trunk/node.h	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/node.h	2005-12-03 11:37:46 UTC (rev 301)
@@ -124,6 +124,7 @@
     NODE_ATTRASGN,
     NODE_PRELUDE,
     NODE_LAMBDA,
+    NODE_OPTBLOCK,
     NODE_LAST
 };
 
@@ -340,6 +341,7 @@
 #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)
+#define NEW_OPTBLOCK(a) NEW_NODE(NODE_OPTBLOCK,a,0,0)
 
 #define NOEX_PUBLIC    0
 #define NOEX_NOSUPER   1

Modified: trunk/numeric.c
===================================================================
--- trunk/numeric.c	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/numeric.c	2005-12-03 11:37:46 UTC (rev 301)
@@ -11,7 +11,7 @@
 **********************************************************************/
 
 #include "ruby.h"
-#include "env.h"
+#include "yarv.h"
 #include <ctype.h>
 #include <math.h>
 #include <stdio.h>
@@ -180,7 +180,7 @@
 static VALUE
 num_sadded(VALUE x, VALUE name)
 {
-    ruby_frame = ruby_frame->prev; /* pop frame for "singleton_method_added" */
+  // ruby_frame = ruby_frame->prev; /* pop frame for "singleton_method_added" */
     /* Numerics should be values; singleton_methods should not be added to them */
     rb_raise(rb_eTypeError,
 	     "can't define singleton method \"%s\" for %s",
@@ -2729,24 +2729,51 @@
 static VALUE
 int_dotimes(VALUE num)
 {
-    if (FIXNUM_P(num)) {
-	long i, end;
+  if(1){
+    yarv_thread_t *th = GET_THREAD();
+    yarv_block_t *orig_block = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
 
-	end = FIX2LONG(num);
-	for (i=0; i<end; i++) {
-	    rb_yield(LONG2FIX(i));
-	}
+    if(BUILTIN_TYPE(orig_block->iseq) != T_NODE){
+      VALUE tsiseqval = yarv_iseq_special_block(orig_block->iseq, idTimes);
+      yarv_iseq_t *tsiseq;
+      VALUE argv[2], val;
+
+      if(tsiseqval){
+        yarv_block_t block = *orig_block;
+        GetISeqVal(tsiseqval, tsiseq);
+        block.iseq = tsiseq;
+        th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
+        argv[0] = INT2FIX(0);
+        argv[1] = num;
+        val = th_invoke_yield(th, 2, argv);
+        if(val == Qundef){
+          return num;
+        }
+        else{
+          return val;
+        }
+      }
     }
-    else {
-	VALUE i = INT2FIX(0);
+  }
 
-	for (;;) {
-	    if (!RTEST(rb_funcall(i, '<', 1, num))) break;
-	    rb_yield(i);
-	    i = rb_funcall(i, '+', 1, INT2FIX(1));
-	}
+  if (FIXNUM_P(num)) {
+    long i, end;
+
+    end = FIX2LONG(num);
+    for (i=0; i<end; i++) {
+      rb_yield(LONG2FIX(i));
     }
-    return num;
+  }
+  else {
+    VALUE i = INT2FIX(0);
+
+    for (;;) {
+      if (!RTEST(rb_funcall(i, '<', 1, num))) break;
+      rb_yield(i);
+      i = rb_funcall(i, '+', 1, INT2FIX(1));
+    }
+  }
+  return num;
 }
 
 /*

Modified: trunk/opt_operand.def
===================================================================
--- trunk/opt_operand.def	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/opt_operand.def	2005-12-03 11:37:46 UTC (rev 301)
@@ -8,13 +8,25 @@
 #
 
 getlocal 2
+getlocal 3
+getlocal 4
+
 setlocal 2
-getlocal 3
 setlocal 3
+setlocal 4
 
 getdynamic *, 0
 getdynamic 1, 0
+getdynamic 2, 0
+getdynamic 3, 0
+getdynamic 4, 0
 
+setdynamic *, 0
+setdynamic 1, 0
+setdynamic 2, 0
+setdynamic 3, 0
+setdynamic 4, 0
+
 putobject INT2FIX(0)
 putobject INT2FIX(1)
 putobject Qtrue

Modified: trunk/range.c
===================================================================
--- trunk/range.c	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/range.c	2005-12-03 11:37:46 UTC (rev 301)
@@ -366,41 +366,66 @@
  *     10 11 12 13 14 15
  */
 
+#include "yarv.h"
+
 static VALUE
 range_each(VALUE range)
 {
-    VALUE beg, end;
+  VALUE beg, end;
 
-    RETURN_ENUMERATOR(range, 0, 0);
+  RETURN_ENUMERATOR(range, 0, 0);
 
-    beg = rb_ivar_get(range, id_beg);
-    end = rb_ivar_get(range, id_end);
+  beg = rb_ivar_get(range, id_beg);
+  end = rb_ivar_get(range, id_end);
+  
+  if(1){
+    yarv_thread_t *th = GET_THREAD();
+    yarv_block_t *orig_block = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
 
-    if (!rb_respond_to(beg, id_succ)) {
-	rb_raise(rb_eTypeError, "can't iterate from %s",
-		 rb_obj_classname(beg));
+    if(BUILTIN_TYPE(orig_block->iseq) != T_NODE){
+      ID id = EXCL(range) ? idRangeEachLT : idRangeEachLE;
+      VALUE tsiseqval = yarv_iseq_special_block(orig_block->iseq, id);
+      yarv_iseq_t *tsiseq;
+      VALUE argv[2];
+
+      if(tsiseqval){
+        yarv_block_t block = *orig_block;
+        GetISeqVal(tsiseqval, tsiseq);
+        block.iseq = tsiseq;
+        th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
+        argv[0] = beg;
+        argv[1] = end;
+        th_invoke_yield(th, 2, argv);
+        return range;
+      }
     }
-    if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
-	long lim = FIX2LONG(end);
-	long i;
+  }
+  
+  if (!rb_respond_to(beg, id_succ)) {
+    rb_raise(rb_eTypeError, "can't iterate from %s",
+             rb_obj_classname(beg));
+  }
+  if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
+    long lim = FIX2LONG(end);
+    long i;
 
-	if (!EXCL(range)) lim += 1;
-	for (i=FIX2LONG(beg); i<lim; i++) {
-	    rb_yield(LONG2NUM(i));
-	}
+    if (!EXCL(range)) lim += 1;
+    for (i=FIX2LONG(beg); i<lim; i++) {
+      rb_yield(LONG2NUM(i));
     }
-    else if (TYPE(beg) == T_STRING) {
-	VALUE args[5];
-	long iter[2];
+  }
+  else if (TYPE(beg) == T_STRING) {
+    VALUE args[5];
+    long iter[2];
 
-	args[0] = beg; args[1] = end; args[2] = range;
-	iter[0] = 1; iter[1] = 1;
-	rb_iterate(str_step, (VALUE)args, step_i, (VALUE)iter);
-    }
-    else {
-	range_each_func(range, each_i, beg, end, NULL);
-    }
-    return range;
+    args[0] = beg; args[1] = end; args[2] = range;
+    iter[0] = 1; iter[1] = 1;
+    rb_iterate(str_step, (VALUE)args, step_i, (VALUE)iter);
+  }
+  else {
+    range_each_func(range, each_i, beg, end, NULL);
+  }
+  return range;
 }
 
 /*

Modified: trunk/rb/insns2vm.rb
===================================================================
--- trunk/rb/insns2vm.rb	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/rb/insns2vm.rb	2005-12-03 11:37:46 UTC (rev 301)
@@ -862,6 +862,8 @@
       val
     when /^ID/
       "INT2FIX(#{val})"
+    when /^BLOCKISEQ/
+      val
     when /GENTRY/
       raise
     when /^\.\.\./

Modified: trunk/test.rb
===================================================================
--- trunk/test.rb	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/test.rb	2005-12-03 11:37:46 UTC (rev 301)
@@ -1,167 +1,82 @@
-module QueryExtension
-  
-  %w[ CONTENT_LENGTH SERVER_PORT ].each do |env|
-    sym = env.sub(/^HTTP_/n, '').downcase
-    p sym
-    define_method(sym.to_sym){|e|
-      (val = env_table[env]) && Integer(val)
-    }
-  end
-end
+r = (1..3)
+p r.map{|e|
+  e+1
+}
 
 __END__
-class Object
-  define_method(:m){|a|
-    p [a, self]
+i=:foo
+prs = []
+3.times{|e|
+  prs << lambda{
+    p i
+    p e
   }
-end
+}
 
-ary = [1,2,3]
-m(ary)
-p 1
+prs.each{|pr|
+  pr.call
+}
 
-__send__ :m, 1
 
 __END__
+3.times{
+  p :a
+  class C
+    p :b
+    next
+  end
+  p :d
+}
+p :e
 
-require 'optparse'
-require 'optparse/time'
-require 'ostruct'
-require 'pp'
+__END__
 
-class OptparseExample
+p 3.times{|bl|
+  break 10
+}
 
-  CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary]
-  CODE_ALIASES = {"jis" => "iso-2022-jp", "sjis" => "shift_jis"}
+__END__
 
-  #
-  # Return a structure describing the options.
-  #
-  def self.parse(args)
-    # The options specified on the command line will be collected in *options*.
-    # We set default values here.
-    options = OpenStruct.new
-    options.library = []
-    options.inplace = false
-    options.encoding = "utf8"
-    options.transfer_type = :auto
-    options.verbose = false
-
-    opts = OptionParser.new do |opts|
-      opts.banner = "Usage: example.rb [options]"
-
-      opts.separator ""
-      opts.separator "Specific options:"
-
-      # Mandatory argument.
-      opts.on("-r", "--require LIBRARY",
-              "Require the LIBRARY before executing your script") do |lib|
-        options.library << lib
-      end
-
-      # Optional argument; multi-line description.
-      opts.on("-i", "--inplace [EXTENSION]",
-              "Edit ARGV files in place",
-              "  (make backup if EXTENSION supplied)") do |ext|
-        options.inplace = true
-        options.extension = ext || ''
-        options.extension.sub!(/\A\.?(?=.)/, ".")  # Ensure extension begins with dot.
-      end
-
-      # Cast 'delay' argument to a Float.
-      opts.on("--delay N", Float, "Delay N seconds before executing") do |n|
-        options.delay = n
-      end
-
-      # Cast 'time' argument to a Time object.
-      opts.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
-        options.time = time
-      end
-
-      # Cast to octal integer.
-      opts.on("-F", "--irs [OCTAL]", OptionParser::OctalInteger,
-              "Specify record separator (default \\0)") do |rs|
-        options.record_separator = rs
-      end
-
-      # List of arguments.
-      opts.on("--list x,y,z", Array, "Example 'list' of arguments") do |list|
-        options.list = list
-      end
-
-      # Keyword completion.  We are specifying a specific set of arguments (CODES
-      # and CODE_ALIASES - notice the latter is a Hash), and the user may provide
-      # the shortest unambiguous text.
-      code_list = (CODE_ALIASES.keys + CODES).join(',')
-      opts.on("--code CODE", CODES, CODE_ALIASES, "Select encoding",
-              "  (#{code_list})") do |encoding|
-        options.encoding = encoding
-      end
-
-      # Optional argument with keyword completion.
-      opts.on("--type [TYPE]", [:text, :binary, :auto], "Select transfer type (text, binary, auto)") do |t|
-        options.transfer_type = t
-      end
-
-      # Boolean switch.
-      opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
-        options.verbose = v
-      end
-
-      opts.separator ""
-      opts.separator "Common options:"
-
-      # No argument, shows at tail.  This will print an options summary.
-      # Try it and see!
-      opts.on_tail("-h", "--help", "Show this message") do
-        puts opts
-        exit
-      end
-
-      # Another typical switch to print the version.
-      opts.on_tail("--version", "Show version") do
-        puts OptionParser::Version.join('.')
-        exit
-      end
-    end
-
-    opts.parse!(args)
-    options
-  end  # parse()
-
-end  # class OptparseExample
-
-1000.times{|i|
-  p i
-  options = OptparseExample.parse(ARGV)
+3.times{|e|
+  p e
+  next if e < 1
+  p self
 }
 
 
 __END__
-1.times{|i|
-  p i
+i = 0
+while i<30000000 # benchmark loop 1
+  i+=1
+end
+__END__
+30000000.times{|i|
 }
-  
 
 __END__
-prs = []
 3.times{|i|
-  a = i+1
-  b = i*2
-  prs << lambda{p [a, b]}
+  4.times{|j|
+    p [i, j]
+  }
+  5.times{|j|
+    p [i, j]
+  }
 }
-prs.each{|pr|
-  pr.call
-}
+__END__
+  
 
+1.times{
+  max = 30000000
+  max.times{}
+  # i=0; while i<max; i=i.succ; end
+}
 __END__
-prs = []
-1.times{|e|
-3.times{|e|
-  prs << lambda{p e}
+3.times{
 }
-}
-prs.each{|pr|
-  pr.call
-}
+__END__
 
+i=0
+while i<3
+  i+=1
+end
+

Modified: trunk/vm.c
===================================================================
--- trunk/vm.c	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/vm.c	2005-12-03 11:37:46 UTC (rev 301)
@@ -26,8 +26,8 @@
 void vm_analysis_insn(int insn);
 
 static inline VALUE
-thread_invoke_yield_cfunc(yarv_thread_t *th,
-                          yarv_block_t *block, int argc, VALUE *argv);
+th_invoke_yield_cfunc(yarv_thread_t *th,
+                      yarv_block_t *block, int argc, VALUE *argv);
 
 VALUE th_eval_body(yarv_thread_t *th);
 
@@ -205,7 +205,7 @@
     env->env[i] = envptr[-local_size + i];
     if(cfp->iseq != 0 && !CMETHOD_INFO_P(cfp->iseq)){
       /* clear value stack for GC */
-      envptr[-local_size + i] = 0;
+      // envptr[-local_size + i] = 0;
     }
   }
 
@@ -493,8 +493,8 @@
 
 
 static inline VALUE
-thread_invoke_yield_cfunc(yarv_thread_t *th,
-                          yarv_block_t *block, int argc, VALUE *argv)
+th_invoke_yield_cfunc(yarv_thread_t *th,
+                      yarv_block_t *block, int argc, VALUE *argv)
 {
   NODE *ifunc = (NODE*)block->iseq;
   VALUE val;
@@ -572,7 +572,7 @@
       val = th_eval_body(th);
     }
     else{
-      val = thread_invoke_yield_cfunc(th, block, argc, argv);
+      val = th_invoke_yield_cfunc(th, block, argc, argv);
     }
   }
   return val;
@@ -621,7 +621,7 @@
     }
     else{
       rb_bug("thread_yield_light_prepare: unsupported ifunc");
-      //val = thread_invoke_yield_cfunc(th, block, argc, argv);
+      //val = th_invoke_yield_cfunc(th, block, argc, argv);
     }
   }
   return Qtrue;
@@ -666,7 +666,7 @@
                      int argc, VALUE *argv, VALUE self)
 {
   if(BUILTIN_TYPE(proc->block.iseq) == T_NODE){
-    return thread_invoke_yield_cfunc(th, &proc->block, argc, argv);
+    return th_invoke_yield_cfunc(th, &proc->block, argc, argv);
   }
   else{
     th_set_finish_env(th);
@@ -682,7 +682,7 @@
 th_invoke_proc(yarv_thread_t *th, yarv_proc_t *proc, int argc, VALUE *argv)
 {
   if(BUILTIN_TYPE(proc->block.iseq) == T_NODE){
-    return thread_invoke_yield_cfunc(th, &proc->block, argc, argv);
+    return th_invoke_yield_cfunc(th, &proc->block, argc, argv);
   }
   else{
     return th_invoke_proc_under(th, proc, argc, argv, proc->block.self);
@@ -1240,8 +1240,6 @@
     if(state == TAG_BREAK || state == TAG_RETURN){
       escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
 
-      // printf("%p, %p\n", escape_dfp, cfp->dfp);
-
       if(cfp->dfp == escape_dfp){
         if(state == TAG_RETURN){
           if((cfp+1)->pc != &yarv_finish_insn_seq[0]){
@@ -1374,17 +1372,14 @@
       /* enter catch scope */
       GetISeqVal(catch_iseqval, catch_iseq);
       cfp->sp = cfp->bp + cont_sp;
-
-      /* PUSH(throwed) */
-      *cfp->sp++ = err;
       cfp->pc = cfp->iseq->iseq_encoded + cont_pc;
 
       /* push block frame */
       th_set_env(th, catch_iseq,
                  FRAME_MAGIC_BLOCK, cfp->self, GC_GUARDED_PTR(cfp->dfp),
                  catch_iseq->iseq_encoded, cfp->sp, cfp->lfp,
-                 catch_iseq->local_size - 1, 0, 0);
-
+                 catch_iseq->local_size - 1, 1, &err);
+      
       state = 0;
       th->errinfo = Qnil;
       goto vm_loop_start;

Modified: trunk/vm_macro.def
===================================================================
--- trunk/vm_macro.def	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/vm_macro.def	2005-12-03 11:37:46 UTC (rev 301)
@@ -207,11 +207,14 @@
 
 MACRO macro_eval_invoke_bmethod(procval, recv, klass, blockptr, num)
 {
+  VALUE *sp  = GET_SP();
+  VALUE *rsp = sp - num - 1;
+
   yarv_proc_t *proc;
   GetProcVal(procval, proc);
 
   if(BUILTIN_TYPE(proc->block.iseq) == T_NODE){
-    val = thread_invoke_yield_cfunc(th, &proc->block, num, STACK_ADDR_FROM_TOP(num));
+    val = th_invoke_yield_cfunc(th, &proc->block, num, STACK_ADDR_FROM_TOP(num));
   }
   else{
     if(proc->block.iseq->argc != num){
@@ -222,6 +225,7 @@
                FRAME_MAGIC_PROC, recv, (VALUE)proc->block.dfp,
                proc->block.iseq->iseq_encoded, th->cfp->sp, proc->block.lfp,
                proc->block.iseq->local_size - num, 0, 0);
+    reg_cfp->sp = rsp;
     RESTORE_REGS();
   }
 }

Modified: trunk/yarvcore.c
===================================================================
--- trunk/yarvcore.c	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/yarvcore.c	2005-12-03 11:37:46 UTC (rev 301)
@@ -33,6 +33,7 @@
 ID idMOD;
 ID idLT;
 ID idLTLT;
+ID idLE;
 ID idEq;
 ID idEqq;
 ID idBackquote;
@@ -48,7 +49,11 @@
 ID idGets;
 ID idSucc;
 ID idEach;
+ID idRangeEachLT;
+ID idRangeEachLE;
+ID idArrayEach;
 ID idTimes;
+ID idEnd;
 ID idBitblt;
 ID idAnswer;
 
@@ -101,6 +106,8 @@
 #define MARK_UNLESS_NULL(ptr) if(ptr){rb_gc_mark(ptr);}
 #define FREE_UNLESS_NULL(ptr) if(ptr){ruby_xfree(ptr);}
 
+VALUE yarv_new_iseqval(VALUE node, VALUE name, VALUE file,
+                       VALUE parent, VALUE type, VALUE opt);
 
 /************/
 /* YARVCore */
@@ -181,7 +188,6 @@
 yarv_load(char *file)
 {
   NODE *node;
-  VALUE argv[5];
   volatile VALUE iseq;
   volatile int critical;
 
@@ -198,14 +204,10 @@
   if(ruby_nerrs > 0){
     return 0;
   }
-  
-  argv[0] = (VALUE)node;
-  argv[1] = rb_str_new2("<top (required)>");
-  argv[2] = rb_str_new2(file);
-  argv[3] = Qfalse;
-  argv[4] = ISEQ_TYPE_TOP;
-  iseq = rb_class_new_instance(5, argv, cYarvISeq);
 
+  iseq = yarv_new_iseqval((VALUE)node, rb_str_new2("<top (required)>"),
+                          rb_str_new2(file), Qfalse, ISEQ_TYPE_TOP, Qfalse);
+
   vm_eval(GET_VM()->self, iseq);
   return 0;
 }
@@ -282,25 +284,20 @@
 VALUE
 yarvcore_eval_parsed(VALUE node, VALUE file)
 {
-  VALUE argv[5];
+
   VALUE iseq;
-  
-  argv[0] = node;
-  argv[2] = file;
-  
+
   if(GET_THREAD()->base_block){
-    /* eval */
-    argv[1] = GET_THREAD()->base_block->iseq->name;
-    argv[3] = GET_THREAD()->base_block->iseq->self;
-    argv[4] = ISEQ_TYPE_EVAL;
+    iseq = yarv_new_iseqval(node,
+                            GET_THREAD()->base_block->iseq->name,
+                            file,
+                            GET_THREAD()->base_block->iseq->self,
+                            ISEQ_TYPE_EVAL, Qfalse);
   }
   else{
-    /* top */
-    argv[1] = rb_str_new2("<main>");
-    argv[3] = Qfalse;
-    argv[4] = ISEQ_TYPE_TOP;
+    iseq = yarv_new_iseqval(node, rb_str_new2("<main>"), file,
+                            Qfalse, ISEQ_TYPE_TOP, Qfalse);
   }
-  iseq = rb_class_new_instance(5, argv, cYarvISeq);
   return yarvcore_eval_iseq(iseq);
 }
 
@@ -312,20 +309,10 @@
   return yarvcore_eval_parsed(node, file);
 }
 
-static VALUE yarvcore_parse(VALUE self, VALUE str, VALUE file, VALUE line){
-  VALUE node;
-  VALUE argv[5];
-  VALUE iseq;
-  
-  node = compile_string(str, file, line);
-  
-  argv[0] = node;
-  argv[1] = rb_str_new2("<main>");
-  argv[2] = file;
-  argv[3] = Qfalse;
-  argv[4] = ISEQ_TYPE_TOP;
-  iseq = rb_class_new_instance(5, argv, cYarvISeq);
-  return iseq;
+static VALUE
+yarvcore_parse(VALUE self, VALUE str, VALUE file, VALUE line){
+  VALUE node = compile_string(str, file, line);
+  return yarv_new_iseqval(node, rb_str_new2("<main>"), file, Qfalse, ISEQ_TYPE_TOP, Qfalse);
 }
 
 
@@ -333,6 +320,20 @@
 /* InstructionSequence */
 /***********************/
 
+VALUE
+yarv_new_iseqval(VALUE node, VALUE name, VALUE file,
+                 VALUE parent, VALUE type, VALUE opt){
+  VALUE argv[6];
+  
+  argv[0] = node;
+  argv[1] = name;
+  argv[2] = file;
+  argv[3] = parent;
+  argv[4] = type;
+  argv[5] = opt;
+  return rb_class_new_instance(6, argv, cYarvISeq);
+}
+
 static void
 compile_data_free(struct iseq_compile_data *compile_data)
 {
@@ -389,6 +390,7 @@
     MARK_UNLESS_NULL(iseq->klass);
     MARK_UNLESS_NULL(iseq->catch_table_ary);
     MARK_UNLESS_NULL((VALUE)iseq->node);
+    MARK_UNLESS_NULL(iseq->cached_special_block);
     
     if(iseq->compile_data != 0){
       MARK_UNLESS_NULL(iseq->compile_data->mark_ary);
@@ -412,7 +414,7 @@
 static VALUE
 prepare_iseq_build(yarv_iseq_t *iseq,
                    VALUE name, VALUE file_name,
-                   VALUE parent, VALUE type)
+                   VALUE parent, VALUE type, VALUE opt)
 {
   iseq->name            = name;
   iseq->file_name       = file_name;
@@ -422,6 +424,11 @@
   iseq->arg_rest        = 0;
   iseq->arg_block       = 0;
   iseq->klass           = 0;
+  if(opt){
+    iseq->special_block_type = SYM2ID(opt);
+  }
+  iseq->cached_special_block_type = 0;
+  iseq->cached_special_block      = 0;
 
   /* set class nest stack */
   if(type == ISEQ_TYPE_CLASS){
@@ -483,14 +490,12 @@
 
 static VALUE
 iseq_init(VALUE self, VALUE node, VALUE name, VALUE file_name,
-          VALUE parent, VALUE type)
+          VALUE parent, VALUE type, VALUE opt)
 {
   yarv_iseq_t *iseq;
-  
   GetISeqVal(self, iseq);
-
   iseq->self = self;
-  prepare_iseq_build(iseq, name, file_name, parent, type);
+  prepare_iseq_build(iseq, name, file_name, parent, type, opt);
   iseq_compile(self, node);
   cleanup_iseq_build(iseq);
   return self;
@@ -870,8 +875,6 @@
   return Qnil;
 }
 
-VALUE yarv_Array_each();
-VALUE yarv_Integer_times();
 // VALUE yarv_Hash_each();
 VALUE insns_name_array();
 VALUE Init_yarvthread();
@@ -948,7 +951,7 @@
   /* declare YARVCore::InstructionSequence */
   cYarvISeq = rb_define_class_under(mYarvCore, "InstructionSequence", rb_cObject);
   rb_define_alloc_func(cYarvISeq, iseq_alloc);
-  rb_define_method(cYarvISeq, "initialize", iseq_init, 5);
+  rb_define_method(cYarvISeq, "initialize", iseq_init, 6);
   rb_define_method(cYarvISeq, "inspect",    iseq_inspect, 0);
   rb_define_method(cYarvISeq, "disasm",     iseq_disasm, 0);
   rb_define_method(cYarvISeq, "assemble",   iseq_assemble, 3);
@@ -989,9 +992,6 @@
   rb_define_global_function("yarv_caller", yarv_caller, 1);
   rb_define_global_function("SDR", sdr, 0);
   
-  /* Integer#times */
-  rb_define_method(rb_cInteger, "times", yarv_Integer_times, 0);
-  
   /* Array#each */
   // rb_define_method(rb_cArray, "each", yarv_Array_each, 0);
   /* Hash#each */
@@ -1008,6 +1008,7 @@
   idMOD  = rb_intern("%");
   idLT   = rb_intern("<");
   idLTLT = rb_intern("<<");
+  idLE   = rb_intern("<=");
   idEq   = rb_intern("==");
   idEqq  = rb_intern("===");
   idBackquote = rb_intern("`");
@@ -1022,7 +1023,10 @@
   idIntern = rb_intern("intern");
   idGets   = rb_intern("gets");
   idSucc   = rb_intern("succ");
-
+  idEnd    = rb_intern("end");
+  idRangeEachLT = rb_intern("Range#each#LT");
+  idRangeEachLE = rb_intern("Range#each#LE");
+  idArrayEach   = rb_intern("Array#each");
   idMethodMissing = rb_intern("method_missing");
 
   idThrowState     = rb_intern("#__ThrowState__");

Modified: trunk/yarvcore.h
===================================================================
--- trunk/yarvcore.h	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/yarvcore.h	2005-12-03 11:37:46 UTC (rev 301)
@@ -100,6 +100,7 @@
 extern ID idMOD;
 extern ID idLT;
 extern ID idLTLT;
+extern ID idLE;
 extern ID idEq;
 extern ID idEqq;
 extern ID idBackquote;
@@ -115,7 +116,11 @@
 extern ID idGets;
 extern ID idSucc;
 extern ID idEach;
+extern ID idRangeEachLT;
+extern ID idRangeEachLE;
+extern ID idArrayEach;
 extern ID idTimes;
+extern ID idEnd;
 extern ID idBitblt;
 extern ID idAnswer;
 
@@ -200,6 +205,10 @@
 
   NODE *node;
 
+  ID special_block_type;
+  ID cached_special_block_type;
+  VALUE cached_special_block;
+  
   /* sequence size */
   unsigned long size;
 

Deleted: trunk/yarvsubst.c
===================================================================
--- trunk/yarvsubst.c	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/yarvsubst.c	2005-12-03 11:37:46 UTC (rev 301)
@@ -1,54 +0,0 @@
-#include "yarv.h"
-
-/* Array#each */
-
-/*  
-VALUE yarv_Array_each(VALUE ary){
-  return rb_ary_each(ary);
-  long i;
-  for (i=0; i<RARRAY(ary)->len; i++) {
-    yarv_yield(RARRAY(ary)->ptr[i]);
-  }
-  return ary;
-}
-  */
-
-
-/* Integer#times */
-VALUE yarv_Integer_times(VALUE num){
-  if (FIXNUM_P(num)) {
-    long i, end;
-    
-    end = FIX2LONG(num);
-
-    if(IS_YARV_WORKING()){
-      /* yarv specific speedup tech */
-      VALUE th = yarv_get_current_running_thread_value();
-      VALUE val;
-      struct yarv_yield_data data;
-      
-      thread_yield_light_prepare(th, 1, &val, &data);
-      
-      for(i=0; i<end; i++){
-        val = LONG2FIX(i);
-        thread_yield_light_invoke(1, &val, &data);
-      }
-    }
-    else{
-      for (i=0; i<end; i++) {
-        rb_yield(LONG2FIX(i));
-      }
-    }
-  }
-  else {
-    VALUE i = INT2FIX(0);
-
-    for (;;) {
-      if (!RTEST(rb_funcall(i, '<', 1, num))) break;
-      rb_yield(i);
-      i = rb_funcall(i, '+', 1, INT2FIX(1));
-    }
-  }
-  return num;
-}
-

Deleted: trunk/yarvtest/test_syn.rb
===================================================================
--- trunk/yarvtest/test_syn.rb	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/yarvtest/test_syn.rb	2005-12-03 11:37:46 UTC (rev 301)
@@ -1,523 +0,0 @@
-require 'yarvtest/yarvtest'
-
-# test of syntax
-class TestSYNTAX < YarvTestBase
-
-  def test_if_unless
-    ae %q(if true  then 1 ; end)
-    ae %q(if false then 1 ; end)
-    ae %q(if true  then 1 ; else; 2; end)
-    ae %q(if false then 1 ; else; 2; end)
-    ae %q(if true  then   ; elsif true then ; 1 ; end)
-    ae %q(if false then   ; elsif true then ; 1 ; end)
-
-    ae %q(unless true  then 1 ; end)
-    ae %q(unless false then 1 ; end)
-    ae %q(unless true  then 1 ; else; 2; end)
-    ae %q(unless false then 1 ; else; 2; end)
-
-    ae %q(1 if true)
-    ae %q(1 if false)
-    ae %q(1 if nil)
-    
-    ae %q(1 unless true)
-    ae %q(1 unless false)
-    ae %q(1 unless nil)
-  end
-
-  def test_while_until
-    ae %q(
-      i = 0
-      while i < 10
-        i+=1
-      end)
-
-    ae %q(
-      i = 0
-      while i < 10
-        i+=1
-      end; i)
-
-    ae %q(
-      i = 0
-      until i > 10
-        i+=1
-      end)
-
-    ae %q(
-      i = 0
-      until i > 10
-        i+=1
-      end; i)
-    # 
-    ae %q{
-      i = 0
-      begin
-        i+=1
-      end while false
-      i
-    }
-    ae %q{
-      i = 0
-      begin
-        i+=1
-      end until true
-      i
-    }
-  end
-
-  def test_and
-    ae %q(1 && 2 && 3 && 4)
-    ae %q(1 && nil && 3 && 4)
-    ae %q(1 && 2 && 3 && nil)
-    ae %q(1 && 2 && 3 && false)
-
-    ae %q(1 and 2 and 3 and 4)
-    ae %q(1 and nil and 3 and 4)
-    ae %q(1 and 2 and 3 and nil)
-    ae %q(1 and 2 and 3 and false)
-    ae %q(nil && true)
-    ae %q(false && true)
-
-  end
-  
-  def test_or
-    ae %q(1 || 2 || 3 || 4)
-    ae %q(1 || false || 3 || 4)
-    ae %q(nil || 2 || 3 || 4)
-    ae %q(false || 2 || 3 || 4)
-    ae %q(nil || false || nil || false)
-
-    ae %q(1 or 2 or 3 or 4)
-    ae %q(1 or false or 3 or 4)
-    ae %q(nil or 2 or 3 or 4)
-    ae %q(false or 2 or 3 or 4)
-    ae %q(nil or false or nil or false)
-  end
-
-  def test_case
-    ae %q(
-      case 1
-      when 2
-        :ng
-      end)
-      
-    ae %q(
-      case 1
-      when 10,20,30
-        :ng1
-      when 1,2,3
-        :ok
-      when 100,200,300
-        :ng2
-      else
-        :elseng
-      end)
-    ae %q(
-      case 123
-      when 10,20,30
-        :ng1
-      when 1,2,3
-        :ng2
-      when 100,200,300
-        :ng3
-      else
-        :elseok
-      end
-    )
-    ae %q(
-      case 'test'
-      when /testx/
-        :ng1
-      when /test/
-        :ok
-      when /tetxx/
-        :ng2
-      else
-        :ng_else
-      end
-    )
-    ae %q(
-      case Object.new
-      when Object
-        :ok
-      end
-    )
-    ae %q(
-      case Object
-      when Object.new
-        :ng
-      else
-        :ok
-      end
-    )
-    ae %q{
-      case 'test'
-      when 'tes'
-        :ng
-      when 'te'
-        :ng
-      else
-        :ok
-      end
-    }
-    ae %q{
-      case 'test'
-      when 'tes'
-        :ng
-      when 'te'
-        :ng
-      when 'test'
-        :ok
-      end
-    }
-    ae %q{
-      case 'test'
-      when 'tes'
-        :ng
-      when /te/
-        :ng
-      else
-        :ok
-      end
-    }
-    ae %q{
-      case 'test'
-      when 'tes'
-        :ng
-      when /test/
-        :ok
-      else
-        :ng
-      end
-    }
-    ae %q{
-      def test(arg)
-        case 1
-        when 2
-          3
-        end
-        return arg
-      end
-      
-      test(100)
-    }
-  end
-
-  def test_case_splat
-    ae %q{
-      ary = [1, 2]
-      case 1
-      when *ary
-        :ok
-      else
-        :ng
-      end
-    }
-    ae %q{
-      ary = [1, 2]
-      case 3
-      when *ary
-        :ng
-      else
-        :ok
-      end
-    }
-    ae %q{
-      ary = [1, 2]
-      case 1
-      when :x, *ary
-        :ok
-      when :z
-        :ng1
-      else
-        :ng2
-      end
-    }
-    ae %q{
-      ary = [1, 2]
-      case 3
-      when :x, *ary
-        :ng1
-      when :z
-        :ng2
-      else
-        :ok
-      end
-    }
-  end
-
-  def test_when
-    ae %q(
-      case
-      when 1==2, 2==3
-        :ng1
-      when false, 4==5
-        :ok
-      when false
-        :ng2
-      else
-        :elseng
-      end)
-
-    ae %q(
-      case
-      when nil, nil
-        :ng1
-      when 1,2,3
-        :ok
-      when false, false
-        :ng2
-      else
-        :elseng
-      end)
-      
-    ae %q(
-      case
-      when nil
-        :ng1
-      when false
-        :ng2
-      else
-        :elseok
-      end)
-      
-    ae %q{
-      case
-      when 1
-      end
-    }
-  end
-
-  def test_when_splat
-    ae %q{
-      ary = []
-      case
-      when false, *ary
-        :ng
-      else
-        :ok
-      end
-    }
-    ae %q{
-      ary = [false, nil]
-      case
-      when *ary
-        :ng
-      else
-        :ok
-      end
-    }
-    ae %q{
-      ary = [false, nil]
-      case
-      when *ary
-        :ng
-      when true
-        :ok
-      else
-        :ng2
-      end
-    }
-    ae %q{
-      ary = [false, nil]
-      case
-      when *ary
-        :ok
-      else
-        :ng
-      end
-    }
-    ae %q{
-      ary = [false, true]
-      case
-      when *ary
-        :ok
-      else
-        :ng
-      end
-    }
-    ae %q{
-      ary = [false, true]
-      case
-      when false, false
-      when false, *ary
-        :ok
-      else
-        :ng
-      end
-    }
-  end
-
-  def test_flipflop
-    ae %q{
-      sum = 0
-      30.times{|ib|
-        if ib % 10 == 0 .. true
-          sum += ib
-        end
-      }
-      sum
-    }
-
-    ae %q{
-      sum = 0
-      30.times{|ib|
-        if ib % 10 == 0 ... true
-          sum += ib
-        end
-      }
-      sum
-    }
-  end
-
-  def test_defined_vars
-    ae %q{
-      defined?(nil) + defined?(self) +
-        defined?(true) + defined?(false)
-    }
-    #ae %q{
-    #  a = 1
-    #  defined?(a) # yarv returns "in block" in eval context
-    #}
-    ae %q{
-      defined?(@a)
-    }
-    ae %q{
-      @a = 1
-      defined?(@a)
-    }
-    ae %q{
-      defined?(@@a)
-    }
-    ae %q{
-      @@a = 1
-      defined?(@@a)
-    }
-    ae %q{
-      defined?($a)
-    }
-    ae %q{
-      $a = 1
-      defined?($a)
-    }
-    ae %q{
-      defined?(C_definedtest)
-    }
-    ae %q{
-      C_definedtest = 1
-      defined?(C_definedtest)
-    } do
-      remove_const :C_definedtest
-    end
-    
-    ae %q{
-      defined?(::C_definedtest)
-    }
-    ae %q{
-      C_definedtest = 1
-      defined?(::C_definedtest)
-    } do
-      remove_const :C_definedtest
-    end
-
-    ae %q{
-      defined?(C_definedtestA::C_definedtestB::C_definedtestC)
-    }
-    ae %q{
-      class C_definedtestA
-        class C_definedtestB
-          C_definedtestC = 1
-        end
-      end
-      defined?(C_definedtestA::C_definedtestB::C_definedtestC)
-    } do
-      remove_const :C_definedtestA
-    end
-  end
-
-  def test_defined_method
-    ae %q{
-      defined?(m)
-    }
-    ae %q{
-      def m
-      end
-      defined?(m)
-    }
-    
-    ae %q{
-      defined?(a.class)
-    }
-    ae %q{
-      a = 1
-      defined?(a.class)
-    }
-  end
-
-  def test_condition
-    ae %q{
-
-      def make_perm ary, num
-        if num == 1
-          ary.map{|e| [e]}
-        else
-          base = make_perm(ary, num-1)
-          res  = []
-          base.each{|b|
-            ary.each{|e|
-              res << [e] + b
-            }
-          }
-          res
-        end
-      end
-      
-      def each_test
-        conds = make_perm(['fv', 'tv'], 3)
-        bangs = make_perm(['', '!'], 3)
-        exprs = make_perm(['and', 'or'], 3)
-        ['if', 'unless'].each{|syn|
-          conds.each{|cs|
-            bangs.each{|bs|
-              exprs.each{|es|
-                yield(syn, cs, bs, es)
-              }
-            }
-          }
-        }
-      end
-      
-      fv = false
-      tv = true
-      
-      $ans = []
-      each_test{|syn, conds, bangs, exprs|
-        c1, c2, c3 = conds
-        bang1, bang2, bang3 = bangs
-        e1, e2 = exprs
-        eval %Q{
-          #{syn} #{bang1}#{c1} #{e1} #{bang2}#{c2} #{e2} #{bang3}#{c3}
-            $ans << :then
-          else
-            $ans << :false
-          end
-        }
-      }
-    
-      each_test{|syn, conds, bangs, exprs|
-        c1, c2, c3 = conds
-        bang1, bang2, bang3 = bangs
-        e1, e2 = exprs
-        eval %Q{
-          #{syn} #{bang1}#{c1} #{e1} #{bang2}#{c2} #{e2} #{bang3}#{c3}
-            $ans << :then
-          end
-          $ans << :sep
-        }
-      }
-      $ans
-    }
-  end
-end
-

Copied: trunk/yarvtest/test_syntax.rb (from rev 296, trunk/yarvtest/test_syn.rb)

Modified: trunk/yarvtest/yarvtest.rb
===================================================================
--- trunk/yarvtest/yarvtest.rb	2005-11-29 16:17:31 UTC (rev 300)
+++ trunk/yarvtest/yarvtest.rb	2005-12-03 11:37:46 UTC (rev 301)
@@ -61,10 +61,13 @@
   def exec exec_file, program
     dir = []
     dir << ENV['RAMDISK'] if ENV['RAMDISK']
-    tmpf = Tempfile.new('yarvtest', *dir)
+    tmpf = Tempfile.new("yarvtest_#{Process.pid}_#{Time.now.to_i}", *dir)
     tmpf.write program
     tmpf.close
-    `#{exec_file} #{tmpf.path}`
+    result = `#{exec_file} #{tmpf.path}`
+    tmpf.open
+    tmpf.close(true)
+    result
   end
   
   def exec_ exec_file, program


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

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