class Dentaku::Calculator
Attributes
aliases[R]
ast_cache[R]
case_sensitive[R]
memory[R]
nested_data_support[R]
raw_date_literals[R]
result[R]
tokenizer[R]
Public Class Methods
add_function(name, type, body, callback = nil)
click to toggle source
# File lib/dentaku/calculator.rb, line 29 def self.add_function(name, type, body, callback = nil) Dentaku::AST::FunctionRegistry.default.register(name, type, body, callback) end
add_functions(functions)
click to toggle source
# File lib/dentaku/calculator.rb, line 33 def self.add_functions(functions) functions.each { |(name, type, body, callback)| add_function(name, type, body, callback) } end
new(options = {})
click to toggle source
# File lib/dentaku/calculator.rb, line 15 def initialize(options = {}) clear @tokenizer = Tokenizer.new @case_sensitive = options.delete(:case_sensitive) @aliases = options.delete(:aliases) || Dentaku.aliases @nested_data_support = options.fetch(:nested_data_support, true) options.delete(:nested_data_support) @raw_date_literals = options.fetch(:raw_date_literals, true) options.delete(:raw_date_literals) @ast_cache = options @disable_ast_cache = false @function_registry = Dentaku::AST::FunctionRegistry.new end
Public Instance Methods
add_function(name, type, body, callback = nil)
click to toggle source
# File lib/dentaku/calculator.rb, line 37 def add_function(name, type, body, callback = nil) @function_registry.register(name, type, body, callback) self end
add_functions(functions)
click to toggle source
# File lib/dentaku/calculator.rb, line 42 def add_functions(functions) functions.each { |(name, type, body, callback)| add_function(name, type, body, callback) } self end
ast(expression)
click to toggle source
# File lib/dentaku/calculator.rb, line 109 def ast(expression) return expression if expression.is_a?(AST::Node) return expression.map { |e| ast(e) } if expression.is_a? Array @ast_cache.fetch(expression) { options = { aliases: aliases, case_sensitive: case_sensitive, function_registry: @function_registry, raw_date_literals: raw_date_literals } tokens = tokenizer.tokenize(expression, options) Parser.new(tokens, options).parse.tap do |node| @ast_cache[expression] = node if cache_ast? end } end
cache_ast?()
click to toggle source
# File lib/dentaku/calculator.rb, line 188 def cache_ast? Dentaku.cache_ast? && !@disable_ast_cache end
clear()
click to toggle source
# File lib/dentaku/calculator.rb, line 180 def clear @memory = {} end
clear_cache(pattern = :all)
click to toggle source
# File lib/dentaku/calculator.rb, line 132 def clear_cache(pattern = :all) case pattern when :all @ast_cache = {} when String @ast_cache.delete(pattern) when Regexp @ast_cache.delete_if { |k, _| k =~ pattern } else raise ::ArgumentError end end
dependencies(expression, context = {})
click to toggle source
# File lib/dentaku/calculator.rb, line 96 def dependencies(expression, context = {}) test_context = context.nil? ? {} : store(context) { memory } case expression when Dentaku::AST::Node expression.dependencies(test_context) when Array expression.flat_map { |e| dependencies(e, context) } else ast(expression).dependencies(test_context) end end
disable_cache() { |self| ... }
click to toggle source
# File lib/dentaku/calculator.rb, line 47 def disable_cache @disable_ast_cache = true yield(self) if block_given? ensure @disable_ast_cache = false end
empty?()
click to toggle source
# File lib/dentaku/calculator.rb, line 184 def empty? memory.empty? end
evaluate(expression, data = {}, &block)
click to toggle source
# File lib/dentaku/calculator.rb, line 54 def evaluate(expression, data = {}, &block) context = evaluation_context(data, :permissive) return evaluate_array(expression, context, &block) if expression.is_a?(Array) evaluate!(expression, context) rescue Dentaku::Error, Dentaku::ArgumentError, Dentaku::ZeroDivisionError => ex block.call(expression, ex) if block_given? end
evaluate!(expression, data = {}, &block)
click to toggle source
# File lib/dentaku/calculator.rb, line 67 def evaluate!(expression, data = {}, &block) context = evaluation_context(data, :strict) return evaluate_array!(expression, context, &block) if expression.is_a? Array store(context) do node = ast(expression) unbound = node.dependencies(memory) unless unbound.empty? raise UnboundVariableError.new(unbound), "no value provided for variables: #{unbound.uniq.join(', ')}" end node.value(memory) end end
evaluation_context(data, evaluation_mode)
click to toggle source
# File lib/dentaku/calculator.rb, line 145 def evaluation_context(data, evaluation_mode) data.key?(:__evaluation_mode) ? data : data.merge(__evaluation_mode: evaluation_mode) end
load_cache(ast_cache)
click to toggle source
# File lib/dentaku/calculator.rb, line 128 def load_cache(ast_cache) @ast_cache = ast_cache end
solve(expression_hash, &block)
click to toggle source
# File lib/dentaku/calculator.rb, line 92 def solve(expression_hash, &block) BulkExpressionSolver.new(expression_hash, self).solve(&block) end
solve!(expression_hash)
click to toggle source
# File lib/dentaku/calculator.rb, line 88 def solve!(expression_hash) BulkExpressionSolver.new(expression_hash, self).solve! end
store(key_or_hash, value = nil) { || ... }
click to toggle source
# File lib/dentaku/calculator.rb, line 149 def store(key_or_hash, value = nil) restore = Hash[memory] if value.nil? key_or_hash = FlatHash.from_hash_with_intermediates(key_or_hash) if nested_data_support key_or_hash.each do |key, val| memory[standardize_case(key.to_s)] = val end else memory[standardize_case(key_or_hash.to_s)] = value end if block_given? begin result = yield @memory = restore return result rescue => e @memory = restore raise e end end self end
Also aliased as: bind
store_formula(key, formula)
click to toggle source
# File lib/dentaku/calculator.rb, line 176 def store_formula(key, formula) store(key, ast(formula)) end
Private Instance Methods
evaluate_array(expression, data = {}, &block)
click to toggle source
# File lib/dentaku/calculator.rb, line 63 def evaluate_array(expression, data = {}, &block) expression.map { |e| evaluate(e, data, &block) } end
evaluate_array!(expression, data = {}, &block)
click to toggle source
# File lib/dentaku/calculator.rb, line 84 def evaluate_array!(expression, data = {}, &block) expression.map { |e| evaluate!(e, data, &block) } end