1# 2# frame.rb - 3# $Release Version: 0.9$ 4# $Revision: 38515 $ 5# by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd) 6# 7# -- 8# 9# 10# 11 12require "e2mmap" 13 14module IRB 15 class Frame 16 extend Exception2MessageMapper 17 def_exception :FrameOverflow, "frame overflow" 18 def_exception :FrameUnderflow, "frame underflow" 19 20 # Default number of stack frames 21 INIT_STACK_TIMES = 3 22 # Default number of frames offset 23 CALL_STACK_OFFSET = 3 24 25 # Creates a new stack frame 26 def initialize 27 @frames = [TOPLEVEL_BINDING] * INIT_STACK_TIMES 28 end 29 30 # Used by Kernel#set_trace_func to register each event in the call stack 31 def trace_func(event, file, line, id, binding) 32 case event 33 when 'call', 'class' 34 @frames.push binding 35 when 'return', 'end' 36 @frames.pop 37 end 38 end 39 40 # Returns the +n+ number of frames on the call stack from the last frame 41 # initialized. 42 # 43 # Raises FrameUnderflow if there are no frames in the given stack range. 44 def top(n = 0) 45 bind = @frames[-(n + CALL_STACK_OFFSET)] 46 Fail FrameUnderflow unless bind 47 bind 48 end 49 50 # Returns the +n+ number of frames on the call stack from the first frame 51 # initialized. 52 # 53 # Raises FrameOverflow if there are no frames in the given stack range. 54 def bottom(n = 0) 55 bind = @frames[n] 56 Fail FrameOverflow unless bind 57 bind 58 end 59 60 # Convenience method for Frame#bottom 61 def Frame.bottom(n = 0) 62 @backtrace.bottom(n) 63 end 64 65 # Convenience method for Frame#top 66 def Frame.top(n = 0) 67 @backtrace.top(n) 68 end 69 70 # Returns the binding context of the caller from the last frame initialized 71 def Frame.sender 72 eval "self", @backtrace.top 73 end 74 75 @backtrace = Frame.new 76 set_trace_func proc{|event, file, line, id, binding, klass| 77 @backtrace.trace_func(event, file, line, id, binding) 78 } 79 end 80end 81