Class: Dentaku::Calculator

Inherits:
Object
  • Object
show all
Defined in:
lib/dentaku/calculator.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ast_cache = {}) ⇒ Calculator

Returns a new instance of Calculator.



12
13
14
15
16
17
18
# File 'lib/dentaku/calculator.rb', line 12

def initialize(ast_cache={})
  clear
  @tokenizer = Tokenizer.new
  @ast_cache = ast_cache
  @disable_ast_cache = false
  @function_registry = Dentaku::AST::FunctionRegistry.new
end

Instance Attribute Details

#memoryObject (readonly)

Returns the value of attribute memory.



10
11
12
# File 'lib/dentaku/calculator.rb', line 10

def memory
  @memory
end

#resultObject (readonly)

Returns the value of attribute result.



10
11
12
# File 'lib/dentaku/calculator.rb', line 10

def result
  @result
end

#tokenizerObject (readonly)

Returns the value of attribute tokenizer.



10
11
12
# File 'lib/dentaku/calculator.rb', line 10

def tokenizer
  @tokenizer
end

Class Method Details

.add_function(name, type, body) ⇒ Object



20
21
22
# File 'lib/dentaku/calculator.rb', line 20

def self.add_function(name, type, body)
  Dentaku::AST::FunctionRegistry.default.register(name, type, body)
end

Instance Method Details

#add_function(name, type, body) ⇒ Object



28
29
30
31
# File 'lib/dentaku/calculator.rb', line 28

def add_function(name, type, body)
  @function_registry.register(name, type, body)
  self
end

#add_functions(fns) ⇒ Object



24
25
26
# File 'lib/dentaku/calculator.rb', line 24

def add_functions(fns)
  fns.each { |(name, type, body)| add_function(name, type, body) }
end

#ast(expression) ⇒ Object



71
72
73
74
75
76
77
# File 'lib/dentaku/calculator.rb', line 71

def ast(expression)
  @ast_cache.fetch(expression) {
    Parser.new(tokenizer.tokenize(expression), function_registry: @function_registry).parse.tap do |node|
      @ast_cache[expression] = node if cache_ast?
    end
  }
end

#cache_ast?Boolean

Returns:

  • (Boolean)


130
131
132
# File 'lib/dentaku/calculator.rb', line 130

def cache_ast?
  Dentaku.cache_ast? && !@disable_ast_cache
end

#clearObject



122
123
124
# File 'lib/dentaku/calculator.rb', line 122

def clear
  @memory = {}
end

#clear_cache(pattern = :all) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/dentaku/calculator.rb', line 79

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
    fail Dentaku::ArgumentError
  end
end

#dependencies(expression) ⇒ Object



67
68
69
# File 'lib/dentaku/calculator.rb', line 67

def dependencies(expression)
  ast(expression).dependencies(memory)
end

#disable_cacheObject



38
39
40
41
42
43
# File 'lib/dentaku/calculator.rb', line 38

def disable_cache
  @disable_ast_cache = true
  yield(self) if block_given?
ensure
  @disable_ast_cache = false
end

#empty?Boolean

Returns:

  • (Boolean)


126
127
128
# File 'lib/dentaku/calculator.rb', line 126

def empty?
  memory.empty?
end

#evaluate(expression, data = {}) ⇒ Object



45
46
47
48
49
# File 'lib/dentaku/calculator.rb', line 45

def evaluate(expression, data={})
  evaluate!(expression, data)
rescue UnboundVariableError, ArgumentError
  yield expression if block_given?
end

#evaluate!(expression, data = {}) ⇒ Object



51
52
53
54
55
56
57
# File 'lib/dentaku/calculator.rb', line 51

def evaluate!(expression, data={})
  store(data) do
    node = expression
    node = ast(node) unless node.is_a?(AST::Node)
    node.value(memory)
  end
end

#solve(expression_hash, &block) ⇒ Object



63
64
65
# File 'lib/dentaku/calculator.rb', line 63

def solve(expression_hash, &block)
  BulkExpressionSolver.new(expression_hash, self).solve(&block)
end

#solve!(expression_hash) ⇒ Object



59
60
61
# File 'lib/dentaku/calculator.rb', line 59

def solve!(expression_hash)
  BulkExpressionSolver.new(expression_hash, self).solve!
end

#store(key_or_hash, value = nil) ⇒ Object Also known as: bind



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/dentaku/calculator.rb', line 92

def store(key_or_hash, value=nil)
  restore = Hash[memory]

  if value.nil?
    _flat_hash(key_or_hash).each do |key, val|
      memory[key.to_s.downcase] = val
    end
  else
    memory[key_or_hash.to_s.downcase] = value
  end

  if block_given?
    begin
      result = yield
      @memory = restore
      return result
    rescue => e
      @memory = restore
      raise e
    end
  end

  self
end

#store_formula(key, formula) ⇒ Object



118
119
120
# File 'lib/dentaku/calculator.rb', line 118

def store_formula(key, formula)
  store(key, ast(formula))
end