furnace 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,13 @@
1
+ module Furnace::AST
2
+ class MatcherSpecial
3
+ attr_reader :type, :params
4
+
5
+ def initialize(type, params=nil)
6
+ @type, @params = type, params
7
+ end
8
+
9
+ def self.define(type)
10
+ lambda { |*args| new(type, args) }
11
+ end
12
+ end
13
+ end
@@ -1,70 +1,96 @@
1
- module Furnace
2
- module AST
3
- class Node
4
- attr_accessor :type, :parent, :children, :metadata
1
+ module Furnace::AST
2
+ class Node
3
+ attr_accessor :type, :parent, :children, :metadata
5
4
 
6
- def initialize(type, children=[], metadata={})
7
- @type, @children, @metadata = type.to_sym, children, metadata
8
- end
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
- # If something non-nil is passed, including default value, then merge.
15
- # Else, clear metadata store.
16
- if metadata
17
- @metadata.merge!(metadata)
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
- self
15
+ if child.respond_to? :normalize_hierarchy!
16
+ child.normalize_hierarchy!
17
+ end
23
18
  end
24
19
 
25
- def index
26
- parent.children.find_index(self)
27
- end
20
+ self
21
+ end
28
22
 
29
- def next
30
- parent.children[index + 1]
31
- end
23
+ def update(type, children=nil, metadata={})
24
+ @type = type
25
+ @children = children || @children
32
26
 
33
- def prev
34
- parent.children[index - 1]
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
- def to_s
38
- "(#{fancy_type} ...)"
39
- end
35
+ self
36
+ end
40
37
 
41
- def to_sexp(indent=0)
42
- str = "#{" " * indent}(#{fancy_type}"
38
+ def dup
39
+ node = super
40
+ node.children = @children.dup
41
+ node.metadata = @metadata.dup
42
+ node
43
+ end
43
44
 
44
- children.each do |child|
45
- if child.is_a? Node
46
- str << "\n#{child.to_sexp(indent + 1)}"
47
- else
48
- str << " #{child.inspect}"
49
- end
50
- end
45
+ def index
46
+ parent.children.find_index(self)
47
+ end
51
48
 
52
- str << ")"
49
+ def next
50
+ parent.children[index + 1]
51
+ end
53
52
 
54
- str
55
- end
56
- alias :inspect :to_sexp
53
+ def prev
54
+ parent.children[index - 1]
55
+ end
57
56
 
58
- protected
57
+ def to_s
58
+ "(#{fancy_type} ...)"
59
+ end
59
60
 
60
- def fancy_type
61
- dasherized = @type.to_s.gsub('_', '-')
62
- if @metadata[:label]
63
- "#{@metadata[:label]}:#{dasherized}"
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
- dasherized
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
- module AST
3
- class SymbolicNode
4
- def initialize(name)
5
- @name = name.to_sym
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
- def ===(name)
13
- @name == name.to_sym
14
- end
7
+ def to_sym
8
+ @name
9
+ end
15
10
 
16
- def inspect
17
- @name.to_s
18
- end
11
+ def ===(name)
12
+ @name == name.to_sym
19
13
  end
20
14
 
21
- class MethodName < SymbolicNode
22
- def inspect
23
- ".#{@name}"
24
- end
15
+ def inspect
16
+ @name.to_s
25
17
  end
18
+ end
26
19
 
27
- class LocalVariable < SymbolicNode
28
- def inspect
29
- "%#{@name}"
30
- end
20
+ class MethodName < SymbolicNode
21
+ def inspect
22
+ ".#{@name}"
31
23
  end
24
+ end
32
25
 
33
- class Constant < SymbolicNode
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
@@ -1,42 +1,40 @@
1
- module Furnace
2
- module AST
3
- module Visitor
4
- def visit(node)
5
- node.children.map! do |child|
6
- if child.is_a? Node
7
- visit child
8
-
9
- if child.type == :expand
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
- node.children.flatten!
13
+ child
14
+ end
18
15
 
19
- node.children.delete_if do |child|
20
- if child.is_a? Node
21
- child.parent = node
16
+ node.children.flatten!
22
17
 
23
- child.type == :remove
24
- end
25
- end
18
+ node.children.delete_if do |child|
19
+ if child.is_a? Node
20
+ child.parent = node
26
21
 
27
- # Invoke a specific handler
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
- # Invoke a generic handler
34
- if respond_to? :on_any
35
- send :on_any, node
36
- end
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
- node
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
@@ -0,0 +1,6 @@
1
+ require "furnace/ast/node"
2
+ require "furnace/ast/symbolic_node"
3
+ require "furnace/ast/visitor"
4
+
5
+ require "furnace/ast/matcher_special"
6
+ require "furnace/ast/matcher"
@@ -1,36 +1,34 @@
1
- module Furnace
2
- module CFG
3
- class Edge
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
- def initialize(cfg, source_operation, source_label, target_label)
7
- @cfg, @source_operation, @source_label, @target_label =
8
- cfg, source_operation, source_label, target_label
9
- end
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
- def source
12
- @cfg.find_node(@source_label)
13
- end
10
+ def source
11
+ @cfg.find_node(@source_label)
12
+ end
14
13
 
