[macruby-changes] [1152] MacRuby/branches/experimental

source_changes at macosforge.org source_changes at macosforge.org
Wed Mar 25 17:55:06 PDT 2009


Revision: 1152
          http://trac.macosforge.org/projects/ruby/changeset/1152
Author:   lsansonetti at 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090325/cb8d6cf1/attachment-0001.html>


More information about the macruby-changes mailing list