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