Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Avoid using a NullScope at top of the scope chain, keep nil.

  • Loading branch information...
commit 4dcfda758fcf342dc6de7e7cbcb446e15330a32e 1 parent d4540f5
@blambeau authored
View
18 lib/wlang/scope.rb
@@ -14,14 +14,10 @@ def self.null
def self.coerce(arg, parent = nil)
return arg if Scope===arg && parent.nil?
- parent ||= null
clazz = case arg
- when Binding
- BindingScope
- when Scope
- ProxyScope
- when Proc
- ProcScope
+ when Binding then BindingScope
+ when Scope then ProxyScope
+ when Proc then ProcScope
else
ObjectScope
end
@@ -31,7 +27,7 @@ def self.coerce(arg, parent = nil)
def self.chain(scopes)
scopes.compact.inject(nil){|parent,child|
Scope.coerce(child, parent)
- } || null
+ }
end
def push(x)
@@ -59,6 +55,12 @@ def evaluate(expr, *default)
end
end
+ protected
+
+ def safe_parent
+ parent || Scope.null
+ end
+
end # class Scope
end # module WLang
require 'wlang/scope/null_scope'
View
2  lib/wlang/scope/binding_scope.rb
@@ -5,7 +5,7 @@ class BindingScope < Scope
def fetch(k, &blk)
subject.eval(k.to_s)
rescue NameError
- parent.fetch(k, &blk)
+ safe_parent.fetch(k, &blk)
end
def inspect
View
21 lib/wlang/scope/object_scope.rb
@@ -4,15 +4,26 @@ class ObjectScope < Scope
def fetch(k, &blk)
s = subject
- return s if k == :self
+
+ # self special case
+ if k == :self
+ return s
+ end
+
+ # hash indirect access
if s.respond_to?(:has_key?)
- return s[k] if s.has_key?(k)
+ return s[k] if s.has_key?(k)
return s[k.to_s] if s.has_key?(k.to_s)
end
- return s.send(k) if s.respond_to?(k)
- parent.fetch(k, &blk)
+
+ # getter
+ if s.respond_to?(k)
+ return s.send(k)
+ end
+
+ safe_parent.fetch(k, &blk)
rescue NameError
- parent.fetch(k, &blk)
+ safe_parent.fetch(k, &blk)
end
def inspect
View
2  lib/wlang/scope/proc_scope.rb
@@ -4,7 +4,7 @@ class ProcScope < Scope
def fetch(key, &blk)
Scope.coerce(subject.call).fetch(key) do
- parent.fetch(key, &blk)
+ safe_parent.fetch(key, &blk)
end
end
View
2  lib/wlang/scope/proxy_scope.rb
@@ -4,7 +4,7 @@ class ProxyScope < Scope
def fetch(key, &blk)
subject.fetch(key) do
- parent.fetch(key, &blk)
+ safe_parent.fetch(key, &blk)
end
end
View
10 spec/unit/scope/test_chain.rb
@@ -1,28 +1,28 @@
module WLang
describe Scope, '.chain' do
- it 'returns Scope.null on empty chain' do
- Scope.chain([]).should eq(Scope.null)
+ it 'returns nil on empty chain' do
+ Scope.chain([]).should be_nil
end
it 'returns a single scope on singleton' do
s = Scope.chain([{:who => "World"}])
s.should be_a(Scope::ObjectScope)
- s.parent.should eq(Scope.null)
+ s.parent.should be_nil
end
it 'uses the last scope as most specific' do
s = Scope.chain([{:who => "World"}, lambda{}])
s.should be_a(Scope::ProcScope)
s.parent.should be_a(Scope::ObjectScope)
- s.parent.parent.should eq(Scope.null)
+ s.parent.parent.should be_nil
end
it 'strips nils' do
s = Scope.chain([nil, {:who => "World"}, nil, lambda{}, nil])
s.should be_a(Scope::ProcScope)
s.parent.should be_a(Scope::ObjectScope)
- s.parent.parent.should eq(Scope.null)
+ s.parent.parent.should be_nil
end
end
View
2  spec/unit/test_scope.rb
@@ -2,7 +2,7 @@
module WLang
describe Scope do
- let(:scope){ Scope.coerce({:who => "World"}) }
+ let(:scope){ Scope.coerce({:who => "World"}, Scope.null) }
it 'acts like a stack' do
s = scope
Please sign in to comment.
Something went wrong with that request. Please try again.