furnace 0.2.5 → 0.2.6
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/node.rb +23 -29
 - data/lib/furnace/ast/strict_visitor.rb +20 -0
 - data/lib/furnace/ast/visitor.rb +0 -2
 - data/lib/furnace/ast.rb +1 -1
 - data/lib/furnace/cfg/graph.rb +37 -23
 - data/lib/furnace/cfg/node.rb +8 -4
 - data/lib/furnace/graphviz.rb +2 -2
 - data/lib/furnace/transform/iterative_process.rb +26 -0
 - data/lib/furnace/transform/pipeline.rb +2 -0
 - data/lib/furnace/version.rb +1 -1
 - data/lib/furnace.rb +1 -0
 - metadata +5 -3
 - data/lib/furnace/ast/symbolic_node.rb +0 -34
 
    
        data/lib/furnace/ast/node.rb
    CHANGED
    
    | 
         @@ -1,25 +1,11 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Furnace::AST
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Node
         
     | 
| 
       3 
     | 
    
         
            -
                attr_accessor :type, : 
     | 
| 
      
 3 
     | 
    
         
            +
                attr_accessor :type, :children, :metadata
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
                def initialize(type, children=[], metadata={})
         
     | 
| 
       6 
6 
     | 
    
         
             
                  @type, @children, @metadata = type.to_sym, children, metadata
         
     | 
| 
       7 
7 
     | 
    
         
             
                end
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
                def normalize_hierarchy!
         
     | 
| 
       10 
     | 
    
         
            -
                  @children.each do |child|
         
     | 
| 
       11 
     | 
    
         
            -
                    if child.respond_to? :parent=
         
     | 
| 
       12 
     | 
    
         
            -
                      child.parent = self
         
     | 
| 
       13 
     | 
    
         
            -
                    end
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
                    if child.respond_to? :normalize_hierarchy!
         
     | 
| 
       16 
     | 
    
         
            -
                      child.normalize_hierarchy!
         
     | 
| 
       17 
     | 
    
         
            -
                    end
         
     | 
| 
       18 
     | 
    
         
            -
                  end
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                  self
         
     | 
| 
       21 
     | 
    
         
            -
                end
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
9 
     | 
    
         
             
                def update(type, children=nil, metadata={})
         
     | 
| 
       24 
10 
     | 
    
         
             
                  @type     = type
         
     | 
| 
       25 
11 
     | 
    
         
             
                  @children = children || @children
         
     | 
| 
         @@ -52,18 +38,6 @@ module Furnace::AST 
     | 
|
| 
       52 
38 
     | 
    
         
             
                  end
         
     | 
| 
       53 
39 
     | 
    
         
             
                end
         
     | 
| 
       54 
40 
     | 
    
         | 
| 
       55 
     | 
    
         
            -
                def index
         
     | 
| 
       56 
     | 
    
         
            -
                  parent.children.find_index(self)
         
     | 
| 
       57 
     | 
    
         
            -
                end
         
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
                def next
         
     | 
| 
       60 
     | 
    
         
            -
                  parent.children[index + 1]
         
     | 
| 
       61 
     | 
    
         
            -
                end
         
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
                def prev
         
     | 
| 
       64 
     | 
    
         
            -
                  parent.children[index - 1]
         
     | 
| 
       65 
     | 
    
         
            -
                end
         
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
       67 
41 
     | 
    
         
             
                def to_s
         
     | 
| 
       68 
42 
     | 
    
         
             
                  "(#{fancy_type} ...)"
         
     | 
| 
       69 
43 
     | 
    
         
             
                end
         
     | 
| 
         @@ -71,6 +45,12 @@ module Furnace::AST 
     | 
|
| 
       71 
45 
     | 
    
         
             
                def to_sexp(indent=0)
         
     | 
| 
       72 
46 
     | 
    
         
             
                  str = "#{"  " * indent}(#{fancy_type}"
         
     | 
| 
       73 
47 
     | 
    
         | 
| 
      
 48 
     | 
    
         
            +
                  if @metadata[:ellipsis]
         
     | 
