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.
- checksums.yaml +7 -0
- data/.circle.yml +6 -0
- data/.gitignore +5 -0
- data/.rspec +4 -0
- data/.rubocop.yml +8 -0
- data/Changelog.md +60 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +56 -0
- data/Rakefile +95 -0
- data/circle.yml +7 -0
- data/config/devtools.yml +2 -0
- data/config/flay.yml +3 -0
- data/config/flog.yml +2 -0
- data/config/heckle.yml +3 -0
- data/config/mutant.yml +8 -0
- data/config/reek.yml +109 -0
- data/config/rubocop.yml +138 -0
- data/config/yardstick.yml +2 -0
- data/examples/README.md +13 -0
- data/examples/a.rb +25 -0
- data/examples/b.rb +35 -0
- data/lib/morpher.rb +111 -0
- data/lib/morpher/compiler.rb +17 -0
- data/lib/morpher/compiler/emitter.rb +82 -0
- data/lib/morpher/compiler/error.rb +84 -0
- data/lib/morpher/compiler/evaluator.rb +63 -0
- data/lib/morpher/compiler/evaluator/emitter.rb +224 -0
- data/lib/morpher/compiler/preprocessor.rb +29 -0
- data/lib/morpher/compiler/preprocessor/emitter.rb +54 -0
- data/lib/morpher/compiler/preprocessor/emitter/anima.rb +69 -0
- data/lib/morpher/compiler/preprocessor/emitter/boolean.rb +31 -0
- data/lib/morpher/compiler/preprocessor/emitter/key.rb +87 -0
- data/lib/morpher/compiler/preprocessor/emitter/noop.rb +45 -0
- data/lib/morpher/compiler/preprocessor/emitter/param.rb +50 -0
- data/lib/morpher/evaluation.rb +118 -0
- data/lib/morpher/evaluator.rb +40 -0
- data/lib/morpher/evaluator/binary.rb +46 -0
- data/lib/morpher/evaluator/nary.rb +97 -0
- data/lib/morpher/evaluator/nullary.rb +92 -0
- data/lib/morpher/evaluator/nullary/parameterized.rb +48 -0
- data/lib/morpher/evaluator/predicate.rb +22 -0
- data/lib/morpher/evaluator/predicate/boolean.rb +76 -0
- data/lib/morpher/evaluator/predicate/contradiction.rb +36 -0
- data/lib/morpher/evaluator/predicate/eql.rb +50 -0
- data/lib/morpher/evaluator/predicate/negation.rb +52 -0
- data/lib/morpher/evaluator/predicate/primitive.rb +49 -0
- data/lib/morpher/evaluator/predicate/tautology.rb +36 -0
- data/lib/morpher/evaluator/transformer.rb +75 -0
- data/lib/morpher/evaluator/transformer/attribute.rb +25 -0
- data/lib/morpher/evaluator/transformer/block.rb +81 -0
- data/lib/morpher/evaluator/transformer/coerce.rb +166 -0
- data/lib/morpher/evaluator/transformer/custom.rb +34 -0
- data/lib/morpher/evaluator/transformer/domain.rb +86 -0
- data/lib/morpher/evaluator/transformer/domain/attribute_accessors.rb +60 -0
- data/lib/morpher/evaluator/transformer/domain/attribute_hash.rb +52 -0
- data/lib/morpher/evaluator/transformer/domain/instance_variables.rb +60 -0
- data/lib/morpher/evaluator/transformer/domain/param.rb +54 -0
- data/lib/morpher/evaluator/transformer/guard.rb +62 -0
- data/lib/morpher/evaluator/transformer/hash_transform.rb +149 -0
- data/lib/morpher/evaluator/transformer/input.rb +37 -0
- data/lib/morpher/evaluator/transformer/key.rb +86 -0
- data/lib/morpher/evaluator/transformer/map.rb +100 -0
- data/lib/morpher/evaluator/transformer/merge.rb +25 -0
- data/lib/morpher/evaluator/transformer/static.rb +27 -0
- data/lib/morpher/evaluator/unary.rb +79 -0
- data/lib/morpher/node_helpers.rb +19 -0
- data/lib/morpher/printer.rb +233 -0
- data/lib/morpher/printer/mixin.rb +58 -0
- data/lib/morpher/registry.rb +51 -0
- data/lib/morpher/type_lookup.rb +51 -0
- data/morpher.gemspec +29 -0
- data/spec/integration_spec.rb +184 -0
- data/spec/rcov.opts +7 -0
- data/spec/shared/evaluator_behavior.rb +155 -0
- data/spec/spec_helper.rb +36 -0
- data/spec/support/ice_nine_config.rb +8 -0
- data/spec/support/let_mock_helper.rb +8 -0
- data/spec/support/strip_helper.rb +12 -0
- data/spec/unit/morpher/compiler/preprocessor_spec.rb +46 -0
- data/spec/unit/morpher/evaluator/nullary/parameterized_spec.rb +25 -0
- data/spec/unit/morpher/evaluator/predicate/boolean/and_spec.rb +11 -0
- data/spec/unit/morpher/evaluator/predicate/boolean/or_spec.rb +26 -0
- data/spec/unit/morpher/evaluator/predicate/boolean/xor_spec.rb +26 -0
- data/spec/unit/morpher/evaluator/predicate/contrandiction_spec.rb +7 -0
- data/spec/unit/morpher/evaluator/predicate/eql_spec.rb +11 -0
- data/spec/unit/morpher/evaluator/predicate/negation_spec.rb +10 -0
- data/spec/unit/morpher/evaluator/predicate/primitive_spec.rb +17 -0
- data/spec/unit/morpher/evaluator/predicate/tautology_spec.rb +7 -0
- data/spec/unit/morpher/evaluator/transformer/attribute_spec.rb +9 -0
- data/spec/unit/morpher/evaluator/transformer/block_spec.rb +92 -0
- data/spec/unit/morpher/evaluator/transformer/coerce/parse_int_spec.rb +23 -0
- data/spec/unit/morpher/evaluator/transformer/custom_spec.rb +13 -0
- data/spec/unit/morpher/evaluator/transformer/domain/attribute_accessors_spec.rb +48 -0
- data/spec/unit/morpher/evaluator/transformer/domain/attribute_hash_spec.rb +40 -0
- data/spec/unit/morpher/evaluator/transformer/domain/instance_variables_spec.rb +47 -0
- data/spec/unit/morpher/evaluator/transformer/guard_spec.rb +12 -0
- data/spec/unit/morpher/evaluator/transformer/hash_transform_spec.rb +47 -0
- data/spec/unit/morpher/evaluator/transformer/input_spec.rb +11 -0
- data/spec/unit/morpher/evaluator/transformer/map_spec.rb +25 -0
- data/spec/unit/morpher/evaluator/transformer/static_spec.rb +10 -0
- data/spec/unit/morpher/evaluator_spec.rb +15 -0
- data/spec/unit/morpher/printer_spec.rb +21 -0
- data/spec/unit/morpher/registry_spec.rb +11 -0
- data/spec/unit/morpher_spec.rb +53 -0
- 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
|