lib/dentaku/calculator.rb in dentaku-1.0.0 vs lib/dentaku/calculator.rb in dentaku-1.1.0

- old
+ new

@@ -1,9 +1,9 @@ require 'dentaku/evaluator' +require 'dentaku/expression' require 'dentaku/rules' require 'dentaku/token' -require 'dentaku/tokenizer' module Dentaku class Calculator attr_reader :result @@ -20,23 +20,24 @@ fns.each { |fn| Rules.add_function(fn) } self end def evaluate(expression, data={}) - @tokenizer ||= Tokenizer.new - @tokens = @tokenizer.tokenize(expression) + evaluate!(expression, data) + rescue UnboundVariableError + yield expression if block_given? + end + def evaluate!(expression, data={}) store(data) do + expr = Expression.new(expression, @memory) + raise UnboundVariableError.new(expr.identifiers) if expr.unbound? @evaluator ||= Evaluator.new - @result = @evaluator.evaluate(replace_identifiers_with_values) + @result = @evaluator.evaluate(expr.tokens) end end - def memory(key=nil) - key ? @memory[key.to_sym] : @memory - end - def store(key_or_hash, value=nil) restore = @memory.dup if value @memory[key_or_hash.to_sym] = value @@ -60,31 +61,8 @@ @memory = {} end def empty? @memory.empty? - end - - private - - def replace_identifiers_with_values - @tokens.map do |token| - if token.is?(:identifier) - value = memory(token.value) - type = type_for_value(value) - - Token.new(type, value) - else - token - end - end - end - - def type_for_value(value) - case value - when String then :string - when TrueClass, FalseClass then :logical - else :numeric - end end end end