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.
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