Skip to content

Commit 7e83483

Browse files
authored
Fix various issue with array arithmetic (#321)
- should work with explicit arrays - should not crash when it has deeply a string that looks like date
1 parent c68567e commit 7e83483

File tree

5 files changed

+39
-30
lines changed

5 files changed

+39
-30
lines changed

lib/dentaku/ast/arithmetic.rb

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,6 @@ class Arithmetic < Operation
99
DECIMAL = /\A-?\d*\.\d+\z/.freeze
1010
INTEGER = /\A-?\d+\z/.freeze
1111

12-
def initialize(*)
13-
super
14-
15-
unless valid_left?
16-
raise NodeError.new(:numeric, left.type, :left),
17-
"#{self.class} requires numeric operands"
18-
end
19-
20-
unless valid_right?
21-
raise NodeError.new(:numeric, right.type, :right),
22-
"#{self.class} requires numeric operands"
23-
end
24-
end
25-
2612
def type
2713
:numeric
2814
end
@@ -69,8 +55,9 @@ def decimal(val)
6955
def datetime?(val)
7056
# val is a Date, Time, or DateTime
7157
return true if val.respond_to?(:strftime)
58+
return false unless val.is_a?(::String)
7259

73-
val.to_s =~ Dentaku::TokenScanner::DATE_TIME_REGEXP
60+
val =~ Dentaku::TokenScanner::DATE_TIME_REGEXP
7461
end
7562

7663
def valid_node?(node)

spec/ast/addition_spec.rb

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,21 @@
2020
expect(node.value).to eq(11)
2121
end
2222

23-
it 'requires numeric operands' do
23+
it 'requires operands that respond to +' do
2424
expect {
25-
described_class.new(five, t)
26-
}.to raise_error(Dentaku::NodeError, /requires numeric operands/)
25+
described_class.new(five, t).value
26+
}.to raise_error(Dentaku::ArgumentError, /requires operands that respond to +/)
2727

2828
expression = Dentaku::AST::Multiplication.new(five, five)
2929
group = Dentaku::AST::Grouping.new(expression)
3030

3131
expect {
32-
described_class.new(group, five)
32+
described_class.new(group, five).value
3333
}.not_to raise_error
3434
end
3535

3636
it 'allows operands that respond to addition' do
3737
# Sample struct that has a custom definition for addition
38-
3938
Addable = Struct.new(:value) do
4039
def +(other)
4140
case other
@@ -51,12 +50,18 @@ def +(other)
5150
operand_six = Dentaku::AST::Numeric.new Dentaku::Token.new(:numeric, Addable.new(6))
5251

5352
expect {
54-
described_class.new(operand_five, operand_six)
53+
described_class.new(operand_five, operand_six).value
5554
}.not_to raise_error
5655

5756
expect {
58-
described_class.new(operand_five, six)
57+
described_class.new(operand_five, six).value
5958
}.not_to raise_error
59+
end
60+
61+
it 'does not try to parse nested string as date' do
62+
a = ['2017-01-01', '2017-01-02']
63+
b = ['2017-01-01']
6064

65+
expect(Dentaku('a + b', a: a, b: b)).to eq(['2017-01-01', '2017-01-02', '2017-01-01'])
6166
end
6267
end

spec/ast/arithmetic_spec.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ def coerce(other)
111111
end
112112
end
113113

114+
it 'does not try to parse nested string as date' do
115+
a = ['2017-01-01', '2017-01-02']
116+
b = ['2017-01-01']
117+
118+
expect(Dentaku('a - b', a: a, b: b)).to eq(['2017-01-02'])
119+
end
120+
114121
it 'raises ArgumentError if given individually valid but incompatible arguments' do
115122
expect { add(one, date) }.to raise_error(Dentaku::ArgumentError)
116123
expect { add(x, one, 'x' => [1]) }.to raise_error(Dentaku::ArgumentError)

spec/ast/division_spec.rb

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,16 @@
2020
expect(node.value.round(4)).to eq(0.8333)
2121
end
2222

23-
it 'requires numeric operands' do
23+
it 'requires operands that respond to /' do
2424
expect {
25-
described_class.new(five, t)
26-
}.to raise_error(Dentaku::NodeError, /requires numeric operands/)
25+
described_class.new(five, t).value
26+
}.to raise_error(Dentaku::ArgumentError, /requires operands that respond to \//)
2727

2828
expression = Dentaku::AST::Multiplication.new(five, five)
2929
group = Dentaku::AST::Grouping.new(expression)
3030

3131
expect {
32-
described_class.new(group, five)
32+
described_class.new(group, five).value
3333
}.not_to raise_error
3434
end
3535

@@ -44,17 +44,21 @@ def /(other)
4444
value + other
4545
end
4646
end
47+
48+
def zero?
49+
value.zero?
50+
end
4751
end
4852

4953
operand_five = Dentaku::AST::Numeric.new Dentaku::Token.new(:numeric, Divisible.new(5))
5054
operand_six = Dentaku::AST::Numeric.new Dentaku::Token.new(:numeric, Divisible.new(6))
5155

5256
expect {
53-
described_class.new(operand_five, operand_six)
57+
described_class.new(operand_five, operand_six).value
5458
}.not_to raise_error
5559

5660
expect {
57-
described_class.new(operand_five, six)
61+
described_class.new(operand_five, six).value
5862
}.not_to raise_error
5963
end
6064
end

spec/parser_spec.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,17 @@
7777
end
7878

7979
it 'evaluates arrays' do
80+
node = parse('{}')
81+
expect(node.value).to eq([])
82+
8083
node = parse('{1, 2, 3}')
8184
expect(node.value).to eq([1, 2, 3])
8285

83-
node = parse('{}')
84-
expect(node.value).to eq([])
86+
node = parse('{1, 2, 3} + {4,5,6}')
87+
expect(node.value).to eq([1, 2, 3, 4, 5, 6])
88+
89+
node = parse('{1, 2, 3} - {2,3}')
90+
expect(node.value).to eq([1])
8591
end
8692

8793
context 'invalid expression' do

0 commit comments

Comments
 (0)