Class: Dentaku::Calculator

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeCalculator

Returns a new instance of Calculator.



12
13
14
# File 'lib/dentaku/calculator.rb', line 12

def initialize
  clear
end

Instance Attribute Details

#resultObject (readonly)

Returns the value of attribute result.



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

def result
  @result
end

Instance Method Details

#add_function(fn) ⇒ Object



16
17
18
19
# File 'lib/dentaku/calculator.rb', line 16

def add_function(fn)
  Rules.add_function(fn)
  self
end

#add_functions(fns) ⇒ Object



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

def add_functions(fns)
  fns.each { |fn| Rules.add_function(fn) }
  self
end

#clearObject



87
88
89
# File 'lib/dentaku/calculator.rb', line 87

def clear
  @memory = {}
end

#dependencies(expression) ⇒ Object



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

def dependencies(expression)
  Expression.new(expression, @memory).identifiers
end

#empty?Boolean

Returns:

  • (Boolean)


91
92
93
# File 'lib/dentaku/calculator.rb', line 91

def empty?
  @memory.empty?
end

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



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

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

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



32
33
34
35
36
37
38
39
# File 'lib/dentaku/calculator.rb', line 32

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(expr.tokens)
  end
end

#solve!(expression_hash) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/dentaku/calculator.rb', line 41

def solve!(expression_hash)
  expressions = Hash[expression_hash.map { |k,v| [k.to_s, v] }]

  # expression_hash: { variable_name: "string expression" }
  # TSort thru the expressions' dependencies, then evaluate all
  expression_dependencies = Hash[expressions.map do |var, expr|
    [var, dependencies(expr)]
  end]

  variables_in_resolve_order = DependencyResolver::find_resolve_order(
    expression_dependencies)

  results = variables_in_resolve_order.each_with_object({}) do |var_name, r|
    r[var_name] = evaluate!(expressions[var_name], r)
  end

  expression_hash.each_with_object({}) do |(k, _), r|
    r[k] = results[k.to_s]
  end
end

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



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/dentaku/calculator.rb', line 66

def store(key_or_hash, value=nil)
  restore = @memory.dup

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

  if block_given?
    result = yield
    @memory = restore
    return result
  end

  self
end