dentaku 3.1.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +4 -3
- data/CHANGELOG.md +9 -0
- data/README.md +2 -2
- data/lib/dentaku/ast.rb +3 -1
- data/lib/dentaku/ast/functions/avg.rb +13 -0
- data/lib/dentaku/ast/functions/count.rb +18 -0
- data/lib/dentaku/ast/functions/mul.rb +12 -0
- data/lib/dentaku/calculator.rb +3 -3
- data/lib/dentaku/parser.rb +32 -27
- data/lib/dentaku/token_scanner.rb +1 -1
- data/lib/dentaku/version.rb +1 -1
- data/spec/ast/avg_spec.rb +33 -0
- data/spec/ast/count_spec.rb +40 -0
- data/spec/ast/mul_spec.rb +38 -0
- data/spec/calculator_spec.rb +26 -14
- metadata +12 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 402c5a79a4d28d7323c53de8852007fa1c49c087
|
|
4
|
+
data.tar.gz: e5bd251b569708d740a7aeedde619e3bbfa34037
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a7dda0285c345400228dd7ec606958a95b9f57bd54f87a4333b4533d8f671b9ac66485ec8d29f66360b0dc026b00bb57ca842f4cf07e763c5840a2d84fa5a89e
|
|
7
|
+
data.tar.gz: d58d8f1451b0092feb6a8038f0d1efe8b6957c5de0a67badf53538395963098912853ea848c5fab03581ffeeddf89e4bb8812a735ec8ba6be48a76db35760e97
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## [v3.2.0] Unreleased
|
|
4
|
+
- add `COUNT` and `AVG` functions
|
|
5
|
+
- add unicode support 😎
|
|
6
|
+
- fix CASE parsing bug
|
|
7
|
+
- allow dependency filtering based on context
|
|
8
|
+
- add variadic MUL function
|
|
9
|
+
- performance optimization
|
|
10
|
+
|
|
3
11
|
## [v3.1.0] 2017-01-10
|
|
4
12
|
- allow decimals with no leading zero
|
|
5
13
|
- nested hash and array support in bulk expression solver
|
|
@@ -151,6 +159,7 @@
|
|
|
151
159
|
## [v0.1.0] 2012-01-20
|
|
152
160
|
- initial release
|
|
153
161
|
|
|
162
|
+
[v3.2.0]: https://github.com/rubysolo/dentaku/compare/v3.1.0...v3.2.0
|
|
154
163
|
[v3.1.0]: https://github.com/rubysolo/dentaku/compare/v3.0.0...v3.1.0
|
|
155
164
|
[v3.0.0]: https://github.com/rubysolo/dentaku/compare/v2.0.11...v3.0.0
|
|
156
165
|
[v2.0.11]: https://github.com/rubysolo/dentaku/compare/v2.0.10...v2.0.11
|
data/README.md
CHANGED
|
@@ -146,7 +146,7 @@ Comparison: `<`, `>`, `<=`, `>=`, `<>`, `!=`, `=`,
|
|
|
146
146
|
|
|
147
147
|
Logic: `IF`, `AND`, `OR`, `NOT`, `SWITCH`
|
|
148
148
|
|
|
149
|
-
Numeric: `MIN`, `MAX`, `SUM`, `ROUND`, `ROUNDDOWN`, `ROUNDUP`
|
|
149
|
+
Numeric: `MIN`, `MAX`, `SUM`, `AVG`, `COUNT`, `ROUND`, `ROUNDDOWN`, `ROUNDUP`
|
|
150
150
|
|
|
151
151
|
Selections: `CASE` (syntax see [spec](https://github.com/rubysolo/dentaku/blob/master/spec/calculator_spec.rb#L292))
|
|
152
152
|
|
|
@@ -321,7 +321,7 @@ LICENSE
|
|
|
321
321
|
|
|
322
322
|
(The MIT License)
|
|
323
323
|
|
|
324
|
-
Copyright © 2012-
|
|
324
|
+
Copyright © 2012-2018 Solomon White
|
|
325
325
|
|
|
326
326
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
327
327
|
this software and associated documentation files (the ‘Software’), to deal in
|
data/lib/dentaku/ast.rb
CHANGED
|
@@ -15,14 +15,16 @@ require_relative './ast/grouping'
|
|
|
15
15
|
require_relative './ast/case'
|
|
16
16
|
require_relative './ast/function_registry'
|
|
17
17
|
require_relative './ast/functions/and'
|
|
18
|
+
require_relative './ast/functions/avg'
|
|
19
|
+
require_relative './ast/functions/count'
|
|
18
20
|
require_relative './ast/functions/if'
|
|
19
21
|
require_relative './ast/functions/max'
|
|
20
22
|
require_relative './ast/functions/min'
|
|
21
23
|
require_relative './ast/functions/not'
|
|
22
24
|
require_relative './ast/functions/or'
|
|
23
25
|
require_relative './ast/functions/round'
|
|
24
|
-
require_relative './ast/functions/roundup'
|
|
25
26
|
require_relative './ast/functions/rounddown'
|
|
27
|
+
require_relative './ast/functions/roundup'
|
|
26
28
|
require_relative './ast/functions/ruby_math'
|
|
27
29
|
require_relative './ast/functions/string_functions'
|
|
28
30
|
require_relative './ast/functions/sum'
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require_relative '../function'
|
|
2
|
+
|
|
3
|
+
Dentaku::AST::Function.register(:avg, :numeric, ->(*args) {
|
|
4
|
+
if args.empty?
|
|
5
|
+
raise Dentaku::ArgumentError.for(
|
|
6
|
+
:too_few_arguments,
|
|
7
|
+
function_name: 'AVG()', at_least: 1, given: 0
|
|
8
|
+
), 'AVG() requires at least one argument'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
flatten_args = args.flatten
|
|
12
|
+
flatten_args.map { |arg| Dentaku::AST::Function.numeric(arg) }.reduce(0, :+) / flatten_args.length
|
|
13
|
+
})
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require_relative '../function'
|
|
2
|
+
|
|
3
|
+
module Dentaku
|
|
4
|
+
module AST
|
|
5
|
+
class Count < Function
|
|
6
|
+
def value(context = {})
|
|
7
|
+
if @args.length == 1
|
|
8
|
+
first_arg = @args[0].value(context)
|
|
9
|
+
return first_arg.length if first_arg.respond_to?(:length)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
@args.length
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
Dentaku::AST::Function.register_class(:count, Dentaku::AST::Count)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require_relative '../function'
|
|
2
|
+
|
|
3
|
+
Dentaku::AST::Function.register(:mul, :numeric, ->(*args) {
|
|
4
|
+
if args.empty?
|
|
5
|
+
raise Dentaku::ArgumentError.for(
|
|
6
|
+
:too_few_arguments,
|
|
7
|
+
function_name: 'MUL()', at_least: 1, given: 0
|
|
8
|
+
), 'MUL() requires at least one argument'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
args.flatten.map { |arg| Dentaku::AST::Function.numeric(arg) }.reduce(1, :*)
|
|
12
|
+
})
|
data/lib/dentaku/calculator.rb
CHANGED
|
@@ -75,11 +75,11 @@ module Dentaku
|
|
|
75
75
|
BulkExpressionSolver.new(expression_hash, self).solve(&block)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
-
def dependencies(expression)
|
|
78
|
+
def dependencies(expression, context = {})
|
|
79
79
|
if expression.is_a? Array
|
|
80
|
-
return expression.flat_map { |e| dependencies(e) }
|
|
80
|
+
return expression.flat_map { |e| dependencies(e, context) }
|
|
81
81
|
end
|
|
82
|
-
ast(expression).dependencies(memory)
|
|
82
|
+
store(context) { ast(expression).dependencies(memory) }
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
def ast(expression)
|
data/lib/dentaku/parser.rb
CHANGED
|
@@ -2,6 +2,28 @@ require_relative './ast'
|
|
|
2
2
|
|
|
3
3
|
module Dentaku
|
|
4
4
|
class Parser
|
|
5
|
+
AST_OPERATIONS = {
|
|
6
|
+
add: AST::Addition,
|
|
7
|
+
subtract: AST::Subtraction,
|
|
8
|
+
multiply: AST::Multiplication,
|
|
9
|
+
divide: AST::Division,
|
|
10
|
+
pow: AST::Exponentiation,
|
|
11
|
+
negate: AST::Negation,
|
|
12
|
+
mod: AST::Modulo,
|
|
13
|
+
bitor: AST::BitwiseOr,
|
|
14
|
+
bitand: AST::BitwiseAnd,
|
|
15
|
+
|
|
16
|
+
lt: AST::LessThan,
|
|
17
|
+
gt: AST::GreaterThan,
|
|
18
|
+
le: AST::LessThanOrEqual,
|
|
19
|
+
ge: AST::GreaterThanOrEqual,
|
|
20
|
+
ne: AST::NotEqual,
|
|
21
|
+
eq: AST::Equal,
|
|
22
|
+
|
|
23
|
+
and: AST::And,
|
|
24
|
+
or: AST::Or,
|
|
25
|
+
}.freeze
|
|
26
|
+
|
|
5
27
|
attr_reader :input, :output, :operations, :arities, :case_sensitive
|
|
6
28
|
|
|
7
29
|
def initialize(tokens, options = {})
|
|
@@ -78,6 +100,9 @@ module Dentaku
|
|
|
78
100
|
operations.push func
|
|
79
101
|
|
|
80
102
|
when :case
|
|
103
|
+
case_index = operations.index { |o| o == AST::Case } || -1
|
|
104
|
+
token_index = case_index + 1
|
|
105
|
+
|
|
81
106
|
case token.value
|
|
82
107
|
when :open
|
|
83
108
|
# special handling for case nesting: strip out inner case
|
|
@@ -113,7 +138,7 @@ module Dentaku
|
|
|
113
138
|
arities.push(0)
|
|
114
139
|
end
|
|
115
140
|
when :close
|
|
116
|
-
if operations[
|
|
141
|
+
if operations[token_index] == AST::CaseThen
|
|
117
142
|
while operations.last != AST::Case
|
|
118
143
|
consume
|
|
119
144
|
end
|
|
@@ -121,7 +146,7 @@ module Dentaku
|
|
|
121
146
|
operations.push(AST::CaseConditional)
|
|
122
147
|
consume(2)
|
|
123
148
|
arities[-1] += 1
|
|
124
|
-
elsif operations[
|
|
149
|
+
elsif operations[token_index] == AST::CaseElse
|
|
125
150
|
while operations.last != AST::Case
|
|
126
151
|
consume
|
|
127
152
|
end
|
|
@@ -129,12 +154,12 @@ module Dentaku
|
|
|
129
154
|
arities[-1] += 1
|
|
130
155
|
end
|
|
131
156
|
|
|
132
|
-
unless operations.count
|
|
157
|
+
unless operations.count >= 1 && operations.last == AST::Case
|
|
133
158
|
fail! :unprocessed_token, token_name: token.value
|
|
134
159
|
end
|
|
135
160
|
consume(arities.pop.succ)
|
|
136
161
|
when :when
|
|
137
|
-
if operations[
|
|
162
|
+
if operations[token_index] == AST::CaseThen
|
|
138
163
|
while ![AST::CaseWhen, AST::Case].include?(operations.last)
|
|
139
164
|
consume
|
|
140
165
|
end
|
|
@@ -148,14 +173,14 @@ module Dentaku
|
|
|
148
173
|
|
|
149
174
|
operations.push(AST::CaseWhen)
|
|
150
175
|
when :then
|
|
151
|
-
if operations[
|
|
176
|
+
if operations[token_index] == AST::CaseWhen
|
|
152
177
|
while ![AST::CaseThen, AST::Case].include?(operations.last)
|
|
153
178
|
consume
|
|
154
179
|
end
|
|
155
180
|
end
|
|
156
181
|
operations.push(AST::CaseThen)
|
|
157
182
|
when :else
|
|
158
|
-
if operations[
|
|
183
|
+
if operations[token_index] == AST::CaseThen
|
|
159
184
|
while operations.last != AST::Case
|
|
160
185
|
consume
|
|
161
186
|
end
|
|
@@ -237,27 +262,7 @@ module Dentaku
|
|
|
237
262
|
end
|
|
238
263
|
|
|
239
264
|
def operation(token)
|
|
240
|
-
|
|
241
|
-
add: AST::Addition,
|
|
242
|
-
subtract: AST::Subtraction,
|
|
243
|
-
multiply: AST::Multiplication,
|
|
244
|
-
divide: AST::Division,
|
|
245
|
-
pow: AST::Exponentiation,
|
|
246
|
-
negate: AST::Negation,
|
|
247
|
-
mod: AST::Modulo,
|
|
248
|
-
bitor: AST::BitwiseOr,
|
|
249
|
-
bitand: AST::BitwiseAnd,
|
|
250
|
-
|
|
251
|
-
lt: AST::LessThan,
|
|
252
|
-
gt: AST::GreaterThan,
|
|
253
|
-
le: AST::LessThanOrEqual,
|
|
254
|
-
ge: AST::GreaterThanOrEqual,
|
|
255
|
-
ne: AST::NotEqual,
|
|
256
|
-
eq: AST::Equal,
|
|
257
|
-
|
|
258
|
-
and: AST::And,
|
|
259
|
-
or: AST::Or,
|
|
260
|
-
}.fetch(token.value)
|
|
265
|
+
AST_OPERATIONS.fetch(token.value)
|
|
261
266
|
end
|
|
262
267
|
|
|
263
268
|
def function(token)
|
data/lib/dentaku/version.rb
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'dentaku/ast/functions/avg'
|
|
3
|
+
require 'dentaku'
|
|
4
|
+
|
|
5
|
+
describe 'Dentaku::AST::Function::Avg' do
|
|
6
|
+
it 'returns the average of an array of Numeric values' do
|
|
7
|
+
result = Dentaku('AVG(1, x, 1.8)', x: 2.3)
|
|
8
|
+
expect(result).to eq 1.7
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'returns the average of a single entry array of a Numeric value' do
|
|
12
|
+
result = Dentaku('AVG(x)', x: 2.3)
|
|
13
|
+
expect(result).to eq 2.3
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'returns the average even if a String is passed' do
|
|
17
|
+
result = Dentaku('AVG(1, x, 1.8)', x: '2.3')
|
|
18
|
+
expect(result).to eq 1.7
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'returns the average even if an array is passed' do
|
|
22
|
+
result = Dentaku('AVG(1, x, 2.3)', x: [4, 5])
|
|
23
|
+
expect(result).to eq 3.075
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'checking errors' do
|
|
27
|
+
let(:calculator) { Dentaku::Calculator.new }
|
|
28
|
+
|
|
29
|
+
it 'raises an error if no arguments are passed' do
|
|
30
|
+
expect { calculator.evaluate!('AVG()') }.to raise_error(ArgumentError)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'dentaku/ast/functions/count'
|
|
3
|
+
require 'dentaku'
|
|
4
|
+
|
|
5
|
+
describe 'Dentaku::AST::Count' do
|
|
6
|
+
it 'returns the length of an array' do
|
|
7
|
+
result = Dentaku('COUNT(1, x, 1.8)', x: 2.3)
|
|
8
|
+
expect(result).to eq 3
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'returns the length of a single number object' do
|
|
12
|
+
result = Dentaku('COUNT(x)', x: 2.3)
|
|
13
|
+
expect(result).to eq 1
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'returns the length if a single String is passed' do
|
|
17
|
+
result = Dentaku('COUNT(x)', x: 'dentaku')
|
|
18
|
+
expect(result).to eq 7
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'returns the length if an array is passed' do
|
|
22
|
+
result = Dentaku('COUNT(x)', x: [4, 5])
|
|
23
|
+
expect(result).to eq 2
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'returns the length if an array with one element is passed' do
|
|
27
|
+
result = Dentaku('COUNT(x)', x: [4])
|
|
28
|
+
expect(result).to eq 1
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'returns the length if an array even if it has nested array' do
|
|
32
|
+
result = Dentaku('COUNT(1, x, 3)', x: [4, 5])
|
|
33
|
+
expect(result).to eq 3
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'returns the length if an array is passed' do
|
|
37
|
+
result = Dentaku('COUNT()')
|
|
38
|
+
expect(result).to eq 0
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'dentaku/ast/functions/mul'
|
|
3
|
+
require 'dentaku'
|
|
4
|
+
|
|
5
|
+
describe 'Dentaku::AST::Function::Mul' do
|
|
6
|
+
it 'returns the product of an array of Numeric values' do
|
|
7
|
+
result = Dentaku('MUL(1, x, 1.8)', x: 2.3)
|
|
8
|
+
expect(result).to eq 4.14
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'returns the product of a single entry array of a Numeric value' do
|
|
12
|
+
result = Dentaku('MUL(x)', x: 2.3)
|
|
13
|
+
expect(result).to eq 2.3
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'coerces string inputs to numeric' do
|
|
17
|
+
result = Dentaku('mul(1, x, 1.8)', x: '2.3')
|
|
18
|
+
expect(result).to eq 4.14
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'returns the product even if an array is passed' do
|
|
22
|
+
result = Dentaku('mul(1, x, 2.3)', x: [4, 5])
|
|
23
|
+
expect(result).to eq 46
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'handles nested calls' do
|
|
27
|
+
result = Dentaku('mul(1, x, mul(4, 5))', x: '2.3')
|
|
28
|
+
expect(result).to eq 46
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context 'checking errors' do
|
|
32
|
+
let(:calculator) { Dentaku::Calculator.new }
|
|
33
|
+
|
|
34
|
+
it 'raises an error if no arguments are passed' do
|
|
35
|
+
expect { calculator.evaluate!('MUL()') }.to raise_error(ArgumentError)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
data/spec/calculator_spec.rb
CHANGED
|
@@ -41,6 +41,10 @@ describe Dentaku::Calculator do
|
|
|
41
41
|
expect(calculator.evaluate("2 & 3 * 9")).to eq (2)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
+
it 'supports unicode characters in identifiers' do
|
|
45
|
+
expect(calculator.evaluate("ρ * 2", ρ: 2)).to eq (4)
|
|
46
|
+
end
|
|
47
|
+
|
|
44
48
|
describe 'memory' do
|
|
45
49
|
it { expect(calculator).to be_empty }
|
|
46
50
|
it { expect(with_memory).not_to be_empty }
|
|
@@ -90,6 +94,10 @@ describe Dentaku::Calculator do
|
|
|
90
94
|
expect(calculator.dependencies("bob + dole / 3")).to eq(['bob', 'dole'])
|
|
91
95
|
end
|
|
92
96
|
|
|
97
|
+
it "ignores dependencies passed in context" do
|
|
98
|
+
expect(calculator.dependencies("a + b", a: 1)).to eq(['b'])
|
|
99
|
+
end
|
|
100
|
+
|
|
93
101
|
it "finds dependencies in formula arguments" do
|
|
94
102
|
allow(Dentaku).to receive(:cache_ast?) { true }
|
|
95
103
|
|
|
@@ -371,19 +379,33 @@ describe Dentaku::Calculator do
|
|
|
371
379
|
end
|
|
372
380
|
|
|
373
381
|
describe 'case statements' do
|
|
374
|
-
|
|
375
|
-
|
|
382
|
+
let(:formula) {
|
|
383
|
+
<<-FORMULA
|
|
376
384
|
CASE fruit
|
|
377
385
|
WHEN 'apple'
|
|
378
|
-
THEN
|
|
386
|
+
THEN 1 * quantity
|
|
379
387
|
WHEN 'banana'
|
|
380
|
-
THEN
|
|
388
|
+
THEN 2 * quantity
|
|
389
|
+
ELSE
|
|
390
|
+
3 * quantity
|
|
381
391
|
END
|
|
382
392
|
FORMULA
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
it 'handles complex then statements' do
|
|
383
396
|
expect(calculator.evaluate(formula, quantity: 3, fruit: 'apple')).to eq(3)
|
|
384
397
|
expect(calculator.evaluate(formula, quantity: 3, fruit: 'banana')).to eq(6)
|
|
385
398
|
end
|
|
386
399
|
|
|
400
|
+
it 'evaluates case statement as part of a larger expression' do
|
|
401
|
+
expect(calculator.evaluate("2 + #{formula}", quantity: 3, fruit: 'apple')).to eq(5)
|
|
402
|
+
expect(calculator.evaluate("2 + #{formula}", quantity: 3, fruit: 'banana')).to eq(8)
|
|
403
|
+
expect(calculator.evaluate("2 + #{formula}", quantity: 3, fruit: 'kiwi')).to eq(11)
|
|
404
|
+
expect(calculator.evaluate("#{formula} + 2", quantity: 3, fruit: 'apple')).to eq(5)
|
|
405
|
+
expect(calculator.evaluate("#{formula} + 2", quantity: 3, fruit: 'banana')).to eq(8)
|
|
406
|
+
expect(calculator.evaluate("#{formula} + 2", quantity: 3, fruit: 'kiwi')).to eq(11)
|
|
407
|
+
end
|
|
408
|
+
|
|
387
409
|
it 'handles complex when statements' do
|
|
388
410
|
formula = <<-FORMULA
|
|
389
411
|
CASE number
|
|
@@ -409,16 +431,6 @@ describe Dentaku::Calculator do
|
|
|
409
431
|
end
|
|
410
432
|
|
|
411
433
|
it 'handles a default else statement' do
|
|
412
|
-
formula = <<-FORMULA
|
|
413
|
-
CASE fruit
|
|
414
|
-
WHEN 'apple'
|
|
415
|
-
THEN 1 * quantity
|
|
416
|
-
WHEN 'banana'
|
|
417
|
-
THEN 2 * quantity
|
|
418
|
-
ELSE
|
|
419
|
-
3 * quantity
|
|
420
|
-
END
|
|
421
|
-
FORMULA
|
|
422
434
|
expect(calculator.evaluate(formula, quantity: 1, fruit: 'banana')).to eq(2)
|
|
423
435
|
expect(calculator.evaluate(formula, quantity: 1, fruit: 'orange')).to eq(3)
|
|
424
436
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dentaku
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Solomon White
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2018-
|
|
11
|
+
date: 2018-03-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: codecov
|
|
@@ -156,9 +156,12 @@ files:
|
|
|
156
156
|
- lib/dentaku/ast/function.rb
|
|
157
157
|
- lib/dentaku/ast/function_registry.rb
|
|
158
158
|
- lib/dentaku/ast/functions/and.rb
|
|
159
|
+
- lib/dentaku/ast/functions/avg.rb
|
|
160
|
+
- lib/dentaku/ast/functions/count.rb
|
|
159
161
|
- lib/dentaku/ast/functions/if.rb
|
|
160
162
|
- lib/dentaku/ast/functions/max.rb
|
|
161
163
|
- lib/dentaku/ast/functions/min.rb
|
|
164
|
+
- lib/dentaku/ast/functions/mul.rb
|
|
162
165
|
- lib/dentaku/ast/functions/not.rb
|
|
163
166
|
- lib/dentaku/ast/functions/or.rb
|
|
164
167
|
- lib/dentaku/ast/functions/round.rb
|
|
@@ -195,12 +198,15 @@ files:
|
|
|
195
198
|
- spec/ast/and_function_spec.rb
|
|
196
199
|
- spec/ast/and_spec.rb
|
|
197
200
|
- spec/ast/arithmetic_spec.rb
|
|
201
|
+
- spec/ast/avg_spec.rb
|
|
198
202
|
- spec/ast/case_spec.rb
|
|
199
203
|
- spec/ast/comparator_spec.rb
|
|
204
|
+
- spec/ast/count_spec.rb
|
|
200
205
|
- spec/ast/division_spec.rb
|
|
201
206
|
- spec/ast/function_spec.rb
|
|
202
207
|
- spec/ast/max_spec.rb
|
|
203
208
|
- spec/ast/min_spec.rb
|
|
209
|
+
- spec/ast/mul_spec.rb
|
|
204
210
|
- spec/ast/node_spec.rb
|
|
205
211
|
- spec/ast/numeric_spec.rb
|
|
206
212
|
- spec/ast/or_spec.rb
|
|
@@ -242,7 +248,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
242
248
|
version: '0'
|
|
243
249
|
requirements: []
|
|
244
250
|
rubyforge_project: dentaku
|
|
245
|
-
rubygems_version: 2.
|
|
251
|
+
rubygems_version: 2.6.13
|
|
246
252
|
signing_key:
|
|
247
253
|
specification_version: 4
|
|
248
254
|
summary: A formula language parser and evaluator
|
|
@@ -251,12 +257,15 @@ test_files:
|
|
|
251
257
|
- spec/ast/and_function_spec.rb
|
|
252
258
|
- spec/ast/and_spec.rb
|
|
253
259
|
- spec/ast/arithmetic_spec.rb
|
|
260
|
+
- spec/ast/avg_spec.rb
|
|
254
261
|
- spec/ast/case_spec.rb
|
|
255
262
|
- spec/ast/comparator_spec.rb
|
|
263
|
+
- spec/ast/count_spec.rb
|
|
256
264
|
- spec/ast/division_spec.rb
|
|
257
265
|
- spec/ast/function_spec.rb
|
|
258
266
|
- spec/ast/max_spec.rb
|
|
259
267
|
- spec/ast/min_spec.rb
|
|
268
|
+
- spec/ast/mul_spec.rb
|
|
260
269
|
- spec/ast/node_spec.rb
|
|
261
270
|
- spec/ast/numeric_spec.rb
|
|
262
271
|
- spec/ast/or_spec.rb
|