| 
      
 49 
     | 
    
         
            +
                    str << " <omitted>)"
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    return str
         
     | 
| 
      
 52 
     | 
    
         
            +
                  end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
       74 
54 
     | 
    
         
             
                  children.each do |child|
         
     | 
| 
       75 
55 
     | 
    
         
             
                    if (!children[0].is_a?(Node) && child.is_a?(Node)) ||
         
     | 
| 
       76 
56 
     | 
    
         
             
                        (children[0].is_a?(Node) && child.is_a?(Node) &&
         
     | 
| 
         @@ -96,10 +76,24 @@ module Furnace::AST 
     | 
|
| 
       96 
76 
     | 
    
         | 
| 
       97 
77 
     | 
    
         
             
                def fancy_type
         
     | 
| 
       98 
78 
     | 
    
         
             
                  dasherized = @type.to_s.gsub('_', '-')
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  if @metadata.any?
         
     | 
| 
      
 81 
     | 
    
         
            +
                    metainfo = @metadata.dup
         
     | 
| 
      
 82 
     | 
    
         
            +
                    metainfo.delete :label
         
     | 
| 
      
 83 
     | 
    
         
            +
                    metainfo.delete :origin
         
     | 
| 
      
 84 
     | 
    
         
            +
                    metainfo.delete :ellipsis
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                    if metainfo.any?
         
     | 
| 
      
 87 
     | 
    
         
            +
                      metainfo = "#{metainfo.inspect}:"
         
     | 
| 
      
 88 
     | 
    
         
            +
                    else
         
     | 
| 
      
 89 
     | 
    
         
            +
                      metainfo = nil
         
     | 
| 
      
 90 
     | 
    
         
            +
                    end
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
       99 
93 
     | 
    
         
             
                  if @metadata[:label]
         
     | 
| 
       100 
     | 
    
         
            -
                    "#{@metadata[:label]}:#{dasherized}"
         
     | 
| 
      
 94 
     | 
    
         
            +
                    "#{@metadata[:label]}:#{metainfo}#{dasherized}"
         
     | 
| 
       101 
95 
     | 
    
         
             
                  else
         
     | 
| 
       102 
     | 
    
         
            -
                    dasherized
         
     | 
| 
      
 96 
     | 
    
         
            +
                    "#{metainfo}#{dasherized}"
         
     | 
| 
       103 
97 
     | 
    
         
             
                  end
         
     | 
| 
       104 
98 
     | 
    
         
             
                end
         
     | 
| 
       105 
99 
     | 
    
         
             
              end
         
     | 
| 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Furnace::AST
         
     | 
| 
      
 2 
     | 
    
         
            +
              module StrictVisitor
         
     | 
| 
      
 3 
     | 
    
         
            +
                def visit(node)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  # Invoke a specific handler
         
     | 
| 
      
 5 
     | 
    
         
            +
                  on_handler = :"on_#{node.type}"
         
     | 
| 
      
 6 
     | 
    
         
            +
                  if respond_to? on_handler
         
     | 
| 
      
 7 
     | 
    
         
            +
                    new_node = send on_handler, node
         
     | 
| 
      
 8 
     | 
    
         
            +
                    node = new_node if new_node
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  node
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def visit_all(nodes)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  nodes.map do |node|
         
     | 
| 
      
 16 
     | 
    
         
            +
                    visit node
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/furnace/ast/visitor.rb
    CHANGED
    
    
    
        data/lib/furnace/ast.rb
    CHANGED
    
    
    
        data/lib/furnace/cfg/graph.rb
    CHANGED
    
    | 
         @@ -22,28 +22,32 @@ module Furnace::CFG 
     | 
|
| 
       22 
22 
     | 
    
         
             
                end
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
       24 
24 
     | 
    
         
             
                def eliminate_unreachable!
         
     | 
| 
       25 
     | 
    
         
            -
                   
     | 
| 
      
 25 
     | 
    
         
            +
                  worklist  = Set[ entry, exit ]
         
     | 
| 
       26 
26 
     | 
    
         
             
                  reachable = Set[]
         
     | 
| 
       27 
27 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
                  while  
     | 
| 
       29 
     | 
    
         
            -
                    node =  
     | 
| 
      
 28 
     | 
    
         
            +
                  while worklist.any?
         
     | 
| 
      
 29 
     | 
    
         
            +
                    node = worklist.first
         
     | 
| 
      
 30 
     | 
    
         
            +
                    worklist.delete node
         
     | 
| 
       30 
31 
     | 
    
         
             
                    reachable.add node
         
     | 
| 
       31 
32 
     | 
    
         | 
| 
       32 
33 
     | 
    
         
             
                    node.targets.each do |target|
         
     | 
| 
       33 
34 
     | 
    
         
             
                      unless reachable.include? target
         
     | 
| 
       34 
     | 
    
         
            -
                         
     | 
| 
      
 35 
     | 
    
         
            +
                        worklist.add target
         
     | 
| 
       35 
36 
     | 
    
         
             
                      end
         
     | 
| 
       36 
37 
     | 
    
         
             
                    end
         
     | 
| 
       37 
38 
     | 
    
         | 
| 
       38 
39 
     | 
    
         
             
                    if node.exception
         
     | 
| 
       39 
40 
     | 
    
         
             
                      unless reachable.include? node.exception
         
     | 
| 
       40 
     | 
    
         
            -
                         
     | 
| 
      
 41 
     | 
    
         
            +
                        worklist.add node.exception
         
     | 
| 
       41 
42 
     | 
    
         
             
                      end
         
     | 
| 
       42 
43 
     | 
    
         
             
                    end
         
     | 
| 
       43 
44 
     | 
    
         
             
                  end
         
     | 
| 
       44 
45 
     | 
    
         | 
| 
       45 
46 
     | 
    
         
             
                  @nodes.each do |node|
         
     | 
| 
       46 
     | 
    
         
            -
                     
     | 
| 
      
 47 
     | 
    
         
            +
                    unless reachable.include? node
         
     | 
| 
      
 48 
     | 
    
         
            +
                      @nodes.delete node
         
     | 
| 
      
 49 
     | 
    
         
            +
                      yield node if block_given?
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
       47 
51 
     | 
    
         
             
                  end
         
     | 
| 
       48 
52 
     | 
    
         | 
| 
       49 
53 
     | 
    
         
             
                  flush
         
     | 
| 
         @@ -59,42 +63,41 @@ module Furnace::CFG 
     | 
|
| 
       59 
63 
     | 
    
         
             
                    next if target == @exit
         
     | 
| 
       60 
64 
     | 
    
         | 
| 
       61 
65 
     | 
    
         
             
                    # Skip explicitly non-redundant nodes
         
     | 
| 
       62 
     | 
    
         
            -
                    if node. 
     | 
| 
      
 66 
     | 
    
         
            +
                    if node.metadata[:keep]
         
     | 
| 
       63 
67 
     | 
    
         
             
                      next
         
     | 
| 
       64 
68 
     | 
    
         
             
                    end
         
     | 
| 
       65 
69 
     | 
    
         | 
| 
       66 
     | 
    
         
            -
                    if node.targets. 
     | 
| 
       67 
     | 
    
         
            -
                        target.sources. 
     | 
| 
      
 70 
     | 
    
         
            +
                    if node.targets.uniq == [target] &&
         
     | 
| 
      
 71 
     | 
    
         
            +
                        target.sources.uniq == [node] &&
         
     | 
| 
       68 
72 
     | 
    
         
             
                        node.exception == target.exception
         
     | 
| 
       69 
73 
     | 
    
         | 
| 
      
 74 
     | 
    
         
            +
                      yield node, target if block_given?
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
       70 
76 
     | 
    
         
             
                      node.insns.delete node.cti
         
     | 
| 
       71 
     | 
    
         
            -
                      @nodes.delete node
         
     | 
| 
       72 
77 
     | 
    
         
             
                      @nodes.delete target
         
     | 
| 
      
 78 
     | 
    
         
            +
                      worklist.delete target
         
     | 
| 
       73 
79 
     | 
    
         | 
| 
       74 
     | 
    
         
            -
                       
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
       77 
     | 
    
         
            -
                          target.cti,
         
     | 
| 
       78 
     | 
    
         
            -
                          target.target_labels,
         
     | 
| 
       79 
     | 
    
         
            -
                          target.exception_label)
         
     | 
