furnace 0.0.1 → 0.0.2
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.
- data/lib/furnace/ast/matcher.rb +116 -0
- data/lib/furnace/ast/matcher_special.rb +13 -0
- data/lib/furnace/ast/node.rb +74 -48
- data/lib/furnace/ast/symbolic_node.rb +23 -25
- data/lib/furnace/ast/visitor.rb +27 -29
- data/lib/furnace/ast.rb +6 -0
- data/lib/furnace/cfg/edge.rb +24 -26
- data/lib/furnace/cfg/graph.rb +39 -41
- data/lib/furnace/cfg/node.rb +26 -28
- data/lib/furnace/cfg.rb +5 -0
- data/lib/furnace/transform/pipeline.rb +1 -1
- data/lib/furnace/transform.rb +14 -0
- data/lib/furnace/version.rb +1 -1
- data/lib/furnace.rb +3 -20
- metadata +9 -4
@@ -0,0 +1,116 @@
|
|
1
|
+
module Furnace::AST
|
2
|
+
class Matcher
|
3
|
+
SpecialAny = MatcherSpecial.new(:any)
|
4
|
+
SpecialSubset = MatcherSpecial.define(:subset)
|
5
|
+
|
6
|
+
def initialize(&block)
|
7
|
+
@pattern = self.class.class_exec(&block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def match(object)
|
11
|
+
genmatch(object.to_astlet, @pattern)
|
12
|
+
end
|
13
|
+
|
14
|
+
def find_one(collection)
|
15
|
+
collection.find do |elem|
|
16
|
+
result = match elem
|
17
|
+
yield elem, result if block_given? && result
|
18
|
+
result
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def find_all(collection)
|
23
|
+
collection.select do |elem|
|
24
|
+
result = match elem
|
25
|
+
yield elem, result if block_given? && result
|
26
|
+
result
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class << self
|
31
|
+
def any
|
32
|
+
SpecialAny
|
33
|
+
end
|
34
|
+
|
35
|
+
def subset
|
36
|
+
SpecialSubset
|
37
|
+
end
|
38
|
+
|
39
|
+
def capture(name)
|
40
|
+
MatcherSpecial.new(:capture, name)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def submatch(array, pattern)
|
47
|
+
matches = true
|
48
|
+
|
49
|
+
pattern.each_with_index do |subpattern, index|
|
50
|
+
if array[index].nil?
|
51
|
+
return false
|
52
|
+
end
|
53
|
+
|
54
|
+
case subpattern
|
55
|
+
when SpecialAny
|
56
|
+
# it matches
|
57
|
+
when MatcherSpecial
|
58
|
+
if subpattern.type == :subset
|
59
|
+
all_submatches = true
|
60
|
+
|
61
|
+
subpattern.params.each do |pattern_case|
|
62
|
+
submatches = false
|
63
|
+
array[index..-1].each do |subset_elem|
|
64
|
+
submatches ||= genmatch(subset_elem, pattern_case)
|
65
|
+
break if submatches
|
66
|
+
end
|
67
|
+
|
68
|
+
all_submatches &&= submatches
|
69
|
+
break unless all_submatches
|
70
|
+
end
|
71
|
+
|
72
|
+
matches &&= all_submatches
|
73
|
+
end
|
74
|
+
when Array
|
75
|
+
matches &&= genmatch(array[index], subpattern)
|
76
|
+
else
|
77
|
+
matches &&= array[index] == subpattern
|
78
|
+
end
|
79
|
+
|
80
|
+
break unless matches
|
81
|
+
end
|
82
|
+
|
83
|
+
matches
|
84
|
+
end
|
85
|
+
|
86
|
+
def genmatch(astlet, pattern)
|
87
|
+
# if astlet.respond_to? :to_sexp
|
88
|
+
# puts "match #{astlet.to_sexp} of #{pattern}"
|
89
|
+
# else
|
90
|
+
# puts "match #{astlet} of #{pattern}"
|
91
|
+
# end
|
92
|
+
|
93
|
+
if pattern.first.is_a?(Symbol)
|
94
|
+
# Match an astlet
|
95
|
+
type, *rest = pattern
|
96
|
+
|
97
|
+
if astlet.is_a? Node
|
98
|
+
if astlet.type == type
|
99
|
+
submatch(astlet.children, rest)
|
100
|
+
else
|
101
|
+
false
|
102
|
+
end
|
103
|
+
else
|
104
|
+
false
|
105
|
+
end
|
106
|
+
else
|
107
|
+
# Match an array
|
108
|
+
if astlet.is_a? Array
|
109
|
+
submatch(astlet, pattern)
|
110
|
+
else
|
111
|
+
false
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/lib/furnace/ast/node.rb
CHANGED
@@ -1,70 +1,96 @@
|
|
1
|
-
module Furnace
|
2
|
-
|
3
|
-
|
4
|
-
attr_accessor :type, :parent, :children, :metadata
|
1
|
+
module Furnace::AST
|
2
|
+
class Node
|
3
|
+
attr_accessor :type, :parent, :children, :metadata
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def update(type, children=nil, metadata={})
|
11
|
-
@type = type
|
12
|
-
@children = children || @children
|
5
|
+
def initialize(type, children=[], metadata={})
|
6
|
+
@type, @children, @metadata = type.to_sym, children, metadata
|
7
|
+
end
|
13
8
|
|
14
|
-
|
15
|
-
|
16
|
-
if
|
17
|
-
|
18
|
-
else
|
19
|
-
@metadata = {}
|
9
|
+
def normalize_hierarchy!
|
10
|
+
@children.each do |child|
|
11
|
+
if child.respond_to? :parent=
|
12
|
+
child.parent = self
|
20
13
|
end
|
21
14
|
|
22
|
-
|
15
|
+
if child.respond_to? :normalize_hierarchy!
|
16
|
+
child.normalize_hierarchy!
|
17
|
+
end
|
23
18
|
end
|
24
19
|
|
25
|
-
|
26
|
-
|
27
|
-
end
|
20
|
+
self
|
21
|
+
end
|
28
22
|
|
29
|
-
|
30
|
-
|
31
|
-
|
23
|
+
def update(type, children=nil, metadata={})
|
24
|
+
@type = type
|
25
|
+
@children = children || @children
|
32
26
|
|
33
|
-
|
34
|
-
|
27
|
+
# If something non-nil is passed, including default value, then merge.
|
28
|
+
# Else, clear metadata store.
|
29
|
+
if metadata
|
30
|
+
@metadata.merge!(metadata)
|
31
|
+
else
|
32
|
+
@metadata = {}
|
35
33
|
end
|
36
34
|
|
37
|
-
|
38
|
-
|
39
|
-
end
|
35
|
+
self
|
36
|
+
end
|
40
37
|
|
41
|
-
|
42
|
-
|
38
|
+
def dup
|
39
|
+
node = super
|
40
|
+
node.children = @children.dup
|
41
|
+
node.metadata = @metadata.dup
|
42
|
+
node
|
43
|
+
end
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
else
|
48
|
-
str << " #{child.inspect}"
|
49
|
-
end
|
50
|
-
end
|
45
|
+
def index
|
46
|
+
parent.children.find_index(self)
|
47
|
+
end
|
51
48
|
|
52
|
-
|
49
|
+
def next
|
50
|
+
parent.children[index + 1]
|
51
|
+
end
|
53
52
|
|
54
|
-
|
55
|
-
|
56
|
-
|
53
|
+
def prev
|
54
|
+
parent.children[index - 1]
|
55
|
+
end
|
57
56
|
|
58
|
-
|
57
|
+
def to_s
|
58
|
+
"(#{fancy_type} ...)"
|
59
|
+
end
|
59
60
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
def to_sexp(indent=0)
|
62
|
+
str = "#{" " * indent}(#{fancy_type}"
|
63
|
+
|
64
|
+
children.each do |child|
|
65
|
+
if (!children[0].is_a?(Node) && child.is_a?(Node)) ||
|
66
|
+
(children[0].is_a?(Node) && child.is_a?(Node) &&
|
67
|
+
child.children.any? { |c| c.is_a?(Node) || c.is_a?(Array) }) ||
|
68
|
+
(child.is_a?(Node) && child.metadata[:label])
|
69
|
+
str << "\n#{child.to_sexp(indent + 1)}"
|
64
70
|
else
|
65
|
-
|
71
|
+
str << " #{child.inspect}"
|
66
72
|
end
|
67
73
|
end
|
74
|
+
|
75
|
+
str << ")"
|
76
|
+
|
77
|
+
str
|
78
|
+
end
|
79
|
+
alias :inspect :to_sexp
|
80
|
+
|
81
|
+
def to_astlet
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
protected
|
86
|
+
|
87
|
+
def fancy_type
|
88
|
+
dasherized = @type.to_s.gsub('_', '-')
|
89
|
+
if @metadata[:label]
|
90
|
+
"#{@metadata[:label]}:#{dasherized}"
|
91
|
+
else
|
92
|
+
dasherized
|
93
|
+
end
|
68
94
|
end
|
69
95
|
end
|
70
96
|
end
|
@@ -1,36 +1,34 @@
|
|
1
|
-
module Furnace
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
end
|
7
|
-
|
8
|
-
def to_sym
|
9
|
-
@name
|
10
|
-
end
|
1
|
+
module Furnace::AST
|
2
|
+
class SymbolicNode
|
3
|
+
def initialize(name)
|
4
|
+
@name = name.to_sym
|
5
|
+
end
|
11
6
|
|
12
|
-
|
13
|
-
|
14
|
-
|
7
|
+
def to_sym
|
8
|
+
@name
|
9
|
+
end
|
15
10
|
|
16
|
-
|
17
|
-
|
18
|
-
end
|
11
|
+
def ===(name)
|
12
|
+
@name == name.to_sym
|
19
13
|
end
|
20
14
|
|
21
|
-
|
22
|
-
|
23
|
-
".#{@name}"
|
24
|
-
end
|
15
|
+
def inspect
|
16
|
+
@name.to_s
|
25
17
|
end
|
18
|
+
end
|
26
19
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
20
|
+
class MethodName < SymbolicNode
|
21
|
+
def inspect
|
22
|
+
".#{@name}"
|
31
23
|
end
|
24
|
+
end
|
32
25
|
|
33
|
-
|
26
|
+
class LocalVariable < SymbolicNode
|
27
|
+
def inspect
|
28
|
+
"%#{@name}"
|
34
29
|
end
|
35
30
|
end
|
31
|
+
|
32
|
+
class Constant < SymbolicNode
|
33
|
+
end
|
36
34
|
end
|
data/lib/furnace/ast/visitor.rb
CHANGED
@@ -1,42 +1,40 @@
|
|
1
|
-
module Furnace
|
2
|
-
module
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
child = child.children
|
11
|
-
end
|
1
|
+
module Furnace::AST
|
2
|
+
module Visitor
|
3
|
+
def visit(node)
|
4
|
+
node.children.map! do |child|
|
5
|
+
if child.is_a? Node
|
6
|
+
visit child
|
7
|
+
|
8
|
+
if child.type == :expand
|
9
|
+
child = child.children
|
12
10
|
end
|
13
|
-
|
14
|
-
child
|
15
11
|
end
|
16
12
|
|
17
|
-
|
13
|
+
child
|
14
|
+
end
|
18
15
|
|
19
|
-
|
20
|
-
if child.is_a? Node
|
21
|
-
child.parent = node
|
16
|
+
node.children.flatten!
|
22
17
|
|
23
|
-
|
24
|
-
|
25
|
-
|
18
|
+
node.children.delete_if do |child|
|
19
|
+
if child.is_a? Node
|
20
|
+
child.parent = node
|
26
21
|
|
27
|
-
|
28
|
-
on_handler = :"on_#{node.type}"
|
29
|
-
if respond_to? on_handler
|
30
|
-
send on_handler, node
|
22
|
+
child.type == :remove
|
31
23
|
end
|
24
|
+
end
|
32
25
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
26
|
+
# Invoke a specific handler
|
27
|
+
on_handler = :"on_#{node.type}"
|
28
|
+
if respond_to? on_handler
|
29
|
+
send on_handler, node
|
30
|
+
end
|
37
31
|
|
38
|
-
|
32
|
+
# Invoke a generic handler
|
33
|
+
if respond_to? :on_any
|
34
|
+
send :on_any, node
|
39
35
|
end
|
36
|
+
|
37
|
+
node
|
40
38
|
end
|
41
39
|
end
|
42
40
|
end
|
data/lib/furnace/ast.rb
ADDED
data/lib/furnace/cfg/edge.rb
CHANGED
@@ -1,36 +1,34 @@
|
|
1
|
-
module Furnace
|
2
|
-
|
3
|
-
|
4
|
-
attr_accessor :source_operation, :source_label, :target_label
|
1
|
+
module Furnace::CFG
|
2
|
+
class Edge
|
3
|
+
attr_accessor :source_operation, :source_label, :target_label
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
def initialize(cfg, source_operation, source_label, target_label)
|
6
|
+
@cfg, @source_operation, @source_label, @target_label =
|
7
|
+
cfg, source_operation, source_label, target_label
|
8
|
+
end
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
def source
|
11
|
+
@cfg.find_node(@source_label)
|
12
|
+
end
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
def target
|
15
|
+
@cfg.find_node(@target_label) if @target_label
|
16
|
+
end
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
def source=(node)
|
19
|
+
@source_label = node.label
|
20
|
+
end
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
22
|
+
def target=(node)
|
23
|
+
if node
|
24
|
+
@target_label = node.label
|
25
|
+
else
|
26
|
+
@target_label = nil
|
29
27
|
end
|
28
|
+
end
|
30
29
|
|
31
|
-
|
32
|
-
|
33
|
-
end
|
30
|
+
def inspect
|
31
|
+
"<#{@source_label.inspect} -> #{@target_label.inspect}>"
|
34
32
|
end
|
35
33
|
end
|
36
34
|
end
|
data/lib/furnace/cfg/graph.rb
CHANGED
@@ -1,57 +1,55 @@
|
|
1
|
-
module Furnace
|
2
|
-
|
3
|
-
|
4
|
-
attr_reader :nodes, :edges
|
1
|
+
module Furnace::CFG
|
2
|
+
class Graph
|
3
|
+
attr_reader :nodes, :edges
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
def initialize
|
6
|
+
@nodes = Set.new
|
7
|
+
@edges = Set.new
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def find_node(label)
|
15
|
-
if node = @nodes.find { |n| n.label == label }
|
16
|
-
node
|
17
|
-
else
|
18
|
-
raise "Cannot find CFG node #{label}"
|
19
|
-
end
|
20
|
-
end
|
9
|
+
@pending_label = nil
|
10
|
+
@pending_operations = []
|
11
|
+
end
|
21
12
|
|
22
|
-
|
23
|
-
|
24
|
-
|
13
|
+
def find_node(label)
|
14
|
+
if node = @nodes.find { |n| n.label == label }
|
15
|
+
node
|
16
|
+
else
|
17
|
+
raise "Cannot find CFG node #{label}"
|
25
18
|
end
|
19
|
+
end
|
26
20
|
|
27
|
-
|
28
|
-
|
21
|
+
def expand(label, operation)
|
22
|
+
@pending_label ||= label
|
23
|
+
@pending_operations << operation
|
24
|
+
end
|
29
25
|
|
30
|
-
|
26
|
+
def transfer(targets)
|
27
|
+
return unless @pending_label
|
31
28
|
|
32
|
-
|
33
|
-
@edges << CFG::Edge.new(self, operation, @pending_label, target)
|
34
|
-
end
|
29
|
+
@nodes << Node.new(self, @pending_label, @pending_operations)
|
35
30
|
|
36
|
-
|
37
|
-
@
|
31
|
+
targets.each do |operation, target|
|
32
|
+
@edges << Edge.new(self, operation, @pending_label, target)
|
38
33
|
end
|
39
34
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
graph.node node.label, node.operations.map(&:inspect).join("\n")
|
44
|
-
end
|
35
|
+
@pending_label = nil
|
36
|
+
@pending_operations = []
|
37
|
+
end
|
45
38
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
39
|
+
def to_graphviz
|
40
|
+
Furnace::Graphviz.new do |graph|
|
41
|
+
@nodes.each do |node|
|
42
|
+
graph.node node.label, node.operations.map(&:inspect).join("\n")
|
43
|
+
end
|
52
44
|
|
53
|
-
|
45
|
+
@edges.each do |edge|
|
46
|
+
if edge.source_operation.nil?
|
47
|
+
label = "~"
|
48
|
+
else
|
49
|
+
label = edge.source_operation
|
54
50
|
end
|
51
|
+
|
52
|
+
graph.edge edge.source_label, edge.target_label, label
|
55
53
|
end
|
56
54
|
end
|
57
55
|
end
|
data/lib/furnace/cfg/node.rb
CHANGED
@@ -1,38 +1,36 @@
|
|
1
|
-
module Furnace
|
2
|
-
|
3
|
-
|
4
|
-
attr_reader :label, :operations
|
1
|
+
module Furnace::CFG
|
2
|
+
class Node
|
3
|
+
attr_reader :label, :operations
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
def initialize(cfg, label, operations)
|
6
|
+
@cfg, @label, @operations = cfg, label, operations
|
7
|
+
end
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
def entering_edges
|
10
|
+
@cfg.edges.select { |e| e.target == self }
|
11
|
+
end
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
def leaving_edges
|
14
|
+
@cfg.edges.select { |e| e.source == self }
|
15
|
+
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
def leaving_edge(source)
|
18
|
+
leaving_edges.find { |e| e.source_operation == source }
|
19
|
+
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
def default_leaving_edge
|
22
|
+
leaving_edge(nil)
|
23
|
+
end
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
def ==(other)
|
26
|
+
self.label == other.label
|
27
|
+
end
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
29
|
+
def inspect
|
30
|
+
if @label
|
31
|
+
"<#{@label}:#{@operations.map(&:inspect).join ", "}>"
|
32
|
+
else
|
33
|
+
"<!exit>"
|
36
34
|
end
|
37
35
|
end
|
38
36
|
end
|
data/lib/furnace/cfg.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Furnace::Transform
|
2
|
+
end
|
3
|
+
|
4
|
+
require "furnace/transform/pipeline"
|
5
|
+
|
6
|
+
require "furnace/transform/rubinius/ast_build"
|
7
|
+
require "furnace/transform/rubinius/ast_normalize"
|
8
|
+
|
9
|
+
require "furnace/transform/generic/label_normalize"
|
10
|
+
require "furnace/transform/generic/cfg_build"
|
11
|
+
require "furnace/transform/generic/cfg_normalize"
|
12
|
+
require "furnace/transform/generic/anf_build"
|
13
|
+
|
14
|
+
require "furnace/transform/optimizing/fold_constants"
|
data/lib/furnace/version.rb
CHANGED
data/lib/furnace.rb
CHANGED
@@ -1,14 +1,7 @@
|
|
1
1
|
require "furnace/version"
|
2
2
|
|
3
|
-
require "
|
4
|
-
|
5
|
-
require "furnace/ast/node"
|
6
|
-
require "furnace/ast/symbolic_node"
|
7
|
-
require "furnace/ast/visitor"
|
8
|
-
|
9
|
-
require "furnace/cfg/node"
|
10
|
-
require "furnace/cfg/edge"
|
11
|
-
require "furnace/cfg/graph"
|
3
|
+
require "furnace/ast"
|
4
|
+
require "furnace/cfg"
|
12
5
|
|
13
6
|
require "furnace/anf/node"
|
14
7
|
require "furnace/anf/edge"
|
@@ -18,17 +11,7 @@ require "furnace/anf/if_node"
|
|
18
11
|
require "furnace/anf/return_node"
|
19
12
|
require "furnace/anf/graph"
|
20
13
|
|
21
|
-
require "furnace/transform
|
22
|
-
|
23
|
-
require "furnace/transform/rubinius/ast_build"
|
24
|
-
require "furnace/transform/rubinius/ast_normalize"
|
25
|
-
|
26
|
-
require "furnace/transform/generic/label_normalize"
|
27
|
-
require "furnace/transform/generic/cfg_build"
|
28
|
-
require "furnace/transform/generic/cfg_normalize"
|
29
|
-
require "furnace/transform/generic/anf_build"
|
30
|
-
|
31
|
-
require "furnace/transform/optimizing/fold_constants"
|
14
|
+
require "furnace/transform"
|
32
15
|
|
33
16
|
require "furnace/graphviz"
|
34
17
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: furnace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 988111682
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Peter Zotov
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-01-
|
18
|
+
date: 2012-01-26 00:00:00 Z
|
19
19
|
dependencies: []
|
20
20
|
|
21
21
|
description: Furnace aims to compile Ruby code into small static executables by restricting its metaprogramming features.
|
@@ -42,13 +42,18 @@ files:
|
|
42
42
|
- lib/furnace/anf/let_node.rb
|
43
43
|
- lib/furnace/anf/node.rb
|
44
44
|
- lib/furnace/anf/return_node.rb
|
45
|
+
- lib/furnace/ast.rb
|
46
|
+
- lib/furnace/ast/matcher.rb
|
47
|
+
- lib/furnace/ast/matcher_special.rb
|
45
48
|
- lib/furnace/ast/node.rb
|
46
49
|
- lib/furnace/ast/symbolic_node.rb
|
47
50
|
- lib/furnace/ast/visitor.rb
|
51
|
+
- lib/furnace/cfg.rb
|
48
52
|
- lib/furnace/cfg/edge.rb
|
49
53
|
- lib/furnace/cfg/graph.rb
|
50
54
|
- lib/furnace/cfg/node.rb
|
51
55
|
- lib/furnace/graphviz.rb
|
56
|
+
- lib/furnace/transform.rb
|
52
57
|
- lib/furnace/transform/generic/anf_build.rb
|
53
58
|
- lib/furnace/transform/generic/cfg_build.rb
|
54
59
|
- lib/furnace/transform/generic/cfg_normalize.rb
|