morpher 0.2.6

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of morpher might be problematic. Click here for more details.

Files changed (106) hide show
  1. checksums.yaml +7 -0
  2. data/.circle.yml +6 -0
  3. data/.gitignore +5 -0
  4. data/.rspec +4 -0
  5. data/.rubocop.yml +8 -0
  6. data/Changelog.md +60 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +20 -0
  9. data/README.md +56 -0
  10. data/Rakefile +95 -0
  11. data/circle.yml +7 -0
  12. data/config/devtools.yml +2 -0
  13. data/config/flay.yml +3 -0
  14. data/config/flog.yml +2 -0
  15. data/config/heckle.yml +3 -0
  16. data/config/mutant.yml +8 -0
  17. data/config/reek.yml +109 -0
  18. data/config/rubocop.yml +138 -0
  19. data/config/yardstick.yml +2 -0
  20. data/examples/README.md +13 -0
  21. data/examples/a.rb +25 -0
  22. data/examples/b.rb +35 -0
  23. data/lib/morpher.rb +111 -0
  24. data/lib/morpher/compiler.rb +17 -0
  25. data/lib/morpher/compiler/emitter.rb +82 -0
  26. data/lib/morpher/compiler/error.rb +84 -0
  27. data/lib/morpher/compiler/evaluator.rb +63 -0
  28. data/lib/morpher/compiler/evaluator/emitter.rb +224 -0
  29. data/lib/morpher/compiler/preprocessor.rb +29 -0
  30. data/lib/morpher/compiler/preprocessor/emitter.rb +54 -0
  31. data/lib/morpher/compiler/preprocessor/emitter/anima.rb +69 -0
  32. data/lib/morpher/compiler/preprocessor/emitter/boolean.rb +31 -0
  33. data/lib/morpher/compiler/preprocessor/emitter/key.rb +87 -0
  34. data/lib/morpher/compiler/preprocessor/emitter/noop.rb +45 -0
  35. data/lib/morpher/compiler/preprocessor/emitter/param.rb +50 -0
  36. data/lib/morpher/evaluation.rb +118 -0
  37. data/lib/morpher/evaluator.rb +40 -0
  38. data/lib/morpher/evaluator/binary.rb +46 -0
  39. data/lib/morpher/evaluator/nary.rb +97 -0
  40. data/lib/morpher/evaluator/nullary.rb +92 -0
  41. data/lib/morpher/evaluator/nullary/parameterized.rb +48 -0
  42. data/lib/morpher/evaluator/predicate.rb +22 -0
  43. data/lib/morpher/evaluator/predicate/boolean.rb +76 -0
  44. data/lib/morpher/evaluator/predicate/contradiction.rb +36 -0
  45. data/lib/morpher/evaluator/predicate/eql.rb +50 -0
  46. data/lib/morpher/evaluator/predicate/negation.rb +52 -0
  47. data/lib/morpher/evaluator/predicate/primitive.rb +49 -0
  48. data/lib/morpher/evaluator/predicate/tautology.rb +36 -0
  49. data/lib/morpher/evaluator/transformer.rb +75 -0
  50. data/lib/morpher/evaluator/transformer/attribute.rb +25 -0
  51. data/lib/morpher/evaluator/transformer/block.rb +81 -0
  52. data/lib/morpher/evaluator/transformer/coerce.rb +166 -0
  53. data/lib/morpher/evaluator/transformer/custom.rb +34 -0
  54. data/lib/morpher/evaluator/transformer/domain.rb +86 -0
  55. data/lib/morpher/evaluator/transformer/domain/attribute_accessors.rb +60 -0
  56. data/lib/morpher/evaluator/transformer/domain/attribute_hash.rb +52 -0
  57. data/lib/morpher/evaluator/transformer/domain/instance_variables.rb +60 -0
  58. data/lib/morpher/evaluator/transformer/domain/param.rb +54 -0
  59. data/lib/morpher/evaluator/transformer/guard.rb +62 -0
  60. data/lib/morpher/evaluator/transformer/hash_transform.rb +149 -0
  61. data/lib/morpher/evaluator/transformer/input.rb +37 -0
  62. data/lib/morpher/evaluator/transformer/key.rb +86 -0
  63. data/lib/morpher/evaluator/transformer/map.rb +100 -0
  64. data/lib/morpher/evaluator/transformer/merge.rb +25 -0
  65. data/lib/morpher/evaluator/transformer/static.rb +27 -0
  66. data/lib/morpher/evaluator/unary.rb +79 -0
  67. data/lib/morpher/node_helpers.rb +19 -0
  68. data/lib/morpher/printer.rb +233 -0
  69. data/lib/morpher/printer/mixin.rb +58 -0
  70. data/lib/morpher/registry.rb +51 -0
  71. data/lib/morpher/type_lookup.rb +51 -0
  72. data/morpher.gemspec +29 -0
  73. data/spec/integration_spec.rb +184 -0
  74. data/spec/rcov.opts +7 -0
  75. data/spec/shared/evaluator_behavior.rb +155 -0
  76. data/spec/spec_helper.rb +36 -0
  77. data/spec/support/ice_nine_config.rb +8 -0
  78. data/spec/support/let_mock_helper.rb +8 -0
  79. data/spec/support/strip_helper.rb +12 -0
  80. data/spec/unit/morpher/compiler/preprocessor_spec.rb +46 -0
  81. data/spec/unit/morpher/evaluator/nullary/parameterized_spec.rb +25 -0
  82. data/spec/unit/morpher/evaluator/predicate/boolean/and_spec.rb +11 -0
  83. data/spec/unit/morpher/evaluator/predicate/boolean/or_spec.rb +26 -0
  84. data/spec/unit/morpher/evaluator/predicate/boolean/xor_spec.rb +26 -0
  85. data/spec/unit/morpher/evaluator/predicate/contrandiction_spec.rb +7 -0
  86. data/spec/unit/morpher/evaluator/predicate/eql_spec.rb +11 -0
  87. data/spec/unit/morpher/evaluator/predicate/negation_spec.rb +10 -0
  88. data/spec/unit/morpher/evaluator/predicate/primitive_spec.rb +17 -0
  89. data/spec/unit/morpher/evaluator/predicate/tautology_spec.rb +7 -0
  90. data/spec/unit/morpher/evaluator/transformer/attribute_spec.rb +9 -0
  91. data/spec/unit/morpher/evaluator/transformer/block_spec.rb +92 -0
  92. data/spec/unit/morpher/evaluator/transformer/coerce/parse_int_spec.rb +23 -0
  93. data/spec/unit/morpher/evaluator/transformer/custom_spec.rb +13 -0
  94. data/spec/unit/morpher/evaluator/transformer/domain/attribute_accessors_spec.rb +48 -0
  95. data/spec/unit/morpher/evaluator/transformer/domain/attribute_hash_spec.rb +40 -0
  96. data/spec/unit/morpher/evaluator/transformer/domain/instance_variables_spec.rb +47 -0
  97. data/spec/unit/morpher/evaluator/transformer/guard_spec.rb +12 -0
  98. data/spec/unit/morpher/evaluator/transformer/hash_transform_spec.rb +47 -0
  99. data/spec/unit/morpher/evaluator/transformer/input_spec.rb +11 -0
  100. data/spec/unit/morpher/evaluator/transformer/map_spec.rb +25 -0
  101. data/spec/unit/morpher/evaluator/transformer/static_spec.rb +10 -0
  102. data/spec/unit/morpher/evaluator_spec.rb +15 -0
  103. data/spec/unit/morpher/printer_spec.rb +21 -0
  104. data/spec/unit/morpher/registry_spec.rb +11 -0
  105. data/spec/unit/morpher_spec.rb +53 -0
  106. metadata +302 -0
