seafoam 0.8 → 0.12
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.
- checksums.yaml +4 -4
- data/bin/bgv2isabelle +1 -5
- data/bin/bgv2json +1 -5
- data/bin/seafoam +1 -5
- data/lib/seafoam/bgv/bgv_parser.rb +1 -2
- data/lib/seafoam/commands.rb +135 -101
- data/lib/seafoam/formatters/base.rb +88 -0
- data/lib/seafoam/formatters/formatters.rb +8 -0
- data/lib/seafoam/formatters/json.rb +82 -0
- data/lib/seafoam/formatters/text.rb +70 -0
- data/lib/seafoam/graal/graph_description.rb +22 -0
- data/lib/seafoam/graal/pi.rb +18 -0
- data/lib/seafoam/graal/source.rb +5 -9
- data/lib/seafoam/graph.rb +9 -1
- data/lib/seafoam/graphviz_writer.rb +3 -0
- data/lib/seafoam/json_writer.rb +1 -3
- data/lib/seafoam/{annotators → passes}/fallback.rb +4 -4
- data/lib/seafoam/{annotators → passes}/graal.rb +43 -15
- data/lib/seafoam/passes/truffle.rb +58 -0
- data/lib/seafoam/passes.rb +61 -0
- data/lib/seafoam/version.rb +1 -1
- data/lib/seafoam.rb +7 -6
- metadata +17 -81
- data/.github/probots.yml +0 -2
- data/.github/workflows/workflows.yml +0 -40
- data/.gitignore +0 -6
- data/.rubocop.yml +0 -37
- data/.ruby-version +0 -1
- data/.seafoam/config +0 -1
- data/CODE_OF_CONDUCT.md +0 -128
- data/CONTRIBUTING.md +0 -5
- data/Gemfile +0 -2
- data/Gemfile.lock +0 -59
- data/LICENSE.md +0 -7
- data/README.md +0 -378
- data/bin/cfg2asm +0 -24
- data/demos/box-unbox-stats +0 -65
- data/docs/annotators.md +0 -43
- data/docs/bgv.md +0 -294
- data/docs/getting-graphs.md +0 -63
- data/docs/images/igv.png +0 -0
- data/docs/images/seafoam.png +0 -0
- data/docs/images/spotlight-igv.png +0 -0
- data/docs/images/spotlight-seafoam.png +0 -0
- data/docs/json.md +0 -35
- data/examples/Fib.java +0 -24
- data/examples/MatMult.java +0 -39
- data/examples/fib-java.bgv.gz +0 -0
- data/examples/fib.js +0 -15
- data/examples/fib.rb +0 -15
- data/examples/identity.rb +0 -13
- data/examples/java/Irreducible.class +0 -0
- data/examples/java/Irreducible.j +0 -35
- data/examples/java/IrreducibleDecompiled.java +0 -21
- data/examples/java/JavaExamples.java +0 -418
- data/examples/matmult.rb +0 -29
- data/examples/overflow.rb +0 -13
- data/examples/ruby/clamps.rb +0 -20
- data/examples/ruby/graal.patch +0 -15
- data/examples/ruby/ruby_examples.rb +0 -278
- data/lib/seafoam/annotators.rb +0 -54
- data/lib/seafoam/cfg/cfg_parser.rb +0 -93
- data/lib/seafoam/cfg/disassembler.rb +0 -70
- data/lib/seafoam/config.rb +0 -34
- data/seafoam.gemspec +0 -22
- data/spec/seafoam/annotators/fallback_spec.rb +0 -69
- data/spec/seafoam/annotators/graal_spec.rb +0 -96
- data/spec/seafoam/annotators_spec.rb +0 -61
- data/spec/seafoam/bgv/bgv_parser_spec.rb +0 -167
- data/spec/seafoam/binary/io_binary_reader_spec.rb +0 -176
- data/spec/seafoam/cfg/cfg_parser_spec.rb +0 -21
- data/spec/seafoam/cfg/disassembler_spec.rb +0 -32
- data/spec/seafoam/command_spec.rb +0 -314
- data/spec/seafoam/graph_spec.rb +0 -172
- data/spec/seafoam/graphviz_writer_spec.rb +0 -63
- data/spec/seafoam/json_writer_spec.rb +0 -14
- data/spec/seafoam/spec_helpers.rb +0 -34
- data/spec/seafoam/spotlight_spec.rb +0 -38
- data/tools/render-all +0 -36
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5365ea61783b2be678609c214262d4df073fa4e66df60e9370b6fd33dd73825a
|
|
4
|
+
data.tar.gz: 322fe5170082c57d51120c3fa43910ca2e79a7839737167955ad1f330084af83
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 33cdf9e0f73e9a41d11ee2c19f60b015f8fe5168ddd92eaee1a254c13c6296e8696514858e0fc0c77c583657c3d01b2292919077f9131768198801bd9610dbc9
|
|
7
|
+
data.tar.gz: 2354dd4f1c5d87c83d265577a0e64b5130cd9dc7de46e6222629b985bdac038b6977f3fe10ffc2624e45b2cc56dbd67ea243734a528a17eab780a80c00996621
|
data/bin/bgv2isabelle
CHANGED
|
@@ -5,12 +5,8 @@ require 'seafoam'
|
|
|
5
5
|
# This is the 'bgv2isabelle' command line entry point.
|
|
6
6
|
|
|
7
7
|
begin
|
|
8
|
-
# Load configuraiton.
|
|
9
|
-
config = Seafoam::Config.new
|
|
10
|
-
config.load_config
|
|
11
|
-
|
|
12
8
|
# Run the command line.
|
|
13
|
-
commands = Seafoam::Commands.new($stdout
|
|
9
|
+
commands = Seafoam::Commands.new($stdout)
|
|
14
10
|
commands.bgv2isabelle(*ARGV)
|
|
15
11
|
rescue StandardError => e
|
|
16
12
|
if $DEBUG
|
data/bin/bgv2json
CHANGED
|
@@ -5,12 +5,8 @@ require 'seafoam'
|
|
|
5
5
|
# This is the 'bgv2json' command line entry point.
|
|
6
6
|
|
|
7
7
|
begin
|
|
8
|
-
# Load configuraiton.
|
|
9
|
-
config = Seafoam::Config.new
|
|
10
|
-
config.load_config
|
|
11
|
-
|
|
12
8
|
# Run the command line.
|
|
13
|
-
commands = Seafoam::Commands.new($stdout
|
|
9
|
+
commands = Seafoam::Commands.new($stdout)
|
|
14
10
|
commands.bgv2json(*ARGV)
|
|
15
11
|
rescue StandardError => e
|
|
16
12
|
if $DEBUG
|
data/bin/seafoam
CHANGED
|
@@ -5,12 +5,8 @@ require 'seafoam'
|
|
|
5
5
|
# This is the 'seafoam' command line entry point.
|
|
6
6
|
|
|
7
7
|
begin
|
|
8
|
-
# Load configuraiton.
|
|
9
|
-
config = Seafoam::Config.new
|
|
10
|
-
config.load_config
|
|
11
|
-
|
|
12
8
|
# Run the command line.
|
|
13
|
-
commands = Seafoam::Commands.new($stdout
|
|
9
|
+
commands = Seafoam::Commands.new($stdout)
|
|
14
10
|
commands.seafoam(*ARGV)
|
|
15
11
|
rescue StandardError => e
|
|
16
12
|
if $DEBUG
|
data/lib/seafoam/commands.rb
CHANGED
|
@@ -1,39 +1,29 @@
|
|
|
1
1
|
require 'json'
|
|
2
|
+
require 'set'
|
|
2
3
|
|
|
3
4
|
module Seafoam
|
|
4
5
|
# Implementations of the command-line commands that you can run in Seafoam.
|
|
5
6
|
class Commands
|
|
6
|
-
def initialize(out
|
|
7
|
+
def initialize(out)
|
|
7
8
|
@out = out
|
|
8
|
-
@config = config
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
# Run the general seafoam command.
|
|
12
12
|
def seafoam(*args)
|
|
13
13
|
first, *args = args
|
|
14
|
+
|
|
15
|
+
if first == '--json'
|
|
16
|
+
formatter_module = Seafoam::Formatters::Json
|
|
17
|
+
first, *args = args
|
|
18
|
+
else
|
|
19
|
+
formatter_module = Seafoam::Formatters::Text
|
|
20
|
+
end
|
|
21
|
+
|
|
14
22
|
case first
|
|
15
23
|
when nil, 'help', '-h', '--help', '-help'
|
|
16
24
|
raise ArgumentError, "unexpected arguments #{args.join(' ')}" unless args.empty?
|
|
17
25
|
|
|
18
|
-
|
|
19
|
-
@out.puts ' file.bgv list'
|
|
20
|
-
@out.puts ' file.bgv[:graph][:node[-edge]] search term...'
|
|
21
|
-
@out.puts ' file.bgv[:graph][:node[-edge]] edges'
|
|
22
|
-
@out.puts ' file.bgv[:graph][:node[-edge]] props'
|
|
23
|
-
@out.puts ' file.bgv:graph:node source'
|
|
24
|
-
@out.puts ' file.bgv:graph render'
|
|
25
|
-
@out.puts ' --spotlight n,n,n...'
|
|
26
|
-
@out.puts ' --out graph.pdf'
|
|
27
|
-
@out.puts ' graph.svg'
|
|
28
|
-
@out.puts ' graph.png'
|
|
29
|
-
@out.puts ' graph.dot'
|
|
30
|
-
@out.puts ' --show-frame-state'
|
|
31
|
-
@out.puts ' --hide-floating'
|
|
32
|
-
@out.puts ' --no-reduce-edges'
|
|
33
|
-
@out.puts ' --draw-blocks'
|
|
34
|
-
@out.puts ' --option key value'
|
|
35
|
-
@out.puts ' --help'
|
|
36
|
-
@out.puts ' --version'
|
|
26
|
+
help(*args)
|
|
37
27
|
when 'version', '-v', '-version', '--version'
|
|
38
28
|
version(*args)
|
|
39
29
|
else
|
|
@@ -43,21 +33,23 @@ module Seafoam
|
|
|
43
33
|
when nil
|
|
44
34
|
help(*args)
|
|
45
35
|
when 'info'
|
|
46
|
-
info name, *args
|
|
36
|
+
info name, formatter_module, *args
|
|
47
37
|
when 'list'
|
|
48
|
-
list name, *args
|
|
38
|
+
list name, formatter_module, *args
|
|
49
39
|
when 'search'
|
|
50
40
|
search name, *args
|
|
51
41
|
when 'edges'
|
|
52
|
-
edges name, *args
|
|
42
|
+
edges name, formatter_module, *args
|
|
53
43
|
when 'props'
|
|
54
44
|
props name, *args
|
|
55
45
|
when 'source'
|
|
56
|
-
source name, *args
|
|
46
|
+
source name, formatter_module, *args
|
|
57
47
|
when 'render'
|
|
58
48
|
render name, *args
|
|
59
49
|
when 'debug'
|
|
60
50
|
debug name, *args
|
|
51
|
+
when 'describe'
|
|
52
|
+
describe name, formatter_module, *args
|
|
61
53
|
else
|
|
62
54
|
raise ArgumentError, "unknown command #{command}"
|
|
63
55
|
end
|
|
@@ -155,82 +147,42 @@ module Seafoam
|
|
|
155
147
|
end
|
|
156
148
|
end
|
|
157
149
|
|
|
158
|
-
def cfg2asm(*args)
|
|
159
|
-
case args.first
|
|
160
|
-
when nil, 'help', '-h', '--help', '-help'
|
|
161
|
-
args = args.drop(1)
|
|
162
|
-
raise ArgumentError, "unexpected arguments #{args.join(' ')}" unless args.empty?
|
|
163
|
-
|
|
164
|
-
@out.puts 'cfg2asm file.bgv...'
|
|
165
|
-
@out.puts ' --no-comments'
|
|
166
|
-
@out.puts ' --help'
|
|
167
|
-
@out.puts ' --version'
|
|
168
|
-
when 'version', '-v', '-version', '--version'
|
|
169
|
-
args = args.drop(1)
|
|
170
|
-
version(*args)
|
|
171
|
-
else
|
|
172
|
-
comments = true
|
|
173
|
-
files = []
|
|
174
|
-
|
|
175
|
-
until args.empty?
|
|
176
|
-
arg = args.shift
|
|
177
|
-
if arg.start_with?('-')
|
|
178
|
-
case arg
|
|
179
|
-
when '--no-comments'
|
|
180
|
-
comments = false
|
|
181
|
-
else
|
|
182
|
-
raise ArgumentError, "unknown option #{arg}"
|
|
183
|
-
end
|
|
184
|
-
else
|
|
185
|
-
files.push arg
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
files.each_with_index do |file, n|
|
|
190
|
-
parser = Seafoam::CFG::CFGParser.new(@out, file)
|
|
191
|
-
parser.skip_over_cfg 'After code installation'
|
|
192
|
-
nmethod = parser.read_nmethod
|
|
193
|
-
|
|
194
|
-
disassembler = Seafoam::CFG::Disassembler.new(@out)
|
|
195
|
-
@out.puts if n.positive?
|
|
196
|
-
@out.puts "[#{file}]"
|
|
197
|
-
disassembler.disassemble(nmethod, comments)
|
|
198
|
-
end
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
|
|
202
150
|
private
|
|
203
151
|
|
|
204
152
|
# seafoam file.bgv info
|
|
205
|
-
def info(name, *args)
|
|
153
|
+
def info(name, formatter_module, *args)
|
|
206
154
|
file, *rest = parse_name(name)
|
|
207
155
|
raise ArgumentError, 'info only works with a file' unless rest == [nil, nil, nil]
|
|
208
|
-
|
|
209
156
|
raise ArgumentError, 'info does not take arguments' unless args.empty?
|
|
210
157
|
|
|
211
158
|
parser = BGV::BGVParser.new(file)
|
|
212
159
|
major, minor = parser.read_file_header(version_check: false)
|
|
213
|
-
|
|
160
|
+
formatter = formatter_module::InfoFormatter.new(major, minor)
|
|
161
|
+
|
|
162
|
+
@out.puts formatter.format
|
|
214
163
|
end
|
|
215
164
|
|
|
216
165
|
# seafoam file.bgv list
|
|
217
|
-
def list(name, *args)
|
|
166
|
+
def list(name, formatter_module, *args)
|
|
218
167
|
file, *rest = parse_name(name)
|
|
219
168
|
raise ArgumentError, 'list only works with a file' unless rest == [nil, nil, nil]
|
|
220
|
-
|
|
221
169
|
raise ArgumentError, 'list does not take arguments' unless args.empty?
|
|
222
170
|
|
|
223
171
|
parser = BGV::BGVParser.new(file)
|
|
224
172
|
parser.read_file_header
|
|
225
173
|
parser.skip_document_props
|
|
174
|
+
entries = []
|
|
226
175
|
loop do
|
|
227
176
|
index, = parser.read_graph_preheader
|
|
228
177
|
break unless index
|
|
229
178
|
|
|
230
179
|
graph_header = parser.read_graph_header
|
|
231
|
-
|
|
180
|
+
entries << formatter_module::ListFormatter::Entry.new(file, parser.graph_name(graph_header), index)
|
|
232
181
|
parser.skip_graph
|
|
233
182
|
end
|
|
183
|
+
|
|
184
|
+
formatter = formatter_module::ListFormatter.new(entries)
|
|
185
|
+
@out.puts formatter.format
|
|
234
186
|
end
|
|
235
187
|
|
|
236
188
|
# seafoam file.bgv:n... search term...
|
|
@@ -263,7 +215,7 @@ module Seafoam
|
|
|
263
215
|
end
|
|
264
216
|
|
|
265
217
|
def search_object(tag, object, terms)
|
|
266
|
-
full_text = JSON.generate(object)
|
|
218
|
+
full_text = JSON.generate(JSONWriter.prepare_json(object))
|
|
267
219
|
full_text_down = full_text.downcase
|
|
268
220
|
start = 0
|
|
269
221
|
terms.each do |t|
|
|
@@ -289,17 +241,18 @@ module Seafoam
|
|
|
289
241
|
end
|
|
290
242
|
|
|
291
243
|
# seafoam file.bgv:n... edges
|
|
292
|
-
def edges(name, *args)
|
|
244
|
+
def edges(name, formatter_module, *args)
|
|
293
245
|
file, graph_index, node_id, edge_id = parse_name(name)
|
|
294
246
|
raise ArgumentError, 'edges needs at least a graph' unless graph_index
|
|
295
|
-
|
|
296
247
|
raise ArgumentError, 'edges does not take arguments' unless args.empty?
|
|
297
248
|
|
|
249
|
+
entry = nil
|
|
250
|
+
|
|
298
251
|
with_graph(file, graph_index) do |parser|
|
|
299
252
|
parser.read_graph_header
|
|
300
253
|
graph = parser.read_graph
|
|
301
254
|
if node_id
|
|
302
|
-
|
|
255
|
+
Passes.apply graph
|
|
303
256
|
node = graph.nodes[node_id]
|
|
304
257
|
raise ArgumentError, 'node not found' unless node
|
|
305
258
|
|
|
@@ -310,24 +263,18 @@ module Seafoam
|
|
|
310
263
|
edges = node.outputs.select { |edge| edge.to == to }
|
|
311
264
|
raise ArgumentError, 'edge not found' if edges.empty?
|
|
312
265
|
|
|
313
|
-
|
|
314
|
-
@out.puts "#{edge.from.id_and_label} ->(#{edge.props[:label]}) #{edge.to.id_and_label}"
|
|
315
|
-
end
|
|
266
|
+
entry = formatter_module::EdgesFormatter::EdgesEntry.new(edges)
|
|
316
267
|
else
|
|
317
|
-
|
|
318
|
-
node.inputs.each do |input|
|
|
319
|
-
@out.puts " #{node.id_and_label} <-(#{input.props[:label]}) #{input.from.id_and_label}"
|
|
320
|
-
end
|
|
321
|
-
@out.puts 'Output:'
|
|
322
|
-
node.outputs.each do |output|
|
|
323
|
-
@out.puts " #{node.id_and_label} ->(#{output.props[:label]}) #{output.to.id_and_label}"
|
|
324
|
-
end
|
|
268
|
+
entry = formatter_module::EdgesFormatter::NodeEntry.new(node)
|
|
325
269
|
end
|
|
326
270
|
break
|
|
327
271
|
else
|
|
328
|
-
|
|
272
|
+
entry = formatter_module::EdgesFormatter::SummaryEntry.new(graph.nodes.count, graph.edges.count)
|
|
329
273
|
end
|
|
330
274
|
end
|
|
275
|
+
|
|
276
|
+
formatter = formatter_module::EdgesFormatter.new(entry)
|
|
277
|
+
@out.puts formatter.format
|
|
331
278
|
end
|
|
332
279
|
|
|
333
280
|
# seafoam file.bgv... props
|
|
@@ -376,7 +323,7 @@ module Seafoam
|
|
|
376
323
|
end
|
|
377
324
|
|
|
378
325
|
# seafoam file.bgv:n:n source
|
|
379
|
-
def source(name, *args)
|
|
326
|
+
def source(name, formatter_module, *args)
|
|
380
327
|
file, graph_index, node_id, edge_id = parse_name(name)
|
|
381
328
|
raise ArgumentError, 'source needs a node' unless node_id
|
|
382
329
|
raise ArgumentError, 'source only works with a node' if edge_id
|
|
@@ -388,7 +335,57 @@ module Seafoam
|
|
|
388
335
|
node = graph.nodes[node_id]
|
|
389
336
|
raise ArgumentError, 'node not found' unless node
|
|
390
337
|
|
|
391
|
-
|
|
338
|
+
formatter = formatter_module::SourceFormatter.new(node.props['nodeSourcePosition'])
|
|
339
|
+
@out.puts formatter.format
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
# seafoam file.bgv:n describe
|
|
344
|
+
def describe(name, formatter_module, *args)
|
|
345
|
+
file, graph_index, *rest = parse_name(name)
|
|
346
|
+
|
|
347
|
+
if graph_index.nil? || !rest.all?(&:nil?)
|
|
348
|
+
raise ArgumentError, 'describe only works with a graph'
|
|
349
|
+
end
|
|
350
|
+
raise ArgumentError, 'describe does not take arguments' unless args.empty?
|
|
351
|
+
|
|
352
|
+
parser = BGV::BGVParser.new(file)
|
|
353
|
+
parser.read_file_header
|
|
354
|
+
parser.skip_document_props
|
|
355
|
+
|
|
356
|
+
loop do
|
|
357
|
+
index, = parser.read_graph_preheader
|
|
358
|
+
break unless index
|
|
359
|
+
|
|
360
|
+
parser.skip_graph_header
|
|
361
|
+
|
|
362
|
+
if index != graph_index
|
|
363
|
+
parser.skip_graph
|
|
364
|
+
next
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
graph = parser.read_graph
|
|
368
|
+
description = Seafoam::Graal::GraphDescription.new
|
|
369
|
+
|
|
370
|
+
graph.nodes.each_value do |node|
|
|
371
|
+
node_class = node.props.dig(:node_class, :node_class)
|
|
372
|
+
case node_class
|
|
373
|
+
when 'org.graalvm.compiler.nodes.IfNode'
|
|
374
|
+
description.branches = true
|
|
375
|
+
when 'org.graalvm.compiler.nodes.LoopBeginNode'
|
|
376
|
+
description.loops = true
|
|
377
|
+
when 'org.graalvm.compiler.nodes.InvokeNode', 'org.graalvm.compiler.nodes.InvokeWithExceptionNode'
|
|
378
|
+
description.calls = true
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
description.deopts = graph.nodes[0].outputs.map(&:to)
|
|
383
|
+
.all? { |t| t.props.dig(:node_class, :node_class) == 'org.graalvm.compiler.nodes.DeoptimizeNode' }
|
|
384
|
+
|
|
385
|
+
formatter = formatter_module::DescribeFormatter.new(graph, description)
|
|
386
|
+
@out.puts formatter.format
|
|
387
|
+
|
|
388
|
+
break
|
|
392
389
|
end
|
|
393
390
|
end
|
|
394
391
|
|
|
@@ -398,8 +395,10 @@ module Seafoam
|
|
|
398
395
|
raise ArgumentError, 'render needs at least a graph' unless graph_index
|
|
399
396
|
raise ArgumentError, 'render only works with a graph' unless rest == [nil, nil]
|
|
400
397
|
|
|
401
|
-
|
|
398
|
+
pass_options = {
|
|
399
|
+
simplify_truffle_args: true,
|
|
402
400
|
hide_frame_state: true,
|
|
401
|
+
hide_pi: true,
|
|
403
402
|
hide_floating: false,
|
|
404
403
|
reduce_edges: true
|
|
405
404
|
}
|
|
@@ -420,12 +419,16 @@ module Seafoam
|
|
|
420
419
|
raise ArgumentError, 'no list for --spotlight' unless spotlight_arg
|
|
421
420
|
|
|
422
421
|
spotlight_nodes = spotlight_arg.split(',').map { |n| Integer(n) }
|
|
422
|
+
when '--full-truffle-args'
|
|
423
|
+
pass_options[:simplify_truffle_args] = false
|
|
423
424
|
when '--show-frame-state'
|
|
424
|
-
|
|
425
|
+
pass_options[:hide_frame_state] = false
|
|
426
|
+
when '--show-pi'
|
|
427
|
+
pass_options[:hide_pi] = false
|
|
425
428
|
when '--hide-floating'
|
|
426
|
-
|
|
429
|
+
pass_options[:hide_floating] = true
|
|
427
430
|
when '--no-reduce-edges'
|
|
428
|
-
|
|
431
|
+
pass_options[:reduce_edges] = false
|
|
429
432
|
when '--draw-blocks'
|
|
430
433
|
draw_blocks = true
|
|
431
434
|
when '--option'
|
|
@@ -436,7 +439,7 @@ module Seafoam
|
|
|
436
439
|
raise ArgumentError, "no value for --option #{key}" unless out_file
|
|
437
440
|
|
|
438
441
|
value = { 'true' => true, 'false' => 'false' }.fetch(key, value)
|
|
439
|
-
|
|
442
|
+
pass_options[key.to_sym] = value
|
|
440
443
|
else
|
|
441
444
|
raise ArgumentError, "unexpected option #{arg}"
|
|
442
445
|
end
|
|
@@ -459,7 +462,7 @@ module Seafoam
|
|
|
459
462
|
with_graph(file, graph_index) do |parser|
|
|
460
463
|
parser.skip_graph_header
|
|
461
464
|
graph = parser.read_graph
|
|
462
|
-
|
|
465
|
+
Passes.apply graph, pass_options
|
|
463
466
|
if spotlight_nodes
|
|
464
467
|
spotlight = Spotlight.new(graph)
|
|
465
468
|
spotlight_nodes.each do |node_id|
|
|
@@ -569,6 +572,32 @@ module Seafoam
|
|
|
569
572
|
raise ArgumentError, 'graph not found' unless graph_found
|
|
570
573
|
end
|
|
571
574
|
|
|
575
|
+
# Prints help.
|
|
576
|
+
def help(*_args)
|
|
577
|
+
@out.puts 'seafoam file.bgv info'
|
|
578
|
+
@out.puts ' file.bgv list'
|
|
579
|
+
@out.puts ' file.bgv[:graph][:node[-edge]] search term...'
|
|
580
|
+
@out.puts ' file.bgv[:graph][:node[-edge]] edges'
|
|
581
|
+
@out.puts ' file.bgv[:graph][:node[-edge]] props'
|
|
582
|
+
@out.puts ' file.bgv:graph:node source'
|
|
583
|
+
@out.puts ' file.bgv:graph describe'
|
|
584
|
+
@out.puts ' file.bgv:graph render'
|
|
585
|
+
@out.puts ' --spotlight n,n,n...'
|
|
586
|
+
@out.puts ' --out graph.pdf'
|
|
587
|
+
@out.puts ' graph.svg'
|
|
588
|
+
@out.puts ' graph.png'
|
|
589
|
+
@out.puts ' graph.dot'
|
|
590
|
+
@out.puts ' --full-truffle-args'
|
|
591
|
+
@out.puts ' --show-frame-state'
|
|
592
|
+
@out.puts ' --show-pi'
|
|
593
|
+
@out.puts ' --hide-floating'
|
|
594
|
+
@out.puts ' --no-reduce-edges'
|
|
595
|
+
@out.puts ' --draw-blocks'
|
|
596
|
+
@out.puts ' --option key value'
|
|
597
|
+
@out.puts ' --help'
|
|
598
|
+
@out.puts ' --version'
|
|
599
|
+
end
|
|
600
|
+
|
|
572
601
|
# Prints the version.
|
|
573
602
|
def version(*args)
|
|
574
603
|
raise ArgumentError, "unexpected arguments #{args.join(' ')}" unless args.empty?
|
|
@@ -602,10 +631,15 @@ module Seafoam
|
|
|
602
631
|
|
|
603
632
|
# Open a file for the user if possible.
|
|
604
633
|
def autoopen(file)
|
|
605
|
-
|
|
634
|
+
return unless @out.tty?
|
|
635
|
+
|
|
636
|
+
case RUBY_PLATFORM
|
|
637
|
+
when /darwin/
|
|
606
638
|
system 'open', file
|
|
607
|
-
|
|
639
|
+
when /linux/
|
|
640
|
+
system 'xdg-open', file
|
|
608
641
|
end
|
|
642
|
+
# Don't worry if it fails.
|
|
609
643
|
end
|
|
610
644
|
end
|
|
611
645
|
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
module Seafoam
|
|
2
|
+
module Formatters
|
|
3
|
+
module Base
|
|
4
|
+
# Formats the output of the `describe` command.
|
|
5
|
+
class DescribeFormatter
|
|
6
|
+
attr_reader :graph, :description
|
|
7
|
+
|
|
8
|
+
def initialize(graph, description)
|
|
9
|
+
@graph = graph
|
|
10
|
+
@description = description
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Formats the output of the `edges` command.
|
|
15
|
+
class EdgesFormatter
|
|
16
|
+
EdgesEntry = Struct.new(:edges) do
|
|
17
|
+
def render(formatter)
|
|
18
|
+
formatter.render_edges_entry(edges)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
NodeEntry = Struct.new(:node) do
|
|
23
|
+
def render(formatter)
|
|
24
|
+
formatter.render_node_entry(node)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
SummaryEntry = Struct.new(:node_count, :edge_count) do
|
|
29
|
+
def render(formatter)
|
|
30
|
+
formatter.render_summary_entry(node_count, edge_count)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
attr_reader :entry
|
|
35
|
+
|
|
36
|
+
def initialize(entry)
|
|
37
|
+
@entry = entry
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def format
|
|
41
|
+
entry.render(self)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def render_edges_entry(edges)
|
|
45
|
+
raise NotImplementedError
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def render_node_entry(node)
|
|
49
|
+
raise NotImplementedError
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def render_summary_entry(node_count, edge_count)
|
|
53
|
+
raise NotImplementedError
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Formats the output of the `info` command.
|
|
58
|
+
class InfoFormatter
|
|
59
|
+
attr_reader :major_version, :minor_version
|
|
60
|
+
|
|
61
|
+
def initialize(major_version, minor_version)
|
|
62
|
+
@major_version = major_version
|
|
63
|
+
@minor_version = minor_version
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Formats the output of the `list` command.
|
|
68
|
+
class ListFormatter
|
|
69
|
+
Entry = Struct.new(:file, :graph_name_components, :index)
|
|
70
|
+
|
|
71
|
+
attr_reader :entries
|
|
72
|
+
|
|
73
|
+
def initialize(entries)
|
|
74
|
+
@entries = entries
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Formats the output of the `source` command.
|
|
79
|
+
class SourceFormatter
|
|
80
|
+
attr_reader :source_position
|
|
81
|
+
|
|
82
|
+
def initialize(source_position)
|
|
83
|
+
@source_position = source_position
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
module Seafoam
|
|
2
|
+
# Formatters are the mechanism by which `seafoam` command output is presented to the user.
|
|
3
|
+
module Formatters
|
|
4
|
+
autoload :Base, 'seafoam/formatters/base'
|
|
5
|
+
autoload :Json, 'seafoam/formatters/json'
|
|
6
|
+
autoload :Text, 'seafoam/formatters/text'
|
|
7
|
+
end
|
|
8
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
module Seafoam
|
|
4
|
+
module Formatters
|
|
5
|
+
module Json
|
|
6
|
+
# A JSON-based formatter for the `describe` command.
|
|
7
|
+
class DescribeFormatter < Seafoam::Formatters::Base::DescribeFormatter
|
|
8
|
+
def format
|
|
9
|
+
ret = Seafoam::Graal::GraphDescription::ATTRIBUTES.map { |attr| [attr, description.send(attr)] }.to_h
|
|
10
|
+
ret[:node_count] = graph.nodes.size
|
|
11
|
+
|
|
12
|
+
ret.to_json
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# A JSON-based formatter for the `edges` command.
|
|
17
|
+
class EdgesFormatter < Seafoam::Formatters::Base::EdgesFormatter
|
|
18
|
+
def render_edges_entry(edges)
|
|
19
|
+
edges.map { |edge| build_edge(edge) }.to_json
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def render_node_entry(node)
|
|
23
|
+
{
|
|
24
|
+
input: node.inputs.map { |input| build_edge(input) },
|
|
25
|
+
output: node.outputs.map { |output| build_edge(output) }
|
|
26
|
+
}.to_json
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def render_summary_entry(node_count, edge_count)
|
|
30
|
+
{ node_count: node_count, edge_count: edge_count }.to_json
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def build_node(node)
|
|
34
|
+
{ id: node.id.to_s, label: node.props[:label] }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def build_edge(edge)
|
|
38
|
+
{ from: build_node(edge.from), to: build_node(edge.to), label: edge.props[:label] }
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# A JSON-based formatter for the `info` command.
|
|
43
|
+
class InfoFormatter < Seafoam::Formatters::Base::InfoFormatter
|
|
44
|
+
def format
|
|
45
|
+
{
|
|
46
|
+
major_version: major_version,
|
|
47
|
+
minor_version: minor_version
|
|
48
|
+
}.to_json
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# A JSON-based formatter for the `list` command.
|
|
53
|
+
class ListFormatter < Seafoam::Formatters::Base::ListFormatter
|
|
54
|
+
def format
|
|
55
|
+
entries.map do |entry|
|
|
56
|
+
{
|
|
57
|
+
graph_index: entry.index,
|
|
58
|
+
graph_file: entry.file,
|
|
59
|
+
graph_name_components: entry.graph_name_components
|
|
60
|
+
}
|
|
61
|
+
end.to_json
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# A JSON-based formatter for the `source` command.
|
|
66
|
+
class SourceFormatter < Seafoam::Formatters::Base::SourceFormatter
|
|
67
|
+
def format
|
|
68
|
+
Seafoam::Graal::Source.walk(source_position, &method(:render_method)).to_json
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def render_method(method)
|
|
72
|
+
declaring_class = method[:declaring_class]
|
|
73
|
+
name = method[:method_name]
|
|
74
|
+
{
|
|
75
|
+
class: declaring_class,
|
|
76
|
+
method: name
|
|
77
|
+
}
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|