-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathframe_stack.rb
98 lines (76 loc) · 1.5 KB
/
frame_stack.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
class FrameStack
attr_reader :stack
include Enumerable
def initialize
@stack = []
end
def each
return to_enum(__method__) unless block_given?
@stack.each { |item| yield item }
end
def push(frame)
@stack << frame
if @stack.size > 100
raise VM::InternalError, '(vm) stack overflow'
end
frame
end
def push_top(**args)
push TopFrame.new(**args)
end
def push_class(**args)
push ClassFrame.new(**args)
end
def push_module(**args)
push ModuleFrame.new(**args)
end
def push_sclass(**args)
push SClassFrame.new(**args)
end
def push_method(**args)
push MethodFrame.new(**args)
end
def push_block(**args)
push BlockFrame.new(**args)
end
def push_rescue(**args)
push RescueFrame.new(**args)
end
def push_ensure(**args)
push EnsureFrame.new(**args)
end
def push_eval(**args)
push EvalFrame.new(**args)
end
def pop
@stack.pop
end
def top
@stack.last
end
def size
@stack.size
end
def closest(&block)
@stack.reverse_each.detect { |frame| block.call(frame) }
end
def frames_until(&block)
result = []
@stack.reverse_each { |frame| r = block.call(frame); result << frame; break if r }
result
end
def empty?
@stack.empty?
end
def to_backtrace
if ENV['DISABLE_TRACES']
return []
end
[
*@stack.map { |frame| BacktraceEntry.new(frame) },
"... MRI backtrace...",
*caller,
"...Internal backtrace..."
]
end
end