15
- def target
16
- @cfg.find_node(@target_label) if @target_label
17
- end
14
+ def target
15
+ @cfg.find_node(@target_label) if @target_label
16
+ end
18
17
 
19
- def source=(node)
20
- @source_label = node.label
21
- end
18
+ def source=(node)
19
+ @source_label = node.label
20
+ end
22
21
 
23
- def target=(node)
24
- if node
25
- @target_label = node.label
26
- else
27
- @target_label = nil
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
- def inspect
32
- "<#{@source_label.inspect} -> #{@target_label.inspect}>"
33
- end
30
+ def inspect
31
+ "<#{@source_label.inspect} -> #{@target_label.inspect}>"
34
32
  end
35
33
  end
36
34
  end
@@ -1,57 +1,55 @@
1
- module Furnace
2
- module CFG
3
- class Graph
4
- attr_reader :nodes, :edges
1
+ module Furnace::CFG
2
+ class Graph
3
+ attr_reader :nodes, :edges
5
4
 
6
- def initialize
7
- @nodes = Set.new
8
- @edges = Set.new
5
+ def initialize
6
+ @nodes = Set.new
7
+ @edges = Set.new
9
8
 
10
- @pending_label = nil
11
- @pending_operations = []
12
- end
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
- def expand(label, operation)
23
- @pending_label ||= label
24
- @pending_operations << operation
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
- def transfer(targets)
28
- return unless @pending_label
21
+ def expand(label, operation)
22
+ @pending_label ||= label
23
+ @pending_operations << operation
24
+ end
29
25
 
30
- @nodes << CFG::Node.new(self, @pending_label, @pending_operations)
26
+ def transfer(targets)
27
+ return unless @pending_label
31
28
 
32
- targets.each do |operation, target|
33
- @edges << CFG::Edge.new(self, operation, @pending_label, target)
34
- end
29
+ @nodes << Node.new(self, @pending_label, @pending_operations)
35
30
 
36
- @pending_label = nil
37
- @pending_operations = []
31
+ targets.each do |operation, target|
32
+ @edges << Edge.new(self, operation, @pending_label, target)
38
33
  end
39
34
 
40
- def to_graphviz
41
- Graphviz.new do |graph|
42
- @nodes.each do |node|
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
- @edges.each do |edge|
47
- if edge.source_operation.nil?
48
- label = "~"
49
- else
50
- label = edge.source_operation
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
- graph.edge edge.source_label, edge.target_label, label
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
@@ -1,38 +1,36 @@
1
- module Furnace
2
- module CFG
3
- class Node
4
- attr_reader :label, :operations
1
+ module Furnace::CFG
2
+ class Node
3
+ attr_reader :label, :operations
5
4
 
6
- def initialize(cfg, label, operations)
7
- @cfg, @label, @operations = cfg, label, operations
8
- end
5
+ def initialize(cfg, label, operations)
6
+ @cfg, @label, @operations = cfg, label, operations
7
+ end
9
8
 
10
- def entering_edges
11
- @cfg.edges.select { |e| e.target == self }
12
- end
9
+ def entering_edges
10
+ @cfg.edges.select { |e| e.target == self }
11
+ end
13
12
 
14
- def leaving_edges
15
- @cfg.edges.select { |e| e.source == self }
16
- end
13
+ def leaving_edges
14
+ @cfg.edges.select { |e| e.source == self }
15
+ end
17
16
 
18
- def leaving_edge(source)
19
- leaving_edges.find { |e| e.source_operation == source }
20
- end
17
+ def leaving_edge(source)
18
+ leaving_edges.find { |e| e.source_operation == source }
19
+ end
21
20
 
22
- def default_leaving_edge
23
- leaving_edge(nil)
24
- end
21
+ def default_leaving_edge
22
+ leaving_edge(nil)
23
+ end
25
24
 
26
- def ==(other)
27
- self.label == other.label
28
- end
25
+ def ==(other)
26
+ self.label == other.label
27
+ end
29
28
 
30
- def inspect
31
- if @label
32
- "<#{@label}:#{@operations.map(&:inspect).join ", "}>"
33
- else
34
- "<!exit>"
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
@@ -0,0 +1,5 @@
1
+ require "set"
2
+
3
+ require "furnace/cfg/edge"
4
+ require "furnace/cfg/graph"
5
+ require "furnace/cfg/node"
@@ -1,7 +1,7 @@
1
1
  module Furnace
2
2
  module Transform
3
3
  class Pipeline
4
- def initialize(*stages)
4
+ def initialize(stages)
5
5
  @stages = stages
6
6
  end
7
7
 
@@ -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"
@@ -1,3 +1,3 @@
1
1
  module Furnace
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/furnace.rb CHANGED
@@ -1,14 +1,7 @@
1
1
  require "furnace/version"
2
2
 
3
- require "set"
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/pipeline"
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: 880347952
4
+ hash: 988111682
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
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-13 00:00:00 Z
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