Class: Kalculator::Evaluator

Inherits:
Object
  • Object
show all
Defined in:
lib/kalculator/evaluator.rb

Instance Method Summary collapse

Constructor Details

#initialize(data_source) ⇒ Evaluator

Returns a new instance of Evaluator.



5
6
7
# File 'lib/kalculator/evaluator.rb', line 5

def initialize(data_source)
  @data_source = data_source
end

Instance Method Details

#!=(_, left, right) ⇒ Object



49
50
51
# File 'lib/kalculator/evaluator.rb', line 49

def !=(_, left, right)
  evaluate(left) != evaluate(right)
end

#*(_, left, right) ⇒ Object



21
22
23
# File 'lib/kalculator/evaluator.rb', line 21

def *(_, left, right)
  evaluate(left) * evaluate(right)
end

#+(_, left, right) ⇒ Object



13
14
15
# File 'lib/kalculator/evaluator.rb', line 13

def +(_, left, right)
  evaluate(left) + evaluate(right)
end

#-(_, left, right) ⇒ Object



17
18
19
# File 'lib/kalculator/evaluator.rb', line 17

def -(_, left, right)
  evaluate(left) - evaluate(right)
end

#/(_, left, right) ⇒ Object



25
26
27
# File 'lib/kalculator/evaluator.rb', line 25

def /(_, left, right)
  evaluate(left) / evaluate(right)
end

#<(_, left, right) ⇒ Object



37
38
39
# File 'lib/kalculator/evaluator.rb', line 37

def <(_, left, right)
  evaluate(left) < evaluate(right)
end

#<=(_, left, right) ⇒ Object



41
42
43
# File 'lib/kalculator/evaluator.rb', line 41

def <=(_, left, right)
  evaluate(left) <= evaluate(right)
end

#==(_, left, right) ⇒ Object



45
46
47
# File 'lib/kalculator/evaluator.rb', line 45

def ==(_, left, right)
  evaluate(left) == evaluate(right)
end

#>(_, left, right) ⇒ Object



29
30
31
# File 'lib/kalculator/evaluator.rb', line 29

def >(_, left, right)
  evaluate(left) > evaluate(right)
end

#>=(_, left, right) ⇒ Object



33
34
35
# File 'lib/kalculator/evaluator.rb', line 33

def >=(_, left, right)
  evaluate(left) >= evaluate(right)
end

#and(_, left, right) ⇒ Object



53
54
55
# File 'lib/kalculator/evaluator.rb', line 53

def and(_, left, right)
  evaluate(left) && evaluate(right)
end

#boolean(_, boolean) ⇒ Object



61
62
63
# File 'lib/kalculator/evaluator.rb', line 61

def boolean(_, boolean)
  boolean
end

#contains(_, collection, item) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
# File 'lib/kalculator/evaluator.rb', line 65

def contains(_, collection, item)
  collection = evaluate(collection)
  item = evaluate(item)
  if collection.is_a?(Array)
    collection.include?(item)
  elsif collection.is_a?(String) && item.is_a?(String)
    collection.include?(item)
  else
    raise TypeError, "contains only works with strings or lists, got #{collection.inspect} and #{item.inspect}"
  end
end

#count(_, collection) ⇒ Object

Raises:



77
78
79
80
81
# File 'lib/kalculator/evaluator.rb', line 77

def count(_, collection)
  collection = evaluate(collection)
  raise TypeError, "count only works with Enumerable types, got #{collection.inspect}" unless collection.is_a?(Enumerable)
  collection.count
end

#date(_, expression) ⇒ Object

Raises:



83
84
85
86
87
# File 'lib/kalculator/evaluator.rb', line 83

def date(_, expression)
  value = evaluate(expression)
  raise TypeError, "date only works with Strings, got #{value.inspect}" unless value.is_a?(String)
  Date.parse(value)
end

#evaluate(ast) ⇒ Object



9
10
11
# File 'lib/kalculator/evaluator.rb', line 9

def evaluate(ast)
  send(ast.first, *ast)
end

#if(_, condition, true_clause, false_clause) ⇒ Object



89
90
91
92
93
94
95
# File 'lib/kalculator/evaluator.rb', line 89

def if(_, condition, true_clause, false_clause)
  if evaluate(condition)
    evaluate(true_clause)
  else
    evaluate(false_clause)
  end
end

#list(_, expressions) ⇒ Object



97
98
99
# File 'lib/kalculator/evaluator.rb', line 97

def list(_, expressions)
  expressions.map{|expression| evaluate(expression) }
end

#max(_, left, right) ⇒ Object

Raises:



101
102
103
104
105
106
107
# File 'lib/kalculator/evaluator.rb', line 101

def max(_, left, right)
  left = evaluate(left)
  right = evaluate(right)
  raise TypeError, "max only works with numbers, got #{left.inspect}" unless left.is_a?(Numeric)
  raise TypeError, "max only works with numbers, got #{right.inspect}" unless right.is_a?(Numeric)
  [left, right].max
end

#min(_, left, right) ⇒ Object

Raises:



109
110
111
112
113
114
115
# File 'lib/kalculator/evaluator.rb', line 109

def min(_, left, right)
  left = evaluate(left)
  right = evaluate(right)
  raise TypeError, "min only works with numbers, got #{left.inspect}" unless left.is_a?(Numeric)
  raise TypeError, "min only works with numbers, got #{right.inspect}" unless right.is_a?(Numeric)
  [left, right].min
end

#not(_, expression) ⇒ Object

Raises:



117
118
119
120
121
# File 'lib/kalculator/evaluator.rb', line 117

def not(_, expression)
  bool = evaluate(expression)
  raise TypeError, "! only works with booleans, got #{bool.inspect}" unless bool === true || bool === false
  !bool
end

#number(_, number) ⇒ Object



123
124
125
# File 'lib/kalculator/evaluator.rb', line 123

def number(_, number)
  number
end

#or(_, left, right) ⇒ Object



57
58
59
# File 'lib/kalculator/evaluator.rb', line 57

def or(_, left, right)
  evaluate(left) || evaluate(right)
end

#string(_, string) ⇒ Object



127
128
129
# File 'lib/kalculator/evaluator.rb', line 127

def string(_, string)
  string
end

#sum(_, array) ⇒ Object



131
132
133
134
135
136
137
# File 'lib/kalculator/evaluator.rb', line 131

def sum(_, array)
  array = evaluate(array)
  unless array.is_a?(Array) && array.all?{|n| n.is_a?(Numeric)}
    raise TypeError, "sum only works with lists of numbers, got #{array.inspect}"
  end
  array.inject(0){|sum, num| sum + num}
end

#variable(_, name) ⇒ Object



139
140
141
142
# File 'lib/kalculator/evaluator.rb', line 139

def variable(_, name)
  raise UndefinedVariableError, "undefined variable #{name}" unless @data_source.key?(name)
  @data_source[name]
end