introspection/tracepoint_sequences_no_parens.rb
tests/_examples/introspection/tracepoint_sequences_no_parens.rb in the metorex repository.
# A TracePoint aimed at an instruction sequence hears the code the sequence
# runs, a `script_compiled` event reports the sequence of the code it
# compiled, and a trace's block runs with no frame between it and the code
# that fired the event.
class Ledger
def total rates
sum = rates.sum
sum * 2
end
end
sequence = RubyVM::InstructionSequence.of Ledger.instance_method(:total)
heard = []
trace = TracePoint.new(:line) { |tp| heard << tp.lineno }
trace.enable target: sequence
Ledger.new.total [1, 2]
trace.disable
p heard
heard.clear
trace.enable target: sequence, target_line: 8
Ledger.new.total [1, 2]
trace.disable
p heard
compiled = []
TracePoint.new(:script_compiled) { |tp| compiled << tp.instruction_sequence }.enable do
eval "def doubled(value)\n [value].map { |held| held * 2 }\nend"
eval "1", nil, "ledger_report.rb", 4
end
compiled.each do |iseq|
children = []
iseq.each_child { |child| children << [child.label, child.first_lineno] }
p [iseq.path.sub(__FILE__, "here"), iseq.absolute_path, iseq.label, iseq.first_lineno, children]
end
labels = nil
calls = TracePoint.new(:call) { |tp| labels ||= caller_locations(0, 3).map(&:label) }
calls.enable(target: Ledger.instance_method(:total)) { Ledger.new.total [1] }
p labels
Output:
[7, 8]
[8]
["(eval at here:28)", nil, "<compiled>", 1, [["doubled", 1]]]
["ledger_report.rb", nil, "<compiled>", 4, []]
["block in <main>", "Ledger#total", "block in <main>"]