dentaku 2.0.9 → 2.0.10
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 +0 -1
- data/CHANGELOG.md +6 -0
- data/lib/dentaku/ast/case.rb +2 -3
- data/lib/dentaku/ast/function.rb +1 -1
- data/lib/dentaku/ast/functions/string_functions.rb +21 -22
- data/lib/dentaku/calculator.rb +2 -2
- data/lib/dentaku/parser.rb +14 -5
- data/lib/dentaku/version.rb +1 -1
- data/spec/ast/case_spec.rb +6 -2
- data/spec/ast/function_spec.rb +6 -0
- data/spec/calculator_spec.rb +34 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2b19bb69372e3700ffb09ca14b5f3fbcb630b06
|
4
|
+
data.tar.gz: 4a67960044c94875d8a0ab2487e9464c820af5ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 017f2d92d2b8110151d51ea2c93abe8964a82a662b40ce1f38a8133b75dea64b51ba774f64d06ffb24353024046eeb59457d239527560a57eeb0671b6dff8cc1
|
7
|
+
data.tar.gz: cd39bb1acee73e4b05d65940310749601bf758c8797c2cca5ed4e45f6850b59a0637b132a8c4eafd0b60ac52a8714ad5b6933ca38fe3dcc0e60ef9588d2565c0
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [v2.0.10] 2016-12-30
|
4
|
+
- fix string function initialization bug
|
5
|
+
- fix issues with CASE statements
|
6
|
+
- allow injecting AST cache
|
7
|
+
|
3
8
|
## [v2.0.9] 2016-09-19
|
4
9
|
- namespace tokenization errors
|
5
10
|
- automatically coerce arguments to string functions as strings
|
@@ -111,6 +116,7 @@
|
|
111
116
|
## [v0.1.0] 2012-01-20
|
112
117
|
- initial release
|
113
118
|
|
119
|
+
[HEAD]: https://github.com/rubysolo/dentaku/compare/v2.0.9...HEAD
|
114
120
|
[v2.0.9]: https://github.com/rubysolo/dentaku/compare/v2.0.8...v2.0.9
|
115
121
|
[v2.0.8]: https://github.com/rubysolo/dentaku/compare/v2.0.7...v2.0.8
|
116
122
|
[v2.0.7]: https://github.com/rubysolo/dentaku/compare/v2.0.6...v2.0.7
|
data/lib/dentaku/ast/case.rb
CHANGED
@@ -43,9 +43,8 @@ module Dentaku
|
|
43
43
|
def dependencies(context={})
|
44
44
|
# TODO: should short-circuit
|
45
45
|
@switch.dependencies(context) +
|
46
|
-
@conditions.flat_map
|
47
|
-
|
48
|
-
end
|
46
|
+
@conditions.flat_map { |condition| condition.dependencies(context) } +
|
47
|
+
@else.dependencies(context)
|
49
48
|
end
|
50
49
|
end
|
51
50
|
end
|
data/lib/dentaku/ast/function.rb
CHANGED
@@ -46,7 +46,7 @@ module Dentaku
|
|
46
46
|
end
|
47
47
|
|
48
48
|
function_class = name.to_s.capitalize
|
49
|
-
Dentaku::AST.send(:remove_const, function_class) if Dentaku::AST.const_defined?(function_class)
|
49
|
+
Dentaku::AST.send(:remove_const, function_class) if Dentaku::AST.const_defined?(function_class, false)
|
50
50
|
Dentaku::AST.const_set(function_class, function)
|
51
51
|
|
52
52
|
function.implementation = implementation
|
@@ -4,9 +4,9 @@ module Dentaku
|
|
4
4
|
module AST
|
5
5
|
module StringFunctions
|
6
6
|
class Left < Function
|
7
|
-
def initialize(
|
8
|
-
|
9
|
-
@length =
|
7
|
+
def initialize(*args)
|
8
|
+
super
|
9
|
+
@string, @length = *@args
|
10
10
|
end
|
11
11
|
|
12
12
|
def value(context={})
|
@@ -17,9 +17,9 @@ module Dentaku
|
|
17
17
|
end
|
18
18
|
|
19
19
|
class Right < Function
|
20
|
-
def initialize(
|
21
|
-
|
22
|
-
@length =
|
20
|
+
def initialize(*args)
|
21
|
+
super
|
22
|
+
@string, @length = *@args
|
23
23
|
end
|
24
24
|
|
25
25
|
def value(context={})
|
@@ -30,10 +30,9 @@ module Dentaku
|
|
30
30
|
end
|
31
31
|
|
32
32
|
class Mid < Function
|
33
|
-
def initialize(
|
34
|
-
|
35
|
-
@offset =
|
36
|
-
@length = length
|
33
|
+
def initialize(*args)
|
34
|
+
super
|
35
|
+
@string, @offset, @length = *@args
|
37
36
|
end
|
38
37
|
|
39
38
|
def value(context={})
|
@@ -45,8 +44,9 @@ module Dentaku
|
|
45
44
|
end
|
46
45
|
|
47
46
|
class Len < Function
|
48
|
-
def initialize(
|
49
|
-
|
47
|
+
def initialize(*args)
|
48
|
+
super
|
49
|
+
@string = @args[0]
|
50
50
|
end
|
51
51
|
|
52
52
|
def value(context={})
|
@@ -56,9 +56,9 @@ module Dentaku
|
|
56
56
|
end
|
57
57
|
|
58
58
|
class Find < Function
|
59
|
-
def initialize(
|
60
|
-
|
61
|
-
@haystack =
|
59
|
+
def initialize(*args)
|
60
|
+
super
|
61
|
+
@needle, @haystack = *@args
|
62
62
|
end
|
63
63
|
|
64
64
|
def value(context={})
|
@@ -71,10 +71,9 @@ module Dentaku
|
|
71
71
|
end
|
72
72
|
|
73
73
|
class Substitute < Function
|
74
|
-
def initialize(
|
75
|
-
|
76
|
-
@search =
|
77
|
-
@replacement = replacement
|
74
|
+
def initialize(*args)
|
75
|
+
super
|
76
|
+
@original, @search, @replacement = *@args
|
78
77
|
end
|
79
78
|
|
80
79
|
def value(context={})
|
@@ -87,9 +86,9 @@ module Dentaku
|
|
87
86
|
end
|
88
87
|
|
89
88
|
class Concat < Function
|
90
|
-
def initialize(
|
91
|
-
|
92
|
-
@right =
|
89
|
+
def initialize(*args)
|
90
|
+
super
|
91
|
+
@left, @right = *@args
|
93
92
|
end
|
94
93
|
|
95
94
|
def value(context={})
|
data/lib/dentaku/calculator.rb
CHANGED
@@ -8,10 +8,10 @@ module Dentaku
|
|
8
8
|
class Calculator
|
9
9
|
attr_reader :result, :memory, :tokenizer
|
10
10
|
|
11
|
-
def initialize
|
11
|
+
def initialize(ast_cache={})
|
12
12
|
clear
|
13
13
|
@tokenizer = Tokenizer.new
|
14
|
-
@ast_cache =
|
14
|
+
@ast_cache = ast_cache
|
15
15
|
@disable_ast_cache = false
|
16
16
|
end
|
17
17
|
|
data/lib/dentaku/parser.rb
CHANGED
@@ -67,15 +67,24 @@ module Dentaku
|
|
67
67
|
# special handling for case nesting: strip out inner case
|
68
68
|
# statements and parse their AST segments recursively
|
69
69
|
if operations.include?(AST::Case)
|
70
|
-
|
71
|
-
|
70
|
+
open_cases = 0
|
71
|
+
case_end_index = nil
|
72
|
+
|
72
73
|
input.each_with_index do |token, index|
|
73
|
-
|
74
|
+
if token.category == :case && token.value == :open
|
75
|
+
open_cases += 1
|
76
|
+
end
|
77
|
+
|
74
78
|
if token.category == :case && token.value == :close
|
75
|
-
|
79
|
+
if open_cases > 0
|
80
|
+
open_cases -= 1
|
81
|
+
else
|
82
|
+
case_end_index = index
|
83
|
+
break
|
84
|
+
end
|
76
85
|
end
|
77
86
|
end
|
78
|
-
inner_case_inputs = input.slice!(0..
|
87
|
+
inner_case_inputs = input.slice!(0..case_end_index)
|
79
88
|
subparser = Parser.new(
|
80
89
|
inner_case_inputs,
|
81
90
|
operations: [AST::Case],
|
data/lib/dentaku/version.rb
CHANGED
data/spec/ast/case_spec.rb
CHANGED
@@ -67,14 +67,18 @@ describe Dentaku::AST::Case do
|
|
67
67
|
let!(:tax) do
|
68
68
|
Dentaku::AST::Identifier.new(Dentaku::Token.new(:identifier, :tax))
|
69
69
|
end
|
70
|
+
let!(:fallback) do
|
71
|
+
Dentaku::AST::Identifier.new(Dentaku::Token.new(:identifier, :fallback))
|
72
|
+
end
|
70
73
|
let!(:addition) { Dentaku::AST::Addition.new(two, tax) }
|
71
74
|
let!(:when2) { Dentaku::AST::CaseWhen.new(banana) }
|
72
75
|
let!(:then2) { Dentaku::AST::CaseThen.new(addition) }
|
76
|
+
let!(:else2) { Dentaku::AST::CaseElse.new(fallback) }
|
73
77
|
let!(:conditional2) { Dentaku::AST::CaseConditional.new(when2, then2) }
|
74
78
|
|
75
79
|
it 'gathers dependencies from switch and conditionals' do
|
76
|
-
node = described_class.new(switch, conditional1, conditional2)
|
77
|
-
expect(node.dependencies).to eq([:fruit, :tax])
|
80
|
+
node = described_class.new(switch, conditional1, conditional2, else2)
|
81
|
+
expect(node.dependencies).to eq([:fruit, :tax, :fallback])
|
78
82
|
end
|
79
83
|
end
|
80
84
|
end
|
data/spec/ast/function_spec.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'dentaku/ast/function'
|
3
3
|
|
4
|
+
class Clazz; end
|
5
|
+
|
4
6
|
describe Dentaku::AST::Function do
|
5
7
|
it 'maintains a function registry' do
|
6
8
|
expect(described_class).to respond_to(:get)
|
@@ -18,4 +20,8 @@ describe Dentaku::AST::Function do
|
|
18
20
|
function = described_class.get("flarble").new
|
19
21
|
expect(function.value).to eq "flarble"
|
20
22
|
end
|
23
|
+
|
24
|
+
it 'does not throw an error when registering a function with a name that matches a currently defined constant' do
|
25
|
+
expect { described_class.register("clazz", :string, -> { "clazzified" }) }.not_to raise_error
|
26
|
+
end
|
21
27
|
end
|
data/spec/calculator_spec.rb
CHANGED
@@ -66,6 +66,12 @@ describe Dentaku::Calculator do
|
|
66
66
|
expect(calculator.dependencies("bob + dole / 3")).to eq(['bob', 'dole'])
|
67
67
|
end
|
68
68
|
|
69
|
+
it "finds dependencies in formula arguments" do
|
70
|
+
allow(Dentaku).to receive(:cache_ast?) { true }
|
71
|
+
|
72
|
+
expect(calculator.dependencies("CONCAT(bob, dole)")).to eq(['bob', 'dole'])
|
73
|
+
end
|
74
|
+
|
69
75
|
it "doesn't consider variables in memory as dependencies" do
|
70
76
|
expect(with_memory.dependencies("apples + oranges")).to eq(['oranges'])
|
71
77
|
end
|
@@ -379,6 +385,34 @@ describe Dentaku::Calculator do
|
|
379
385
|
fruit: 'banana')
|
380
386
|
expect(value).to eq(5)
|
381
387
|
end
|
388
|
+
|
389
|
+
it 'handles multiple nested case statements' do
|
390
|
+
formula = <<-FORMULA
|
391
|
+
CASE fruit
|
392
|
+
WHEN 'apple'
|
393
|
+
THEN
|
394
|
+
CASE quantity
|
395
|
+
WHEN 2 THEN 3
|
396
|
+
END
|
397
|
+
WHEN 'banana'
|
398
|
+
THEN
|
399
|
+
CASE quantity
|
400
|
+
WHEN 1 THEN 2
|
401
|
+
END
|
402
|
+
END
|
403
|
+
FORMULA
|
404
|
+
value = calculator.evaluate(
|
405
|
+
formula,
|
406
|
+
quantity: 1,
|
407
|
+
fruit: 'banana')
|
408
|
+
expect(value).to eq(2)
|
409
|
+
|
410
|
+
value = calculator.evaluate(
|
411
|
+
formula,
|
412
|
+
quantity: 2,
|
413
|
+
fruit: 'apple')
|
414
|
+
expect(value).to eq(3)
|
415
|
+
end
|
382
416
|
end
|
383
417
|
|
384
418
|
describe 'math functions' do
|
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: 2.0.
|
4
|
+
version: 2.0.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Solomon White
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-12-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|