15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
# File 'lib/benchmark-interface/frontends/mri.rb', line 15
def self.load_mri(path, options)
if options['--use-cache']
load CACHE_FILE
else
require 'parser/current'
require 'unparser'
source = File.read(path)
buffer = Parser::Source::Buffer.new(source)
buffer.source = source
parser = Parser::CurrentRuby.new
ast = parser.parse(buffer)
abort "AST rooted at unexpected #{ast.type.inspect}" unless ast.type == :begin
last = ast.children.last
abort "Last statement #{last.type.inspect} unexpected" unless [:while, :block, :send, :lvasgn].include? last.type
assigns = {}
rewriter = Class.new(Parser::Rewriter) do
define_method :on_lvasgn do |node|
if node == last
on_node node
elsif node.children.last.type == :int
name = node.children.first
value = node.children.last.children.last
assigns[name] = value
end
end
define_method :on_node do |node|
return unless node == last
assigns_source = ''
assigns.each do |name, value|
if node.to_s.include? "(lvar #{name.inspect})"
assigns_source += "#{name} = #{value}; "
end
end
insert_before node.location.expression, 'BenchmarkInterface.benchmark { ' + assigns_source
insert_after node.location.expression, ' }'
end
alias_method :on_while, :on_node
alias_method :on_block, :on_node
alias_method :on_send, :on_node
end
rewriter = rewriter.new
rewritten = rewriter.rewrite(buffer, ast)
if options['--show-rewrite']
puts rewritten
end
if options['--cache']
File.write(CACHE_FILE, rewritten)
exit 1
else
Object.instance_eval rewritten
end
end
end
|