ducktrap 0.0.1

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 (165) hide show
  1. checksums.yaml +7 -0
  2. data/.circle.yml +6 -0
  3. data/.gitignore +5 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +16 -0
  6. data/Gemfile +6 -0
  7. data/Gemfile.devtools +59 -0
  8. data/Guardfile +18 -0
  9. data/LICENSE +20 -0
  10. data/README.md +47 -0
  11. data/Rakefile +2 -0
  12. data/TODO +4 -0
  13. data/config/devtools.yml +2 -0
  14. data/config/flay.yml +3 -0
  15. data/config/flog.yml +2 -0
  16. data/config/heckle.yml +3 -0
  17. data/config/mutant.yml +2 -0
  18. data/config/reek.yml +98 -0
  19. data/config/yardstick.yml +2 -0
  20. data/ducktrap.gemspec +23 -0
  21. data/lib/ducktrap.rb +73 -0
  22. data/lib/ducktrap/builder.rb +36 -0
  23. data/lib/ducktrap/error.rb +48 -0
  24. data/lib/ducktrap/evaluator.rb +127 -0
  25. data/lib/ducktrap/evaluator/invalid.rb +30 -0
  26. data/lib/ducktrap/evaluator/static.rb +25 -0
  27. data/lib/ducktrap/formatter.rb +138 -0
  28. data/lib/ducktrap/mapper.rb +59 -0
  29. data/lib/ducktrap/nary.rb +148 -0
  30. data/lib/ducktrap/node.rb +94 -0
  31. data/lib/ducktrap/node/anima.rb +40 -0
  32. data/lib/ducktrap/node/anima/dump.rb +39 -0
  33. data/lib/ducktrap/node/anima/load.rb +39 -0
  34. data/lib/ducktrap/node/block.rb +44 -0
  35. data/lib/ducktrap/node/coercion.rb +7 -0
  36. data/lib/ducktrap/node/custom.rb +121 -0
  37. data/lib/ducktrap/node/disjunction.rb +8 -0
  38. data/lib/ducktrap/node/forward.rb +55 -0
  39. data/lib/ducktrap/node/guard_nil.rb +42 -0
  40. data/lib/ducktrap/node/hash.rb +7 -0
  41. data/lib/ducktrap/node/hash/transform.rb +53 -0
  42. data/lib/ducktrap/node/invalid.rb +29 -0
  43. data/lib/ducktrap/node/inverse.rb +46 -0
  44. data/lib/ducktrap/node/key.rb +61 -0
  45. data/lib/ducktrap/node/key/add.rb +42 -0
  46. data/lib/ducktrap/node/key/delete.rb +44 -0
  47. data/lib/ducktrap/node/key/dump.rb +38 -0
  48. data/lib/ducktrap/node/key/fetch.rb +49 -0
  49. data/lib/ducktrap/node/map.rb +42 -0
  50. data/lib/ducktrap/node/noop.rb +30 -0
  51. data/lib/ducktrap/node/primitive.rb +61 -0
  52. data/lib/ducktrap/node/static.rb +33 -0
  53. data/lib/ducktrap/nullary.rb +41 -0
  54. data/lib/ducktrap/pretty_dump.rb +31 -0
  55. data/lib/ducktrap/registry.rb +60 -0
  56. data/lib/ducktrap/singleton.rb +55 -0
  57. data/lib/ducktrap/unary.rb +153 -0
  58. data/spec/rcov.opts +7 -0
  59. data/spec/shared/inverse_behavior.rb +7 -0
  60. data/spec/spec_helper.rb +20 -0
  61. data/spec/support/ice_nine_config.rb +8 -0
  62. data/spec/support/let_mock_helper.rb +13 -0
  63. data/spec/unit/ducktrap/builder/class_methods/new_spec.rb +41 -0
  64. data/spec/unit/ducktrap/builder/new_spec.rb +41 -0
  65. data/spec/unit/ducktrap/class_methods/build_spec.rb +11 -0
  66. data/spec/unit/ducktrap/error/exception/pretty_inspect_spec.rb +22 -0
  67. data/spec/unit/ducktrap/error/pretty_inspect_spec.rb +19 -0
  68. data/spec/unit/ducktrap/evaluator/assert_successful_spec.rb +38 -0
  69. data/spec/unit/ducktrap/evaluator/invalid/output_spec.rb +14 -0
  70. data/spec/unit/ducktrap/evaluator/noop/output_spec.rb +14 -0
  71. data/spec/unit/ducktrap/evaluator/output_spec.rb +52 -0
  72. data/spec/unit/ducktrap/evaluator/pretty_inspect_spec.rb +63 -0
  73. data/spec/unit/ducktrap/evaluator/successful_predicate_spec.rb +36 -0
  74. data/spec/unit/ducktrap/failed_transformation_error/message_spec.rb +10 -0
  75. data/spec/unit/ducktrap/formatter/attribute_spec.rb +24 -0
  76. data/spec/unit/ducktrap/formatter/body_spec.rb +19 -0
  77. data/spec/unit/ducktrap/formatter/class_methods/new_spec.rb +14 -0
  78. data/spec/unit/ducktrap/formatter/initialize_spec.rb +14 -0
  79. data/spec/unit/ducktrap/formatter/name_spec.rb +25 -0
  80. data/spec/unit/ducktrap/formatter/nest_spec.rb +48 -0
  81. data/spec/unit/ducktrap/formatter/puts_spec.rb +36 -0
  82. data/spec/unit/ducktrap/mapper/builder/dumper_spec.rb +20 -0
  83. data/spec/unit/ducktrap/mapper/builder/loader_spec.rb +20 -0
  84. data/spec/unit/ducktrap/mapper/builder/object_spec.rb +90 -0
  85. data/spec/unit/ducktrap/mapper/class_methods/build_spec.rb +20 -0
  86. data/spec/unit/ducktrap/nary/builder/add_spec.rb +16 -0
  87. data/spec/unit/ducktrap/nary/builder/method_missing_spec.rb +44 -0
  88. data/spec/unit/ducktrap/nary/builder/output_spec.rb +16 -0
  89. data/spec/unit/ducktrap/nary/class_methods/build_spec.rb +22 -0
  90. data/spec/unit/ducktrap/nary/class_methods/included_spec.rb +13 -0
  91. data/spec/unit/ducktrap/nary/evaluator/output_spec.rb +79 -0
  92. data/spec/unit/ducktrap/nary/instance_methods/inverse_spec.rb +24 -0
  93. data/spec/unit/ducktrap/nary/instance_methods/pretty_inspect_spec.rb +31 -0
  94. data/spec/unit/ducktrap/node/anima/dump/evaluator/output_spec.rb +18 -0
  95. data/spec/unit/ducktrap/node/anima/dump/inverse_spec.rb +10 -0
  96. data/spec/unit/ducktrap/node/anima/dump/pretty_inspect_spec.rb +15 -0
  97. data/spec/unit/ducktrap/node/anima/evaluator/output_spec.rb +18 -0
  98. data/spec/unit/ducktrap/node/anima/load/evaluator/output_spec.rb +35 -0
  99. data/spec/unit/ducktrap/node/anima/load/inverse_spec.rb +10 -0
  100. data/spec/unit/ducktrap/node/anima/load/pretty_inspect_spec.rb +15 -0
  101. data/spec/unit/ducktrap/node/anima/pretty_inspect_spec.rb +15 -0
  102. data/spec/unit/ducktrap/node/block/evaluator/output_spec.rb +79 -0
  103. data/spec/unit/ducktrap/node/block/inverse_spec.rb +24 -0
  104. data/spec/unit/ducktrap/node/call_spec.rb +21 -0
  105. data/spec/unit/ducktrap/node/class_methods/build_spec.rb +11 -0
  106. data/spec/unit/ducktrap/node/class_methods/register_spec.rb +16 -0
  107. data/spec/unit/ducktrap/node/custom/builder/forward_spec.rb +54 -0
  108. data/spec/unit/ducktrap/node/custom/builder/inverse_spec.rb +54 -0
  109. data/spec/unit/ducktrap/node/custom/builder/object_spec.rb +54 -0
  110. data/spec/unit/ducktrap/node/custom/call_spec.rb +21 -0
  111. data/spec/unit/ducktrap/node/custom/class_methods/build_spec.rb +20 -0
  112. data/spec/unit/ducktrap/node/custom/inverse_spec.rb +12 -0
  113. data/spec/unit/ducktrap/node/custom/pretty_inspect_spec.rb +15 -0
  114. data/spec/unit/ducktrap/node/forward/evaluator/output_spec.rb +13 -0
  115. data/spec/unit/ducktrap/node/forward/inverse_spec.rb +14 -0
  116. data/spec/unit/ducktrap/node/forward/pretty_inspect_spec.rb +19 -0
  117. data/spec/unit/ducktrap/node/guard_nil/call_spec.rb +21 -0
  118. data/spec/unit/ducktrap/node/guard_nil/evaluator/output_spec.rb +27 -0
  119. data/spec/unit/ducktrap/node/guard_nil/inverse_spec.rb +12 -0
  120. data/spec/unit/ducktrap/node/hash/transform/evaluator/output_spec.rb +51 -0
  121. data/spec/unit/ducktrap/node/hash/transform/inverse_spec.rb +27 -0
  122. data/spec/unit/ducktrap/node/invalid/call_spec.rb +13 -0
  123. data/spec/unit/ducktrap/node/invalid/inverse_spec.rb +11 -0
  124. data/spec/unit/ducktrap/node/inverse/call_spec.rb +11 -0
  125. data/spec/unit/ducktrap/node/inverse/inverse_spec.rb +14 -0
  126. data/spec/unit/ducktrap/node/inverse/pretty_inspect_spec.rb +19 -0
  127. data/spec/unit/ducktrap/node/key/add/call_spec.rb +15 -0
  128. data/spec/unit/ducktrap/node/key/add/evaluator/call_spec.rb +15 -0
  129. data/spec/unit/ducktrap/node/key/add/inverse_spec.rb +14 -0
  130. data/spec/unit/ducktrap/node/key/delete/call_spec.rb +13 -0
  131. data/spec/unit/ducktrap/node/key/delete/evaluator/call_spec.rb +13 -0
  132. data/spec/unit/ducktrap/node/key/delete/inverse_spec.rb +13 -0
  133. data/spec/unit/ducktrap/node/key/dump/evaluator/output_spec.rb +37 -0
  134. data/spec/unit/ducktrap/node/key/dump/inverse_spec.rb +14 -0
  135. data/spec/unit/ducktrap/node/key/evaluator/key_spec.rb +26 -0
  136. data/spec/unit/ducktrap/node/key/fetch/evaluator/output_spec.rb +48 -0
  137. data/spec/unit/ducktrap/node/key/fetch/inverse_spec.rb +14 -0
  138. data/spec/unit/ducktrap/node/key/pretty_inspect_spec.rb +20 -0
  139. data/spec/unit/ducktrap/node/map/evaluator/output_spec.rb +22 -0
  140. data/spec/unit/ducktrap/node/map/inverse_spec.rb +15 -0
  141. data/spec/unit/ducktrap/node/noop/call_spec.rb +11 -0
  142. data/spec/unit/ducktrap/node/noop/inverse_spec.rb +9 -0
  143. data/spec/unit/ducktrap/node/pretty_inspect_spec.rb +17 -0
  144. data/spec/unit/ducktrap/node/primitive/call_spec.rb +19 -0
  145. data/spec/unit/ducktrap/node/primitive/inverse_spec.rb +13 -0
  146. data/spec/unit/ducktrap/node/primitive/pretty_inspect_spec.rb +15 -0
  147. data/spec/unit/ducktrap/node/run_spec.rb +46 -0
  148. data/spec/unit/ducktrap/node/static/call_spec.rb +13 -0
  149. data/spec/unit/ducktrap/node/static/inverse_spec.rb +14 -0
  150. data/spec/unit/ducktrap/nullary/class_methods/build_spec.rb +37 -0
  151. data/spec/unit/ducktrap/nullary/class_methods/included_spec.rb +7 -0
  152. data/spec/unit/ducktrap/pretty_dump/pretty_dump_spec.rb +47 -0
  153. data/spec/unit/ducktrap/pretty_dump/pretty_inspect_spec.rb +22 -0
  154. data/spec/unit/ducktrap/registry/lookup_spec.rb +27 -0
  155. data/spec/unit/ducktrap/registry/register_spec.rb +21 -0
  156. data/spec/unit/ducktrap/singleton/class_methods/included_spec.rb +13 -0
  157. data/spec/unit/ducktrap/singleton/class_methods/instance_spec.rb +19 -0
  158. data/spec/unit/ducktrap/singleton/instance_methods/inspect_spec.rb +19 -0
  159. data/spec/unit/ducktrap/singleton/instance_methods/pretty_inspect_spec.rb +17 -0
  160. data/spec/unit/ducktrap/unary/class_methods/build_spec.rb +18 -0
  161. data/spec/unit/ducktrap/unary/class_methods/included_spec.rb +14 -0
  162. data/spec/unit/ducktrap/unary/evaluator/output2_spec.rb +48 -0
  163. data/spec/unit/ducktrap/unary/evaluator/output_spec.rb +37 -0
  164. data/spec/unit/ducktrap/unary/instance_methods/pretty_inspect_spec.rb +15 -0
  165. metadata +399 -0
