furnace 0.4.0.beta.1 → 0.4.0.beta.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +6 -0
  3. data/INSTRUMENT.md +250 -0
  4. data/Rakefile +1 -1
  5. data/lib/furnace.rb +10 -6
  6. data/lib/furnace/ast/node.rb +15 -1
  7. data/lib/furnace/awesome_printer.rb +121 -0
  8. data/lib/furnace/context.rb +0 -0
  9. data/lib/furnace/ssa.rb +7 -25
  10. data/lib/furnace/ssa/argument.rb +14 -10
  11. data/lib/furnace/ssa/basic_block.rb +70 -25
  12. data/lib/furnace/ssa/builder.rb +11 -7
  13. data/lib/furnace/ssa/constant.rb +19 -11
  14. data/lib/furnace/ssa/event_stream.rb +145 -0
  15. data/lib/furnace/ssa/function.rb +78 -57
  16. data/lib/furnace/ssa/generic_instruction.rb +12 -5
  17. data/lib/furnace/ssa/instruction.rb +50 -35
  18. data/lib/furnace/ssa/instruction_syntax.rb +9 -25
  19. data/lib/furnace/ssa/instructions/branch.rb +2 -2
  20. data/lib/furnace/ssa/instructions/phi.rb +12 -10
  21. data/lib/furnace/ssa/instructions/return.rb +3 -3
  22. data/lib/furnace/ssa/instructions/return_value.rb +11 -0
  23. data/lib/furnace/ssa/instrumentation.rb +33 -0
  24. data/lib/furnace/ssa/module.rb +5 -1
  25. data/lib/furnace/ssa/named_value.rb +31 -10
  26. data/lib/furnace/ssa/terminator_instruction.rb +6 -6
  27. data/lib/furnace/ssa/types/basic_block.rb +4 -8
  28. data/lib/furnace/ssa/types/function.rb +4 -8
  29. data/lib/furnace/ssa/user.rb +14 -15
  30. data/lib/furnace/ssa/value.rb +9 -5
  31. data/lib/furnace/transform/iterative.rb +20 -4
  32. data/lib/furnace/type.rb +9 -0
  33. data/lib/furnace/type/bottom.rb +11 -0
  34. data/lib/furnace/type/top.rb +72 -0
  35. data/lib/furnace/type/value.rb +13 -0
  36. data/lib/furnace/type/variable.rb +61 -0
  37. data/lib/furnace/version.rb +1 -1
  38. data/test/{test_helper.rb → helper.rb} +28 -3
  39. data/test/{ast_test.rb → test_ast.rb} +13 -1
  40. data/test/test_awesome_printer.rb +148 -0
  41. data/test/{ssa_test.rb → test_ssa.rb} +276 -315
  42. data/test/{transform_test.rb → test_transform.rb} +2 -2
  43. data/test/test_type.rb +138 -0
  44. metadata +83 -105
  45. data/lib/furnace/graphviz.rb +0 -49
  46. data/lib/furnace/ssa/generic_type.rb +0 -16
  47. data/lib/furnace/ssa/pretty_printer.rb +0 -113
  48. data/lib/furnace/ssa/type.rb +0 -27
  49. data/lib/furnace/ssa/types/void.rb +0 -15
@@ -1,4 +1,4 @@
1
- require_relative 'test_helper'
1
+ require_relative 'helper'
2
2
 
3
3
  describe Transform do
4
4
  class Context
@@ -71,4 +71,4 @@ describe Transform do
71
71
  pipeline.run(@context).should == false
72
72
  end
73
73
  end
