# = NAME # +RubyVM+::+Frame+ # # = SYNOPSES # # The +RubyVM+::+Frame+ class gives call-stack frame information # (controlled access to +rb_control_frame_t+) # # # It is possible that a The +Thread+::+Frame+ may be proposed for # all Ruby 1.9 implementations. +RubyVM+::+Frame+ # contains routines in the YARV 1.9 implementation. # # Should there be a +Thread+::+Frame+ +RubyVM+::+Frame+ would be # a subclass of +Thread+::+Frame+. In code: # # class Thread # class Frame # In all 1.9 implementations # # ... # end # def threadframe # RubyVM::Frame.new(self) # or possibly Thread::Frame.new(self) # end # end # # class RubyVM::Frame < Thread::Frame # In YARV # def initialize(thread_object) # # implementation-specific code # end # def iseq # # implementation of iseq # end # # ... # end # # A +RubyVM+::Thread+Frame+ contains information from a frame running +Thread+ # object, and the information may change or disappear in the course of # running that thread. Therefore, it is advisable ensure that the # threads of the Frame objects are blocked. # # # === RubyVM::Frame::new(thread_object) # Creates a thread-frame object for the given thread object. # # === RubyVM::Frame::current # Shorthand for RubyVM::Frame.new(Thread::current) # # === Thread#threadframe # tf = Thread::current.threadframe() # # Creates a thread-frame object for the given thread object. # Note: # Thread::current.threadframe() == RubyVM::Frame.new(Thread::current) # # == RubyVM::Frame Instance Methods # # === RubyVM::Frame#prev # tf.prev(n) -> tf or nil # tf.prev() -> tf or nil # same as tf.prev(1) # # Returns the previous control frame. If tail recursion has removed # frames as seen in the source, deal with it. ;-) +nil+ can be # returned if there is no previous frame or if tf is no longer exists. # If a number is passed go back that many frames. The value 0 gives back # tf. A negative number of a number greater than the number of frames # returns nil. # # === RubyVM::Frame#invalid? # tf.invalid?() -> boolean # # Returns true if the frame is no longer valid. On the other hand, # since the test we use is weak, returning false might not mean the # frame is valid, just that we can't disprove that it is not invalid. # # It is suggested that frames are used in a way that ensures they will # be valid. In particular frames should have local scope and frames to # threads other than the running one should be stopped while the frame # variable is active. # # # === RubyVM::Frame#thread # tf.thread() -> Thread # RubyVM::Frame.current().thread == Thread.current # # === RubyVM::Frame#type # tf.type() -> 'C' or 'Ruby' # # Indicates whether the frame is implemented in C or Ruby. # # === RubyVM::Frame#source_container # RubyVM::Threadframe#source_container() -> [Type, String] # # Returns a tuple representing kind of container, e.g. file # eval'd string object, and the name of the container. If file, # it would be a file name. If an eval'd string it might be the string. # # === RubyVM::Frame#source_location # RubyVM::Frame#.source_location() -> Array # # Returns an array of source location positions that match # +tf.instruction_offset+. A source location position is left # implementation dependent. It could be line number, a line number # and start and end column, or a start line number, start column, end # line number, end column. # # === RubyVM::Frame#stack_size # RubyVM::Frame#.stack_size -> Fixnum # # Returns the number of entries # # === RubyVM::Frame#binding # tf.binding() -> binding # # # If the frame is still valid, a binding that is in effect for the # scope of the frame is created. As with all bindings, over the # execution of the program, variables may spring into existence and # values may change. # == RubyVM::Frame # # === RubyVM::new(thread_object) # Like RubyVM::Frame.new(thread_object), but has additional information # available. # # === RubyVM::Frame#iseq # tf.iseq() -> ISeq # # Returns an instruction sequence object from the instruction sequence # found inside the +Frame+ object or +nil+ if there is none. # But if iseq is +nil+ and tf.type is not C, +binding+, and # +instruction_offset+, and +source_location+ are probably meaningless # and will be +nil+ as well. # # # === RubyVM::Frame#instruction_offset # tf.instruction_offset -> Fixnum # Offset inside ISeq of instruction that the frame is currently on. # # === RubyVM::Frame#instruction_offset= # # tf.instruction_offset=(Fixnum) # Sets the threadframe to a new offset. Some restrictions may apply, e.g. # the offset will have to refer to a valid offset location and the scope # and block level has to be the same. # # Don't need to implement initially. # # === RubyVM::Frame#return_changed? # tf.return_changed?() -> boolean # # Returns true if tf _may_ be part of tail recursion removal so when # the code in frame returns it may not be to the immediate caller as # seen in the source code. Koichi says this is too difficult to do in # YARV. # # Don't need to implement initially. # # = THANKS # # Martin Davis for suggesting # RubyVM::Frame#new == Thread::current.threadframe