[macruby-changes] [2363] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Mon Aug 24 19:35:49 PDT 2009


Revision: 2363
          http://trac.macosforge.org/projects/ruby/changeset/2363
Author:   lsansonetti at apple.com
Date:     2009-08-24 19:35:45 -0700 (Mon, 24 Aug 2009)
Log Message:
-----------
fixing bugs in instance_eval & friends + fixed some specs so that they pass under both 1.8 and 1.9

Modified Paths:
--------------
    MacRuby/trunk/class.c
    MacRuby/trunk/compiler.cpp
    MacRuby/trunk/compiler.h
    MacRuby/trunk/load.c
    MacRuby/trunk/object.c
    MacRuby/trunk/spec/frozen/core/class/inherited_spec.rb
    MacRuby/trunk/spec/frozen/core/kernel/eval_spec.rb
    MacRuby/trunk/spec/frozen/language/defined_spec.rb
    MacRuby/trunk/spec/frozen/tags/macruby/core/basicobject/instance_exec_tags.txt
    MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/instance_eval_tags.txt
    MacRuby/trunk/spec/macruby/core/exception_spec.rb
    MacRuby/trunk/spec/macruby/core/object_spec.rb
    MacRuby/trunk/vm.cpp
    MacRuby/trunk/vm.h
    MacRuby/trunk/vm_eval.c

Removed Paths:
-------------
    MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_class_method_tags.txt

Modified: MacRuby/trunk/class.c
===================================================================
--- MacRuby/trunk/class.c	2009-08-24 02:40:28 UTC (rev 2362)
+++ MacRuby/trunk/class.c	2009-08-25 02:35:45 UTC (rev 2363)
@@ -1052,7 +1052,13 @@
 		break;
 
 	    default:
-		klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
+		if (RCLASS_SINGLETON(RBASIC(obj)->klass) &&
+		    rb_iv_get(RBASIC(obj)->klass, "__attached__") == obj) {
+		    klass = RBASIC(obj)->klass;
+		}
+		else {
+		    klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
+		}
 		break;
 	}
     }

Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp	2009-08-24 02:40:28 UTC (rev 2362)
+++ MacRuby/trunk/compiler.cpp	2009-08-25 02:35:45 UTC (rev 2363)
@@ -43,6 +43,7 @@
     current_block_node = NULL;
     current_block_func = NULL;
     current_opened_class = NULL;
+    dynamic_class = false;
     current_module = false;
     current_loop_begin_bb = NULL;
     current_loop_body_bb = NULL;
@@ -627,11 +628,11 @@
 }
 
 void
