Skip to content

Commit

Permalink
evaluate for enumerable function fully evaluates
Browse files Browse the repository at this point in the history
  • Loading branch information
project-eutopia committed Nov 23, 2018
1 parent 7d09195 commit 0a5ace2
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 12 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ calculator.evaluate("f(0-a)", a: 2)
#=> -20
calculator.evaluate("n") # n only exists in the definition of f(x)
#=> Keisan::Exceptions::UndefinedVariableError: n
calculator.evaluate("includes(a, element) = a.reduce(false, found, x, found || (x == element))")
calculator.evaluate("[3, 9].map(x, [1, 3, 5].includes(x))").value
#=> [true, false]
```

This form even supports recursion, but you must explicitly allow it.
Expand Down
12 changes: 10 additions & 2 deletions lib/keisan/functions/enumerable_function.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ def value(ast_function, context = nil)
evaluate(ast_function, context)
end

def unbound_variables(children, context)
super - Set.new(shadowing_variable_names(children).map(&:name))
end

def shadowing_variable_names(children)
raise Exceptions::NotImplementedError.new
end

def evaluate(ast_function, context = nil)
validate_arguments!(ast_function.children.count)
context ||= Context.new
Expand All @@ -20,9 +28,9 @@ def evaluate(ast_function, context = nil)

case operand
when AST::List
evaluate_list(operand, arguments, expression, context)
evaluate_list(operand, arguments, expression, context).evaluate(context)
when AST::Hash
evaluate_hash(operand, arguments, expression, context)
evaluate_hash(operand, arguments, expression, context).evaluate(context)
else
raise Exceptions::InvalidFunctionError.new("Unhandled first argument to #{name}: #{operand}")
end
Expand Down
6 changes: 3 additions & 3 deletions lib/keisan/functions/filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ def initialize
super("filter")
end

def unbound_variables(children, context)
def shadowing_variable_names(children)
if children.size == 3
super - Set[children[1].name]
children[1..1]
else
super - Set[children[1].name, children[2].name]
children[1..2]
end
end

Expand Down
6 changes: 3 additions & 3 deletions lib/keisan/functions/map.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ def initialize
super("map")
end

def unbound_variables(children, context)
def shadowing_variable_names(children)
if children.size == 3
super - Set[children[1].name]
children[1..1]
else
super - Set[children[1].name, children[2].name]
children[1..2]
end
end

Expand Down
6 changes: 3 additions & 3 deletions lib/keisan/functions/reduce.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ def initialize
super("reduce")
end

def unbound_variables(children, context)
def shadowing_variable_names(children)
if children.size == 5
super - Set[children[2].name, children[3].name]
children[2..3]
else
super - Set[children[2].name, children[3].name, children[4].name]
children[2..4]
end
end

Expand Down
3 changes: 3 additions & 0 deletions spec/keisan/ast/function_assignment_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,8 @@
calculator = Keisan::Calculator.new
calculator.evaluate("minimum(a) = a.reduce(INF, current_min, element, if (element < current_min, element, current_min))")
expect(calculator.evaluate("minimum([5,1,3])")).to eq 1

calculator.evaluate("includes(a, element) = a.reduce(false, found, x, found || (x == element))")
expect(calculator.evaluate("[3, 9].map(x, [1, 3, 5].includes(x))")).to eq([true, false])
end
end
2 changes: 1 addition & 1 deletion spec/readme_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
digest = Digest::SHA256.hexdigest(content)

# cat README.md | sha256sum
expected_digest = "399be39e65ec8aaace1f9ce266415bf49627572bcd2ee6f8e05d9f4a62cc241c"
expected_digest = "c430ca4bd926e553e7414c96f89b8f81ef8bf3c491c5484e9f9599f38e06e2f7"
if digest != expected_digest
raise "Invalid README file detected with SHA256 digest of #{digest}. Use command `cat README.md | sha256sum` to get correct digest if your changes to the README are safe. Aborting README test."
end
Expand Down

0 comments on commit 0a5ace2

Please sign in to comment.