| 
       80 
     | 
    
         
            -
                      @nodes.add new_node
         
     | 
| 
       81 
     | 
    
         
            -
                      worklist.add new_node
         
     | 
| 
      
 80 
     | 
    
         
            +
                      node.insns.concat target.insns
         
     | 
| 
      
 81 
     | 
    
         
            +
                      node.cti           = target.cti
         
     | 
| 
      
 82 
     | 
    
         
            +
                      node.target_labels = target.target_labels
         
     | 
| 
       82 
83 
     | 
    
         | 
| 
       83 
     | 
    
         
            -
                       
     | 
| 
       84 
     | 
    
         
            -
                        @entry = new_node
         
     | 
| 
       85 
     | 
    
         
            -
                      end
         
     | 
| 
      
 84 
     | 
    
         
            +
                      worklist.add node
         
     | 
| 
       86 
85 
     | 
    
         | 
| 
       87 
86 
     | 
    
         
             
                      flush
         
     | 
| 
       88 
87 
     | 
    
         
             
                    elsif node.targets.count == 1 &&
         
     | 
| 
       89 
88 
     | 
    
         
             
                        node.insns.empty?
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
       90 
90 
     | 
    
         
             
                      target = node.targets.first
         
     | 
| 
       91 
91 
     | 
    
         | 