@@ -0,0 +1,30 @@
1
+ module Ducktrap
2
+ class Node
3
+ # Noope node, returns input as output
4
+ class Noop < self
5
+ include Singleton
6
+
7
+ register :noop
8
+
9
+ # Run ducktrap
10
+ #
11
+ # @param [Object] input
12
+ #
13
+ # @return [Evaluator]
14
+ #
15
+ # @api private
16
+ #
17
+ def call(input)
18
+ Evaluator::Noop.new(self, input)
19
+ end
20
+
21
+ # Return inverse ducktrap
22
+ #
23
+ # @return [Ducktrap]
24
+ #
25
+ # @api private
26
+ #
27
+ def inverse; self; end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,61 @@
1
+ module Ducktrap
2
+ class Node
3
+ # Primitive check
4
+ class Primitive < self
5
+ include Concord::Public.new(:primitive)
6
+
7
+ register :primitive
8
+
9
+ # Run ducktrap in input
10
+ #
11
+ # @param [Object] input
12
+ #
13
+ # @return [Evaluator]
14
+ #
15
+ # @api private
16
+ #
17
+ def call(input)
18
+ unless input.kind_of?(primitive)
19
+ return Evaluator::Invalid.new(self, input)
20
+ end
21
+
22
+ Evaluator::Noop.new(self, input)
23
+ end
24
+
25
+ # Return inverse ducktrap
26
+ #
27
+ # @return [self]
28
+ #
29
+ # @api private
30
+ #
31
+ def inverse; self end
32
+
33
+ private
34
+
35
+ # Perfrom pretty dump
36
+ #
37
+ # @param [Formatter] output
38
+ #
39
+ # @return [undefined]
40
+ #
41
+ # @api private
42
+ #
43
+ def dump(output)
44
+ output.name(self)
45
+ output.attribute(:primitive, primitive)
46
+ end
47
+
48
+ class << self
49
+
50
+ # Build node
51
+ #
52
+ # @return [node]
53
+ #
54
+ # @api private
55
+ #
56
+ alias_method :build, :new
57
+ end
58
+
59
+ end # Primitive
60
+ end # node
61
+ end # Ducktrap
@@ -0,0 +1,33 @@
1
+ module Ducktrap
2
+ class Node
3
+ # Transformer with static output
4
+ class Static < self
5
+ include Nullary, Concord::Public.new(:value, :inverse_value)
6
+
7
+ register :static
8
+
9
+ # Run ducktrap on input
10
+ #
11
+ # @param [Object] input
12
+ #
13
+ # @return [Evaluator]
14
+ #
15
+ # @api private
16
+ #
17
+ def call(input)
18
+ Evaluator::Static.new(self, input, value)
19
+ end
20
+
21
+ # Return inverse ducktrap
22
+ #
23
+ # @return [Ducktrap]
24
+ #
25
+ # @api private
26
+ #
27
+ def inverse
28
+ Static.new(inverse_value, value)
29
+ end
30
+
31
+ end # Static
32
+ end # Node
33
+ end # Ducktrap
@@ -0,0 +1,41 @@
1
+ module Ducktrap
2
+ # Mixin for defining nullary ducktraps
3
+ module Nullary
4
+ # Class method mixin
5
+ module ClassMethods
6
+
7
+ # Build ducktrap
8
+ #
9
+ # @return [Ducktrap]
10
+ #
11
+ # @api private
12
+ #
13
+ def build(*args)
14
+ if block_given?
15
+ raise "#{name}.build does not take a block"
16
+ end
17
+ new(*args)
18
+ end
19
+
20
+ end # ClassMethods
21
+
22
+ # Hook called when module is included
23
+ #
24
+ # @param [Module] scope
25
+ #
26
+ # @return [undefined]
27
+ #
28
+ # @api private
29
+ #
30
+ def self.included(scope)
31
+ scope.extend(ClassMethods)
32
+ end
33
+ private_class_method :included
34
+
35
+ # Evaluator for nullary nodes
36
+ class Evaluator < Ducktrap::Evaluator
37
+
38
+ end # Evaluator
39
+
40
+ end # Nullary
41
+ end # Ducktrap
@@ -0,0 +1,31 @@
1
+ module Ducktrap
2
+ # Mixin for pretty dumpable objects
3
+ module PrettyDump
4
+
5
+ # Perform pretty dump of ducktrap
6
+ #
7
+ # @return [self]
8
+ #
9
+ # @api private
10
+ #
11
+ def pretty_dump(output=Formatter.new)
12
+ dump(output)
13
+ self
14
+ end
15
+
16
+ # Return pretty inspection
17
+ #
18
+ # @return [String]
19
+ #
20
+ # @api private
21
+ #
22
+ def pretty_inspect
23
+ io = StringIO.new
24
+ formatter = Formatter.new(io)
25
+ pretty_dump(formatter)
26
+ io.rewind
27
+ io.read
28
+ end
29
+
30
+ end # PrettyDump
31
+ end # Ducktrap
@@ -0,0 +1,60 @@
1
+ module Ducktrap
2
+
3
+ # Registry for ducktraps
4
+ class Registry
5
+
6
+ # Register ducktrap under name
7
+ #
8
+ # @param [Symbol] name
9
+ # @param [Ducktrap] ducktrap
10
+ #
11
+ # @return [self]
12
+ #
13
+ # @api private
14
+ #
15
+ def register(name, ducktrap)
16
+ if @index.key?(name)
17
+ raise "name: #{name.inspect} does already exist"
18
+ end
19
+
20
+ @index[name] = ducktrap
21
+
22
+ self
23
+ end
24
+
25
+ # Lookup ducktrap for name
26
+ #
27
+ # @param [Symbol] name
28
+ #
29
+ # @return [Ducktrap]
30
+ # if found
31
+ #
32
+ # @return [self]
33
+ # otherwise
34
+ #
35
+ # @yield
36
+ # if no ducktrap found for name
37
+ #
38
+ # @api private
39
+ #
40
+ def lookup(name)
41
+ @index.fetch(name) do
42
+ yield
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ # Initialize object
49
+ #
50
+ # @return [undefined]
51
+ #
52
+ # @api private
53
+ #
54
+ def initialize
55
+ @index = {}
56
+ end
57
+ end
58
+
59
+ DSL = Registry.new
60
+ end
@@ -0,0 +1,55 @@
1
+ module Ducktrap
2
+ # Mixin to define nullary ducktraps
3
+ module Singleton
4
+ module InstanceMethods
5
+ include Adamantium::Flat
6
+
7
+ # Return inspect string
8
+ #
9
+ # @return [String]
10
+ #
11
+ # @api private
12
+ #
13
+ def inspect
14
+ "<#{self.class.name}>"
15
+ end
16
+ memoize :inspect
17
+
18
+ private
19
+
20
+ end # InstanceMethods
21
+
22
+ module ClassMethods
23
+
24
+ # Return instance
25
+ #
26
+ # @return [Ducktrap]
27
+ #
28
+ # @api private
29
+ #
30
+ def instance
31
+ @instance ||= new
32
+ end
33
+
34
+ alias_method :build, :instance
35
+
36
+ end # ClassMethods
37
+
38
+ # Hook called when module is included
39
+ #
40
+ # @param [Module] scope
41
+ #
42
+ # @return [undefined]
43
+ #
44
+ # @api private
45
+ #
46
+ def self.included(scope)
47
+ scope.module_eval do
48
+ extend ClassMethods
49
+ include InstanceMethods
50
+ private_class_method :new
51
+ end
52
+ end
53
+
54
+ end # Singleton
55
+ end # Ducktrap
@@ -0,0 +1,153 @@
1
+ module Ducktrap
2
+ # Mixin for defining unary ducktraps
3
+ module Unary
4
+ # Instance methods mixin for unary ducktraps
5
+ module InstanceMethods
6
+
7
+ # Return ducktrap
8
+ #
9
+ # @return [Ducktrap]
10
+ #
11
+ # @api private
12
+ #
13
+ attr_reader :operand
14
+
15
+ # Initialize object
16
+ #
17
+ # @param [Ducktrap] operand
18
+ #
19
+ # @api private
20
+ #
21
+ def initialize(operand)
22
+ @operand = operand
23
+ end
24
+
25
+ private
26
+
27
+ # Perform pretty dump
28
+ #
29
+ # @return [undefined]
30
+ #
31
+ # @api private
32
+ #
33
+ def dump(output)
34
+ output.name(self)
35
+ output.nest(:operand, operand)
36
+ end
37
+
38
+ end
39
+
40
+ module ClassMethods
41
+
42
+ # Build ducktrap
43
+ #
44
+ # @return [Ducktrap]
45
+ #
46
+ # @api private
47
+ #
48
+ def build(*args, &block)
49
+ postprocessor = Node::Noop.instance
50
+ if block
51
+ postprocessor = Node::Block.build(&block)
52
+ end
53
+ new(postprocessor, *args)
54
+ end
55
+
56
+ end
57
+
58
+ # Hook called when module is included
59
+ #
60
+ # @param [Module] scope
61
+ #
62
+ # @return [undefined]
63
+ #
64
+ # @api private
65
+ #
66
+ def self.included(scope)
67
+ scope.module_eval do
68
+ include InstanceMethods, Equalizer.new(:operand)
69
+ extend ClassMethods
70
+ end
71
+ end
72
+
73
+ private_class_method :included
74
+
75
+ # Evaluator for unary nodes
76
+ class Evaluator < Ducktrap::Evaluator
77
+
78
+ private
79
+
80
+ # Return operand
81
+ #
82
+ # @return [Ducktrap]
83
+ #
84
+ # @api private
85
+ #
86
+ def operand
87
+ context.operand
88
+ end
89
+
90
+ # Process operand
91
+ #
92
+ # @param [Object] input
93
+ #
94
+ # @return [Evaluator]
95
+ #
96
+ # @api private
97
+ #
98
+ def process_operand(input)
99
+ operand.call(input)
100
+ end
101
+
102
+ # Process input with operand
103
+ #
104
+ # @return [Evaluator]
105
+ #
106
+ # @api private
107
+ #
108
+ def operand_evaluator
109
+ process_operand(input)
110
+ end
111
+ memoize :operand_evaluator
112
+
113
+ # Return operand output
114
+ #
115
+ # @return [Object]
116
+ #
117
+ # @api private
118
+ #
119
+ def operand_output
120
+ operand_evaluator.output
121
+ end
122
+
123
+ # Process input
124
+ #
125
+ # @param [Object]
126
+ #
127
+ # @return [Object]
128
+ # if successful
129
+ #
130
+ # @return [Error]
131
+ # otherwise
132
+ #
133
+ # @api private
134
+ #
135
+ def process
136
+ evaluator = operand_evaluator
137
+ unless evaluator.successful?
138
+ return nested_error(evaluator)
139
+ end
140
+ process_operand_output
141
+ end
142
+
143
+ # Process operand output
144
+ #
145
+ # @return [Object]
146
+ #
147
+ # @api private
148
+ #
149
+ abstract_method :process_operand_output
150
+
151
+ end # Evaluator
152
+ end # Unary
153
+ end # Ducktrap