abstract_mapper 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -4
  3. data/CHANGELOG.md +26 -0
  4. data/README.md +5 -5
  5. data/Rakefile +1 -1
  6. data/abstract_mapper.gemspec +1 -0
  7. data/lib/abstract_mapper.rb +4 -15
  8. data/lib/abstract_mapper/ast.rb +16 -0
  9. data/lib/abstract_mapper/ast/branch.rb +121 -0
  10. data/lib/abstract_mapper/ast/node.rb +91 -0
  11. data/lib/abstract_mapper/builder.rb +2 -2
  12. data/lib/abstract_mapper/commands.rb +4 -2
  13. data/lib/abstract_mapper/commands/base.rb +69 -0
  14. data/lib/abstract_mapper/dsl.rb +2 -2
  15. data/lib/abstract_mapper/errors.rb +17 -0
  16. data/lib/abstract_mapper/errors/wrong_node.rb +1 -1
  17. data/lib/abstract_mapper/errors/wrong_rule.rb +1 -1
  18. data/lib/abstract_mapper/optimizer.rb +1 -1
  19. data/lib/abstract_mapper/rules.rb +10 -5
  20. data/lib/abstract_mapper/rules/base.rb +74 -0
  21. data/lib/abstract_mapper/rules/pair.rb +68 -0
  22. data/lib/abstract_mapper/rules/sole.rb +60 -0
  23. data/lib/abstract_mapper/settings.rb +22 -30
  24. data/lib/abstract_mapper/version.rb +1 -1
  25. data/lib/rspec/nodes.rb +2 -2
  26. data/spec/integration/faceter.rb +4 -4
  27. data/spec/integration/rspec_examples_spec.rb +0 -6
  28. data/spec/unit/abstract_mapper/{branch_spec.rb → ast/branch_spec.rb} +28 -61
  29. data/spec/unit/abstract_mapper/{node_spec.rb → ast/node_spec.rb} +16 -53
  30. data/spec/unit/abstract_mapper/builder_spec.rb +9 -24
  31. data/spec/unit/abstract_mapper/{command_spec.rb → commands/base_spec.rb} +10 -25
  32. data/spec/unit/abstract_mapper/commands_spec.rb +9 -14
  33. data/spec/unit/abstract_mapper/dsl_spec.rb +23 -15
  34. data/spec/unit/abstract_mapper/errors/unknown_command_spec.rb +1 -4
  35. data/spec/unit/abstract_mapper/errors/wrong_node_spec.rb +5 -4
  36. data/spec/unit/abstract_mapper/errors/wrong_rule_spec.rb +5 -5
  37. data/spec/unit/abstract_mapper/functions/compact_spec.rb +0 -2
  38. data/spec/unit/abstract_mapper/functions/filter_spec.rb +0 -2
  39. data/spec/unit/abstract_mapper/functions/identity_spec.rb +0 -2
  40. data/spec/unit/abstract_mapper/functions/restrict_spec.rb +0 -3
  41. data/spec/unit/abstract_mapper/functions/subclass_spec.rb +0 -2
  42. data/spec/unit/abstract_mapper/optimizer_spec.rb +13 -17
  43. data/spec/unit/abstract_mapper/{rule_spec.rb → rules/base_spec.rb} +17 -34
  44. data/spec/unit/abstract_mapper/{pair_rule_spec.rb → rules/pair_spec.rb} +8 -8
  45. data/spec/unit/abstract_mapper/{sole_rule_spec.rb → rules/sole_spec.rb} +5 -5
  46. data/spec/unit/abstract_mapper/rules_spec.rb +24 -37
  47. data/spec/unit/abstract_mapper/settings_spec.rb +38 -32
  48. data/spec/unit/abstract_mapper_spec.rb +9 -16
  49. metadata +37 -22
  50. data/lib/abstract_mapper/attributes.rb +0 -65
  51. data/lib/abstract_mapper/branch.rb +0 -120
  52. data/lib/abstract_mapper/command.rb +0 -68
  53. data/lib/abstract_mapper/node.rb +0 -87
  54. data/lib/abstract_mapper/pair_rule.rb +0 -64
  55. data/lib/abstract_mapper/rule.rb +0 -73
  56. data/lib/abstract_mapper/sole_rule.rb +0 -56
@@ -2,7 +2,7 @@
2
2
 
3
3
  class AbstractMapper
4
4
 
5
- describe AbstractMapper::Command do
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::Command
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 Command
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 Command
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 Command
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(PairRule) do
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 { is_expected.to eql dsl }
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
- subject { dsl.finalize }
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
- subject(:error) { described_class.new Symbol }
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
- subject(:error) { described_class.new Symbol }
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.to eql "Symbol is not a subclass of AbstractMapper::Rule"
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
- subject { optimizer.update(tree) }
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(:rules) { Rules.new([rule]) }
30
- let(:rule) { Class.new(PairRule) }
31
- let(:tree) { Branch.new { [foo3, bar1] } }
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(tree.inspect)
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