From 2a20dde7f27e24cc13f620c116b561a98dea63fc Mon Sep 17 00:00:00 2001 From: Ryo Onodera Date: Thu, 5 Jul 2012 21:41:50 +0900 Subject: [PATCH] Make Object constants invisible from BasicObject --- kernel/bootstrap/basicobject.rb | 6 +++--- kernel/bootstrap/weakref.rb | 2 +- kernel/common/basicobject.rb | 2 +- kernel/common/eval19.rb | 30 ++++++++++++++--------------- vm/helpers.cpp | 34 ++++++++++++++++++++++++++------- 5 files changed, 47 insertions(+), 27 deletions(-) diff --git a/kernel/bootstrap/basicobject.rb b/kernel/bootstrap/basicobject.rb index 1444d29e17..4fbbd36ee6 100644 --- a/kernel/bootstrap/basicobject.rb +++ b/kernel/bootstrap/basicobject.rb @@ -8,7 +8,7 @@ def initialize def equal?(other) Rubinius.primitive :object_equal - raise PrimitiveFailure, "BasicObject#equal? primitive failed" + raise ::PrimitiveFailure, "BasicObject#equal? primitive failed" end alias_method :==, :equal? @@ -31,11 +31,11 @@ def !=(other) # def __send__(message, *args) Rubinius.primitive :object_send - raise PrimitiveFailure, "#__send__ primitive failed" + raise ::PrimitiveFailure, "#__send__ primitive failed" end def __id__ Rubinius.primitive :object_id - raise PrimitiveFailure, "#__id__ primitive failed" + raise ::PrimitiveFailure, "#__id__ primitive failed" end end diff --git a/kernel/bootstrap/weakref.rb b/kernel/bootstrap/weakref.rb index 6d2014fdcc..7fe0813506 100644 --- a/kernel/bootstrap/weakref.rb +++ b/kernel/bootstrap/weakref.rb @@ -2,7 +2,7 @@ class WeakRef - class RefError < RuntimeError; end + class RefError < ::RuntimeError; end def self.new Rubinius.primitive :weakref_new diff --git a/kernel/common/basicobject.rb b/kernel/common/basicobject.rb index 06548843d4..0e06c65a90 100644 --- a/kernel/common/basicobject.rb +++ b/kernel/common/basicobject.rb @@ -2,7 +2,7 @@ class BasicObject def method_missing(meth, *args) - Kernel.raise NoMethodError, "Unable to send '#{meth}' on instance of BasicObject" + ::Kernel.raise ::NoMethodError, "Unable to send '#{meth}' on instance of BasicObject" end private :method_missing diff --git a/kernel/common/eval19.rb b/kernel/common/eval19.rb index 90c1b39c8b..59bfb2237a 100644 --- a/kernel/common/eval19.rb +++ b/kernel/common/eval19.rb @@ -23,15 +23,15 @@ class BasicObject # k.instance_eval { @secret } #=> 99 def instance_eval(string=nil, filename="(eval)", line=1, &prc) - if ImmediateValue === self + if ::ImmediateValue === self sc = nil else - sc = Rubinius::Type.object_singleton_class(self) + sc = ::Rubinius::Type.object_singleton_class(self) end if prc if string - raise ArgumentError, 'cannot pass both a block and a string to evaluate' + raise ::ArgumentError, 'cannot pass both a block and a string to evaluate' end # Return a copy of the BlockEnvironment with the receiver set to self env = prc.block @@ -46,24 +46,24 @@ def instance_eval(string=nil, filename="(eval)", line=1, &prc) elsif string string = StringValue(string) - constant_scope = Rubinius::ConstantScope.of_sender + constant_scope = ::Rubinius::ConstantScope.of_sender if sc - constant_scope = Rubinius::ConstantScope.new(sc, constant_scope) + constant_scope = ::Rubinius::ConstantScope.new(sc, constant_scope) else constant_scope = constant_scope.using_disabled_scope end - binding = Binding.setup(Rubinius::VariableScope.of_sender, - Rubinius::CompiledMethod.of_sender, - constant_scope) + binding = ::Binding.setup(::Rubinius::VariableScope.of_sender, + ::Rubinius::CompiledMethod.of_sender, + constant_scope) - be = Rubinius::Compiler.construct_block string, binding, - filename, line + be = ::Rubinius::Compiler.construct_block string, binding, + filename, line be.call_on_instance(self) else - raise ArgumentError, 'block not supplied' + raise ::ArgumentError, 'block not supplied' end end @@ -87,18 +87,18 @@ def instance_eval(string=nil, filename="(eval)", line=1, &prc) # k.instance_exec(5) { |x| @secret+x } #=> 104 def instance_exec(*args, &prc) - raise LocalJumpError, "Missing block" unless block_given? + raise ::LocalJumpError, "Missing block" unless block_given? env = prc.block - if prc.kind_of? Proc::Method + if prc.kind_of? ::Proc::Method return prc.bound_method.call(*args) end constant_scope = env.constant_scope - if ImmediateValue === self + if ::ImmediateValue === self constant_scope = constant_scope.using_disabled_scope else - sc = Rubinius::Type.object_singleton_class(self) + sc = ::Rubinius::Type.object_singleton_class(self) constant_scope = constant_scope.using_current_as(sc) end diff --git a/vm/helpers.cpp b/vm/helpers.cpp index ad953a5382..76c96c0b5c 100644 --- a/vm/helpers.cpp +++ b/vm/helpers.cpp @@ -61,9 +61,11 @@ namespace rubinius { // Ok, this has to be explained or it will be considered black magic. // The scope chain always ends with an entry at the top that contains // a parent of nil, and a module of Object. This entry is put in - // regardless of lexical scoping, it's the default scope. + // regardless of lexical scoping, it's the fallback scope (the default + // scope). This is not case when deriving from BasicObject, which is + // explained later. // - // When looking up a constant, we don't want to consider the default + // When looking up a constant, we don't want to consider the fallback // scope (ie, Object) initially because we need to lookup up // the superclass chain first, because falling back on the default. // @@ -88,6 +90,12 @@ namespace rubinius { // // So, in this case, foo would print "1", not "2". // + // As indicated above, the fallback scope isn't used when the superclass + // chain directly rooted from BasicObject. To determine this is the + // case, we record whether Object is seen when looking up the superclass + // chain. If Object isn't seen, this means we are directly deriving from + // BasicObject. + cur = call_frame->constant_scope(); while(!cur->nil_p()) { // Detect the toplevel scope (the default) and get outta dodge. @@ -103,10 +111,20 @@ namespace rubinius { } // Now look up the superclass chain. + Module *fallback = G(object); + bool object_seen = false; + cur = call_frame->constant_scope(); if(!cur->nil_p()) { Module* mod = cur->module(); while(!mod->nil_p()) { + if(mod == G(object)) { + object_seen = true; + } + if(!object_seen && mod == G(basicobject)) { + fallback = NULL; + } + result = mod->get_const(state, name, found); if(*found) { if(result != filter) return result; @@ -117,11 +135,13 @@ namespace rubinius { } } - // Lastly, check Object specifically - result = G(object)->get_const(state, name, found, true); - if(*found) { - if(result != filter) return result; - *found = false; + // Lastly, check the fallback scope (=Object) specifically if needed + if(fallback) { + result = fallback->get_const(state, name, found, true); + if(*found) { + if(result != filter) return result; + *found = false; + } } return cNil;