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

yarv-diff:184

From: ko1 atdot.net
Date: 29 Dec 2005 20:12:33 -0000
Subject: [yarv-diff:184] r342 - in trunk: . yarvtest

Author: ko1
Date: 2005-12-30 05:12:32 +0900 (Fri, 30 Dec 2005)
New Revision: 342

Added:
   trunk/yarvtest/test_eval.rb
Modified:
   trunk/ChangeLog
   trunk/common.mk
   trunk/eval.c
   trunk/eval_intern.h
   trunk/eval_load.c
   trunk/eval_method.h
   trunk/insnhelper.h
   trunk/insns.def
   trunk/test.rb
   trunk/vm.c
   trunk/vm_dump.c
   trunk/yarvcore.c
   trunk/yarvcore.h
   trunk/yarvtest/test_proc.rb
Log:
	* common.mk : add dependency (yarvcore.h) for gc.c

	* eval.c, eval_intern.h, eval_load.c, eval_method.h,
	insns.def, insnhelper.h, vm.c, yarvcore.c, yarvcore.h :
	re-write class reference

	* yarvtest/test_eval.rb : added

	* yarvtest/test_proc.rb : 



Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2005-12-29 03:29:26 UTC (rev 341)
+++ trunk/ChangeLog	2005-12-29 20:12:32 UTC (rev 342)
@@ -4,6 +4,19 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2005-12-30(Fri) 05:06:49 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* common.mk : add dependency (yarvcore.h) for gc.c
+
+	* eval.c, eval_intern.h, eval_load.c, eval_method.h,
+	insns.def, insnhelper.h, vm.c, yarvcore.c, yarvcore.h :
+	re-write class reference
+
+	* yarvtest/test_eval.rb : added
+
+	* yarvtest/test_proc.rb : 
+
+
 2005-12-29(Thu) 12:27:12 +0900  Koichi Sasada  <ko1 atdot.net>
 
 	* compile.c, yarvcore.h :

