abstract_mapper 0.0.2 → 0.1.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 +0 -4
- data/CHANGELOG.md +26 -0
- data/README.md +5 -5
- data/Rakefile +1 -1
- data/abstract_mapper.gemspec +1 -0
- data/lib/abstract_mapper.rb +4 -15
- data/lib/abstract_mapper/ast.rb +16 -0
- data/lib/abstract_mapper/ast/branch.rb +121 -0
- data/lib/abstract_mapper/ast/node.rb +91 -0
- data/lib/abstract_mapper/builder.rb +2 -2
- data/lib/abstract_mapper/commands.rb +4 -2
- data/lib/abstract_mapper/commands/base.rb +69 -0
- data/lib/abstract_mapper/dsl.rb +2 -2
- data/lib/abstract_mapper/errors.rb +17 -0
- data/lib/abstract_mapper/errors/wrong_node.rb +1 -1
- data/lib/abstract_mapper/errors/wrong_rule.rb +1 -1
- data/lib/abstract_mapper/optimizer.rb +1 -1
- data/lib/abstract_mapper/rules.rb +10 -5
- data/lib/abstract_mapper/rules/base.rb +74 -0
- data/lib/abstract_mapper/rules/pair.rb +68 -0
- data/lib/abstract_mapper/rules/sole.rb +60 -0
- data/lib/abstract_mapper/settings.rb +22 -30
- data/lib/abstract_mapper/version.rb +1 -1
- data/lib/rspec/nodes.rb +2 -2
- data/spec/integration/faceter.rb +4 -4
- data/spec/integration/rspec_examples_spec.rb +0 -6
- data/spec/unit/abstract_mapper/{branch_spec.rb → ast/branch_spec.rb} +28 -61
- data/spec/unit/abstract_mapper/{node_spec.rb → ast/node_spec.rb} +16 -53
- data/spec/unit/abstract_mapper/builder_spec.rb +9 -24
- data/spec/unit/abstract_mapper/{command_spec.rb → commands/base_spec.rb} +10 -25
- data/spec/unit/abstract_mapper/commands_spec.rb +9 -14
- data/spec/unit/abstract_mapper/dsl_spec.rb +23 -15
- data/spec/unit/abstract_mapper/errors/unknown_command_spec.rb +1 -4
- data/spec/unit/abstract_mapper/errors/wrong_node_spec.rb +5 -4
- data/spec/unit/abstract_mapper/errors/wrong_rule_spec.rb +5 -5
- data/spec/unit/abstract_mapper/functions/compact_spec.rb +0 -2
- data/spec/unit/abstract_mapper/functions/filter_spec.rb +0 -2
- data/spec/unit/abstract_mapper/functions/identity_spec.rb +0 -2
- data/spec/unit/abstract_mapper/functions/restrict_spec.rb +0 -3
- data/spec/unit/abstract_mapper/functions/subclass_spec.rb +0 -2
- data/spec/unit/abstract_mapper/optimizer_spec.rb +13 -17
- data/spec/unit/abstract_mapper/{rule_spec.rb → rules/base_spec.rb} +17 -34
- data/spec/unit/abstract_mapper/{pair_rule_spec.rb → rules/pair_spec.rb} +8 -8
- data/spec/unit/abstract_mapper/{sole_rule_spec.rb → rules/sole_spec.rb} +5 -5
- data/spec/unit/abstract_mapper/rules_spec.rb +24 -37
- data/spec/unit/abstract_mapper/settings_spec.rb +38 -32
- data/spec/unit/abstract_mapper_spec.rb +9 -16
- metadata +37 -22
- data/lib/abstract_mapper/attributes.rb +0 -65
- data/lib/abstract_mapper/branch.rb +0 -120
- data/lib/abstract_mapper/command.rb +0 -68
- data/lib/abstract_mapper/node.rb +0 -87
- data/lib/abstract_mapper/pair_rule.rb +0 -64
- data/lib/abstract_mapper/rule.rb +0 -73
- data/lib/abstract_mapper/sole_rule.rb +0 -56
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
class AbstractMapper
|
4
4
|
|
5
|
-
describe AbstractMapper::
|
5
|
+
describe AbstractMapper::Commands::Base do
|
6
6
|
|
7
7
|
let(:command) { described_class.new name, klass, converter }
|
8
8
|
let(:name) { "foo" }
|
@@ -12,55 +12,44 @@ class AbstractMapper
|
|
12
12
|
let(:block) { proc { :foo } }
|
13
13
|
|
14
14
|
describe ".new" do
|
15
|
-
|
16
15
|
subject { command }
|
17
|
-
it { is_expected.to be_frozen }
|
18
16
|
|
17
|
+
it { is_expected.to be_frozen }
|
19
18
|
end # describe .new
|
20
19
|
|
21
20
|
describe "#name" do
|
22
|
-
|
23
21
|
subject { command.name }
|
24
|
-
it { is_expected.to eql name.to_sym }
|
25
22
|
|
23
|
+
it { is_expected.to eql name.to_sym }
|
26
24
|
end # describe #name
|
27
25
|
|
28
26
|
describe "#klass" do
|
29
|
-
|
30
27
|
subject { command.klass }
|
31
|
-
it { is_expected.to eql klass }
|
32
28
|
|
29
|
+
it { is_expected.to eql klass }
|
33
30
|
end # describe #name
|
34
31
|
|
35
32
|
describe "#converter" do
|
36
|
-
|
37
33
|
subject { command.converter }
|
38
34
|
|
39
35
|
context "by default" do
|
40
|
-
|
41
36
|
let(:command) { described_class.new name, klass }
|
42
37
|
|
43
38
|
it "returns identity function" do
|
44
39
|
expect(subject.call(foo: :BAR)).to eql(foo: :BAR)
|
45
40
|
expect(subject.call).to eql({})
|
46
41
|
end
|
47
|
-
|
48
|
-
end # context
|
42
|
+
end
|
49
43
|
|
50
44
|
context "initialized" do
|
51
|
-
|
52
45
|
it { is_expected.to eql converter }
|
53
|
-
|
54
|
-
end # context
|
55
|
-
|
46
|
+
end
|
56
47
|
end # describe #name
|
57
48
|
|
58
49
|
describe "#call" do
|
59
|
-
|
60
50
|
subject { command.call(arguments, &block) }
|
61
51
|
|
62
52
|
context "when the klass is not a branch" do
|
63
|
-
|
64
53
|
it "builds a node" do
|
65
54
|
expect(klass).to receive(:new) do |args, &blk|
|
66
55
|
expect(args).to eql(converter.call(arguments))
|
@@ -68,12 +57,10 @@ class AbstractMapper
|
|
68
57
|
end
|
69
58
|
subject
|
70
59
|
end
|
71
|
-
|
72
|
-
end # context
|
60
|
+
end
|
73
61
|
|
74
62
|
context "when the klass is a branch" do
|
75
|
-
|
76
|
-
let(:klass) { Class.new(Branch) }
|
63
|
+
let(:klass) { Class.new(AST::Branch) }
|
77
64
|
|
78
65
|
it "builds a branch" do
|
79
66
|
expect(klass).to receive(:new) do |args, &blk|
|
@@ -82,11 +69,9 @@ class AbstractMapper
|
|
82
69
|
end
|
83
70
|
subject
|
84
71
|
end
|
85
|
-
|
86
|
-
end # context
|
87
|
-
|
72
|
+
end
|
88
73
|
end # describe #call
|
89
74
|
|
90
|
-
end # describe AbstractMapper::
|
75
|
+
end # describe AbstractMapper::Commands::Base
|
91
76
|
|
92
77
|
end # class AbstractMapper
|
@@ -4,31 +4,29 @@ class AbstractMapper
|
|
4
4
|
|
5
5
|
describe AbstractMapper::Commands do
|
6
6
|
|
7
|
-
let(:foo) { Test::Foo = Class.new(AbstractMapper::Branch) }
|
8
|
-
let(:bar) { Test::Bar = Class.new(AbstractMapper::Node)
|
9
|
-
let(:test) { Class.new(described_class)
|
10
|
-
let(:commands) { test.new
|
11
|
-
let(:converter) { -> v { v.reverse }
|
7
|
+
let(:foo) { Test::Foo = Class.new(AbstractMapper::AST::Branch) }
|
8
|
+
let(:bar) { Test::Bar = Class.new(AbstractMapper::AST::Node) }
|
9
|
+
let(:test) { Class.new(described_class) }
|
10
|
+
let(:commands) { test.new }
|
11
|
+
let(:converter) { -> v { v.reverse } }
|
12
12
|
|
13
13
|
describe ".new" do
|
14
|
+
subject { test.new(registry) }
|
14
15
|
|
15
16
|
let(:registry) { { foo: foo, bar: bar } }
|
16
|
-
subject { test.new(registry) }
|
17
17
|
|
18
18
|
it { is_expected.to be_frozen }
|
19
19
|
|
20
20
|
it "doesn't freeze arguments" do
|
21
21
|
expect { subject }.not_to change { registry.frozen? }
|
22
22
|
end
|
23
|
-
|
24
23
|
end # describe .new
|
25
24
|
|
26
25
|
describe "#[]" do
|
27
|
-
|
28
26
|
subject { commands << ["foo", foo] }
|
29
27
|
|
30
28
|
it "returns registered command" do
|
31
|
-
expect(subject["foo"]).to be_kind_of
|
29
|
+
expect(subject["foo"]).to be_kind_of Commands::Base
|
32
30
|
end
|
33
31
|
|
34
32
|
it "complains about unknown command" do
|
@@ -37,26 +35,23 @@ class AbstractMapper
|
|
37
35
|
expect(error.message).to include "baz"
|
38
36
|
end
|
39
37
|
end
|
40
|
-
|
41
38
|
end # describe #[]
|
42
39
|
|
43
40
|
describe "#<<" do
|
44
|
-
|
45
41
|
subject { commands << ["foo", foo] << ["bar", bar, converter] }
|
46
42
|
|
47
43
|
it { is_expected.to be_kind_of test }
|
48
44
|
|
49
45
|
it "preserves registered commands" do
|
50
|
-
expect(subject[:foo]).to be_kind_of
|
46
|
+
expect(subject[:foo]).to be_kind_of Commands::Base
|
51
47
|
end
|
52
48
|
|
53
49
|
it "registers new command" do
|
54
|
-
expect(subject[:bar]).to be_kind_of
|
50
|
+
expect(subject[:bar]).to be_kind_of Commands::Base
|
55
51
|
expect(subject[:bar].name).to eql :bar
|
56
52
|
expect(subject[:bar].klass).to eql bar
|
57
53
|
expect(subject[:bar].converter).to eql converter
|
58
54
|
end
|
59
|
-
|
60
55
|
end # describe #<<
|
61
56
|
|
62
57
|
end # describe AbstractMapper::Commands
|
@@ -5,11 +5,10 @@ class AbstractMapper
|
|
5
5
|
describe AbstractMapper::DSL do
|
6
6
|
|
7
7
|
let!(:dsl) { Class.new { extend DSL } }
|
8
|
-
let!(:foo) { Test::Foo = Class.new(Node) { attribute :foo } }
|
9
|
-
let!(:bar) { Test::Bar = Class.new(Branch) { attribute :bar } }
|
10
|
-
|
8
|
+
let!(:foo) { Test::Foo = Class.new(AST::Node) { attribute :foo } }
|
9
|
+
let!(:bar) { Test::Bar = Class.new(AST::Branch) { attribute :bar } }
|
11
10
|
let!(:rule) do
|
12
|
-
Test::Rule = Class.new(
|
11
|
+
Test::Rule = Class.new(Rules::Pair) do
|
13
12
|
def optimize?
|
14
13
|
left.instance_of?(Test::Foo)
|
15
14
|
end
|
@@ -19,7 +18,6 @@ class AbstractMapper
|
|
19
18
|
end
|
20
19
|
end
|
21
20
|
end
|
22
|
-
|
23
21
|
let!(:config) do
|
24
22
|
dsl.configure do
|
25
23
|
command :foo, Test::Foo
|
@@ -29,21 +27,36 @@ class AbstractMapper
|
|
29
27
|
end
|
30
28
|
|
31
29
|
describe "#configure" do
|
32
|
-
|
33
30
|
subject { config }
|
34
31
|
|
35
|
-
it
|
32
|
+
it "returns self" do
|
33
|
+
expect(subject).to eql dsl
|
34
|
+
end
|
36
35
|
|
37
36
|
it "configures settings" do
|
38
37
|
subject
|
38
|
+
|
39
39
|
expect(dsl.settings).to be_kind_of Settings
|
40
40
|
expect(dsl.settings.rules.registry).to eql [rule]
|
41
41
|
expect { dsl.settings.commands[:foo] }.not_to raise_error
|
42
42
|
end
|
43
43
|
|
44
|
+
it "updates existing settings" do
|
45
|
+
subject
|
46
|
+
dsl.configure do
|
47
|
+
command :baz, Test::Foo
|
48
|
+
end
|
49
|
+
|
50
|
+
expect(dsl.settings).to be_kind_of Settings
|
51
|
+
expect(dsl.settings.rules.registry).to eql [rule]
|
52
|
+
expect { dsl.settings.commands[:foo] }.not_to raise_error
|
53
|
+
expect { dsl.settings.commands[:bar] }.not_to raise_error
|
54
|
+
expect { dsl.settings.commands[:baz] }.not_to raise_error
|
55
|
+
end
|
44
56
|
end # describe #configure
|
45
57
|
|
46
58
|
describe "#finalize" do
|
59
|
+
subject { dsl.finalize }
|
47
60
|
|
48
61
|
before do
|
49
62
|
dsl.instance_eval do
|
@@ -55,31 +68,26 @@ class AbstractMapper
|
|
55
68
|
end
|
56
69
|
end
|
57
70
|
|
58
|
-
|
59
|
-
|
60
|
-
it { is_expected.to be_kind_of Branch }
|
71
|
+
it { is_expected.to be_kind_of AST::Branch }
|
61
72
|
|
62
73
|
it "is optimized" do
|
63
74
|
desc = "<Root [<Bar(bar: :baz) [<Foo(foo: :quxx)>]>, <Foo(foo: :foo)>]>"
|
64
75
|
expect(subject.inspect).to eql(desc)
|
65
76
|
end
|
66
|
-
|
67
77
|
end # describe #finalize
|
68
78
|
|
69
79
|
describe "#respond_to?" do
|
70
|
-
|
71
80
|
subject { dsl.respond_to? :anything }
|
72
|
-
it { is_expected.to eql true }
|
73
81
|
|
82
|
+
it { is_expected.to eql true }
|
74
83
|
end # describe #respond_to?
|
75
84
|
|
76
85
|
describe ".inherited" do
|
86
|
+
subject { subklass.settings }
|
77
87
|
|
78
88
|
let(:subklass) { Class.new(dsl) }
|
79
|
-
subject { subklass.settings }
|
80
89
|
|
81
90
|
it { is_expected.to eql dsl.settings }
|
82
|
-
|
83
91
|
end # describe .inherited
|
84
92
|
|
85
93
|
end # describe AbstractMapper::DSL
|
@@ -5,17 +5,14 @@ describe AbstractMapper::Errors::UnknownCommand do
|
|
5
5
|
subject(:error) { described_class.new :foo }
|
6
6
|
|
7
7
|
describe ".new" do
|
8
|
-
|
9
8
|
it { is_expected.to be_kind_of NameError }
|
10
9
|
it { is_expected.to be_frozen }
|
11
|
-
|
12
10
|
end # describe .new
|
13
11
|
|
14
12
|
describe "#message" do
|
15
|
-
|
16
13
|
subject { error.message }
|
17
|
-
it { is_expected.to eql "'foo' is not a registered DSL command" }
|
18
14
|
|
15
|
+
it { is_expected.to eql "'foo' is not a registered DSL command" }
|
19
16
|
end # describe #message
|
20
17
|
|
21
18
|
end # describe AbstractMapper::Errors::UnknownCommand
|
@@ -2,20 +2,21 @@
|
|
2
2
|
|
3
3
|
describe AbstractMapper::Errors::WrongNode do
|
4
4
|
|
5
|
-
|
5
|
+
let(:error) { described_class.new Symbol }
|
6
6
|
|
7
7
|
describe ".new" do
|
8
|
+
subject { error }
|
8
9
|
|
9
10
|
it { is_expected.to be_kind_of TypeError }
|
10
11
|
it { is_expected.to be_frozen }
|
11
|
-
|
12
12
|
end # describe .new
|
13
13
|
|
14
14
|
describe "#message" do
|
15
|
-
|
16
15
|
subject { error.message }
|
17
|
-
it { is_expected.to eql "Symbol is not a subclass of AbstractMapper::Node" }
|
18
16
|
|
17
|
+
it do
|
18
|
+
is_expected.to eql "Symbol is not a subclass of AbstractMapper::AST::Node"
|
19
|
+
end
|
19
20
|
end # describe #message
|
20
21
|
|
21
22
|
end # describe AbstractMapper::Errors::WrongNode
|
@@ -2,22 +2,22 @@
|
|
2
2
|
|
3
3
|
describe AbstractMapper::Errors::WrongRule do
|
4
4
|
|
5
|
-
|
5
|
+
let(:error) { described_class.new Symbol }
|
6
6
|
|
7
7
|
describe ".new" do
|
8
|
+
subject { error }
|
8
9
|
|
9
10
|
it { is_expected.to be_kind_of TypeError }
|
10
11
|
it { is_expected.to be_frozen }
|
11
|
-
|
12
12
|
end # describe .new
|
13
13
|
|
14
14
|
describe "#message" do
|
15
|
-
|
16
15
|
subject { error.message }
|
16
|
+
|
17
17
|
it do
|
18
|
-
is_expected
|
18
|
+
is_expected
|
19
|
+
.to eql "Symbol is not a subclass of AbstractMapper::Rules::Base"
|
19
20
|
end
|
20
|
-
|
21
21
|
end # describe #message
|
22
22
|
|
23
23
|
end # describe AbstractMapper::Errors::WrongRule
|
@@ -3,7 +3,6 @@
|
|
3
3
|
require "transproc/rspec"
|
4
4
|
|
5
5
|
describe AbstractMapper::Functions, "#compact" do
|
6
|
-
|
7
6
|
let(:fn) { -> a, b { (a == b) ? [a + b] : [a, b] } }
|
8
7
|
let(:arguments) { [:compact, fn] }
|
9
8
|
|
@@ -21,5 +20,4 @@ describe AbstractMapper::Functions, "#compact" do
|
|
21
20
|
let(:input) { [1, 1, 2, 3, 3] }
|
22
21
|
let(:output) { [4, 6] }
|
23
22
|
end
|
24
|
-
|
25
23
|
end # describe AbstractMapper::Functions#compact
|
@@ -3,7 +3,6 @@
|
|
3
3
|
require "transproc/rspec"
|
4
4
|
|
5
5
|
describe AbstractMapper::Functions, "#filter" do
|
6
|
-
|
7
6
|
let(:arguments) { [:filter, -> v { v - 1 if v > 3 }] }
|
8
7
|
|
9
8
|
it_behaves_like :transforming_immutable_data do
|
@@ -22,5 +21,4 @@ describe AbstractMapper::Functions, "#filter" do
|
|
22
21
|
let(:input) { [1, 4, 9, 7, 2, 5] }
|
23
22
|
let(:output) { [3, 8, 6, 4] }
|
24
23
|
end
|
25
|
-
|
26
24
|
end # describe AbstractMapper::Functions#filter
|
@@ -3,7 +3,6 @@
|
|
3
3
|
require "transproc/rspec"
|
4
4
|
|
5
5
|
describe AbstractMapper::Functions, "#identity" do
|
6
|
-
|
7
6
|
it_behaves_like :transforming_immutable_data do
|
8
7
|
let(:arguments) { [:identity] }
|
9
8
|
|
@@ -17,5 +16,4 @@ describe AbstractMapper::Functions, "#identity" do
|
|
17
16
|
let(:input) { :foo }
|
18
17
|
let(:output) { :foo }
|
19
18
|
end
|
20
|
-
|
21
19
|
end # describe AbstractMapper::Functions#identity
|
@@ -3,14 +3,11 @@
|
|
3
3
|
require "transproc/rspec"
|
4
4
|
|
5
5
|
describe AbstractMapper::Functions, "#restrict" do
|
6
|
-
|
7
6
|
let(:arguments) { [:restrict, default] }
|
8
7
|
let(:default) { { foo: :FOO, bar: :BAR } }
|
9
8
|
|
10
9
|
it_behaves_like :transforming_immutable_data do
|
11
|
-
|
12
10
|
let(:input) { { foo: :BAZ, qux: :QUX } }
|
13
11
|
let(:output) { { foo: :BAZ, bar: :BAR } }
|
14
12
|
end
|
15
|
-
|
16
13
|
end # describe AbstractMapper::Functions#restrict
|
@@ -3,7 +3,6 @@
|
|
3
3
|
require "transproc/rspec"
|
4
4
|
|
5
5
|
describe AbstractMapper::Functions, "#subclass?" do
|
6
|
-
|
7
6
|
let(:klass) { Class.new }
|
8
7
|
let(:modul) { Module.new }
|
9
8
|
|
@@ -62,5 +61,4 @@ describe AbstractMapper::Functions, "#subclass?" do
|
|
62
61
|
let(:input) { Module.new.send :extend, modul }
|
63
62
|
let(:output) { false }
|
64
63
|
end
|
65
|
-
|
66
64
|
end # describe AbstractMapper::Functions#subclass?
|
@@ -9,44 +9,40 @@ class AbstractMapper # namespace
|
|
9
9
|
let(:rules) { Rules.new }
|
10
10
|
|
11
11
|
describe ".new" do
|
12
|
-
|
13
12
|
subject { optimizer }
|
14
|
-
it { is_expected.to be_frozen }
|
15
13
|
|
14
|
+
it { is_expected.to be_frozen }
|
16
15
|
end # describe .new
|
17
16
|
|
18
17
|
describe "#rules" do
|
19
|
-
|
20
18
|
subject { optimizer.rules }
|
21
|
-
it { is_expected.to eql rules }
|
22
19
|
|
20
|
+
it { is_expected.to eql rules }
|
23
21
|
end # describe #rules
|
24
22
|
|
25
23
|
describe "#update" do
|
24
|
+
subject { optimizer.update(input) }
|
26
25
|
|
27
|
-
|
26
|
+
let(:rules) { Rules.new([rule]) }
|
27
|
+
let(:rule) { Class.new(Rules::Pair) }
|
28
|
+
let(:input) { AST::Branch.new { [foo3, bar1] } }
|
28
29
|
|
29
|
-
let(:
|
30
|
-
let(:
|
31
|
-
let(:
|
32
|
-
|
33
|
-
let(:foo1) { Test::Foo.new(n: 1) }
|
34
|
-
let(:foo2) { Test::Foo.new(n: 2) }
|
35
|
-
let(:foo3) { Test::Foo.new(n: 3) }
|
30
|
+
let(:foo1) { Test::Foo.new(n: 1) }
|
31
|
+
let(:foo2) { Test::Foo.new(n: 2) }
|
32
|
+
let(:foo3) { Test::Foo.new(n: 3) }
|
36
33
|
let(:bar1) { Test::Bar.new(n: 4) { [foo1, foo2] } }
|
37
34
|
|
38
|
-
before { Test::Foo = Class.new(Node) { attribute :n }
|
39
|
-
before { Test::Bar = Class.new(Branch)
|
40
|
-
before { rule.send(:define_method, :optimize?) { true }
|
35
|
+
before { Test::Foo = Class.new(AST::Node) { attribute :n } }
|
36
|
+
before { Test::Bar = Class.new(AST::Branch) }
|
37
|
+
before { rule.send(:define_method, :optimize?) { true } }
|
41
38
|
before { rule.send(:define_method, :optimize) { nodes.reverse } }
|
42
39
|
|
43
40
|
it "optimizes the tree deeply" do
|
44
|
-
expect(
|
41
|
+
expect(input.inspect)
|
45
42
|
.to eql "<Root [<Foo(n: 3)>, <Bar [<Foo(n: 1)>, <Foo(n: 2)>]>]>"
|
46
43
|
expect(subject.inspect)
|
47
44
|
.to eql "<Root [<Bar [<Foo(n: 2)>, <Foo(n: 1)>]>, <Foo(n: 3)>]>"
|
48
45
|
end
|
49
|
-
|
50
46
|
end # describe #update
|
51
47
|
|
52
48
|
end # describe AbstractMapper::Optimize
|