| 
      
 92 
     | 
    
         
            +
                      yield target, node if block_given?
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
       92 
94 
     | 
    
         
             
                      node.sources.each do |source|
         
     | 
| 
       93 
95 
     | 
    
         
             
                        index = source.targets.index(node)
         
     | 
| 
       94 
96 
     | 
    
         
             
                        source.target_labels[index] = target.label
         
     | 
| 
       95 
97 
     | 
    
         
             
                      end
         
     | 
| 
       96 
98 
     | 
    
         | 
| 
       97 
99 
     | 
    
         
             
                      @nodes.delete node
         
     | 
| 
      
 100 
     | 
    
         
            +
                      worklist.delete node
         
     | 
| 
       98 
101 
     | 
    
         | 
| 
       99 
102 
     | 
    
         
             
                      if @entry == node
         
     | 
| 
       100 
103 
     | 
    
         
             
                        @entry = target
         
     | 
| 
         @@ -231,6 +234,9 @@ module Furnace::CFG 
     | 
|
| 
       231 
234 
     | 
    
         
             
                def flush
         
     | 
| 
       232 
235 
     | 
    
         
             
                  @source_map = nil
         
     | 
| 
       233 
236 
     | 
    
         
             
                  @label_map.clear
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                  @dominators = nil
         
     | 
| 
      
 239 
     | 
    
         
            +
                  @postdominators = nil
         
     | 
| 
       234 
240 
     | 
    
         
             
                end
         
     | 
| 
       235 
241 
     | 
    
         | 
| 
       236 
242 
     | 
    
         
             
                def to_graphviz
         
     | 
| 
         @@ -239,7 +245,15 @@ module Furnace::CFG 
     | 
|
| 
       239 
245 
     | 
    
         
             
                      if node.label == nil
         
     | 
| 
       240 
246 
     | 
    
         
             
                        contents = "<exit>"
         
     | 
| 
       241 
247 
     | 
    
         
             
                      else
         
     | 
| 
       242 
     | 
    
         
            -
                        contents = "<#{node.label.inspect} 
     | 
| 
      
 248 
     | 
    
         
            +
                        contents = "<#{node.label.inspect}>"
         
     | 
| 
      
 249 
     | 
    
         
            +
                      end
         
     | 
| 
      
 250 
     | 
    
         
            +
             
     | 
| 
      
 251 
     | 
    
         
            +
                      if node.metadata.any?
         
     | 