-RoxorCompiler::compile_prepare_method(Value *classVal, bool singleton,
-	Value *sel, Function *new_function, rb_vm_arity_t &arity, NODE *body)
+RoxorCompiler::compile_prepare_method(Value *classVal, Value *sel,
+	bool singleton, Function *new_function, rb_vm_arity_t &arity, NODE *body)
 {
     if (prepareMethodFunc == NULL) {
-	// void rb_vm_prepare_method(Class klass, unsigned char singleton,
+	// void rb_vm_prepare_method(Class klass, unsigned char dynamic_class,
 	//	SEL sel, Function *func, rb_vm_arity_t arity, int flags)
 	prepareMethodFunc = 
 	    cast<Function>(module->getOrInsertFunction(
@@ -643,7 +644,8 @@
     std::vector<Value *> params;
 
     params.push_back(classVal);
-    params.push_back(ConstantInt::get(Type::Int8Ty, singleton));
+    params.push_back(ConstantInt::get(Type::Int8Ty,
+		!singleton && dynamic_class ? 1 : 0));
     params.push_back(sel);
 
     params.push_back(compile_const_pointer(new_function));
@@ -656,11 +658,11 @@
 }
 
 void
-RoxorAOTCompiler::compile_prepare_method(Value *classVal, bool singleton,
-	Value *sel, Function *new_function, rb_vm_arity_t &arity, NODE *body)
+RoxorAOTCompiler::compile_prepare_method(Value *classVal, Value *sel,
+	bool singleton, Function *new_function, rb_vm_arity_t &arity, NODE *body)
 {
     if (prepareMethodFunc == NULL) {
-	// void rb_vm_prepare_method2(Class klass, unsigned char singleton,
+	// void rb_vm_prepare_method2(Class klass, unsigned char dynamic_class,
 	//	SEL sel, IMP ruby_imp, rb_vm_arity_t arity, int flags)
 	prepareMethodFunc = 
 	    cast<Function>(module->getOrInsertFunction(
@@ -672,7 +674,8 @@
     std::vector<Value *> params;
 
     params.push_back(classVal);
-    params.push_back(ConstantInt::get(Type::Int8Ty, singleton));
+    params.push_back(ConstantInt::get(Type::Int8Ty,
+		!singleton && dynamic_class ? 1 : 0));
     params.push_back(sel);
 
     // Make sure the function is compiled before use, this way LLVM won't use
@@ -1134,10 +1137,12 @@
 RoxorCompiler::compile_cvar_get(ID id, bool check)
 {
     if (cvarGetFunc == NULL) {
-	// VALUE rb_vm_cvar_get(VALUE klass, ID id, unsigned char check);
+	// VALUE rb_vm_cvar_get(VALUE klass, ID id, unsigned char check,
+	//	unsigned char dynamic_class);
 	cvarGetFunc = cast<Function>(module->getOrInsertFunction(
 		    "rb_vm_cvar_get", 
-		    RubyObjTy, RubyObjTy, IntTy, Type::Int8Ty, NULL));
+		    RubyObjTy, RubyObjTy, IntTy, Type::Int8Ty, Type::Int8Ty,
+		    NULL));
     }
 
     std::vector<Value *> params;
@@ -1145,6 +1150,7 @@
     params.push_back(compile_current_class());
     params.push_back(compile_id(id));
     params.push_back(ConstantInt::get(Type::Int8Ty, check ? 1 : 0));
+    params.push_back(ConstantInt::get(Type::Int8Ty, dynamic_class ? 1 : 0));
 
     return compile_protected_call(cvarGetFunc, params);
 }
@@ -1153,10 +1159,11 @@
 RoxorCompiler::compile_cvar_assignment(ID name, Value *val)
 {
     if (cvarSetFunc == NULL) {
-	// VALUE rb_vm_cvar_set(VALUE klass, ID id, VALUE val);
+	// VALUE rb_vm_cvar_set(VALUE klass, ID id, VALUE val,
+	//	unsigned char dynamic_class);
 	cvarSetFunc = cast<Function>(module->getOrInsertFunction(
 		    "rb_vm_cvar_set", 
-		    RubyObjTy, RubyObjTy, IntTy, RubyObjTy, NULL));
+		    RubyObjTy, RubyObjTy, IntTy, RubyObjTy, Type::Int8Ty, NULL));
     }
 
     std::vector<Value *> params;
@@ -1164,6 +1171,7 @@
     params.push_back(compile_current_class());
     params.push_back(compile_id(name));
     params.push_back(val);
+    params.push_back(ConstantInt::get(Type::Int8Ty, dynamic_class ? 1 : 0));
 
     return CallInst::Create(cvarSetFunc, params.begin(),
 	    params.end(), "", bb);
@@ -1192,13 +1200,16 @@
 RoxorCompiler::compile_constant_declaration(NODE *node, Value *val)
 {
     if (setConstFunc == NULL) {
-	// VALUE rb_vm_set_const(VALUE mod, ID id, VALUE obj);
+	// VALUE rb_vm_set_const(VALUE mod, ID id, VALUE obj,
+	//	unsigned char dynamic_class);
 	setConstFunc = cast<Function>(module->getOrInsertFunction(
 		    "rb_vm_set_const",
-		    Type::VoidTy, RubyObjTy, IntTy, RubyObjTy, NULL));
+		    Type::VoidTy, RubyObjTy, IntTy, RubyObjTy, Type::Int8Ty,
+		    NULL));
     }
 
     std::vector<Value *> params;
+    bool outer = false;
 
     if (node->nd_vid > 0) {
 	params.push_back(compile_current_class());
@@ -1206,12 +1217,13 @@
     }
     else {
 	assert(node->nd_else != NULL);
-	params.push_back(compile_class_path(node->nd_else, NULL));
+	params.push_back(compile_class_path(node->nd_else, &outer));
 	assert(node->nd_else->nd_mid > 0);
 	params.push_back(compile_id(node->nd_else->nd_mid));
     }
-
     params.push_back(val);
+    params.push_back(ConstantInt::get(Type::Int8Ty,
+		dynamic_class && outer ? 1 : 0));
 
     CallInst::Create(setConstFunc, params.begin(), params.end(), "", bb);
 
@@ -1288,10 +1300,11 @@
 
     if (getConstFunc == NULL) {
 	// VALUE rb_vm_get_const(VALUE mod, unsigned char lexical_lookup,
-	//			 struct ccache *cache, ID id);
+	//	struct ccache *cache, ID id, unsigned char dynamic_class);
 	getConstFunc = cast<Function>(module->getOrInsertFunction(
 		    "rb_vm_get_const", 
-		    RubyObjTy, RubyObjTy, Type::Int8Ty, PtrTy, IntTy, NULL));
+		    RubyObjTy, RubyObjTy, Type::Int8Ty, PtrTy, IntTy, Type::Int8Ty,
+		    NULL));
     }
 
     std::vector<Value *> params;
@@ -1300,6 +1313,7 @@
     params.push_back(ConstantInt::get(Type::Int8Ty, outer_given ? 0 : 1));
     params.push_back(compile_ccache(id));
     params.push_back(compile_id(id));
+    params.push_back(ConstantInt::get(Type::Int8Ty, dynamic_class ? 1 : 0));
 
     return compile_protected_call(getConstFunc, params);
 }
@@ -3671,7 +3685,8 @@
 
 		Value *classVal;
 		if (nd_type(node) == NODE_SCLASS) {
-		    classVal = compile_singleton_class(compile_node(node->nd_recv));
+		    classVal =
+			compile_singleton_class(compile_node(node->nd_recv));
 		}
 		else {
 		    assert(node->nd_cpath->nd_mid > 0);
@@ -3680,16 +3695,18 @@
 		    NODE *super = node->nd_super;
 
 		    if (defineClassFunc == NULL) {
-			// VALUE rb_vm_define_class(ID path, VALUE outer, VALUE super,
-			//			    int flags);
-			defineClassFunc = cast<Function>(module->getOrInsertFunction(
+			// VALUE rb_vm_define_class(ID path, VALUE outer,
+			//	VALUE super, int flags,
+			//	unsigned char dynamic_class);
+			defineClassFunc = cast<Function>(
+				module->getOrInsertFunction(
 				    "rb_vm_define_class",
 				    RubyObjTy, IntTy, RubyObjTy, RubyObjTy,
-				    Type::Int32Ty, NULL));
+				    Type::Int32Ty, Type::Int8Ty, NULL));
 		    }
 
 		    std::vector<Value *> params;
-		    bool outer = true;
+		    bool outer = false;
 
 		    params.push_back(compile_id(path));
 		    params.push_back(compile_class_path(node->nd_cpath, &outer));
@@ -3703,6 +3720,8 @@
 			flags |= DEFINE_OUTER;
 		    }
 		    params.push_back(ConstantInt::get(Type::Int32Ty, flags));
