Created
April 10, 2010 13:49
-
-
Save kronos/362029 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/kernel/common/module.rb b/kernel/common/module.rb | |
index 5f98a67..f4b661a 100644 | |
--- a/kernel/common/module.rb | |
+++ b/kernel/common/module.rb | |
@@ -69,6 +69,13 @@ class Module | |
class_variable_defined? verify_class_variable_name(name) | |
end | |
+ def remove_class_variable(name) | |
+ Ruby.primitive :module_cvar_remove | |
+ | |
+ remove_class_variable verify_class_variable_name(name) | |
+ end | |
+ private :remove_class_variable | |
+ | |
def __class_variables__ | |
Ruby.primitive :module_class_variables | |
diff --git a/spec/ruby/core/module/class_variable_set_spec.rb b/spec/ruby/core/module/class_variable_set_spec.rb | |
index 3864935..39700a8 100644 | |
--- a/spec/ruby/core/module/class_variable_set_spec.rb | |
+++ b/spec/ruby/core/module/class_variable_set_spec.rb | |
@@ -13,7 +13,7 @@ describe "Module#class_variable_set" do | |
end | |
it "sets the value of a class variable with the given name defined in an included module" do | |
- c = Class.new { include ModuleSpecs::MVars } | |
+ c = Class.new { include ModuleSpecs::MVars.dup } | |
c.send(:class_variable_set, "@@mvar", :new_mvar).should == :new_mvar | |
c.send(:class_variable_get, "@@mvar").should == :new_mvar | |
end | |
diff --git a/spec/ruby/core/module/fixtures/classes.rb b/spec/ruby/core/module/fixtures/classes.rb | |
index 36d541d..4fd0e35 100644 | |
--- a/spec/ruby/core/module/fixtures/classes.rb | |
+++ b/spec/ruby/core/module/fixtures/classes.rb | |
@@ -7,6 +7,9 @@ module ModuleSpecs | |
class SubclassSpec | |
end | |
+ class RemoveClassVariable | |
+ end | |
+ | |
module LookupModInMod | |
INCS = :ethereal | |
end | |
diff --git a/spec/ruby/core/module/remove_class_variable_spec.rb b/spec/ruby/core/module/remove_class_variable_spec.rb | |
index 47ee321..95678ac 100644 | |
--- a/spec/ruby/core/module/remove_class_variable_spec.rb | |
+++ b/spec/ruby/core/module/remove_class_variable_spec.rb | |
@@ -1,8 +1,45 @@ | |
require File.expand_path('../../../spec_helper', __FILE__) | |
require File.expand_path('../fixtures/classes', __FILE__) | |
-ruby_version_is "1.9" do | |
- describe "Module#remove_class_variable" do | |
- it "needs to be reviewed for spec completeness" | |
+describe "Module#remove_class_variable" do | |
+ it "removes class variable" do | |
+ m = ModuleSpecs::MVars.dup | |
+ m.send(:remove_class_variable, :@@mvar) | |
+ m.class_variable_defined?(:@@mvar).should == false | |
+ end | |
+ | |
+ it "returns the value of removing class variable" do | |
+ m = ModuleSpecs::MVars.dup | |
+ m.send(:remove_class_variable, :@@mvar).should == :mvar | |
+ end | |
+ | |
+ it "raises a NameError when removing class variable declared in included module" do | |
+ c = ModuleSpecs::RemoveClassVariable.new { include ModuleSpecs::MVars.dup } | |
+ lambda { c.send(:remove_class_variable, :@@mvar) }.should raise_error(NameError) | |
+ end | |
+ | |
+ it "dunno how to name this block" do | |
+ c = ModuleSpecs::RemoveClassVariable.new { @@mvar = :mvar } | |
+ lambda { c.send(:remove_class_variable, :@@mvar) }.should raise_error(NameError) | |
+ end | |
+ | |
+ it "raises a NameError when passed a symbol with one leading @" do | |
+ lambda { ModuleSpecs::MVars.send(:remove_class_variable, :@mvar) }.should raise_error(NameError) | |
+ end | |
+ | |
+ it "raises a NameError when passed a symbol with no leading @" do | |
+ lambda { ModuleSpecs::MVars.send(:remove_class_variable, :mvar) }.should raise_error(NameError) | |
+ end | |
+ | |
+ it "raises a NameError when a Fixnum for an uninitialized class variable is given" do | |
+ lambda { ModuleSpecs::MVars.send(:remove_class_variable, :@@nonexisting_class_variable) }.should raise_error(NameError) | |
+ end | |
+ | |
+ ruby_version_is "" ... "1.9" do | |
+ it "is private" do | |
+ lambda { ModuleSpecs::MVars.dup.remove_class_variable(:@@mvar) }.should raise_error(NoMethodError) | |
+ end | |
end | |
end | |
diff --git a/vm/builtin/module.cpp b/vm/builtin/module.cpp | |
index de5fb54..ae04f76 100644 | |
--- a/vm/builtin/module.cpp | |
+++ b/vm/builtin/module.cpp | |
@@ -311,7 +311,60 @@ namespace rubinius { | |
mod_to_query->set_table_ivar(state, name, value); | |
return value; | |
+ } | |
+ | |
+ Object* Module::cvar_remove(STATE, Symbol* name) { | |
+ if(!name->is_cvar_p(state)->true_p()) return Primitives::failure(); | |
+ | |
+ Module* mod = this; | |
+ Module* mod_to_query; | |
+ if(MetaClass* mc = try_as<MetaClass>(mod)) { | |
+ mod_to_query = as<Module>(mc->attached_instance()); | |
+ } else if(IncludedModule* im = try_as<IncludedModule>(mod)) { | |
+ mod_to_query = im->module(); | |
+ } else { | |
+ mod_to_query = mod; | |
+ } | |
+ | |
+ if(mod_to_query->table_ivar_defined(state, name)->true_p()) { | |
+ Object* value = mod_to_query->get_table_ivar(state, name); | |
+ mod_to_query->del_table_ivar(state, name); | |
+ return value; | |
+ } | |
+ | |
+ std::stringstream ss; | |
+ mod = this; | |
+ if(MetaClass* mc = try_as<MetaClass>(mod)) { | |
+ mod = as<Module>(mc->attached_instance()); | |
+ } | |
+ | |
+ if (this->cvar_defined(state, name) == Qtrue) { | |
+ ss << "cannot remove "; | |
+ ss << name->c_str(state); | |
+ ss << " for "; | |
+ } else { | |
+ ss << "uninitialized class variable "; | |
+ ss << name->c_str(state); | |
+ ss << " in module "; | |
+ } | |
+ | |
+ if(mod->name()->nil_p()) { | |
+ if(kind_of<Class>(mod)) { | |
+ ss << "#<Class>"; | |
+ } else { | |
+ ss << "#<Module>"; | |
+ } | |
+ } else { | |
+ ss << mod->name()->c_str(state); | |
+ } | |
+ | |
+ RubyException::raise( | |
+ Exception::make_exception(state, | |
+ as<Class>(G(object)->get_const(state, "NameError")), | |
+ ss.str().c_str())); | |
+ | |
+ return NULL; | |
} | |
void Module::Info::show(STATE, Object* self, int level) { | |
diff --git a/vm/builtin/module.hpp b/vm/builtin/module.hpp | |
index a6cba64..11913f6 100644 | |
--- a/vm/builtin/module.hpp | |
+++ b/vm/builtin/module.hpp | |
@@ -61,6 +61,9 @@ namespace rubinius { | |
// Ruby.primitive :module_cvar_get_or_set | |
Object* cvar_get_or_set(STATE, Symbol* name, Object* val); | |
+ // Ruby.primitive :module_cvar_remove | |
+ Object* cvar_remove(STATE, Symbol* name); | |
+ | |
void setup(STATE); | |
void setup(STATE, const char* name, Module* under = NULL); | |
void setup(STATE, Symbol* name, Module* under = NULL); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment