diff --git a/kernel/core/context.rb b/kernel/core/context.rb index eeb76fd..256d456 100644 --- a/kernel/core/context.rb +++ b/kernel/core/context.rb @@ -291,7 +291,11 @@ class BlockContext # Static scope of home method context. def current_scope - home.current_scope + if ss = method.staticscope + return ss.module + else + home.current_scope + end end end diff --git a/kernel/core/eval.rb b/kernel/core/eval.rb index 9e28c76..9c340dd 100644 --- a/kernel/core/eval.rb +++ b/kernel/core/eval.rb @@ -91,6 +91,7 @@ module Kernel script.path = filename compiled_method.staticscope.script = script + ctx = binding.context be = BlockEnvironment.new be.from_eval! @@ -134,7 +135,14 @@ module Kernel flags = { :binding => binding } compiled_method = Compile.compile_string string, flags, filename, line + compiled_method.inherit_scope binding.context.method + + # This has to be setup so __FILE__ works in eval. + script = CompiledMethod::Script.new + script.path = filename + compiled_method.staticscope.script = script compiled_method.hints = { :source => :eval } + ctx = binding.context be = BlockEnvironment.new be.from_eval! diff --git a/kernel/core/kernel.rb b/kernel/core/kernel.rb index da36a59..8f68813 100644 --- a/kernel/core/kernel.rb +++ b/kernel/core/kernel.rb @@ -399,6 +399,8 @@ module Kernel def __add_method__(name, obj) scope = MethodContext.current.sender.current_scope + meth = MethodContext.current.sender.method + Rubinius::VM.reset_method_cache(name) scope.method_table[name] = Tuple[:public, obj] @@ -531,6 +533,7 @@ module Kernel def instance_exec(*args, &prc) raise ArgumentError, "Missing block" unless block_given? env = prc.block.redirect_to self + env.method.staticscope = StaticScope.new(metaclass, env.method.staticscope) env.call(*args) end diff --git a/kernel/core/module.rb b/kernel/core/module.rb index 8bc03b1..4107957 100644 --- a/kernel/core/module.rb +++ b/kernel/core/module.rb @@ -286,17 +286,17 @@ class Module # All userland added methods start out with a serial of 1. obj.serial = 1 - - Rubinius::VM.reset_method_cache(name) - - method_table[name] = Tuple[visibility, obj] - + # Push the scoping down. # HACK they all should have staticscopes if ss = s.method.staticscope obj.staticscope = ss end + Rubinius::VM.reset_method_cache(name) + + ss.module.method_table[name] = Tuple[visibility, obj] + if scope == :module module_function name end diff --git a/shotgun/lib/cpu.c b/shotgun/lib/cpu.c index 8c62575..b1b7c29 100644 --- a/shotgun/lib/cpu.c +++ b/shotgun/lib/cpu.c @@ -341,11 +341,21 @@ OBJECT cpu_const_set(STATE, cpu c, OBJECT sym, OBJECT val, OBJECT under) { void cpu_set_encloser_path(STATE, cpu c, OBJECT cls) { int len; + OBJECT method, ss_debug; len = ptr_array_length(c->paths); ptr_array_append(c->paths, (xpointer)c->enclosing_class); + method = cpu_current_method(state, c); - cmethod_set_staticscope(cpu_current_method(state, c), - cpu_scope_push(state, c, cls)); + // only set static scope if it doesn't have one + if(NIL_P(cmethod_get_staticscope(method))) { + cmethod_set_staticscope(method, cpu_scope_push(state, c, cls)); + } else { + ss_debug = cmethod_get_staticscope(method); + printf("set_encloser_path already had mod: %s and parent: %s\n", + _inspect(staticscope_get_module(ss_debug)), + _inspect(staticscope_get_parent(ss_debug))); + cmethod_set_staticscope(method, cpu_scope_push(state, c, cls)); + } c->enclosing_class = cls; } diff --git a/spec/ruby/1.8/language/def_spec.rb b/spec/ruby/1.8/language/def_spec.rb index 5374933..df0261c 100644 --- a/spec/ruby/1.8/language/def_spec.rb +++ b/spec/ruby/1.8/language/def_spec.rb @@ -370,20 +370,20 @@ describe "A method definition in an eval" do end it "creates a class method" do - class DefSpecNested + class DefSpecNestedB class << self def eval_class_method - eval "def an_eval_class_method;self;end", binding + eval "def an_eval_class_method;self;end" #, binding an_eval_class_method end end end - DefSpecNested.eval_class_method.should == DefSpecNested - DefSpecNested.an_eval_class_method.should == DefSpecNested + DefSpecNestedB.eval_class_method.should == DefSpecNestedB + DefSpecNestedB.an_eval_class_method.should == DefSpecNestedB lambda { Object.an_eval_class_method }.should raise_error(NoMethodError) - lambda { DefSpecNested.new.an_eval_class_method}.should raise_error(NoMethodError) + lambda { DefSpecNestedB.new.an_eval_class_method}.should raise_error(NoMethodError) end it "creates a singleton method" do