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