+		    params.push_back(ConstantInt::get(Type::Int8Ty,
+				outer && dynamic_class ? 1 : 0));
 
 		    classVal = compile_protected_call(defineClassFunc, params);
 		}
@@ -3739,13 +3758,12 @@
 			current_module = nd_type(node) == NODE_MODULE;
 
 			compile_set_current_scope(classVal, publicScope);
-			Value *old_current_class = 
-			    compile_set_current_class(
-				    ConstantInt::get(RubyObjTy, 0));
+			bool old_dynamic_class = dynamic_class;
+			dynamic_class = false;
 
 			Value *val = compile_node(body->nd_body);
 
-			compile_set_current_class(old_current_class);
+			dynamic_class = old_dynamic_class;
 			compile_set_current_scope(classVal, defaultScope);
 
 			BasicBlock::InstListType &list = bb->getInstList();
@@ -4263,9 +4281,12 @@
 	case NODE_ALIAS:
 	    {
 		if (aliasFunc == NULL) {
-		    // void rb_vm_alias(VALUE outer, ID from, ID to);
-		    aliasFunc = cast<Function>(module->getOrInsertFunction("rb_vm_alias",
-				Type::VoidTy, RubyObjTy, IntTy, IntTy, NULL));
+		    // void rb_vm_alias2(VALUE outer, ID from, ID to,
+		    //	unsigned char dynamic_class);
+		    aliasFunc = cast<Function>(module->getOrInsertFunction(
+				"rb_vm_alias2",
+				Type::VoidTy, RubyObjTy, IntTy, IntTy, Type::Int8Ty,
+				NULL));
 		}
 
 		std::vector<Value *> params;
@@ -4273,6 +4294,8 @@
 		params.push_back(compile_current_class());
 		params.push_back(compile_id(node->u1.node->u1.node->u2.id));
 		params.push_back(compile_id(node->u2.node->u1.node->u2.id));
+		params.push_back(ConstantInt::get(Type::Int8Ty,
+			    dynamic_class ? 1 : 0));
 
 		compile_protected_call(aliasFunc, params);
 
@@ -4326,8 +4349,8 @@
 		rb_vm_arity_t arity = rb_vm_node_arity(body);
 		const SEL sel = mid_to_sel(mid, arity.real);
 
-		compile_prepare_method(classVal, singleton_method, compile_sel(sel),
-			new_function, arity, body);
+		compile_prepare_method(classVal, compile_sel(sel),
+			singleton_method, new_function, arity, body);
 
 		return nilVal;
 	    }
@@ -4336,11 +4359,13 @@
 	case NODE_UNDEF:
 	    {
 		if (undefFunc == NULL) {
-		    // VALUE rb_vm_undef(VALUE klass, ID name);
+		    // VALUE rb_vm_undef(VALUE klass, ID name,
+		    //	unsigned char dynamic_class);
 		    undefFunc =
 			cast<Function>(module->getOrInsertFunction(
 				"rb_vm_undef",
-				Type::VoidTy, RubyObjTy, IntTy, NULL));
+				Type::VoidTy, RubyObjTy, IntTy, Type::Int8Ty,
+				NULL));
 		}
 
 		assert(node->u2.node != NULL);
@@ -4349,6 +4374,8 @@
 		std::vector<Value *> params;
 		params.push_back(compile_current_class());
 		params.push_back(compile_id(name));
+		params.push_back(ConstantInt::get(Type::Int8Ty,
+			    dynamic_class ? 1 : 0));
 
 		compile_protected_call(undefFunc, params);
 
@@ -4700,15 +4727,19 @@
 		bool old_current_block_chain = current_block_chain;
 		int old_return_from_block = return_from_block;
 		BasicBlock *old_rescue_bb = rescue_bb;
+		bool old_dynamic_class = dynamic_class;
 
 		current_mid = 0;
 		current_block = true;
 		current_block_chain = true;
+		dynamic_class = true;
 
 		assert(node->nd_body != NULL);
 		Value *block = compile_node(node->nd_body);	
 		assert(Function::classof(block));
 
+		dynamic_class = old_dynamic_class;
+
 		BasicBlock *return_from_block_bb = NULL;
 		if (!old_current_block_chain && return_from_block != -1) {
 		    // The block we just compiled contains one or more

Modified: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h	2009-08-24 02:40:28 UTC (rev 2362)
+++ MacRuby/trunk/compiler.h	2009-08-25 02:35:45 UTC (rev 2363)
@@ -59,6 +59,8 @@
 
 	bool is_inside_eval(void) { return inside_eval; }
 	void set_inside_eval(bool flag) { inside_eval = flag; }
+	bool is_dynamic_class(void) { return dynamic_class; }
+	void set_dynamic_class(bool flag) { dynamic_class = flag; }
 
     protected:
 	const char *fname;
@@ -97,6 +99,7 @@
 	NODE *current_block_node;
 	Function *current_block_func;
 	GlobalVariable *current_opened_class;
+	bool dynamic_class;
 	bool current_module;
 	BasicBlock *current_loop_begin_bb;
 	BasicBlock *current_loop_body_bb;
@@ -228,8 +231,8 @@
 		BasicBlock *thenBB);
 	void compile_single_when_argument(NODE *arg, Value *comparedToVal,
 		BasicBlock *thenBB);