| 
      
 252 
     | 
    
         
            +
                        contents << "\n#{node.metadata.inspect}"
         
     | 
| 
      
 253 
     | 
    
         
            +
                      end
         
     | 
| 
      
 254 
     | 
    
         
            +
             
     | 
| 
      
 255 
     | 
    
         
            +
                      if node.insns.any?
         
     | 
| 
      
 256 
     | 
    
         
            +
                        contents << "\n#{node.insns.map(&:inspect).join("\n")}"
         
     | 
| 
       243 
257 
     | 
    
         
             
                      end
         
     | 
| 
       244 
258 
     | 
    
         | 
| 
       245 
259 
     | 
    
         
             
                      options = {}
         
     | 
| 
         @@ -256,7 +270,7 @@ module Furnace::CFG 
     | 
|
| 
       256 
270 
     | 
    
         
             
                      end
         
     | 
| 
       257 
271 
     | 
    
         | 
| 
       258 
272 
     | 
    
         
             
                      if node.exception_label
         
     | 
| 
       259 
     | 
    
         
            -
                        graph.edge node.label, node.exception_label, " 
     | 
| 
      
 273 
     | 
    
         
            +
                        graph.edge node.label, node.exception_label, "", color: 'orange'
         
     | 
| 
       260 
274 
     | 
    
         
             
                      end
         
     | 
| 
       261 
275 
     | 
    
         
             
                    end
         
     | 
| 
       262 
276 
     | 
    
         
             
                  end
         
     | 
    
        data/lib/furnace/cfg/node.rb
    CHANGED
    
    | 
         @@ -5,14 +5,18 @@ module Furnace::CFG 
     | 
|
| 
       5 
5 
     | 
    
         
             
                attr_accessor :target_labels, :exception_label
         
     | 
| 
       6 
6 
     | 
    
         
             
                attr_accessor :instructions, :control_transfer_instruction
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
      
 8 
     | 
    
         
            +
                attr_accessor :metadata
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
       8 
10 
     | 
    
         
             
                alias :insns  :instructions
         
     | 
| 
       9 
11 
     | 
    
         
             
                alias :insns= :instructions=
         
     | 
| 
       10 
12 
     | 
    
         
             
                alias :cti    :control_transfer_instruction
         
     | 
| 
       11 
13 
     | 
    
         
             
                alias :cti=   :control_transfer_instruction=
         
     | 
| 
       12 
14 
     | 
    
         | 
| 
       13 
15 
     | 
    
         
             
                def initialize(cfg, label=nil, insns=[], cti=nil,
         
     | 
| 
       14 
     | 
    
         
            -
                        target_labels=[], exception_label=nil 
     | 
| 
      
 16 
     | 
    
         
            +
                        target_labels=[], exception_label=nil,
         
     | 
| 
      
 17 
     | 
    
         
            +
                        metadata={})
         
     | 
| 
       15 
18 
     | 
    
         
             
                  @cfg, @label  = cfg, label
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @metadata = metadata
         
     | 
| 
       16 
20 
     | 
    
         | 
| 
       17 
21 
     | 
    
         
             
                  @instructions = insns
         
     | 
| 
       18 
22 
     | 
    
         
             
                  @control_transfer_instruction = cti
         
     | 
| 
         @@ -64,10 +68,10 @@ module Furnace::CFG 
     | 
|
| 
       64 
68 
     | 
    
         
             
                    "<#{@label}:#{@instructions.join ", "}>"
         
     | 
| 
       65 
69 
     | 
    
         
             
                  elsif @label
         
     | 
| 
       66 
70 
     | 
    
         
             
                    "<#{@label}>"
         
     | 
| 
       67 
     | 
    
         
            -
                  elsif @ 
     | 
| 
       68 
     | 
    
         
            -
                    "<!unlabeled>"
         
     | 
| 
      
 71 
     | 
    
         
            +
                  elsif @instructions
         
     | 
| 
      
 72 
     | 
    
         
            +
                    "<!unlabeled:#{@instructions.join ", "}>"
         
     | 