@@ -0,0 +1,40 @@
1
+ module Morpher
2
+
3
+ # Abstract namespace class for non tracking evaluators
4
+ class Evaluator
5
+ include Adamantium::Flat,
6
+ Registry,
7
+ AbstractType,
8
+ Printer::Mixin,
9
+ NodeHelpers
10
+
11
+ # Call evaluator in non tracking mode
12
+ #
13
+ # @param [Object] input
14
+ #
15
+ # @return [Object]
16
+ #
17
+ # @api private
18
+ #
19
+ abstract_method :call
20
+
21
+ # Call evaluator in tracking mode
22
+ #
23
+ # @param [Object] input
24
+ #
25
+ # @return [Evaluation]
26
+ #
27
+ # @api private
28
+ #
29
+ abstract_method :evaluation
30
+
31
+ # Return inverse evaluator
32
+ #
33
+ # @return [Evaluator]
34
+ #
35
+ # @api private
36
+ #
37
+ abstract_method :inverse
38
+
39
+ end # Evaluator
40
+ end # Morpher
@@ -0,0 +1,46 @@
1
+ module Morpher
2
+
3
+ class Evaluator
4
+
5
+ # Mixin for binary evaluators
6
+ module Binary
7
+ CONCORD = Concord::Public.new(:left, :right)
8
+
9
+ PRINTER = lambda do |_|
10
+ name
11
+ indent do
12
+ visit(:left)
13
+ visit(:right)
14
+ end
15
+ end
16
+
17
+ # Return node
18
+ #
19
+ # @return [AST::Node]
20
+ #
21
+ # @api private
22
+ #
23
+ def node
24
+ s(type, left.node, right.node)
25
+ end
26
+
27
+ private
28
+
29
+ # Hook called when module gets included
30
+ #
31
+ # @return [undefined]
32
+ #
33
+ # @api private
34
+ #
35
+ def self.included(descendant)
36
+ descendant.class_eval do
37
+ include CONCORD
38
+ printer(&PRINTER)
39
+ end
40
+ end
41
+ private_class_method :included
42
+
43
+ end # Nary
44
+
45
+ end # Evaluator
46
+ end # Morpher
@@ -0,0 +1,97 @@
1
+ module Morpher
2
+ class Evaluator
3
+
4
+ # Mixin for nary evaluators
5
+ module Nary
6
+ CONCORD = Concord::Public.new(:body)
7
+
8
+ PRINTER = lambda do |_|
9
+ name
10
+ indent do
11
+ visit_many(:body)
12
+ end
13
+ end
14
+
15
+ # Return AST
16
+ #
17
+ # @return [AST::Node]
18
+ #
19
+ # @api private
20
+ #
21
+ def node
22
+ s(type, *body.map(&:node))
23
+ end
24
+
25
+ private
26
+
27
+ # Return positive evaluation
28
+ #
29
+ # @param [Object] input
30
+ # @param [Array<Evaluation>] evaluations
31
+ #
32
+ # @return [Evaluation]
33
+ #
34
+ # @api private
35
+ #
36
+ def evaluation_positive(input, evaluations)
37
+ Evaluation::Nary.success(
38
+ evaluator: self,
39
+ input: input,
40
+ output: true,
41
+ evaluations: evaluations
42
+ )
43
+ end
44
+
45
+ # Return negative evaluation
46
+ #
47
+ # @param [Object] input
48
+ # @param [Array<Evaluation>] evaluations
49
+ #
50
+ # @return [Evaluation]
51
+ #
52
+ # @api private
53
+ #
54
+ def evaluation_negative(input, evaluations)
55
+ Evaluation::Nary.success(
56
+ evaluator: self,
57
+ input: input,
58
+ output: false,
59
+ evaluations: evaluations
60
+ )
61
+ end
62
+
63
+ # Return evaluation error
64
+ #
65
+ # @param [Object] input
66
+ # @param [Array<Evaluation>] evaluations
67
+ #
68
+ # @return [Evaluation]
69
+ #
70
+ # @api private
71
+ #
72
+ def evaluation_error(input, evaluations)
73
+ Evaluation::Nary.error(
74
+ evaluator: self,
75
+ input: input,
76
+ evaluations: evaluations
77
+ )
78
+ end
79
+
80
+ # Hook called when module gets included
81
+ #
82
+ # @return [undefined]
83
+ #
84
+ # @api private
85
+ #
86
+ def self.included(descendant)
87
+ descendant.class_eval do
88
+ include CONCORD
89
+ printer(&PRINTER)
90
+ end
91
+ end
92
+ private_class_method :included
93
+
94
+ end # Nary
95
+
96
+ end # Evaluator
97
+ end # Morpher
@@ -0,0 +1,92 @@
1
+ module Morpher
2
+ class Evaluator
3
+ # Mixin to define nullary evaluators
4
+ module Nullary
5
+
6
+ CONCORD = Concord::Public.new
7
+
8
+ PRINTER = lambda do |_|
9
+ name
10
+ end
11
+
12
+ # Instance methods for nullary evaluators
13
+ module InstanceMethods
14
+
15
+ # Return default successful evaluation
16
+ #
17
+ # @param [Object] input
18
+ #
19
+ # @return [Evaluation]
20
+ #
21
+ # @api private
22
+ #
23
+ def evaluation(input)
24
+ evaluation_success(input, call(input))
25
+ end
26
+
27
+ # Return node
28
+ #
29
+ # @return [AST::Node]
30
+ #
31
+ # @api private
32
+ #
33
+ def node
34
+ s(type)
35
+ end
36
+
37
+ private
38
+
39
+ # Return evaluation error for input
40
+ #
41
+ # @param [Object] input
42
+ #
43
+ # @return [Evaluation]
44
+ #
45
+ # @api private
46
+ #
47
+ def evaluation_error(input)
48
+ Evaluation::Nullary.new(
49
+ evaluator: self,
50
+ input: input,
51
+ output: Undefined,
52
+ success: false
53
+ )
54
+ end
55
+
56
+ # Return evaluation success for input and output
57
+ #
58
+ # @param [Object] input
59
+ # @param [Object] output
60
+ #
61
+ # @return [Evaluation]
62
+ #
63
+ # @api private
64
+ #
65
+ def evaluation_success(input, output)
66
+ Evaluation::Nullary.new(
67
+ evaluator: self,
68
+ input: input,
69
+ output: output,
70
+ success: true
71
+ )
72
+ end
73
+
74
+ end # InstanceMethods
75
+
76
+ # Hook called when module gets included
77
+ #
78
+ # @return [undefined]
79
+ #
80
+ # @api private
81
+ #
82
+ def self.included(descendant)
83
+ descendant.class_eval do
84
+ include InstanceMethods, CONCORD
85
+ printer(&PRINTER)
86
+ end
87
+ end
88
+ private_class_method :included
89
+
90
+ end # Nullary
91
+ end # Evaluator
92
+ end # Morpher
@@ -0,0 +1,48 @@
1
+ module Morpher
2
+ class Evaluator
3
+ module Nullary
4
+ # Mixin to define parameterized nullary evaluators
5
+ module Parameterized
6
+
7
+ CONCORD = Concord::Public.new(:param)
8
+
9
+ PRINTER = lambda do |_|
10
+ name
11
+ indent do
12
+ attribute :param
13
+ end
14
+ end
15
+
16
+ # Mixin for nullary parameterized evaluators
17
+ module InstanceMethods
18
+
19
+ # Return node
20
+ #
21
+ # @return [AST::Node]
22
+ #
23
+ # @api private
24
+ #
25
+ def node
26
+ s(type, param)
27
+ end
28
+
29
+ end # InstanceMethods
30
+
31
+ # Hook called when module gets included
32
+ #
33
+ # @return [undefined]
34
+ #
35
+ # @api private
36
+ #
37
+ def self.included(descendant)
38
+ descendant.class_eval do
39
+ include InstanceMethods, Nullary::InstanceMethods, CONCORD
40
+ printer(&PRINTER)
41
+ end
42
+ end
43
+ private_class_method :included
44
+
45
+ end # Nullary
46
+ end # Parameterized
47
+ end # Evaluator
48
+ end # Morpher
@@ -0,0 +1,22 @@
1
+ module Morpher
2
+ class Evaluator
3
+ # Abstract namespace class for predicate evaluators
4
+ class Predicate < self
5
+ include Transformer::Intransitive
6
+
7
+ # Return inverse evaluator
8
+ #
9
+ # This is a very naive implementation.
10
+ # Subclasses can do a more elaborated choice.
11
+ #
12
+ # @return [Evaluator]
13
+ #
14
+ # @api private
15
+ #
16
+ def inverse
17
+ Negation.new(self)
18
+ end
19
+
20
+ end # Predicate
21
+ end # Evaluator
22
+ end # Morpher
@@ -0,0 +1,76 @@
1
+ module Morpher
2
+ class Evaluator
3
+ class Predicate
4
+ # Evaluator for nary boolean predicates
5
+ class Boolean < self
6
+ include Nary
7
+
8
+ # Call evaluator with input
9
+ #
10
+ # @param [Object] input
11
+ #
12
+ # @return [Boolean]
13
+ #
14
+ # @api private
15
+ #
16
+ def call(input)
17
+ body .public_send(
18
+ self.class::ENUMERABLE_METHOD
19
+ ) { |evaluator| evaluator.call(input) }
20
+ end
21
+
22
+ # Return evaluation for input
23
+ #
24
+ # @param [Object] input
25
+ #
26
+ # @return [Evaluation::Nary]
27
+ #
28
+ # @api private
29
+ #
30
+ def evaluation(input)
31
+ klass = self.class
32
+
33
+ evaluations = body.each_with_object([]) do |evaluator, aggregate|
34
+ evaluation = evaluator.evaluation(input)
35
+ aggregate << evaluation
36
+ next if evaluation.output.equal?(klass::OUTPUT_EXPECTATION)
37
+ return send(klass::ERROR_METHOD, input, aggregate)
38
+ end
39
+
40
+ send(klass::SUCCESS_METHOD, input, evaluations)
41
+ end
42
+
43
+ # Evaluator for nary and predicates
44
+ class And < self
45
+ register :and
46
+
47
+ ENUMERABLE_METHOD = :all?
48
+ OUTPUT_EXPECTATION = true
49
+ ERROR_METHOD = :evaluation_negative
50
+ SUCCESS_METHOD = :evaluation_positive
51
+ end # And
52
+
53
+ # Evaluator for nary or predicates
54
+ class Or < self
55
+ register :or
56
+
57
+ ENUMERABLE_METHOD = :any?
58
+ OUTPUT_EXPECTATION = false
59
+ ERROR_METHOD = :evaluation_positive
60
+ SUCCESS_METHOD = :evaluation_negative
61
+ end # Or
62
+
63
+ # Evaluator for nary xor predicates
64
+ class Xor < self
65
+ register :xor
66
+
67
+ ENUMERABLE_METHOD = :one?
68
+ OUTPUT_EXPECTATION = false
69
+ ERROR_METHOD = :evaluation_positive
70
+ SUCCESS_METHOD = :evaluation_negative
71
+ end # Xor
72
+
73
+ end # Boolean
74
+ end # Predicate
75
+ end # Evaluator
76
+ end # Morpher
@@ -0,0 +1,36 @@
1
+ module Morpher
2
+ class Evaluator
3
+ class Predicate
4
+
5
+ # Evaluator for contradiction
6
+ class Contradiction < self
7
+ include Nullary
8
+
9
+ register :false
10
+
11
+ # Call predicate evaluator
12
+ #
13
+ # @param [Object] _input
14
+ #
15
+ # @return [false]
16
+ #
17
+ # @api private
18
+ #
19
+ def call(_input)
20
+ false
21
+ end
22
+
23
+ # Return inverse evaluator
24
+ #
25
+ # @return [Evaluator]
26
+ #
27
+ # @api private
28
+ #
29
+ def inverse
30
+ Tautology.new
31
+ end
32
+
33
+ end # Contradiction
34
+ end # Predicate
35
+ end # Evaluator
36
+ end # Morpher