Skip to content

Commit

Permalink
Allow local definitions to shadow defaults
Browse files Browse the repository at this point in the history
  • Loading branch information
project-eutopia committed Dec 27, 2017
1 parent 6322e5f commit 1809b57
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 9 deletions.
12 changes: 10 additions & 2 deletions lib/keisan/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,12 @@ def has_variable?(name)
@variable_registry.has?(name)
end

def variable_is_modifiable?(name)
@variable_registry.modifiable?(name)
end

def register_variable!(name, value, local: false)
if !@variable_registry.shadowed.member?(name) && (transient? || !local && @parent&.has_variable?(name))
if !@variable_registry.shadowed.member?(name) && (transient? || !local && @parent&.variable_is_modifiable?(name))
@parent.register_variable!(name, value)
else
@variable_registry.register!(name, value)
Expand All @@ -77,8 +81,12 @@ def has_function?(name)
@function_registry.has?(name)
end

def function_is_modifiable?(name)
@function_registry.modifiable?(name)
end

def register_function!(name, function, local: false)
if transient? || !local && @parent&.has_function?(name)
if transient? || !local && @parent&.function_is_modifiable?(name)
@parent.register_function!(name, function)
else
@function_registry.register!(name.to_s, function)
Expand Down
8 changes: 4 additions & 4 deletions lib/keisan/functions/registry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ def has?(name)
false
end

def modifiable?(name)
!frozen? && has?(name)
end

def register!(name, function, force: false)
raise Exceptions::UnmodifiableError.new("Cannot modify frozen functions registry") if frozen?
name = name.to_s

if !force && @use_defaults && default_registry.has_name?(name)
raise Exceptions::UnmodifiableError.new("Cannot overwrite default function")
end

case function
when Proc
self[name] = ProcFunction.new(name, function)
Expand Down
7 changes: 4 additions & 3 deletions lib/keisan/variables/registry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@ def has?(name)
false
end

def modifiable?(name)
!frozen? && has?(name)
end

def register!(name, value, force: false)
name = name.to_s
name = name.name if name.is_a?(AST::Variable)

raise Exceptions::UnmodifiableError.new("Cannot modify frozen variables registry") if frozen?
if !force && @use_defaults && default_registry.has_name?(name)
raise Exceptions::UnmodifiableError.new("Cannot overwrite default variable")
end
self[name.to_s] = AST::Cell.new(value.to_node)
end

Expand Down
8 changes: 8 additions & 0 deletions spec/keisan/default_functions_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@
expect { registry.register!(:bad, Proc.new { false }) }.to raise_error(Keisan::Exceptions::UnmodifiableError)
end

it "creates local function when conflicting with function in default registry" do
calculator = Keisan::Calculator.new
calculator.evaluate("sin(theta) = theta")

expect(calculator.evaluate("sin(1)").value).to eq 1
expect(registry["sin"].call(nil, 1).value).to eq Math.sin(1)
end

context "array methods" do
it "works as expected" do
expect(registry["min"].name).to eq "min"
Expand Down
8 changes: 8 additions & 0 deletions spec/keisan/default_variables_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,12 @@
it "is unmodifiable" do
expect { registry.register!(:bad, false) }.to raise_error(Keisan::Exceptions::UnmodifiableError)
end

it "creates local variable when conflicting with variable in default registry" do
calculator = Keisan::Calculator.new
calculator.evaluate("PI = 3")

expect(calculator.evaluate("PI").value).to eq 3
expect(registry["PI"].value).to eq Math::PI
end
end

0 comments on commit 1809b57

Please sign in to comment.