| 
       69 
73 
     | 
    
         
             
                  else
         
     | 
| 
       70 
     | 
    
         
            -
                    "<!exit>"
         
     | 
| 
      
 74 
     | 
    
         
            +
                    "<!exit#{metadata}>"
         
     | 
| 
       71 
75 
     | 
    
         
             
                  end
         
     | 
| 
       72 
76 
     | 
    
         
             
                end
         
     | 
| 
       73 
77 
     | 
    
         
             
              end
         
     | 
    
        data/lib/furnace/graphviz.rb
    CHANGED
    
    | 
         @@ -29,14 +29,14 @@ class Furnace::Graphviz 
     | 
|
| 
       29 
29 
     | 
    
         
             
                  label: label
         
     | 
| 
       30 
30 
     | 
    
         
             
                })
         
     | 
| 
       31 
31 
     | 
    
         | 
| 
       32 
     | 
    
         
            -
                @code << %Q{#{name.inspect} #{graphviz_options(options)};\n}
         
     | 
| 
      
 32 
     | 
    
         
            +
                @code << %Q{"#{name.inspect}" #{graphviz_options(options)};\n}
         
     | 
| 
       33 
33 
     | 
    
         
             
              end
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
       35 
35 
     | 
    
         
             
              def edge(from, to, label="", options={})
         
     | 
| 
       36 
36 
     | 
    
         
             
                options = options.merge({
         
     | 
| 
       37 
37 
     | 
    
         
             
                  label: label.inspect
         
     | 
| 
       38 
38 
     | 
    
         
             
                })
         
     | 
| 
       39 
     | 
    
         
            -
                @code << %Q{#{from.inspect} -> #{to.inspect} #{graphviz_options(options)};\n}
         
     | 
| 
      
 39 
     | 
    
         
            +
                @code << %Q{"#{from.inspect}" -> "#{to.inspect}" #{graphviz_options(options)};\n}
         
     | 
| 
       40 
40 
     | 
    
         
             
              end
         
     | 
| 
       41 
41 
     | 
    
         | 
| 
       42 
42 
     | 
    
         
             
              def to_s
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Furnace
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Transform
         
     | 
| 
      
 3 
     | 
    
         
            +
                class IterativeProcess
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def initialize(stages)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    @stages = stages
         
     | 
| 
      
 6 
     | 
    
         
            +
                  end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def transform(*sequence)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    loop do
         
     | 
| 
      
 10 
     | 
    
         
            +
                      changed = false
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                      @stages.each do |stage|
         
     | 
| 
      
 13 
     | 
    
         
            +
                        return sequence if stage.nil?
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                        if new_sequence = stage.transform(*sequence)
         
     | 
| 
      
 16 
     | 
    
         
            +
                          changed = true
         
     | 
| 
      
 17 
     | 
    
         
            +
                          sequence = new_sequence
         
     | 
| 
      
 18 
     | 
    
         
            +
                        end
         
     | 
| 
      
 19 
     | 
    
         
            +
                      end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                      return sequence unless changed
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/furnace/version.rb
    CHANGED
    
    
    
        data/lib/furnace.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: furnace
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.2. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.2.6
         
     | 
| 
       5 
5 
     | 
    
         
             
              prerelease: 
         
     | 
| 
       6 
6 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       7 
7 
     | 
    
         
             
            authors:
         
     | 
| 
         @@ -9,7 +9,7 @@ authors: 
     | 
|
| 
       9 
9 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       10 
10 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       11 
11 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       12 
     | 
    
         
            -
            date: 2012- 
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2012-09-30 00:00:00.000000000 Z
         
     | 
| 
       13 
13 
     | 
    
         
             
            dependencies: []
         
     | 
| 
       14 
14 
     | 
    
         
             
            description: Furnace is a static code analysis framework for dynamic languages, aimed
         
     | 
| 
       15 
15 
     | 
    
         
             
              at efficient type and behavior inference.
         
     | 
| 
         @@ -30,7 +30,7 @@ files: 
     | 
|
| 
       30 
30 
     | 
    
         
             
            - lib/furnace/ast/matcher/dsl.rb
         
     | 
| 
       31 
31 
     | 
    
         
             
            - lib/furnace/ast/matcher/special.rb
         
     | 
| 
       32 
32 
     | 
    
         
             
            - lib/furnace/ast/node.rb
         
     | 
| 
       33 
     | 
    
         
            -
            - lib/furnace/ast/ 
     | 
| 
      
 33 
     | 
    
         
            +
            - lib/furnace/ast/strict_visitor.rb
         
     | 
| 
       34 
34 
     | 
    
         
             
            - lib/furnace/ast/visitor.rb
         
     | 
| 
       35 
35 
     | 
    
         
             
            - lib/furnace/cfg.rb
         
     | 
| 
       36 
36 
     | 
    
         
             
            - lib/furnace/cfg/graph.rb
         
     | 
| 
         @@ -43,6 +43,7 @@ files: 
     | 
|
| 
       43 
43 
     | 
    
         
             
            - lib/furnace/code/terminal_token.rb
         
     | 
| 
       44 
44 
     | 
    
         
             
            - lib/furnace/code/token.rb
         
     | 
| 
       45 
45 
     | 
    
         
             
            - lib/furnace/graphviz.rb
         
     | 
| 
      
 46 
     | 
    
         
            +
            - lib/furnace/transform/iterative_process.rb
         
     | 
| 
       46 
47 
     | 
    
         
             
            - lib/furnace/transform/pipeline.rb
         
     | 
| 
       47 
48 
     | 
    
         
             
            - lib/furnace/version.rb
         
     | 
| 
       48 
49 
     | 
    
         
             
            homepage: http://github.com/whitequark/furnace
         
     | 
| 
         @@ -70,3 +71,4 @@ signing_key: 
     | 
|
| 
       70 
71 
     | 
    
         
             
            specification_version: 3
         
     | 
| 
       71 
72 
     | 
    
         
             
            summary: A static code analysis framework
         
     | 
| 
       72 
73 
     | 
    
         
             
            test_files: []
         
     | 
| 
      
 74 
     | 
    
         
            +
            has_rdoc: 
         
     | 
| 
         @@ -1,34 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module Furnace::AST
         
     | 
| 
       2 
     | 
    
         
            -
              class SymbolicNode
         
     | 
| 
       3 
     | 
    
         
            -
                def initialize(name)
         
     | 
| 
       4 
     | 
    
         
            -
                  @name = name.to_sym
         
     | 
| 
       5 
     | 
    
         
            -
                end
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
                def to_sym
         
     | 
| 
       8 
     | 
    
         
            -
                  @name
         
     | 
| 
       9 
     | 
    
         
            -
                end
         
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
                def ===(name)
         
     | 
| 
       12 
     | 
    
         
            -
                  @name == name.to_sym
         
     | 
| 
       13 
     | 
    
         
            -
                end
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
                def inspect
         
     | 
| 
       16 
     | 
    
         
            -
                  @name.to_s
         
     | 
| 
       17 
     | 
    
         
            -
                end
         
     | 
| 
       18 
     | 
    
         
            -
              end
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
              class MethodName < SymbolicNode
         
     | 
| 
       21 
     | 
    
         
            -
                def inspect
         
     | 
| 
       22 
     | 
    
         
            -
                  ".#{@name}"
         
     | 
| 
       23 
     | 
    
         
            -
                end
         
     | 
| 
       24 
     | 
    
         
            -
              end
         
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
              class LocalVariable < SymbolicNode
         
     | 
| 
       27 
     | 
    
         
            -
                def inspect
         
     | 
| 
       28 
     | 
    
         
            -
                  "%#{@name}"
         
     | 
| 
       29 
     | 
    
         
            -
                end
         
     | 
| 
       30 
     | 
    
         
            -
              end
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
              class Constant < SymbolicNode
         
     | 
| 
       33 
     | 
    
         
            -
              end
         
     | 
| 
       34 
     | 
    
         
            -
            end
         
     |