-	virtual void compile_prepare_method(Value *classVal, bool singleton,
-		Value *sel, Function *new_function, rb_vm_arity_t &arity,
+	virtual void compile_prepare_method(Value *classVal, Value *sel,
+		bool singleton, Function *new_function, rb_vm_arity_t &arity,
 		NODE *body);
 	Value *compile_dispatch_call(std::vector<Value *> &params);
 	Value *compile_when_splat(Value *comparedToVal, Value *splatVal);
@@ -343,8 +346,8 @@
 	Value *compile_mcache(SEL sel, bool super);
 	Value *compile_ccache(ID id);
 	Instruction *compile_sel(SEL sel, bool add_to_bb=true);
-	void compile_prepare_method(Value *classVal, bool singleton,
-		Value *sel, Function *new_function, rb_vm_arity_t &arity,
+	void compile_prepare_method(Value *classVal, Value *sel,
+		bool singleton, Function *new_function, rb_vm_arity_t &arity,
 		NODE *body);
 	Value *compile_prepare_block_args(Function *func, int *flags);
 	Value *compile_nsobject(void);

Modified: MacRuby/trunk/load.c
===================================================================
--- MacRuby/trunk/load.c	2009-08-24 02:40:28 UTC (rev 2362)
+++ MacRuby/trunk/load.c	2009-08-25 02:35:45 UTC (rev 2363)
@@ -290,7 +290,9 @@
     if (node == NULL) {
 	rb_raise(rb_eSyntaxError, "compile error");
     }
+    Class old_klass = rb_vm_set_current_class(NULL);
     rb_vm_run(fname_str, node, NULL, false);
+    rb_vm_set_current_class(old_klass);
 }
 
 void

Modified: MacRuby/trunk/object.c
===================================================================
--- MacRuby/trunk/object.c	2009-08-24 02:40:28 UTC (rev 2362)
+++ MacRuby/trunk/object.c	2009-08-25 02:35:45 UTC (rev 2363)
@@ -2852,6 +2852,7 @@
     rb_const_set(rb_cObject, rb_intern("Object"), rb_cNSObject);
     rb_set_class_path(rb_cObject, rb_cObject, "NSObject");
     rb_cBasicObject = (VALUE)objc_duplicateClass((Class)rb_cObject, "BasicObject", 0);
+    rb_const_set(rb_cObject, rb_intern("BasicObject"), rb_cBasicObject);
     rb_cModule = boot_defclass("Module", rb_cNSObject);
     rb_cClass =  boot_defclass("Class",  rb_cModule);
 

Modified: MacRuby/trunk/spec/frozen/core/class/inherited_spec.rb
===================================================================
--- MacRuby/trunk/spec/frozen/core/class/inherited_spec.rb	2009-08-24 02:40:28 UTC (rev 2362)
+++ MacRuby/trunk/spec/frozen/core/class/inherited_spec.rb	2009-08-25 02:35:45 UTC (rev 2363)
@@ -37,36 +37,36 @@
   it "is called when marked as a private class method" do
     CoreClassSpecs::A.private_class_method :inherited
     CoreClassSpecs::Record.called?.should == nil
-    module CoreClassSpecs; class B < A; end; end
+    module ::CoreClassSpecs; class B < A; end; end
     CoreClassSpecs::Record.called?.should == CoreClassSpecs::B
   end
   
   it "is called when marked as a protected class method" do
-    class << CoreClassSpecs::A
+    class << ::CoreClassSpecs::A
       protected :inherited
     end
     CoreClassSpecs::Record.called?.should == nil
-    module CoreClassSpecs; class C < A; end; end
+    module ::CoreClassSpecs; class C < A; end; end
     CoreClassSpecs::Record.called?.should == CoreClassSpecs::C
   end
   
   it "is called when marked as a public class method" do
     CoreClassSpecs::A.public_class_method :inherited
     CoreClassSpecs::Record.called?.should == nil
-    module CoreClassSpecs; class D < A; end; end
+    module ::CoreClassSpecs; class D < A; end; end
     CoreClassSpecs::Record.called?.should == CoreClassSpecs::D
   end
   
   it "is called by super from a method provided by an included module" do
     CoreClassSpecs::Record.called?.should == nil
-    module CoreClassSpecs; class E < F; end; end
+    module ::CoreClassSpecs; class E < F; end; end
     CoreClassSpecs::Record.called?.should == CoreClassSpecs::E
   end
   
   it "is called by super even when marked as a private class method" do
     CoreClassSpecs::Record.called?.should == nil
     CoreClassSpecs::H.private_class_method :inherited
-    module CoreClassSpecs; class I < H; end; end
+    module ::CoreClassSpecs; class I < H; end; end
     CoreClassSpecs::Record.called?.should == CoreClassSpecs::I
   end
   

Modified: MacRuby/trunk/spec/frozen/core/kernel/eval_spec.rb
===================================================================
--- MacRuby/trunk/spec/frozen/core/kernel/eval_spec.rb	2009-08-24 02:40:28 UTC (rev 2362)
+++ MacRuby/trunk/spec/frozen/core/kernel/eval_spec.rb	2009-08-25 02:35:45 UTC (rev 2363)
@@ -212,7 +212,7 @@
 
   it "should perform top level evaluations from inside a block" do
     # The class Object bit is needed to workaround some mspec oddness
-    class Object
+    class ::Object
       [1].each { eval "Const = 1"}
       Const.should == 1
       remove_const :Const

Modified: MacRuby/trunk/spec/frozen/language/defined_spec.rb
===================================================================
--- MacRuby/trunk/spec/frozen/language/defined_spec.rb	2009-08-24 02:40:28 UTC (rev 2362)
+++ MacRuby/trunk/spec/frozen/language/defined_spec.rb	2009-08-25 02:35:45 UTC (rev 2363)
@@ -177,19 +177,19 @@
   end
 
   not_compliant_on :rubinius do
-    # I (Evan) am not certain we'll support defined?(super) ever.
-    # for now, i'm marking these as compliant.
-    it "returns 'super' when Subclass#no_args uses defined?" do
-      ret = (LanguageDefinedSpecs::LanguageDefinedSubclass.new.no_args)
-      ret.should == "super"
-    end
+    ruby_version_is "" ... "1.9" do
+      # I (Evan) am not certain we'll support defined?(super) ever.
+      # for now, i'm marking these as compliant.
+      it "returns 'super' when Subclass#no_args uses defined?" do
+        ret = (LanguageDefinedSpecs::LanguageDefinedSubclass.new.no_args)
+        ret.should == "super"
+      end
+  
+      it "returns 'super' when Subclass#args uses defined?" do
+        ret = (LanguageDefinedSpecs::LanguageDefinedSubclass.new.args)
+        ret.should == "super"
+      end
 
-    it "returns 'super' when Subclass#args uses defined?" do
-      ret = (LanguageDefinedSpecs::LanguageDefinedSubclass.new.args)
-      ret.should == "super"
-    end
-
-    ruby_version_is "" ... "1.9" do
       it "returns 'local-variable(in-block)' when defined? is called on a block var" do
         block = Proc.new { |xxx| defined?(xxx) }
         ret = block.call(1)
@@ -198,6 +198,16 @@
     end
 
     ruby_version_is "1.9" do
+      it "returns 'super' when Subclass#no_args uses defined?" do
+        ret = (LanguageDefinedSubclass.new.no_args)
+        ret.should == "super"
+      end
+  
+      it "returns 'super' when Subclass#args uses defined?" do
+        ret = (LanguageDefinedSubclass.new.args)
+        ret.should == "super"
+      end
+
       it "returns 'local-variable' when defined? is called on a block var" do
         block = Proc.new { |xxx| defined?(xxx) }
         ret = block.call(1)

Modified: MacRuby/trunk/spec/frozen/tags/macruby/core/basicobject/instance_exec_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/basicobject/instance_exec_tags.txt	2009-08-24 02:40:28 UTC (rev 2362)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/basicobject/instance_exec_tags.txt	2009-08-25 02:35:45 UTC (rev 2363)
@@ -1,4 +1,3 @@
-critical:BasicObject#instance_exec raises a LocalJumpError unless given a block
-fails:BasicObject#instance_exec only binds the exec to the receiver
 fails:BasicObject#instance_exec raises a TypeError when defining methods on an immediate
 fails:BasicObject#instance_exec raises a TypeError when defining methods on numerics
+fails:BasicObject#instance_exec sets class variables in the receiver

Modified: MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/instance_eval_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/instance_eval_tags.txt	2009-08-24 02:40:28 UTC (rev 2362)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/kernel/instance_eval_tags.txt	2009-08-25 02:35:45 UTC (rev 2363)
@@ -1,7 +1,3 @@
-critical:Kernel#instance_eval treats block-local variables as local to the block
-fails:Kernel#instance_eval passes the object to the block
-fails:Kernel#instance_eval only binds the eval to the receiver
-fails:Kernel#instance_eval shares a scope across sibling evals
-fails:Kernel#instance_eval sets class variables in the receiver
+fails:Kernel#instance_eval treats block-local variables as local to the block
 fails:Kernel#instance_eval raises a TypeError when defining methods on an immediate
 fails:Kernel#instance_eval raises a TypeError when defining methods on numerics

Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_class_method_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_class_method_tags.txt	2009-08-24 02:40:28 UTC (rev 2362)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/module/private_class_method_tags.txt	2009-08-25 02:35:45 UTC (rev 2363)
@@ -1,2 +0,0 @@
-fails:Module#private_class_method raises a NameError when the given name is not a method
-fails:Module#private_class_method raises a NameError when the given name is an instance method

Modified: MacRuby/trunk/spec/macruby/core/exception_spec.rb
===================================================================
--- MacRuby/trunk/spec/macruby/core/exception_spec.rb	2009-08-24 02:40:28 UTC (rev 2362)
+++ MacRuby/trunk/spec/macruby/core/exception_spec.rb	2009-08-25 02:35:45 UTC (rev 2363)
@@ -1,5 +1,6 @@
 require File.dirname(__FILE__) + "/../spec_helper"
 FixtureCompiler.require! "exception"
+TestException # force dynamic load
 
 =begin # TODO
 describe "An Objective-C exception" do

Modified: MacRuby/trunk/spec/macruby/core/object_spec.rb
===================================================================
--- MacRuby/trunk/spec/macruby/core/object_spec.rb	2009-08-24 02:40:28 UTC (rev 2362)
+++ MacRuby/trunk/spec/macruby/core/object_spec.rb	2009-08-25 02:35:45 UTC (rev 2363)
@@ -1,5 +1,6 @@
 require File.dirname(__FILE__) + "/../spec_helper"
 FixtureCompiler.require! "object"
+TestObject # force dynamic load
 
 require File.join(FIXTURES, 'object')
 

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2009-08-24 02:40:28 UTC (rev 2362)
+++ MacRuby/trunk/vm.cpp	2009-08-25 02:35:45 UTC (rev 2363)
@@ -828,11 +828,13 @@
 
 extern "C"
 void 
-rb_vm_set_const(VALUE outer, ID id, VALUE obj)
+rb_vm_set_const(VALUE outer, ID id, VALUE obj, unsigned char dynamic_class)
 {
-    Class k = GET_VM()->get_current_class();
-    if (k != NULL) {
-	outer = (VALUE)k;
+    if (dynamic_class) {
+	Class k = GET_VM()->get_current_class();
+	if (k != NULL) {
+	    outer = (VALUE)k;
+	}
     }
     rb_const_set(outer, id, obj);
     GET_CORE()->const_defined(id);
@@ -890,11 +892,13 @@
 extern "C"
 VALUE
 rb_vm_get_const(VALUE outer, unsigned char lexical_lookup,
-	struct ccache *cache, ID path)
+	struct ccache *cache, ID path, unsigned char dynamic_class)
 {
-    Class k = GET_VM()->get_current_class();
-    if (lexical_lookup && k != NULL) {
-	outer = (VALUE)k;
+    if (dynamic_class) {
+	Class k = GET_VM()->get_current_class();
+	if (lexical_lookup && k != NULL) {
+	    outer = (VALUE)k;
+	}
     }
 
     assert(cache != NULL);
@@ -950,14 +954,17 @@
 
 extern "C"
 VALUE
-rb_vm_define_class(ID path, VALUE outer, VALUE super, int flags)
+rb_vm_define_class(ID path, VALUE outer, VALUE super, int flags,
+	unsigned char dynamic_class)
 {
     assert(path > 0);
     check_if_module(outer);
 
-    Class k = GET_VM()->get_current_class();
-    if (k != NULL) {
-	outer = (VALUE)k;
+    if (dynamic_class) {
+	Class k = GET_VM()->get_current_class();
+	if (k != NULL) {
+	    outer = (VALUE)k;
+	}
     }
 
     VALUE klass;
@@ -1023,6 +1030,7 @@
 		FROM_GV(Args[0], ID),
 		FROM_GV(Args[1], VALUE),
 		FROM_GV(Args[2], VALUE),
+		FROM_GV(Args[3], int),
 		FROM_GV(Args[3], unsigned char)));
 }
 
@@ -1063,22 +1071,27 @@
 
 extern "C"
 VALUE
-rb_vm_cvar_get(VALUE klass, ID id, unsigned char check)
+rb_vm_cvar_get(VALUE klass, ID id, unsigned char check,
+	unsigned char dynamic_class)
 {
-    Class k = GET_VM()->get_current_class();
-    if (k != NULL) {
-	klass = (VALUE)k;
+    if (dynamic_class) {
+	Class k = GET_VM()->get_current_class();
+	if (k != NULL) {
+	    klass = (VALUE)k;
+	}
     }
     return rb_cvar_get2(klass, id, check);
 }
 
 extern "C"
 VALUE
-rb_vm_cvar_set(VALUE klass, ID id, VALUE val)
+rb_vm_cvar_set(VALUE klass, ID id, VALUE val, unsigned char dynamic_class)
 {
-    Class k = GET_VM()->get_current_class();
-    if (k != NULL) {
-	klass = (VALUE)k;
+    if (dynamic_class) {
+	Class k = GET_VM()->get_current_class();
+	if (k != NULL) {
+	    klass = (VALUE)k;
+	}
     }
     rb_cvar_set(klass, id, val);
     return val;
@@ -1157,11 +1170,13 @@
 
 extern "C"
 void
-rb_vm_alias(VALUE outer, ID name, ID def)
+rb_vm_alias2(VALUE outer, ID name, ID def, unsigned char dynamic_class)
 {
-    Class k = GET_VM()->get_current_class();
-    if (k != NULL) {
-	outer = (VALUE)k;
+    if (dynamic_class) {
+	Class k = GET_VM()->get_current_class();
+	if (k != NULL) {
+	    outer = (VALUE)k;
+	}
     }
     rb_frozen_class_p(outer);
     if (outer == rb_cObject) {
@@ -1193,11 +1208,20 @@
 
 extern "C"
 void
-rb_vm_undef(VALUE klass, VALUE name)
+rb_vm_alias(VALUE outer, ID name, ID def)
 {
-    Class k = GET_VM()->get_current_class();
-    if (k != NULL) {
-	klass = (VALUE)k;
+    rb_vm_alias2(outer, name, def, false);
+}
+
+extern "C"
+void
+rb_vm_undef(VALUE klass, VALUE name, unsigned char dynamic_class)
+{
+    if (dynamic_class) {
+	Class k = GET_VM()->get_current_class();
+	if (k != NULL) {
+	    klass = (VALUE)k;
+	}
     }
     rb_vm_undef_method((Class)klass, rb_to_id(name), true);
 }
@@ -1477,10 +1501,10 @@
 }
 
 static void
-prepare_method(Class klass, bool singleton, SEL sel, void *data,
+prepare_method(Class klass, bool dynamic_class, SEL sel, void *data,
 	const rb_vm_arity_t &arity, int flags, bool precompiled)
 {
-    if (!singleton) {
+    if (dynamic_class) {
 	Class k = GET_VM()->get_current_class();
 	if (k != NULL) {
 	    const bool meta = class_isMetaClass(klass);
@@ -1561,8 +1585,8 @@
 	    for (i = 0; i < count; i++) {
 		VALUE mod = RARRAY_AT(included_in_classes, i);
 		rb_vm_set_current_scope(mod, SCOPE_PUBLIC);
-		prepare_method((Class)mod, false, orig_sel, data, arity, flags,
-			precompiled);
+		prepare_method((Class)mod, false, orig_sel, data, arity,
+			flags, precompiled);
 		rb_vm_set_current_scope(mod, SCOPE_DEFAULT);
 	    }
 	}
@@ -1571,18 +1595,20 @@
 
 extern "C"
 void
-rb_vm_prepare_method(Class klass, bool singleton, SEL sel, Function *func,
-	const rb_vm_arity_t arity, int flags)
+rb_vm_prepare_method(Class klass, unsigned char dynamic_class, SEL sel,
+	Function *func, const rb_vm_arity_t arity, int flags)
 {
-    prepare_method(klass, singleton, sel, (void *)func, arity, flags, false);
+    prepare_method(klass, dynamic_class, sel, (void *)func, arity,
+	    flags, false);
 }
 
 extern "C"
 void
-rb_vm_prepare_method2(Class klass, bool singleton, SEL sel, IMP ruby_imp,
-	const rb_vm_arity_t arity, int flags)
+rb_vm_prepare_method2(Class klass, unsigned char dynamic_class, SEL sel,
+	IMP ruby_imp, const rb_vm_arity_t arity, int flags)
 {
-    prepare_method(klass, singleton, sel, (void *)ruby_imp, arity, flags, true);
+    prepare_method(klass, dynamic_class, sel, (void *)ruby_imp, arity,
+	    flags, true);
 }
 
 static rb_vm_method_node_t * __rb_vm_define_method(Class klass, SEL sel,
@@ -2758,24 +2784,30 @@
 #endif
 
 	bool block_already_current = vm->is_block_current(block);
+	Class current_klass = vm->get_current_class();
 	if (!block_already_current) {
 	    vm->add_current_block(block);
 	}
+	vm->set_current_class(NULL);
 
 	struct Finally {
 	    bool block_already_current;
+	    Class current_class;
 	    RoxorVM *vm;
-	    Finally(bool _block_already_current, RoxorVM *_vm) {
+	    Finally(bool _block_already_current, Class _current_class,
+		    RoxorVM *_vm) {
 		block_already_current = _block_already_current;
+		current_class = _current_class;
 		vm = _vm;
 	    }
 	    ~Finally() {
 		if (!block_already_current) {
 		    vm->pop_current_block();
 		}
+		vm->set_current_class(current_class);
 		vm->pop_broken_with();
 	    }
-	} finalizer(block_already_current, vm);
+	} finalizer(block_already_current, current_klass, vm);
 
 	return __rb_vm_ruby_dispatch(self, sel, rcache.node, opt, argc, argv);
     }
@@ -3322,9 +3354,10 @@
 	int dvars_size, ...)
 {
     assert(function != NULL);
+    RoxorVM *vm = GET_VM();
 
     bool cached = false;
-    rb_vm_block_t *b = GET_VM()->uncache_or_create_block(function, &cached,
+    rb_vm_block_t *b = vm->uncache_or_create_block(function, &cached,
 	dvars_size);
 
     bool aot_block = false;
@@ -3361,6 +3394,7 @@
 
     b->proc = Qnil;
     b->self = self;
+    b->klass = (VALUE)vm->get_current_class();
     b->parent_var_uses = parent_var_uses;
     GC_WB(&b->parent_block, parent_block);
 
@@ -3779,6 +3813,7 @@
 
     b->proc = Qnil;
     GC_WB(&b->self, method->recv);
+    b->klass = 0;
     b->arity = method->node == NULL
 	? rb_vm_arity(method->arity) : method->node->arity;
     b->imp = (IMP)method;
@@ -3808,6 +3843,7 @@
     rb_vm_block_t *b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t)
 	    + sizeof(VALUE *));
 
+    b->klass = 0;
     b->proc = Qnil;
     b->arity = rb_vm_arity(1);
     b->flags = VM_BLOCK_PROC;
@@ -3841,6 +3877,7 @@
     rb_vm_block_t *b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t)
 	    + (3 * sizeof(VALUE *)));
 
+    b->klass = 0;
     b->proc = Qnil;
     b->arity.min = 0;
     b->arity.max = -1;
@@ -3922,11 +3959,24 @@
     }
     b->flags |= VM_BLOCK_ACTIVE;
 
+    RoxorVM *vm = GET_VM();
+    Class old_current_class = vm->get_current_class();
+    vm->set_current_class((Class)b->klass);
+
     struct Finally {
+	RoxorVM *vm;
 	rb_vm_block_t *b;
-	Finally(rb_vm_block_t *_b) { b = _b; }
-	~Finally() { b->flags &= ~VM_BLOCK_ACTIVE; }
-    } finalizer(b);
+	Class c;
+	Finally(RoxorVM *_vm, rb_vm_block_t *_b, Class _c) {
+	    vm = _vm;
+	    b = _b;
+	    c = _c;
+	}
+	~Finally() {
+	    b->flags &= ~VM_BLOCK_ACTIVE;
+	    vm->set_current_class(c);
+	}
+    } finalizer(vm, b, old_current_class);
 
     if (b->flags & VM_BLOCK_METHOD) {
 	rb_vm_method_t *m = (rb_vm_method_t *)b->imp;
@@ -3966,8 +4016,13 @@
     struct Finally {
 	RoxorVM *vm;
 	rb_vm_block_t *b;
-	Finally(RoxorVM *_vm, rb_vm_block_t *_b) { vm = _vm; b = _b; }
-	~Finally() { vm->add_current_block(b); }
+	Finally(RoxorVM *_vm, rb_vm_block_t *_b) { 
+	    vm = _vm;
+	    b = _b;
+	}
+	~Finally() {
+	    vm->add_current_block(b);
+	}
     } finalizer(vm, b);
 
     return rb_vm_block_eval0(b, b->self, argc, argv);
@@ -3990,20 +4045,15 @@
 
     VALUE old_self = b->self;
     b->self = self;
-    Class old_class = vm->get_current_class();
-    if (klass == self) {
-	// We only toggle the VM current klass in case #module_eval or
-	// #class_eval is used (where the given klass and self objects are 
-	// actually the same instances).
-	vm->set_current_class((Class)klass);
-    }
+    VALUE old_class = b->klass;
+    b->klass = klass;
 
     struct Finally {
 	RoxorVM *vm;
 	rb_vm_block_t *b;
-	Class old_class;
+	VALUE old_class;
 	VALUE old_self;
-	Finally(RoxorVM *_vm, rb_vm_block_t *_b, Class _old_class,
+	Finally(RoxorVM *_vm, rb_vm_block_t *_b, VALUE _old_class,
 		VALUE _old_self) {
 	    vm = _vm;
 	    b = _b;
@@ -4012,7 +4062,7 @@
 	}
 	~Finally() {
 	    b->self = old_self;
-	    vm->set_current_class(old_class);
+	    b->klass = old_class;
 	    vm->add_current_block(b);
 	}
     } finalizer(vm, b, old_class, old_self);
@@ -4552,22 +4602,28 @@
 rb_vm_run_under(VALUE klass, VALUE self, const char *fname, NODE *node,
 		rb_vm_binding_t *binding, bool inside_eval)
 {
-    VALUE old_top_object = GET_VM()->get_current_top_object();
+    RoxorVM *vm = GET_VM();
+    RoxorCompiler *compiler = RoxorCompiler::shared;
+
+    VALUE old_top_object = vm->get_current_top_object();
     if (binding != NULL) {
 	self = binding->self;
     }
     if (self != 0) {
-	GET_VM()->set_current_top_object(self);
+	vm->set_current_top_object(self);
     }
     Class old_class = GET_VM()->get_current_class();
+    bool old_dynamic_class = compiler->is_dynamic_class();
     if (klass != 0) {
-	GET_VM()->set_current_class((Class)klass);
+	vm->set_current_class((Class)klass);
+	compiler->set_dynamic_class(true);
     }
 
     VALUE val = rb_vm_run(fname, node, binding, inside_eval);
 
-    GET_VM()->set_current_top_object(old_top_object);
-    GET_VM()->set_current_class(old_class);
+    compiler->set_dynamic_class(old_dynamic_class);
+    vm->set_current_top_object(old_top_object);
+    vm->set_current_class(old_class);
 
     return val;
 }

Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h	2009-08-24 02:40:28 UTC (rev 2362)
+++ MacRuby/trunk/vm.h	2009-08-25 02:35:45 UTC (rev 2363)
@@ -38,6 +38,7 @@
 typedef struct rb_vm_block {
     VALUE proc; // a reference to a Proc object, or nil
     VALUE self;
+    VALUE klass;
     VALUE userdata; // if VM_BLOCK_IFUNC, contains the user data, otherwise
 		    // contains the key used in the blocks cache.
     rb_vm_arity_t arity;
@@ -373,6 +374,8 @@
 bool rb_vm_abort_on_exception(void);
 void rb_vm_set_abort_on_exception(bool flag);
 
+Class rb_vm_set_current_class(Class klass);
+
 bool rb_vm_is_multithreaded(void);
 void rb_vm_set_multithreaded(bool flag);
 

Modified: MacRuby/trunk/vm_eval.c
===================================================================
--- MacRuby/trunk/vm_eval.c	2009-08-24 02:40:28 UTC (rev 2362)
+++ MacRuby/trunk/vm_eval.c	2009-08-25 02:35:45 UTC (rev 2363)
@@ -534,6 +534,9 @@
     else {
 	klass = rb_singleton_class(self);
     }
+    if (!rb_block_given_p()) {
+	rb_raise(rb_eLocalJumpError, "no block given");
+    }
     return rb_vm_yield_under(klass, self, argc, argv);
 }
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090824/257445d8/attachment-0001.html>


More information about the macruby-changes mailing list