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,29 @@
|
|
1
|
+
module Morpher
|
2
|
+
class Compiler
|
3
|
+
# AST preprocessor
|
4
|
+
class Preprocessor < self
|
5
|
+
include Concord.new(:emitters)
|
6
|
+
|
7
|
+
# Call preprocessor
|
8
|
+
#
|
9
|
+
# @param [Node] node
|
10
|
+
# the raw AST node after DSL
|
11
|
+
#
|
12
|
+
# @return [Node]
|
13
|
+
# the transformed ast node
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
#
|
17
|
+
def call(node)
|
18
|
+
loop do
|
19
|
+
emitter = emitters.fetch(node.type, Emitter::Noop)
|
20
|
+
node = emitter.call(self, node)
|
21
|
+
break if emitter.equal?(Emitter::Noop)
|
22
|
+
end
|
23
|
+
|
24
|
+
node
|
25
|
+
end
|
26
|
+
|
27
|
+
end # Preprocessor
|
28
|
+
end # Compiler
|
29
|
+
end # Morpher
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Morpher
|
2
|
+
class Compiler
|
3
|
+
class Preprocessor
|
4
|
+
# Abstract preprocessor emitter
|
5
|
+
class Emitter < Compiler::Emitter
|
6
|
+
include Registry, Concord.new(:preprocessor, :node)
|
7
|
+
|
8
|
+
# Return output
|
9
|
+
#
|
10
|
+
# @return [AST::Node]
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
#
|
14
|
+
def output
|
15
|
+
validate_node
|
16
|
+
processed_node
|
17
|
+
end
|
18
|
+
memoize :output
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# Visit node
|
23
|
+
#
|
24
|
+
# @param [Node] node
|
25
|
+
# original untransformed node
|
26
|
+
#
|
27
|
+
# @return [Node]
|
28
|
+
# transformed node
|
29
|
+
#
|
30
|
+
# @api private
|
31
|
+
#
|
32
|
+
def visit(node)
|
33
|
+
preprocessor.call(node)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Validate node
|
37
|
+
#
|
38
|
+
# @return [undefined]
|
39
|
+
# if successful
|
40
|
+
#
|
41
|
+
# @raise [Error]
|
42
|
+
# otherwise
|
43
|
+
#
|
44
|
+
# @api private
|
45
|
+
#
|
46
|
+
def validate_node
|
47
|
+
assert_children_amount(named_children.length)
|
48
|
+
end
|
49
|
+
|
50
|
+
end # Emitter
|
51
|
+
|
52
|
+
end # Preprocessor
|
53
|
+
end # Compiler
|
54
|
+
end # Morpher
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Morpher
|
2
|
+
class Compiler
|
3
|
+
class Preprocessor
|
4
|
+
class Emitter
|
5
|
+
# Abstract base class for anima emitters
|
6
|
+
class Anima < self
|
7
|
+
include AbstractType
|
8
|
+
|
9
|
+
children :model
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
# Return domain param
|
14
|
+
#
|
15
|
+
# @return [Transformer::Domain::Param]
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
#
|
19
|
+
def param
|
20
|
+
Morpher::Evaluator::Transformer::Domain::Param.new(
|
21
|
+
model,
|
22
|
+
model.anima.attribute_names
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
class Dump < self
|
27
|
+
|
28
|
+
register :anima_dump
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# Return transformed node
|
33
|
+
#
|
34
|
+
# @param [Node] node
|
35
|
+
#
|
36
|
+
# @return [Node]
|
37
|
+
#
|
38
|
+
# @api private
|
39
|
+
#
|
40
|
+
def processed_node
|
41
|
+
s(:dump_attribute_hash, param)
|
42
|
+
end
|
43
|
+
|
44
|
+
end # Dump
|
45
|
+
|
46
|
+
class Load < self
|
47
|
+
|
48
|
+
register :anima_load
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# Return transformed node
|
53
|
+
#
|
54
|
+
# @param [Node] node
|
55
|
+
#
|
56
|
+
# @return [Node]
|
57
|
+
#
|
58
|
+
# @api private
|
59
|
+
#
|
60
|
+
def processed_node
|
61
|
+
s(:load_attribute_hash, param)
|
62
|
+
end
|
63
|
+
|
64
|
+
end # Load
|
65
|
+
end # Anima
|
66
|
+
end # Emitter
|
67
|
+
end # Preprocessor
|
68
|
+
end # Compiler
|
69
|
+
end # Morpher
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Morpher
|
2
|
+
class Compiler
|
3
|
+
class Preprocessor
|
4
|
+
class Emitter
|
5
|
+
# Preprocessor for boolean primitive
|
6
|
+
class Boolean < self
|
7
|
+
register :boolean
|
8
|
+
|
9
|
+
children
|
10
|
+
|
11
|
+
NODE = s(:xor, s(:primitive, TrueClass), s(:primitive, FalseClass))
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
# Return transformed node
|
16
|
+
#
|
17
|
+
# @param [Node] node
|
18
|
+
#
|
19
|
+
# @return [Node]
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
#
|
23
|
+
def processed_node
|
24
|
+
NODE
|
25
|
+
end
|
26
|
+
|
27
|
+
end # Boolean
|
28
|
+
end # Emitter
|
29
|
+
end # Preprocessor
|
30
|
+
end # Compiler
|
31
|
+
end # Morpher
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Morpher
|
2
|
+
class Compiler
|
3
|
+
class Preprocessor
|
4
|
+
class Emitter
|
5
|
+
|
6
|
+
# Namespace class for key preprocessors
|
7
|
+
class Key < self
|
8
|
+
include AbstractType
|
9
|
+
|
10
|
+
# Key symbolization preprocessor
|
11
|
+
class Symbolize < self
|
12
|
+
|
13
|
+
register :key_symbolize
|
14
|
+
|
15
|
+
children :key, :operand
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
# Return transformed node
|
20
|
+
#
|
21
|
+
# @param [Node] node
|
22
|
+
#
|
23
|
+
# @return [Node]
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
#
|
27
|
+
def processed_node
|
28
|
+
s(:key_transform, key.to_s, key.to_sym, operand)
|
29
|
+
end
|
30
|
+
|
31
|
+
end # Symbolize
|
32
|
+
|
33
|
+
# Neutral key preprocessor
|
34
|
+
class Neutral < self
|
35
|
+
|
36
|
+
register :key
|
37
|
+
|
38
|
+
children :key, :operand
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# Return transformed node
|
43
|
+
#
|
44
|
+
# @param [Node] node
|
45
|
+
#
|
46
|
+
# @return [Node]
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
#
|
50
|
+
def processed_node
|
51
|
+
s(:key_transform, key, key, operand)
|
52
|
+
end
|
53
|
+
|
54
|
+
end # Neutral
|
55
|
+
|
56
|
+
# Key transformation preprocessor
|
57
|
+
class Transform < self
|
58
|
+
register :key_transform
|
59
|
+
|
60
|
+
children :from, :to, :operand
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
# Return transformed node
|
65
|
+
#
|
66
|
+
# @param [Node] node
|
67
|
+
#
|
68
|
+
# @return [Node]
|
69
|
+
#
|
70
|
+
# @api private
|
71
|
+
#
|
72
|
+
def processed_node
|
73
|
+
s(
|
74
|
+
:block,
|
75
|
+
s(:key_fetch, from),
|
76
|
+
visit(operand),
|
77
|
+
s(:key_dump, to)
|
78
|
+
)
|
79
|
+
end
|
80
|
+
|
81
|
+
end # Transform
|
82
|
+
|
83
|
+
end # Key
|
84
|
+
end # Emitter
|
85
|
+
end # Preprocessor
|
86
|
+
end # Compiler
|
87
|
+
end # Morpher
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Morpher
|
2
|
+
class Compiler
|
3
|
+
class Preprocessor
|
4
|
+
class Emitter
|
5
|
+
|
6
|
+
# Noop emitter just descending into children
|
7
|
+
class Noop < self
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
# Return output
|
12
|
+
#
|
13
|
+
# @return [Node]
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
#
|
17
|
+
def processed_node
|
18
|
+
mapped_children = node.children.map do |child|
|
19
|
+
if child.kind_of?(node.class)
|
20
|
+
visit(child)
|
21
|
+
else
|
22
|
+
child
|
23
|
+
end
|
24
|
+
end
|
25
|
+
s(node.type, *mapped_children)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Validate node
|
29
|
+
#
|
30
|
+
# @return [undefined]
|
31
|
+
# if successful
|
32
|
+
#
|
33
|
+
# @raise [Error]
|
34
|
+
# otherwise
|
35
|
+
#
|
36
|
+
# @api private
|
37
|
+
#
|
38
|
+
def validate_node
|
39
|
+
end
|
40
|
+
|
41
|
+
end # Noop
|
42
|
+
end # Emitter
|
43
|
+
end # Preprocessor
|
44
|
+
end # Compiler
|
45
|
+
end # Morpher
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Morpher
|
2
|
+
class Compiler
|
3
|
+
class Preprocessor
|
4
|
+
class Emitter
|
5
|
+
|
6
|
+
# Param domain transformer specific emitter
|
7
|
+
class Param < self
|
8
|
+
|
9
|
+
register :param
|
10
|
+
|
11
|
+
children :model
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
# Return output
|
16
|
+
#
|
17
|
+
# @return [Node]
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
#
|
21
|
+
def processed_node
|
22
|
+
param = Morpher::Evaluator::Transformer::Domain::Param.new(
|
23
|
+
model,
|
24
|
+
remaining_children
|
25
|
+
)
|
26
|
+
s(:raw, param)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Validate node
|
30
|
+
#
|
31
|
+
# @return [undefined]
|
32
|
+
# if successful
|
33
|
+
#
|
34
|
+
# @raise [Error]
|
35
|
+
# otherwise
|
36
|
+
#
|
37
|
+
# @api private
|
38
|
+
#
|
39
|
+
def validate_node
|
40
|
+
remaining_children.each_with_index do |child, index|
|
41
|
+
next if child.kind_of?(Symbol)
|
42
|
+
fail Error::ChildType, Symbol, child, index
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end # Noop
|
47
|
+
end # Emitter
|
48
|
+
end # Preprocessor
|
49
|
+
end # Compiler
|
50
|
+
end # Morpher
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module Morpher
|
2
|
+
# Abstract namespace class for evaluation states
|
3
|
+
class Evaluation
|
4
|
+
include AbstractType, Printer::Mixin, Adamantium::Flat, Anima.new(
|
5
|
+
:evaluator,
|
6
|
+
:input,
|
7
|
+
:output,
|
8
|
+
:success
|
9
|
+
)
|
10
|
+
|
11
|
+
private :success
|
12
|
+
|
13
|
+
# Test if evaluation was successful
|
14
|
+
#
|
15
|
+
# @return [true]
|
16
|
+
# if evaluation was successful
|
17
|
+
#
|
18
|
+
# @return [false]
|
19
|
+
# otherwise
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
#
|
23
|
+
alias_method :success?, :success
|
24
|
+
public :success?
|
25
|
+
|
26
|
+
ERROR_DEFAULTS = IceNine.deep_freeze(
|
27
|
+
output: Undefined,
|
28
|
+
success: false
|
29
|
+
)
|
30
|
+
|
31
|
+
SUCCESS_DEFAULTS = IceNine.deep_freeze(
|
32
|
+
success: true
|
33
|
+
)
|
34
|
+
|
35
|
+
# Return error instance
|
36
|
+
#
|
37
|
+
# @param [Hash<Symbol, Object>] attributes
|
38
|
+
#
|
39
|
+
# @return [Evaluation]
|
40
|
+
#
|
41
|
+
# @api private
|
42
|
+
#
|
43
|
+
def self.error(attributes)
|
44
|
+
new(ERROR_DEFAULTS.merge(attributes))
|
45
|
+
end
|
46
|
+
|
47
|
+
# Return successful instance
|
48
|
+
#
|
49
|
+
# @param [Hash<Symbol, Object>] attributes
|
50
|
+
#
|
51
|
+
# @return [Evaluation]
|
52
|
+
#
|
53
|
+
# @api private
|
54
|
+
#
|
55
|
+
def self.success(attributes)
|
56
|
+
new(SUCCESS_DEFAULTS.merge(attributes))
|
57
|
+
end
|
58
|
+
|
59
|
+
# Evaluation state for nullary evaluators
|
60
|
+
class Nullary < self
|
61
|
+
|
62
|
+
printer do
|
63
|
+
name
|
64
|
+
indent do
|
65
|
+
attributes :input, :output, :success?
|
66
|
+
visit :evaluator
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
# Evaluation state for nary evaluators
|
73
|
+
class Nary < self
|
74
|
+
include anima.add(:evaluations)
|
75
|
+
|
76
|
+
printer do
|
77
|
+
name
|
78
|
+
indent do
|
79
|
+
attributes :input, :output, :success?
|
80
|
+
attribute_class :evaluator
|
81
|
+
visit_many :evaluations
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end # Evaluation
|
86
|
+
|
87
|
+
# Evaluation state for unary evaluators
|
88
|
+
class Binary < self
|
89
|
+
include anima.add(:left_evaluation, :right_evaluation)
|
90
|
+
|
91
|
+
printer do
|
92
|
+
name
|
93
|
+
indent do
|
94
|
+
attributes :input, :output, :success?
|
95
|
+
visit :left_evaluation
|
96
|
+
visit :right_evaluation
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end # Unary
|
101
|
+
|
102
|
+
# Evaluation state for unary evaluators
|
103
|
+
class Unary < self
|
104
|
+
include anima.add(:operand_evaluation)
|
105
|
+
|
106
|
+
printer do
|
107
|
+
name
|
108
|
+
indent do
|
109
|
+
attributes :input, :output, :success?
|
110
|
+
visit :operand_evaluation
|
111
|
+
visit :evaluator
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end # Unary
|
116
|
+
|
117
|
+
end # Evaluation
|
118
|
+
end # Morpher
|