Modified: trunk/common.mk
===================================================================
--- trunk/common.mk	2005-12-29 03:29:26 UTC (rev 341)
+++ trunk/common.mk	2005-12-29 20:12:32 UTC (rev 342)
@@ -291,7 +291,7 @@
 gc.$(OBJEXT): {$(VPATH)}gc.c {$(VPATH)}ruby.h config.h \
   {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
   {$(VPATH)}rubysig.h {$(VPATH)}st.h {$(VPATH)}node.h \
-  {$(VPATH)}env.h {$(VPATH)}re.h {$(VPATH)}regex.h
+  {$(VPATH)}env.h {$(VPATH)}re.h {$(VPATH)}regex.h {$(VPATH)}yarvcore.h
 hash.$(OBJEXT): {$(VPATH)}hash.c {$(VPATH)}ruby.h config.h \
   {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
   {$(VPATH)}st.h {$(VPATH)}util.h {$(VPATH)}rubysig.h

Modified: trunk/eval.c
===================================================================
--- trunk/eval.c	2005-12-29 03:29:26 UTC (rev 341)
+++ trunk/eval.c	2005-12-29 20:12:32 UTC (rev 342)
@@ -409,19 +409,19 @@
  */
 
 static VALUE
-rb_mod_nesting()
+rb_mod_nesting(void)
 {
-    NODE *cbase = ruby_cref();
-    VALUE ary = rb_ary_new();
-
-    while (cbase && cbase->nd_next) {
-	if (!NIL_P(cbase->nd_clss)) rb_ary_push(ary, cbase->nd_clss);
-	cbase = cbase->nd_next;
+  VALUE ary = rb_ary_new();
+  VALUE cref = ruby_cref();
+  int i;
+  
+  for(i=0; i<RARRAY(cref)->len-1 /* exclude Object */; i++){
+    VALUE klass = rb_ary_entry(cref, -(i+1));
+    if(!NIL_P(klass)){
+      rb_ary_push(ary, klass);
     }
-    if (ruby_wrapper && RARRAY(ary)->len == 0) {
-	rb_ary_push(ary, ruby_wrapper);
-    }
-    return ary;
+  }
+  return ary;
 }
 
 /*
@@ -439,44 +439,48 @@
  */
 
 static VALUE
-rb_mod_s_constants()
+rb_mod_s_constants(void)
 {
-    NODE *cbase = ruby_cref();
-    void *data = 0;
-
-    while (cbase) {
-	if (!NIL_P(cbase->nd_clss)) {
-	    data = rb_mod_const_at(cbase->nd_clss, data);
-	}
-	cbase = cbase->nd_next;
+  VALUE cref = GET_THREAD()->cref_stack;
+  VALUE klass;
+  VALUE cbase = 0;
+  void *data = 0;
+  int i;
+  
+  for(i=0; i<RARRAY(cref)->len; i++){
+    klass = rb_ary_entry(cref, -(i+1));
+    if(!NIL_P(klass)){
+      data = rb_mod_const_at(klass, data);
+      if(cbase == 0){
+        cbase = klass;
+      }
     }
-
-    if (!NIL_P(ruby_cbase())) {
-	data = rb_mod_const_of(ruby_cbase(), data);
-    }
-    return rb_const_list(data);
+  }
+  if(cbase){
+    data = rb_mod_const_of(cbase, data);
+  }
+  return rb_const_list(data);
 }
 
 void
-rb_frozen_class_p(klass)
-    VALUE klass;
+rb_frozen_class_p(VALUE klass)
 {
-    char *desc = "something(?!)";
+  char *desc = "something(?!)";
 
-    if (OBJ_FROZEN(klass)) {
-	if (FL_TEST(klass, FL_SINGLETON))
-	    desc = "object";
-	else {
-	    switch (TYPE(klass)) {
-	      case T_MODULE:
-	      case T_ICLASS:
-		desc = "module"; break;
-	      case T_CLASS:
-		desc = "class"; break;
-	    }
-	}
-	rb_error_frozen(desc);
+  if (OBJ_FROZEN(klass)) {
+    if (FL_TEST(klass, FL_SINGLETON))
+      desc = "object";
+    else {
+      switch (TYPE(klass)) {
+      case T_MODULE:
+      case T_ICLASS:
+        desc = "module"; break;
+      case T_CLASS:
+        desc = "class"; break;
+      }
     }
+    rb_error_frozen(desc);
+  }
 }
 
 #ifdef C_ALLOCA
@@ -1836,10 +1840,13 @@
   if(!iseq){
     return 0;
   }
-  if(CMETHOD_INFO_P(iseq)){
+  if(YARV_CMETHOD_INFO_P(iseq)){
     struct yarv_cmethod_info *cmi = (void *)iseq;
     return cmi->id;
   }
+  else if(YARV_IFUNC_P(iseq)){
+    return rb_intern("<ifunc>");
+  }
   else{
     return rb_intern(RSTRING(iseq->name)->ptr);
   }
@@ -1874,8 +1881,7 @@
 const char *
 rb_sourcefile(void){
   yarv_iseq_t *iseq = GET_THREAD()->cfp->iseq;
-  if(iseq &&
-     !CMETHOD_INFO_P(iseq)){
+  if(YARV_NORMAL_ISEQ_P(iseq)){
     return RSTRING(iseq->file_name)->ptr;
   }
   return 0;
@@ -1924,7 +1930,9 @@
       th->base_block = &env->block;
     }
     else{
-      yarv_control_frame_t *cfp = YARV_PREVIOUS_CONTROL_FRAME(th->cfp);
+      
+      yarv_control_frame_t *cfp =
+        th_get_ruby_level_cfp(th, YARV_PREVIOUS_CONTROL_FRAME(th->cfp));
       th->base_block = GET_BLOCK_PTR_IN_CFP(cfp);
       th->base_block->iseq = cfp->iseq;
     }
@@ -2005,14 +2013,20 @@
     return eval(self, src, scope, file, line);
 }
 
+VALUE *th_cfp_svar(yarv_control_frame_t *cfp, int idx);
+
 /* function to call func under the specified class/module context */
 static VALUE
-exec_under(VALUE (*func) (VALUE), VALUE under, VALUE cbase, VALUE self, VALUE args)
+exec_under(VALUE (*func) (VALUE), VALUE under, VALUE cbase, VALUE self,
+           VALUE args, VALUE needcref)
 {
   VALUE val = Qnil;		/* OK */
   yarv_thread_t *th = GET_THREAD();
   yarv_control_frame_t *pcfp = YARV_PREVIOUS_CONTROL_FRAME(th->cfp);
   VALUE stored_self = pcfp->self;
+  VALUE stored_cref = 0;
+  VALUE *pcref = 0;
+
   yarv_block_t block;
   yarv_block_t *blockptr;
   int state;
@@ -2025,12 +2039,17 @@
     block.self = self;
     *th->cfp->lfp = GC_GUARDED_PTR(&block);
   }
-  if(cbase){
-    rb_thread_push_cref(th, cbase, NOEX_PUBLIC);
-    if(!CMETHOD_INFO_P(pcfp->iseq) &&
-       pcfp->iseq->klass_nest_stack){
-      rb_ary_push(pcfp->iseq->klass_nest_stack, cbase);
+
+  rb_thread_push_klass(th, under, cbase, NOEX_PUBLIC);
+  
+  if(cbase && needcref){
+    yarv_control_frame_t *cfp = th->cfp;
+    while(!YARV_NORMAL_ISEQ_P(cfp->iseq)){
+      cfp = YARV_PREVIOUS_CONTROL_FRAME(cfp);
     }
+    pcref = th_cfp_svar(cfp, -1);
+    stored_cref = *pcref;
+    *pcref = rb_ary_dup(th->cref_stack);
   }
 
   PUSH_TAG(PROT_NONE);
@@ -2040,13 +2059,10 @@
   POP_TAG();
 
   /* restore environment */
-  if(cbase){
-    rb_thread_pop_cref(th);
-    if(!CMETHOD_INFO_P(pcfp->iseq) &&
-       pcfp->iseq->klass_nest_stack){
-      rb_ary_pop(pcfp->iseq->klass_nest_stack);
-    }
+  if(pcref){
+    *pcref = stored_cref;
   }
+  rb_thread_pop_klass(th);
   pcfp->self = stored_self;
   
   if(state){
@@ -2065,7 +2081,7 @@
 static VALUE
 yield_under(VALUE under, VALUE self)
 {
-  return exec_under(yield_under_i, under, 0, self, self);
+  return exec_under(yield_under_i, under, 0, self, self, Qfalse);
 }
 
 static VALUE
@@ -2091,7 +2107,7 @@
   args[1] = src;
   args[2] = (VALUE)file;
   args[3] = (VALUE)line;
-  return exec_under(eval_under_i, under, under, self, (VALUE)args);
+  return exec_under(eval_under_i, under, under, self, (VALUE)args, Qtrue);
 }
 
 static VALUE

Modified: trunk/eval_intern.h
===================================================================
--- trunk/eval_intern.h	2005-12-29 03:29:26 UTC (rev 341)
+++ trunk/eval_intern.h	2005-12-29 20:12:32 UTC (rev 342)
@@ -245,12 +245,12 @@
 static int scope_vmode;
 
 #define SCOPE_TEST(f)   \
-  (FIX2INT(rb_ary_entry(GET_THREAD()->visibility_nest_stack, -1)) == f)
+  (FIX2INT(rb_ary_entry(GET_THREAD()->visibility_stack, -1)) == f)
 
 #define SCOPE_SET(f)  \
 { \
   yarv_thread_t *th = GET_THREAD(); \
-  rb_ary_store(th->visibility_nest_stack, -1, INT2FIX(f)); \
+  rb_ary_store(th->visibility_stack, -1, INT2FIX(f)); \
 }
 
 struct ruby_env {
@@ -287,4 +287,47 @@
 
 rb_thread_t rb_vm_curr_thread();
 
+
+VALUE th_get_cref(yarv_thread_t *th, yarv_iseq_t *iseq, yarv_control_frame_t *cfp);
+
+static yarv_control_frame_t *
+th_get_ruby_level_cfp(yarv_thread_t *th, yarv_control_frame_t *cfp)
+{
+  yarv_iseq_t *iseq = 0;
+  while(!YARV_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)){
+    if(YARV_NORMAL_ISEQ_P(cfp->iseq)){
+      iseq = cfp->iseq;
+      break;
+    }
+    cfp = YARV_PREVIOUS_CONTROL_FRAME(cfp);
+  }
+  if(!iseq){
+    rb_bug("th_get_ruby_level_cfp: unreachable");
+  }
+  return cfp;
+}
+
+static VALUE
+ruby_cref()
+{
+  yarv_thread_t *th = GET_THREAD();
+  yarv_control_frame_t *cfp = th_get_ruby_level_cfp(th, th->cfp);
+  return th_get_cref(th, cfp->iseq, cfp);
+}
+
+static VALUE
+ruby_cbase()
+{
+  VALUE cref = ruby_cref();
+  int i;
+
+  for(i=0; i<RARRAY(cref)->len; i++){
+    VALUE klass = rb_ary_entry(cref, -(i+1));
+    if(klass){
+      return klass;
+    }
+  }
+  return Qnil;
+}
+
 #endif /* EVAL_INTERN_H_INCLUDED */

Modified: trunk/eval_load.c
===================================================================
--- trunk/eval_load.c	2005-12-29 03:29:26 UTC (rev 341)
+++ trunk/eval_load.c	2005-12-29 20:12:32 UTC (rev 342)
@@ -114,15 +114,17 @@
   int state;
   volatile ID callee, this_func;
   volatile VALUE self = ruby_top_self;
-  volatile VALUE stored_klass_nest_stack;
-  volatile VALUE stored_visibility_nest_stack;
+  volatile VALUE stored_klass_stack;
+  volatile VALUE stored_cref_stack;
+  volatile VALUE stored_visibility_stack;
   yarv_thread_t *th = GET_THREAD();
 
-  stored_klass_nest_stack = th->klass_nest_stack;
-  stored_visibility_nest_stack = th->visibility_nest_stack;
+  stored_klass_stack      = th->klass_stack;
+  stored_cref_stack       = th->cref_stack;
+  stored_visibility_stack = th->visibility_stack;
 
   /* default visibility is private at loading toplevel */
-  th_cref_init(th);
+  th_klass_init(th);
 
   FilePathValue(fname);
   fname = rb_str_new4(fname);
@@ -148,8 +150,10 @@
   }
   POP_TAG();
 
-  th->klass_nest_stack = stored_klass_nest_stack;
-  th->visibility_nest_stack = stored_visibility_nest_stack;
+  
+  th->klass_stack      = stored_klass_stack;
+  th->cref_stack       = stored_cref_stack;
+  th->visibility_stack = stored_visibility_stack;
 
   if (ruby_nerrs > 0) {
     ruby_nerrs = 0;
@@ -349,24 +353,10 @@
 {
   VALUE result = Qnil;
   volatile VALUE errinfo = GET_THREAD()->errinfo;
-  VALUE stored_klass_nest_stack;
   yarv_thread_t *th = GET_THREAD();
   int state;
-  struct {
-    NODE *node;
-    ID this_func, callee;
-    int vmode, safe;
-  } volatile saved;
   char *volatile ftptr = 0;
-
-  /* store */
-  stored_klass_nest_stack = th->klass_nest_stack;
-  th->klass_nest_stack = rb_ary_push(rb_ary_new(), rb_cObject);
   
-  saved.vmode = scope_vmode;
-  saved.node = ruby_current_node;
-  saved.safe = ruby_safe_level;
-  
   PUSH_TAG(PROT_NONE);
   if ((state = EXEC_TAG()) == 0) {
     VALUE path;
@@ -410,16 +400,7 @@
     }
   }
   POP_TAG();
-
-  /* restore */
   
-  ruby_current_node = saved.node;
-  ruby_set_current_source();
-  SCOPE_SET(saved.vmode);
-  ruby_safe_level = saved.safe;
-  
-  th->klass_nest_stack = stored_klass_nest_stack;
-  
   if (ftptr) {
     if (st_delete(loading_tbl, (st_data_t *)&ftptr, 0)) { /* loading done */
       free(ftptr);
@@ -494,11 +475,13 @@
 static VALUE
 rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
 {
-  // TODO: fix me
-  return rb_mod_autoload(rb_cObject, sym, file);
+  VALUE klass = ruby_cbase();
+  if(NIL_P(klass)){
+    rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
+  }
+  return rb_mod_autoload(klass, sym, file);
 }
 
-
 /*
  * MISSING: documentation
  */
@@ -507,8 +490,11 @@
 rb_f_autoload_p(VALUE obj, VALUE sym)
 {
   /* use ruby_cbase() as same as rb_f_autoload. */
-  // TODO: fix me
-  return rb_mod_autoload_p(rb_cObject, sym);
+  VALUE klass = ruby_cbase();
+  if(NIL_P(klass)){
+    return Qnil;
+  }
+  return rb_mod_autoload_p(klass, sym);
 }
 
 void

Modified: trunk/eval_method.h
===================================================================
--- trunk/eval_method.h	2005-12-29 03:29:26 UTC (rev 341)
+++ trunk/eval_method.h	2005-12-29 20:12:32 UTC (rev 342)
@@ -393,36 +393,6 @@
   }
 }
 
-static VALUE
-ruby_cbase(){
-  yarv_thread_t *th = GET_THREAD();
-  yarv_control_frame_t *cfp = th->cfp;
-  yarv_iseq_t *iseq = 0;
-  VALUE cref;
-
-  while(YARV_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)){
-    if(!CMETHOD_INFO_P(cfp->iseq)){
-      iseq = cfp->iseq;
-      break;
-    }
-    cfp = YARV_PREVIOUS_CONTROL_FRAME(cfp);
-  }
-
-  if(iseq && iseq->klass_nest_stack){
-    cref = iseq->klass_nest_stack;
-  }
-  else{
-    cref = th->klass_nest_stack;
-  }
-  return rb_ary_entry(cref, -1);
-}
-
-static NODE *
-ruby_cref(){
-  UNSUPPORTED(ruby_cref());
-  return 0;
-}
-
 void
 rb_undef(VALUE klass, ID id)
 {

Modified: trunk/insnhelper.h
===================================================================
--- trunk/insnhelper.h	2005-12-29 03:29:26 UTC (rev 341)
+++ trunk/insnhelper.h	2005-12-29 20:12:32 UTC (rev 342)
@@ -124,33 +124,8 @@
 #define GET_GLOBAL(entry)       rb_gvar_get((struct global_entry*)entry)
 #define SET_GLOBAL(entry, val)  rb_gvar_set((struct global_entry*)entry, val)
 
-#define GET_EV_KLASS(klass)                                 \
-  if(GET_SELF() == ruby_top_self){                          \
-    klass = rb_cObject;                                     \
-  }                                                         \
-  else if(GET_ISEQ()->klass_nest_stack){                    \
-    /* method scope? */                                     \
-    klass = rb_ary_entry(GET_ISEQ()->klass_nest_stack, -1); \
-  }                                                         \
-  else{                                                     \
-    /* class scope? */                                      \
-    klass = GET_SELF();                                     \
-  }
+#define GET_KLASS() rb_ary_entry(th->klass_stack, -1)
 
-#define GET_CVAR_EV_KLASS(klass) \
-  VALUE cref; \
-  int i=-1; \
-  if(GET_ISEQ()->klass_nest_stack){ \
-    cref = GET_ISEQ()->klass_nest_stack; \
-  } \
-  else{ \
-    cref = th->klass_nest_stack; \
-  } \
-  while((klass = rb_ary_entry(cref, i--)) == Qnil || \
-        FL_TEST(klass, FL_SINGLETON)){ \
-    /* loop */ \
-  }
-
 /**********************************************************/
 /* deal with values                                       */
 /**********************************************************/

Modified: trunk/insns.def
===================================================================
--- trunk/insns.def	2005-12-29 03:29:26 UTC (rev 341)
+++ trunk/insns.def	2005-12-29 20:12:32 UTC (rev 342)
@@ -241,8 +241,7 @@
 ()
 (VALUE val)
 {
-  VALUE klass;
-  GET_CVAR_EV_KLASS(klass);
+  VALUE klass = eval_get_cvar_base(th, GET_ISEQ());
   val = rb_cvar_get(klass, id);
 }
 
@@ -257,8 +256,7 @@
 (VALUE val)
 ()
 {
-  VALUE klass;
-  GET_CVAR_EV_KLASS(klass);
+  VALUE klass = eval_get_cvar_base(th, GET_ISEQ());
   
   if(declp == Qtrue && RTEST(ruby_verbose) && FL_TEST(klass, FL_SINGLETON)) {
     rb_warn("declaring singleton class variable");
@@ -284,7 +282,7 @@
 (VALUE klass)
 (VALUE val)
 {
-  val = eval_get_ev_const(th, GET_ISEQ(), klass, id);
+  val = eval_get_ev_const(th, GET_ISEQ(), klass, id, 0);
 }
 
 /**
@@ -308,8 +306,12 @@
 ()
 {
   if(klass == Qnil){
-    klass = rb_ary_entry(th->klass_nest_stack, -1);
+    klass = th_get_cbase(th);
   }
+  if(NIL_P(klass)){
+    rb_raise(rb_eTypeError, "no class/module to define constant");
+  }
+  
   rb_const_set(klass, id, val);
   INC_VM_STATE_VERSION();
 }
@@ -833,12 +835,12 @@
   NODE *newbody;
   VALUE klass;
   yarv_iseq_t *miseq;
-  int noex = FIX2INT(rb_ary_entry(th->visibility_nest_stack, -1));
+  int noex = th_get_visibility(th);
 
   /* dup */
   GetISeqVal(body, miseq);
-  rb_ary_replace(miseq->klass_nest_stack, th->klass_nest_stack);
-  miseq->klass = rb_ary_entry(th->klass_nest_stack, -1);
+  rb_ary_replace(miseq->cref_stack, th->cref_stack);
+  miseq->klass = th_get_cbase(th);
 
   /* make new node */
   newbody = NEW_NODE(YARV_METHOD_NODE, NOEX_PUBLIC, body, 0);
@@ -848,12 +850,7 @@
   //printf("%s\n", body_name(nd_type(newbody)));
   //fflush(stdout);
 
-  if(BUILTIN_TYPE(GET_SELF()) == T_CLASS){
-    klass = GET_SELF();
-  }
-  else{
-    GET_EV_KLASS(klass);
-  }
+  klass = GET_KLASS();
 
   rb_add_method(klass, id, newbody, noex);
 
@@ -909,7 +906,7 @@
   }
   
   GetISeqVal(body, iseq);
-  rb_ary_replace(iseq->klass_nest_stack, th->klass_nest_stack);
+  rb_ary_replace(iseq->cref_stack, th->cref_stack);
   
   iseq->klass = CLASS_OF(obj);
   
@@ -938,7 +935,7 @@
     rb_alias_variable(id1, id2);
   }
   else{
-    GET_EV_KLASS(klass);
+    klass = GET_KLASS();
     rb_alias(klass, id1, id2);
   }
 }
@@ -955,8 +952,7 @@
 ()
 ()
 {
-  VALUE klass;
-  GET_EV_KLASS(klass);
+  VALUE klass = GET_KLASS();
   rb_undef(klass, id);
   INC_VM_STATE_VERSION();
 }
@@ -990,14 +986,14 @@
     }
     break;
   case DEFINED_CVAR:
-    GET_EV_KLASS(klass); /* TODO: it should be such as cvar_cbase */
+    klass = GET_KLASS();
     if(rb_cvar_defined(klass, SYM2ID(obj))){
       expr_type = "class variable";
     }
     break;
   case DEFINED_CONST:
     klass = v;
-    if(eval_get_ev_defined(th, GET_ISEQ(), klass, SYM2ID(obj))){
+    if(eval_get_ev_const(th, GET_ISEQ(), klass, SYM2ID(obj), 1)){
       expr_type = "constant";
     }
     break;
@@ -1093,7 +1089,7 @@
     super = rb_cObject;
   }
   if(cbase == Qnil){
-    cbase = rb_ary_entry(th->klass_nest_stack, -1);
+    cbase = th_get_cbase(th);
   }
 
   /* find klass */
@@ -1125,8 +1121,10 @@
              klass_iseq->iseq_encoded, GET_SP(), 0,
              klass_iseq->local_size, 0, 0);
   RESTORE_REGS();
+  
   /* others */
-  rb_thread_push_cref(th, klass, NOEX_PUBLIC);
+  rb_thread_push_klass(th, klass, klass, NOEX_PUBLIC);
+  rb_ary_replace(klass_iseq->cref_stack, th->cref_stack);
   
   INC_VM_STATE_VERSION();
   NEXT_INSN();
@@ -1158,7 +1156,8 @@
              klass_iseq->local_size, 0, 0);
   RESTORE_REGS();
   /* others */
-  rb_thread_push_cref(th, klass, NOEX_PUBLIC);
+  rb_thread_push_klass(th, klass, klass, NOEX_PUBLIC);
+  rb_ary_replace(klass_iseq->cref_stack, th->cref_stack);
 
   INC_VM_STATE_VERSION();
   NEXT_INSN();
@@ -1180,7 +1179,7 @@
   VALUE module;
   
   if(mbase == Qnil){
-    mbase = rb_ary_entry(th->klass_nest_stack, -1);
+    mbase = th_get_cbase(th);
   }
   
   /* find klass */
@@ -1207,7 +1206,8 @@
   RESTORE_REGS();
   
   /* others */
-  rb_thread_push_cref(th, module, NOEX_PUBLIC);
+  rb_thread_push_klass(th, module, module, NOEX_PUBLIC);
+  rb_ary_replace(module_iseq->cref_stack, th->cref_stack);
   
   INC_VM_STATE_VERSION();
   NEXT_INSN();
@@ -1224,7 +1224,7 @@
 ()
 ()
 {
-  rb_thread_pop_cref(th);
+  rb_thread_pop_klass(th);
 }
 
 

Modified: trunk/test.rb
===================================================================
--- trunk/test.rb	2005-12-29 03:29:26 UTC (rev 341)
+++ trunk/test.rb	2005-12-29 20:12:32 UTC (rev 342)
@@ -1,38 +1,25 @@
-Const = :top
-class C
-  Const = :C
-end
 
-$nest = false
-def m
-  p Const
-  C.module_eval %{
-    p Const
-    Boo = false
-    unless $nest
-      $nest = true
-      m
+class C
+#  private
+  $pr = proc{
+    def m
     end
   }
 end
 
-m
+$pr.call
+C.new.m
 
 __END__
 
-$nested = false
-$pr = proc{
-  p self
-  unless $nested
-    $nested = true
-    $pr.call
-  end
-}
-
+Const = :top
 class C
-  def initialize &b
-    10.instance_eval(&b)
-  end
+  Const = :C
 end
-
-C.new(&$pr)
+C.class_eval %{
+  Const
+  def m
+     Const
+  end
+}
+C.new.m

Modified: trunk/vm.c
===================================================================
--- trunk/vm.c	2005-12-29 03:29:26 UTC (rev 341)
+++ trunk/vm.c	2005-12-29 20:12:32 UTC (rev 342)
@@ -126,8 +126,6 @@
   yarv_iseq_t *iseq;
   GetISeqVal(iseqval, iseq);
 
-//  iseq->klass_nest_stack = rb_ary_push(rb_ary_new(), rb_cObject);
-
   /* for return */
   th_set_finish_env(th);
 
@@ -194,7 +192,7 @@
   envval = rb_obj_alloc(cYarvEnv);
   GetEnvVal(envval, env);
 
-  if(cfp->iseq == 0 || CMETHOD_INFO_P(cfp->iseq)){
+  if(!YARV_NORMAL_ISEQ_P(cfp->iseq)){
     local_size = 2;
   }
   else{
@@ -208,7 +206,7 @@
 
   for(i=0; i<=local_size; i++){
     env->env[i] = envptr[-local_size + i];
-    if(cfp->iseq != 0 && !CMETHOD_INFO_P(cfp->iseq)){
+    if(YARV_NORMAL_ISEQ_P(cfp->iseq)){
       /* clear value stack for GC */
       // envptr[-local_size + i] = 0;
     }
@@ -233,7 +231,7 @@
   env->block.dfp  = cfp->dfp;
   env->block.iseq = cfp->iseq;
 
-  if(cfp->iseq && CMETHOD_INFO_P(cfp->iseq)){
+  if(!YARV_NORMAL_ISEQ_P(cfp->iseq)){
     /* TODO */
     env->block.iseq = 0;
   }
@@ -370,17 +368,7 @@
   proc->envval       = envval;
 
   /* set cref */
-  if(BUILTIN_TYPE(block->iseq) != T_NODE){
-    if(cfp->iseq &&
-       BUILTIN_TYPE(cfp->iseq) != T_NODE &&
-       !CMETHOD_INFO_P(cfp->iseq) &&
-       cfp->iseq->klass_nest_stack){
-      block->iseq->klass_nest_stack = cfp->iseq->klass_nest_stack;
-    }
-    else if(block->iseq->klass_nest_stack == 0){
-      block->iseq->klass_nest_stack = rb_ary_dup(th->klass_nest_stack);
-    }
-  }
+  // TODO: store cref?
   return procval;
 }
 
@@ -635,9 +623,8 @@
 }
 
 VALUE *
-th_svar(yarv_thread_t *th, int cnt)
+th_cfp_svar(yarv_control_frame_t *cfp, int cnt)
 {
-  yarv_control_frame_t *cfp = th->cfp;
   NODE *node;
 
   while(cfp->pc == 0){
@@ -648,8 +635,8 @@
 
   if((VALUE)node == Qnil){
     cfp->lfp[-1] = (VALUE)(node = NEW_IF(Qnil, Qnil, 0));
+    node->nd_file = 0;
   }
-  // printf("== %p, %p\n", node, &cfp->lfp[-1]);
   
   if(cnt == 0){
     return &node->u1.value;
@@ -657,6 +644,9 @@
   else if(cnt == 1){
     return &node->u2.value;
   }
+  else if(cnt == -1){
+    return (VALUE*)&node->nd_file;
+  }
   else{
     VALUE ary;
     if((ary = node->u3.value) == 0){
@@ -670,6 +660,13 @@
 }
 
 VALUE *
+th_svar(yarv_thread_t *th, int cnt)
+{
+  yarv_control_frame_t *cfp = th->cfp;
+  return th_cfp_svar(cfp, cnt);
+}
+
+VALUE *
 thread_svar(VALUE self, int cnt)
 {
   yarv_thread_t *th;
@@ -682,7 +679,7 @@
 {
   int line_no = 0;
   yarv_iseq_t *iseq = cfp->iseq;
-  if(iseq && !CMETHOD_INFO_P(iseq) && BUILTIN_TYPE(iseq) != T_NODE){
+  if(YARV_NORMAL_ISEQ_P(iseq)){
     int i;
     int pos = cfp->pc - cfp->iseq->iseq_encoded;
 
@@ -764,36 +761,75 @@
 }
 
 /*
- *
  * vm main loop helper functions
- *
  */
 
-
-EVALBODY_HELPER_FUNCTION
 VALUE
-eval_get_ev_const(yarv_thread_t *th,
-                  yarv_iseq_t *iseq, VALUE klass, ID id)
+th_get_cref(yarv_thread_t *th, yarv_iseq_t *iseq, yarv_control_frame_t *cfp)
 {
+  VALUE cref;
+  NODE *node;
+
+  if(((VALUE)(node = (NODE*)cfp->lfp[-1])) != Qnil &&
+     node->nd_file){
+    cref = (VALUE)node->nd_file;
+  }
+  else if(iseq->cref_stack){
+    cref = iseq->cref_stack;
+  }
+  else{
+    cref = th->cref_stack;
+    dp(cref);
+    rb_bug("th_get_cref: unreachable");
+  }
+  return cref;
+}
+
+static VALUE
+th_get_cbase(yarv_thread_t *th){
+  int i;
+  VALUE cref = th->cref_stack;
+  VALUE klass;
+  for(i=0; i<RARRAY(cref)->len; i++){
+    if((klass = rb_ary_entry(th->cref_stack, -(1+i))) != 0){
+      break;
+    }
+  }
+  return klass;
+}
+
+static int
+th_get_visibility(yarv_thread_t *th)
+{
+  return FIX2INT(rb_ary_entry(th->visibility_stack, -1));
+}
+
+EVALBODY_HELPER_FUNCTION VALUE
+eval_get_ev_const(yarv_thread_t *th, yarv_iseq_t *iseq,
+                  VALUE klass, ID id, int is_defined)
+{
   VALUE val;
   
   if(klass == Qnil){
     /* in current lexical scope */
-    VALUE cref; /* Array */
-    int i, last_pos;
+    VALUE cref = th_get_cref(th, iseq, th->cfp);
+    int i;
 
-    cref = iseq->klass_nest_stack;
-    if(cref == 0){
-      /* in module or class scope */
-      cref = th->klass_nest_stack;
-    }
-    
-    last_pos = RARRAY(cref)->len-1;
-    for(i = last_pos; i>0; i--){
-      klass = RARRAY(cref)->ptr[i];
-      if(NIL_P(klass)){
+    for(i = 0; i<RARRAY(cref)->len; i++){
+      klass = rb_ary_entry(cref, -(1+i));
+      if(klass == 0){
         continue;
       }
+      if(NIL_P(klass)){
+        if(is_defined){
+          /* TODO: check */
+          return 1;
+        }
+        else{
+          klass = CLASS_OF(th->cfp->self);
+          return rb_const_get(klass, id);
+        }
+      }
     search_continue:
       if(RCLASS(klass)->iv_tbl &&
          st_lookup(RCLASS(klass)->iv_tbl, id, &val)){
@@ -802,54 +838,56 @@
           goto search_continue;
         }
         else{
-          break;
+          if(is_defined){
+            return 1;
+          }
+          else{
+            return val;
+          }
         }
       }
     }
-    if(i==0){
-      klass = RARRAY(cref)->ptr[last_pos];
-      val = rb_const_get(klass, id);
+    klass = rb_ary_entry(cref, -1);
+    if(is_defined){
+      return rb_const_defined(klass, id);
     }
+    else{
+      return rb_const_get(klass, id);
+    }
   }
   else{
-    val = rb_const_get(klass, id);
+    if(is_defined){
+      return rb_const_defined(klass, id);
+    }
+    else{
+      return rb_const_get(klass, id);
+    }
   }
-  return val;
 }
 
-EVALBODY_HELPER_FUNCTION int
-eval_get_ev_defined(yarv_thread_t *th,
-                    yarv_iseq_t *iseq, VALUE klass, ID id)
-{
-  VALUE val;
-  if(klass == Qnil){
-    VALUE cref;
-    int i, last_pos;
-
-    if((cref = iseq->klass_nest_stack) == 0){
-      cref = th->klass_nest_stack;
+EVALBODY_HELPER_FUNCTION VALUE
+eval_get_cvar_base(yarv_thread_t *th, yarv_iseq_t *iseq){
+  VALUE cref = th_get_cref(th, iseq, th->cfp);
+  VALUE klass = Qnil;
+  int i;
+  
+  for(i=0; i<RARRAY(cref)->len; i++){
+    klass = rb_ary_entry(cref, -(i+1));
+    if(cref == 0){
+      continue;
     }
-    last_pos = RARRAY(cref)->len-1;
-    for(i = last_pos; i>0; i--){
-      klass = RARRAY(cref)->ptr[i];
-    search_continue:
-      if(RCLASS(klass)->iv_tbl &&
-         st_lookup(RCLASS(klass)->iv_tbl, id, &val)){
-        if(val == Qundef){
-          rb_autoload_load(klass, id);
-          goto search_continue;
-        }
-        else{
-          return 1;
-        }
+    if(NIL_P(cref) || FL_TEST(klass, FL_SINGLETON)){
+      if(RARRAY(cref)->len == i+1){
+        rb_warn("class variable access from toplevel singleton method");
       }
+      continue;
     }
-    klass = RARRAY(cref)->ptr[last_pos];
-    return rb_const_defined(klass, id);
+    break;
   }
-  else{
-    return rb_const_defined(klass, id);
+  if(NIL_P(klass)){
+    rb_raise(rb_eTypeError, "no class variables available");
   }
+  return klass;
 }
 
 EVALBODY_HELPER_FUNCTION VALUE
@@ -958,17 +996,19 @@
 }
 
 void
-rb_thread_push_cref(yarv_thread_t *th, VALUE klass, int noex)
+rb_thread_push_klass(yarv_thread_t *th, VALUE klass, VALUE cref, int noex)
 {
-  rb_ary_push(th->klass_nest_stack, klass);
-  rb_ary_push(th->visibility_nest_stack, INT2FIX(noex));
+  rb_ary_push(th->klass_stack, klass);
+  rb_ary_push(th->cref_stack, cref);
+  rb_ary_push(th->visibility_stack, INT2FIX(noex));
 }
 
 void
-rb_thread_pop_cref(yarv_thread_t *th)
+rb_thread_pop_klass(yarv_thread_t *th)
 {
-  rb_ary_pop(th->klass_nest_stack);
-  rb_ary_pop(th->visibility_nest_stack);
+  rb_ary_pop(th->klass_stack);
+  rb_ary_pop(th->cref_stack);
+  rb_ary_pop(th->visibility_stack);
 }
 
 static void
@@ -1333,7 +1373,7 @@
     else{
       /* pop cref */
       if(cfp->iseq->type == ISEQ_TYPE_CLASS){
-        rb_thread_pop_cref(th);
+        rb_thread_pop_klass(th);
       }
       
       th->cfp++;

Modified: trunk/vm_dump.c
===================================================================
--- trunk/vm_dump.c	2005-12-29 03:29:26 UTC (rev 341)
+++ trunk/vm_dump.c	2005-12-29 20:12:32 UTC (rev 342)
@@ -47,11 +47,11 @@
   }
 
   if(cfp->iseq != 0){
-    if(CMETHOD_INFO_P(cfp->iseq)){
+    if(YARV_CMETHOD_INFO_P(cfp->iseq)){
       struct yarv_cmethod_info *cmi = (void *)cfp->iseq;
       iseq_name = rb_id2name(cmi->id);
     }
-    else if(BUILTIN_TYPE(cfp->iseq) == T_NODE){
+    else if(YARV_IFUNC_P(cfp->iseq)){
       iseq_name = "<ifunc>";
     }
     else{
@@ -168,12 +168,17 @@
     name = "?";
     local_size = 0;
   }
-  else if(CMETHOD_INFO_P(iseq)){
+  else if(YARV_CMETHOD_INFO_P(iseq)){
     struct yarv_cmethod_info *cmi = (void *)iseq;
     argc       = 0;
     local_size = 0;
     name       = rb_id2name(cmi->id);
   }
+  else if(YARV_IFUNC_P(iseq)){
+    argc       = 0;
+    local_size = 0;
+    name       = "<ifunc>";
+  }
   else{
     argc       = iseq->argc;
     local_size = iseq->local_size;
@@ -242,7 +247,7 @@
   int dfp = cfp->dfp - th->stack;
   int cfpi;
 
-  if(cfp->iseq && !CMETHOD_INFO_P(cfp->iseq)){
+  if(YARV_NORMAL_ISEQ_P(cfp->iseq)){
     pc = cfp->pc - cfp->iseq->iseq_encoded;
   }
 

Modified: trunk/yarvcore.c
===================================================================
--- trunk/yarvcore.c	2005-12-29 03:29:26 UTC (rev 341)
+++ trunk/yarvcore.c	2005-12-29 20:12:32 UTC (rev 342)
@@ -387,7 +387,7 @@
     MARK_UNLESS_NULL(iseq->iseq_mark_ary);
     MARK_UNLESS_NULL(iseq->name);
     MARK_UNLESS_NULL(iseq->file_name);
-    MARK_UNLESS_NULL(iseq->klass_nest_stack);
+    MARK_UNLESS_NULL(iseq->cref_stack);
     MARK_UNLESS_NULL(iseq->klass);
     MARK_UNLESS_NULL(iseq->catch_table_ary);
     MARK_UNLESS_NULL((VALUE)iseq->node);
@@ -430,19 +430,17 @@
   iseq->cached_special_block         = 0;
 
   /* set class nest stack */
-  if(type == ISEQ_TYPE_CLASS){
-    iseq->klass_nest_stack = 0;
+  if(type == ISEQ_TYPE_TOP){
+    iseq->cref_stack = rb_ary_push(rb_ary_new(), rb_cObject);
   }
-  else if(type == ISEQ_TYPE_TOP){
-    iseq->klass_nest_stack = 0;
+  else if(type == ISEQ_TYPE_METHOD ||
+          type == ISEQ_TYPE_CLASS){
+    iseq->cref_stack = rb_ary_new();
   }
-  else if(type == ISEQ_TYPE_METHOD){
-    iseq->klass_nest_stack = rb_ary_new();
-  }
   else if(parent){
     yarv_iseq_t *piseq;
     GetISeqVal(parent, piseq);
-    iseq->klass_nest_stack = piseq->klass_nest_stack;
+    iseq->cref_stack = piseq->cref_stack;
   }
   
   iseq->compile_data = ALLOC(struct iseq_compile_data);
@@ -650,8 +648,9 @@
     }
 
     /* mark ruby objects */
-    MARK_UNLESS_NULL(th->klass_nest_stack);
-    MARK_UNLESS_NULL(th->visibility_nest_stack);
+    MARK_UNLESS_NULL(th->klass_stack);
+    MARK_UNLESS_NULL(th->cref_stack);
+    MARK_UNLESS_NULL(th->visibility_stack);
 
     MARK_UNLESS_NULL(th->first_proc);
     MARK_UNLESS_NULL(th->first_args);
@@ -708,17 +707,18 @@
 }
 
 void
-th_cref_init(yarv_thread_t *th)
+th_klass_init(yarv_thread_t *th)
 {
-  th->klass_nest_stack = rb_ary_push(rb_ary_new(), rb_cObject);
-  th->visibility_nest_stack = rb_ary_push(rb_ary_new(), INT2FIX(NOEX_PRIVATE));
+  th->klass_stack      = rb_ary_push(rb_ary_new(), rb_cObject);
+  th->cref_stack       = rb_ary_push(rb_ary_new(), rb_cObject);
+  th->visibility_stack = rb_ary_push(rb_ary_new(), INT2FIX(NOEX_PRIVATE));
 }
 
 static void
 th_init(yarv_thread_t *th)
 {
   th_init2(th);
-  th_cref_init(th);
+  th_klass_init(th);
 }
 
 static VALUE

Modified: trunk/yarvcore.h
===================================================================
--- trunk/yarvcore.h	2005-12-29 03:29:26 UTC (rev 341)
+++ trunk/yarvcore.h	2005-12-29 20:12:32 UTC (rev 342)
@@ -249,7 +249,7 @@
   int stack_max;
 
   /* klass/module nest information stack (cref) */
-  VALUE klass_nest_stack; /* Array */
+  VALUE cref_stack; /* Array */
   VALUE klass;
 
   /* catch table */
@@ -355,8 +355,9 @@
   yarv_block_t *passed_block;
 
   /* klass/module nest information stack */
-  VALUE klass_nest_stack; /* Array */
-  VALUE visibility_nest_stack; /* Array */
+  VALUE klass_stack;
+  VALUE cref_stack;
+  VALUE visibility_stack;
 
   /* passed via parse.y, eval.c (rb_scope_setup_local_tbl) */
   ID *top_local_tbl;
@@ -472,7 +473,10 @@
 #define YARV_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp) \
   ((th)->stack + (th)->stack_size < (VALUE *)cfp)
 
-#define CMETHOD_INFO_P(ptr) (*((VALUE*)(ptr)) == 0)
+#define YARV_CMETHOD_INFO_P(ptr) (*((VALUE*)(ptr)) == 0)
+#define YARV_IFUNC_P(ptr)        (BUILTIN_TYPE(ptr) == T_NODE)
+#define YARV_NORMAL_ISEQ_P(ptr) \
+  (ptr && !YARV_CMETHOD_INFO_P(ptr) && !YARV_IFUNC_P(ptr))
 
 struct yarv_cmethod_info{
   VALUE sig; /* must be null */
@@ -500,10 +504,10 @@
 #define SDR()     vm_stack_dump_raw(GET_THREAD(), GET_THREAD()->cfp)
 #define SDR2(cfp) vm_stack_dump_raw(GET_THREAD(), (cfp))
 
+void rb_thread_push_klass(yarv_thread_t *th,
+                          VALUE klass, VALUE cref, int noex);
+void rb_thread_pop_klass(yarv_thread_t *th);
 
-void rb_thread_push_cref(yarv_thread_t *th, VALUE klass, int noex);
-void rb_thread_pop_cref(yarv_thread_t *th);
-
 /* for thread */
 
 #include "yarv.h"

Added: trunk/yarvtest/test_eval.rb
===================================================================
--- trunk/yarvtest/test_eval.rb	2005-12-29 03:29:26 UTC (rev 341)
+++ trunk/yarvtest/test_eval.rb	2005-12-29 20:12:32 UTC (rev 342)
@@ -0,0 +1,139 @@
+require 'yarvtest/yarvtest'
+
+class TestEval < YarvTestBase
+  def test_eval
+    ae %q{
+      eval('1')
+    }
+    ae %q{
+      eval('a=1; a')
+    }
+    ae %q{
+      a = 1
+      eval('a')
+    }
+  end
+
+  def test_eval_with_send
+    ae %q{
+      __send__ :eval, %{
+        :ok
+      }
+    }
+    ae %q{
+      1.__send__ :instance_eval, %{
+        :ok
+      }
+    }
+  end
+
+  def test_module_eval
+    ae %q{
+      Const = :top
+      class C
+        Const = :C
+      end
+      C.module_eval{
+        Const
+      }
+    }
+    ae %q{
+      Const = :top
+      class C
+        Const = :C
+      end
+      C.module_eval %{
+        Const
+      }
+    } if false # TODO: Ruby 1.9 error
+
+    ae %q{
+      Const = :top
+      class C
+        Const = :C
+      end
+      C.class_eval %{
+        def m
+          Const
+        end
+      }
+      C.new.m
+    }
+    ae %q{
+      Const = :top
+      class C
+        Const = :C
+      end
+      C.class_eval{
+        def m
+          Const
+        end
+      }
+      C.new.m
+    }
+  end
+
+  def test_instance_eval
+    ae %q{
+      1.instance_eval{
+        self
+      }
+    }
+    ae %q{
+      'foo'.instance_eval{
+        self
+      }
+    }
+    ae %q{
+      class Fixnum
+        Const = 1
+      end
+      1.instance_eval %{
+        p Const
+      }
+    }
+  end
+  
+  def test_nest_eval
+    ae %q{
+      Const = :top
+      class C
+        Const = :C
+      end
+      $nest = false
+      $ans = []
+      def m
+        $ans << Const
+        C.module_eval %{
+          $ans << Const
+          Boo = false
+          unless $nest
+            $nest = true
+            m
+          end
+        }
+      end
+      m
+      $ans
+    }
+    ae %q{
+      $nested = false
+      $ans = []
+      $pr = proc{
+        $ans << self
+        unless $nested
+          $nested = true
+          $pr.call
+        end
+      }
+      class C
+        def initialize &b
+          10.instance_eval(&b)
+        end
+      end
+      C.new(&$pr)
+      $ans
+    }
+  end
+end
+

Modified: trunk/yarvtest/test_proc.rb
===================================================================
--- trunk/yarvtest/test_proc.rb	2005-12-29 03:29:26 UTC (rev 341)
+++ trunk/yarvtest/test_proc.rb	2005-12-29 20:12:32 UTC (rev 342)
@@ -6,7 +6,6 @@
       def m(&b)
         b
       end
-
       m{1}.call
     }
 
@@ -115,6 +114,21 @@
     }
   end
 
+  def test_proc_with_cref
+    ae %q{
+      Const = :top
+      class C
+        Const = :C
+        $pr = proc{
+          (1..2).map{
+            Const
+          }
+        }
+      end
+      $pr.call
+    }
+  end
+  
   def test_3nest
     ae %q{
       def getproc &b


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

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