74
- end
74
+ end
@@ -0,0 +1,138 @@
1
+ require_relative 'helper'
2
+
3
+ describe Type do
4
+ describe Type::Top do
5
+ before do
6
+ @type = Type::Top.new
7
+ end
8
+
9
+ it 'converts to type' do
10
+ @type.to_type.should.be.equal @type
11
+ end
12
+
13
+ it 'is a singleton' do
14
+ @type.should.be.equal @type
15
+ end
16
+
17
+ it 'should be ==, eql?, subtype_of? and have the same hash as itself' do
18
+ @type.should == @type
19
+ @type.should.be.eql @type
20
+ @type.should.be.subtype_of @type
21
+ @type.hash.should == @type.hash
22
+ end
23
+
24
+ it 'can replace itself' do
25
+ @type.replace_type_with(@type, Type::Bottom.new).
26
+ should == Type::Bottom.new
27
+ @type.replace_type_with(Type::Bottom.new, nil).
28
+ should == @type
29
+ end
30
+
31
+ it 'can specialize only itself' do
32
+ @type.specialize(@type).should == {}
33
+ -> { @type.specialize(Type::Bottom.new) }.should.raise(ArgumentError)
34
+ end
35
+
36
+ it 'pretty prints' do
37
+ @type.awesome_print.should == 'top'
38
+ end
39
+ end
40
+
41
+ describe Type::Bottom do
42
+ before do
43
+ @type = Type::Bottom.new
44
+ end
45
+
46
+ it 'converts to string' do
47
+ @type.to_s.should == 'bottom'
48
+ end
49
+
50
+ it 'pretty prints' do
51
+ @type.awesome_print.should == 'bottom'
52
+ end
53
+ end
54
+
55
+ describe Type::Value do
56
+ before do
57
+ @type = Type::Value.new(1)
58
+ end
59
+
60
+ it 'allows to retrieve value' do
61
+ @type.value.should == 1
62
+ end
63
+
64
+ it 'is a singleton' do
65
+ @type.should.be.equal Type::Value.new(1)
66
+ end
67
+
68
+ it 'converts to string as \'value' do
69
+ @type.to_s.should == %{'1}
70
+ end
71
+
72
+ it 'pretty prints' do
73
+ @type.awesome_print.should == '\'1'
74
+ end
75
+ end
76
+
77
+ describe Type::Variable do
78
+ before do
79
+ @var = Type::Variable.new
80
+ end
81
+
82
+ it 'allocates distinct instances' do
83
+ Type::Variable.new.
84
+ should.not.equal? Type::Variable.new
85
+ end
86
+
87
+ it 'converts to type' do
88
+ @var.to_type.should.equal? @var
89
+ end
90
+
91
+ it 'is a subtype of itself' do
92
+ @var.should.be.subtype_of @var
93
+ end
94
+
95
+ it 'is a supertype of itself' do
96
+ @var.should.be.supertype_of @var
97
+ end
98
+
99
+ it 'compares by identity' do
100
+ @var.should == @var
101
+ @var.should.not == Type::Variable.new
102
+ end
103
+
104
+ it 'can replace itself' do
105
+ @var.replace_type_with(@var, Type::Bottom.new).
106
+ should == Type::Bottom.new
107
+ @var.replace_type_with(Type::Bottom.new, nil).
108
+ should == @var
109
+ end
110
+
111
+ it 'specializes' do
112
+ @var.specialize(Type::Top.new).
113
+ should == { @var => Type::Top.new }
114
+ end
115
+
116
+ it 'pretty prints' do
117
+ @var.awesome_print.should == '~a'
118
+ end
119
+ end
120
+
121
+ describe Type::Variable::Annotator do
122
+ before do
123
+ @annotator = Type::Variable::Annotator.new
124
+ end
125
+
126
+ it 'annotates variables with successive letters' do
127
+ var1, var2 = 2.times.map { Type::Variable.new }
128
+
129
+ @annotator.annotate(var1).should == 'a'
130
+ @annotator.annotate(var1).should == 'a'
131
+ @annotator.annotate(var2).should == 'b'
132
+ end
133
+
134
+ it 'only annotates type variables' do
135
+ -> { @annotator.annotate(:foo) }.should.raise(ArgumentError)
136
+ end
137
+ end
138
+ end
metadata CHANGED
@@ -1,149 +1,126 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: furnace
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: 6
5
- version: 0.4.0.beta.1
4
+ version: 0.4.0.beta.2
6
5
  platform: ruby
7
6
  authors:
8
7
  - Peter Zotov
9
- autorequire:
8
+ autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-01-10 00:00:00.000000000 Z
11
+ date: 2013-03-31 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: ansi
16
- version_requirements: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - ">="
19
- - !ruby/object:Gem::Version
20
- version: !binary |-
21
- MA==
22
- none: false
23
15
  requirement: !ruby/object:Gem::Requirement
24
16
  requirements:
25
- - - ">="
17
+ - - '>='
26
18
  - !ruby/object:Gem::Version
27
- version: !binary |-
28
- MA==
29
- none: false
30
- prerelease: false
19
+ version: '0'
31
20
  type: :runtime
32
- - !ruby/object:Gem::Dependency
33
- name: rake
21
+ prerelease: false
34
22
  version_requirements: !ruby/object:Gem::Requirement
35
23
  requirements:
36
- - - "~>"
24
+ - - '>='
37
25
  - !ruby/object:Gem::Version
38
- version: '10.0'
39
- none: false
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
40
29
  requirement: !ruby/object:Gem::Requirement
41
30
  requirements:
42
- - - "~>"
31
+ - - ~>
43
32
  - !ruby/object:Gem::Version
44
33
  version: '10.0'
45
- none: false
46
- prerelease: false
47
34
  type: :development
48
- - !ruby/object:Gem::Dependency
49
- name: bacon
35
+ prerelease: false
50
36
  version_requirements: !ruby/object:Gem::Requirement
51
37
  requirements:
52
- - - "~>"
38
+ - - ~>
53
39
  - !ruby/object:Gem::Version
54
- version: '1.2'
55
- none: false
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bacon
56
43
  requirement: !ruby/object:Gem::Requirement
57
44
  requirements:
58
- - - "~>"
45
+ - - ~>
59
46
  - !ruby/object:Gem::Version
60
47
  version: '1.2'
61
- none: false
62
- prerelease: false
63
48
  type: :development
64
- - !ruby/object:Gem::Dependency
65
- name: bacon-colored_output
49
+ prerelease: false
66
50
  version_requirements: !ruby/object:Gem::Requirement
67
51
  requirements:
68
- - - ">="
52
+ - - ~>
69
53
  - !ruby/object:Gem::Version
70
- version: !binary |-
71
- MA==
72
- none: false
54
+ version: '1.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bacon-colored_output
73
57
  requirement: !ruby/object:Gem::Requirement
74
58
  requirements:
75
- - - ">="
59
+ - - '>='
76
60
  - !ruby/object:Gem::Version
77
- version: !binary |-
78
- MA==
79
- none: false
80
- prerelease: false
61
+ version: '0'
81
62
  type: :development
82
- - !ruby/object:Gem::Dependency
83
- name: simplecov
63
+ prerelease: false
84
64
  version_requirements: !ruby/object:Gem::Requirement
85
65
  requirements:
86
- - - ">="
66
+ - - '>='
87
67
  - !ruby/object:Gem::Version
88
- version: !binary |-
89
- MA==
90
- none: false
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
91
71
  requirement: !ruby/object:Gem::Requirement
92
72
  requirements:
93
- - - ">="
73
+ - - '>='
94
74
  - !ruby/object:Gem::Version
95
- version: !binary |-
96
- MA==
97
- none: false
98
- prerelease: false
75
+ version: '0'
99
76
  type: :development
100
- - !ruby/object:Gem::Dependency
101
- name: yard
77
+ prerelease: false
102
78
  version_requirements: !ruby/object:Gem::Requirement
103
79
  requirements:
104
- - - ">="
80
+ - - '>='
105
81
  - !ruby/object:Gem::Version
106
- version: !binary |-
107
- MA==
108
- none: false
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: yard
109
85
  requirement: !ruby/object:Gem::Requirement
110
86
  requirements:
111
- - - ">="
87
+ - - '>='
112
88
  - !ruby/object:Gem::Version
113
- version: !binary |-
114
- MA==
115
- none: false
116
- prerelease: false
89
+ version: '0'
117
90
  type: :development
118
- - !ruby/object:Gem::Dependency
119
- name: kramdown
91
+ prerelease: false
120
92
  version_requirements: !ruby/object:Gem::Requirement
121
93
  requirements:
122
- - - ">="
94
+ - - '>='
123
95
  - !ruby/object:Gem::Version
124
- version: !binary |-
125
- MA==
126
- none: false
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: kramdown
127
99
  requirement: !ruby/object:Gem::Requirement
128
100
  requirements:
129
- - - ">="
101
+ - - '>='
130
102
  - !ruby/object:Gem::Version
131
- version: !binary |-
132
- MA==
133
- none: false
134
- prerelease: false
103
+ version: '0'
135
104
  type: :development
136
- description: Furnace is a static code analysis framework for dynamic languages, aimed at efficient type and behavior inference.
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Furnace is a static code analysis framework for dynamic languages, aimed
112
+ at efficient type and behavior inference.
137
113
  email:
138
114
  - whitequark@whitequark.org
139
115
  executables: []
140
116
  extensions: []
141
117
  extra_rdoc_files: []
142
118
  files:
143
- - ".gitignore"
144
- - ".travis.yml"
145
- - ".yardopts"
119
+ - .gitignore
120
+ - .travis.yml
121
+ - .yardopts
146
122
  - Gemfile
123
+ - INSTRUMENT.md
147
124
  - LICENSE.MIT
148
125
  - Rakefile
149
126
  - furnace.gemspec
@@ -152,65 +129,66 @@ files:
152
129
  - lib/furnace/ast/node.rb
153
130
  - lib/furnace/ast/processor.rb
154
131
  - lib/furnace/ast/sexp.rb
155
- - lib/furnace/graphviz.rb
132
+ - lib/furnace/awesome_printer.rb
133
+ - lib/furnace/context.rb
156
134
  - lib/furnace/ssa.rb
157
135
  - lib/furnace/ssa/argument.rb
158
136
  - lib/furnace/ssa/basic_block.rb
159
137
  - lib/furnace/ssa/builder.rb
160
138
  - lib/furnace/ssa/constant.rb
139
+ - lib/furnace/ssa/event_stream.rb
161
140
  - lib/furnace/ssa/function.rb
162
141
  - lib/furnace/ssa/generic_instruction.rb
163
- - lib/furnace/ssa/generic_type.rb
164
142
  - lib/furnace/ssa/instruction.rb
165
143
  - lib/furnace/ssa/instruction_syntax.rb
166
144
  - lib/furnace/ssa/instructions/branch.rb
167
145
  - lib/furnace/ssa/instructions/phi.rb
168
146
  - lib/furnace/ssa/instructions/return.rb
147
+ - lib/furnace/ssa/instructions/return_value.rb
148
+ - lib/furnace/ssa/instrumentation.rb
169
149
  - lib/furnace/ssa/module.rb
170
150
  - lib/furnace/ssa/named_value.rb
171
- - lib/furnace/ssa/pretty_printer.rb
172
151
  - lib/furnace/ssa/terminator_instruction.rb
173
- - lib/furnace/ssa/type.rb
174
152
  - lib/furnace/ssa/types/basic_block.rb
175
153
  - lib/furnace/ssa/types/function.rb
176
- - lib/furnace/ssa/types/void.rb
177
154
  - lib/furnace/ssa/user.rb
178
155
  - lib/furnace/ssa/value.rb
179
156
  - lib/furnace/transform/iterative.rb
180
157
  - lib/furnace/transform/pipeline.rb
158
+ - lib/furnace/type.rb
159
+ - lib/furnace/type/bottom.rb
160
+ - lib/furnace/type/top.rb
161
+ - lib/furnace/type/value.rb
162
+ - lib/furnace/type/variable.rb
181
163
  - lib/furnace/version.rb
182
- - test/ast_test.rb
183
- - test/ssa_test.rb
184
- - test/test_helper.rb
185
- - test/transform_test.rb
164
+ - test/helper.rb
165
+ - test/test_ast.rb
166
+ - test/test_awesome_printer.rb
167
+ - test/test_ssa.rb
168
+ - test/test_transform.rb
169
+ - test/test_type.rb
186
170
  homepage: http://github.com/whitequark/furnace
187
171
  licenses: []
188
- post_install_message:
172
+ metadata: {}
173
+ post_install_message:
189
174
  rdoc_options: []
190
175
  require_paths:
191
176
  - lib
192
177
  required_ruby_version: !ruby/object:Gem::Requirement
193
178
  requirements:
194
- - - ">="
179
+ - - '>='
195
180
  - !ruby/object:Gem::Version
196
- segments:
197
- - 0
198
- hash: 2
199
- version: !binary |-
200
- MA==
201
- none: false
181
+ version: '0'
202
182
  required_rubygems_version: !ruby/object:Gem::Requirement
203
183
  requirements:
204
- - - !binary |-
205
- Pg==
184
+ - - '>'
206
185
  - !ruby/object:Gem::Version
207
186
  version: 1.3.1
208
- none: false
209
187
  requirements: []
210
- rubyforge_project:
211
- rubygems_version: 1.8.24
212
- signing_key:
213
- specification_version: 3
188
+ rubyforge_project:
189
+ rubygems_version: 2.0.0
190
+ signing_key:
191
+ specification_version: 4
214
192
  summary: A static code analysis framework
215
193
  test_files: []
216
- has_rdoc:
194
+ has_rdoc:
@@ -1,49 +0,0 @@
1
- require 'furnace'
2
-
3
- class Furnace::Graphviz
4
- def initialize
5
- @code = "digraph {\n"
6
- @code << "node [labeljust=l,nojustify=true,fontname=monospace];"
7
- @code << "rankdir=TB;\n"
8
-
9
- yield self
10
-
11
- @code << "}"
12
- end
13
-
14
- def node(name, content, options={})
15
- content.gsub!("&", "&amp;")
16
- content.gsub!(">", "&gt;")
17
- content.gsub!("<", "&lt;")
18
- content.gsub!(/\*\*(.+?)\*\*/, '<b>\1</b>')
19
- content = content.lines.map { |l| %Q{<tr><td align="left">#{l}</td></tr>} }.join
20
-
21
- if content.empty?
22
- label = "<&lt;empty&gt;>"
23
- else
24
- label = "<<table border=\"0\">#{content}</table>>"
25
- end
26
-
27
- options = options.merge({
28
- shape: 'box',
29
- label: label
30
- })
31
-
32
- @code << %Q{"#{name.inspect}" #{graphviz_options(options)};\n}
33
- end
34
-
35
- def edge(from, to, label="", options={})
36
- options = options.merge({
37
- label: label.inspect
38
- })
39
- @code << %Q{"#{from.inspect}" -> "#{to.inspect}" #{graphviz_options(options)};\n}
40
- end
41
-
42
- def to_s
43
- @code
44
- end
45
-
46
- def graphviz_options(options)
47
- "[#{options.map { |k,v| "#{k}=#{v}" }.join(",")}]"
48
- end
49
- end