Revision: 1152 http://trac.macosforge.org/projects/ruby/changeset/1152 Author: lsansonetti@apple.com Date: 2009-03-25 17:55:06 -0700 (Wed, 25 Mar 2009) Log Message: ----------- fixed bugs in const lookup Modified Paths: -------------- MacRuby/branches/experimental/class.c MacRuby/branches/experimental/roxor.cpp MacRuby/branches/experimental/roxor.h MacRuby/branches/experimental/test_roxor.rb MacRuby/branches/experimental/variable.c Modified: MacRuby/branches/experimental/class.c =================================================================== --- MacRuby/branches/experimental/class.c 2009-03-26 00:54:43 UTC (rev 1151) +++ MacRuby/branches/experimental/class.c 2009-03-26 00:55:06 UTC (rev 1152) @@ -372,6 +372,7 @@ RCLASS_SET_VERSION(klass, v); } RCLASS_SET_VERSION_FLAG(klass, RCLASS_IS_SINGLETON); + rb_vm_set_outer(klass, rb_cNSObject); rb_singleton_class_attached(klass, obj); Modified: MacRuby/branches/experimental/roxor.cpp =================================================================== --- MacRuby/branches/experimental/roxor.cpp 2009-03-26 00:54:43 UTC (rev 1151) +++ MacRuby/branches/experimental/roxor.cpp 2009-03-26 00:55:06 UTC (rev 1152) @@ -370,6 +370,11 @@ } }; +struct rb_vm_outer { + Class klass; + struct rb_vm_outer *outer; +}; + class RoxorVM { private: @@ -384,6 +389,7 @@ std::map<ID, struct ccache *> ccache; std::map<Class, std::map<ID, int> *> ivar_slots; std::map<SEL, GlobalVariable *> redefined_ops_gvars; + std::map<Class, struct rb_vm_outer *> outers; public: static RoxorVM *current; @@ -482,6 +488,21 @@ } int find_ivar_slot(VALUE klass, ID name, bool create); bool class_can_have_ivar_slots(VALUE klass); + + struct rb_vm_outer *get_outer(Class klass) { + std::map<Class, struct rb_vm_outer *>::iterator iter = + outers.find(klass); + return iter == outers.end() ? NULL : iter->second; + } + + void set_outer(Class klass, Class mod) { + struct rb_vm_outer *mod_outer = get_outer(mod); + struct rb_vm_outer *class_outer = (struct rb_vm_outer *) + malloc(sizeof(struct rb_vm_outer)); + class_outer->klass = klass; + class_outer->outer = mod_outer; + outers[klass] = class_outer; + } }; RoxorVM *RoxorVM::current = NULL; @@ -991,16 +1012,25 @@ Value * RoxorCompiler::compile_const(ID id, Value *outer) { + bool outer_given = true; + if (outer == NULL) { + outer = compile_current_class(); + outer_given = false; + } + if (getConstFunc == NULL) { - // VALUE rb_vm_get_const(VALUE mod, struct ccache *cache, ID id); - getConstFunc = cast<Function>(module->getOrInsertFunction("rb_vm_get_const", - RubyObjTy, RubyObjTy, PtrTy, IntTy, NULL)); + // VALUE rb_vm_get_const(VALUE mod, unsigned char lexical_lookup, + // struct ccache *cache, ID id); + getConstFunc = cast<Function>(module->getOrInsertFunction( + "rb_vm_get_const", + RubyObjTy, RubyObjTy, Type::Int8Ty, PtrTy, IntTy, NULL)); } std::vector<Value *> params; struct ccache *cache = GET_VM()->constant_cache_get(id); params.push_back(outer); + params.push_back(ConstantInt::get(Type::Int8Ty, outer_given ? 0 : 1)); params.push_back(compile_const_pointer(cache)); params.push_back(ConstantInt::get(IntTy, id)); @@ -1027,8 +1057,9 @@ #define DEFINED_GVAR 2 #define DEFINED_CVAR 3 #define DEFINED_CONST 4 -#define DEFINED_SUPER 5 -#define DEFINED_METHOD 6 +#define DEFINED_LCONST 5 +#define DEFINED_SUPER 6 +#define DEFINED_METHOD 7 Value * RoxorCompiler::compile_defined_expression(NODE *node) @@ -1116,8 +1147,9 @@ break; case NODE_CONST: - type = DEFINED_CONST; + type = DEFINED_LCONST; what1 = (VALUE)node->nd_vid; + what2 = compile_current_class(); break; case NODE_SUPER: @@ -3236,7 +3268,7 @@ case NODE_CONST: assert(node->nd_vid > 0); - return compile_const(node->nd_vid, compile_current_class()); + return compile_const(node->nd_vid, NULL); case NODE_CDECL: { @@ -4114,27 +4146,84 @@ GET_VM()->const_defined(id); } +static inline VALUE +rb_const_get_direct(VALUE klass, ID id) +{ + CFDictionaryRef iv_dict = rb_class_ivar_dict(klass); + if (iv_dict != NULL) { + VALUE value; + if (CFDictionaryGetValueIfPresent(iv_dict, (const void *)id, + (const void **)&value)) { + return value; + } + } + VALUE mods = rb_attr_get(klass, idIncludedModules); + if (mods != Qnil) { + int i, count = RARRAY_LEN(mods); + for (i = 0; i < count; i++) { + VALUE val = rb_const_get_direct(RARRAY_AT(mods, i), id); + if (val != Qundef) { + return val; + } + } + } + return Qundef; +} + +static VALUE +rb_vm_const_lookup(VALUE outer, ID path, bool lexical, bool defined) +{ + if (lexical) { + struct rb_vm_outer *o = GET_VM()->get_outer((Class)outer); + while (o != NULL && o->klass != (Class)rb_cNSObject) { + VALUE val = rb_const_get_direct((VALUE)o->klass, path); + if (val != Qundef) { + return defined ? Qtrue : val; + } + o = o->outer; + } + } + + return defined ? rb_const_defined(outer, path) : rb_const_get(outer, path); +} + extern "C" VALUE -rb_vm_get_const(VALUE outer, struct ccache *cache, ID path) +rb_vm_get_const(VALUE outer, unsigned char lexical_lookup, + struct ccache *cache, ID path) { - // TODO if called within module_eval, we should update outer + if (GET_VM()->current_class != NULL && lexical_lookup) { + outer = (VALUE)GET_VM()->current_class; + } + assert(cache != NULL); if (cache->outer == outer && cache->val != Qundef) { return cache->val; } + + VALUE val = rb_vm_const_lookup(outer, path, lexical_lookup, false); + cache->outer = outer; - return cache->val = rb_const_get(outer, path); + cache->val = val; + + return val; } extern "C" void -rb_vm_const_defined(ID path) +rb_vm_const_is_defined(ID path) { GET_VM()->const_defined(path); } extern "C" +void +rb_vm_set_outer(VALUE klass, VALUE under) +{ + GET_VM()->set_outer((Class)klass, (Class)under); +} + +extern "C" VALUE rb_vm_define_class(ID path, VALUE outer, VALUE super, unsigned char is_module) { @@ -4340,12 +4429,10 @@ break; case DEFINED_CONST: + case DEFINED_LCONST: { - VALUE outer = what2; - if (NIL_P(outer)) { - outer = CLASS_OF(self); - } - if (rb_const_defined(outer, (ID)what)) { + if (rb_vm_const_lookup(what2, (ID)what, + type == DEFINED_LCONST, true)) { str = "constant"; } } Modified: MacRuby/branches/experimental/roxor.h =================================================================== --- MacRuby/branches/experimental/roxor.h 2009-03-26 00:54:43 UTC (rev 1151) +++ MacRuby/branches/experimental/roxor.h 2009-03-26 00:55:06 UTC (rev 1152) @@ -18,7 +18,7 @@ int rb_vm_safe_level(void); void rb_vm_set_safe_level(int level); VALUE rb_vm_top_self(void); -void rb_vm_const_defined(ID path); +void rb_vm_const_is_defined(ID path); bool rb_vm_lookup_method(Class klass, SEL sel, IMP *pimp, NODE **pnode); bool rb_vm_lookup_method2(Class klass, ID mid, SEL *psel, IMP *pimp, NODE **pnode); void rb_vm_define_method(Class klass, SEL sel, IMP imp, NODE *node); @@ -33,6 +33,7 @@ bool rb_vm_respond_to(VALUE obj, SEL sel, bool priv); VALUE rb_vm_method_missing(VALUE obj, int argc, const VALUE *argv); int rb_vm_find_class_ivar_slot(VALUE klass, ID name); +void rb_vm_set_outer(VALUE klass, VALUE under); static inline void rb_vm_regrow_robject_slots(struct RObject *obj, unsigned int new_num_slot) Modified: MacRuby/branches/experimental/test_roxor.rb =================================================================== --- MacRuby/branches/experimental/test_roxor.rb 2009-03-26 00:54:43 UTC (rev 1151) +++ MacRuby/branches/experimental/test_roxor.rb 2009-03-26 00:55:06 UTC (rev 1152) @@ -435,6 +435,21 @@ assert 'true', 'p ::String == String' + assert '42', %q{ + o = Object.new + class << o + module Foo + Bar = 42 + end + class Baz; include Foo; end + class Baz; + def self.bar; Bar; end + end + def baz; Baz; end + end + p o.baz.bar + } + end test "ranges" do Modified: MacRuby/branches/experimental/variable.c =================================================================== --- MacRuby/branches/experimental/variable.c 2009-03-26 00:54:43 UTC (rev 1151) +++ MacRuby/branches/experimental/variable.c 2009-03-26 00:55:06 UTC (rev 1152) @@ -273,6 +273,8 @@ } OBJ_FREEZE(str); rb_ivar_set(klass, classpath, str); + + rb_vm_set_outer(klass, under); } VALUE @@ -1831,7 +1833,7 @@ DLOG("CONS", "%s::%s <- %p", class_getName((Class)klass), rb_id2name(id), (void *)val); CFDictionarySetValue(iv_dict, (const void *)id, (const void *)val); - rb_vm_const_defined(id); + rb_vm_const_is_defined(id); } void
participants (1)
-
source_changes@macosforge.org