furnace 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|