4 # Stores all the information about a running method.
6 # Hey! Be careful with this! This is used by backtrace and if it doesn't work,
7 # you can get recursive exceptions being raised (THATS BAD, BTW).
11 attr_accessor :last_match
14 # The Nth group of the last regexp match.
25 # One of the special globals $&, $`, $' or $+.
47 "#<#{self.class}:0x#{self.object_id.to_s(16)} #{receiver}##{name} #{file}:#{line}>"
49 alias_method :inspect, :to_s
50 # File in which associated method defined.
52 return "(unknown)" unless self.method
56 # See CompiledMethod#lines
58 return [] unless self.method
62 # Current line being executed by the VM.
64 return 0 unless self.method
65 # We subtract 1 because the ip is actually set to what it should do
66 # next, not what it's currently doing (unless we are at the start of
68 return self.method.line_from_ip(self.ip == 0 ? self.ip : self.ip - 1)
71 # Copies context. If locals is true
72 # local variable values are also
73 # copied into new context.
74 def copy(locals=false)
76 return d unless locals
101 def disable_long_return!
103 # CTX_FLAG_NO_LONG_RETURN => 1
107 def calling_hierarchy(start=1)
114 ret << "#{ctx.file}:#{ctx.line}:in `#{ctx.method.name}'"
116 ret << "#{ctx.file}:#{ctx.line}"
119 # In a backtrace, an eval'd context's binding shows up
120 if ctx.kind_of?(BlockContext) and ctx.env.from_eval? then
122 ret << "#{home.file}:#{home.line} in `#{home.method.name}'"
131 return nil if start > i + 1
136 if method_module.equal?(Kernel)
138 elsif method_module.kind_of?(MetaClass)
140 elsif method_module and method_module != receiver.class
141 str = "#{method_module}(#{receiver.class})#"
143 str = "#{receiver.class}#"
146 if kind_of? BlockContext
148 elsif name == method.name
151 str << "#{name} (#{method.name})"
155 def const_defined?(name)
156 scope = method.staticscope
158 return true if scope.module.const_defined?(name)
162 return Object.const_defined?(name)
165 def const_path_defined?(path)
166 scope = method.staticscope
167 scope.module.const_path_defined?(path)
170 def class_variable_get(name)
171 return current_scope.class_variable_get(name)
174 def class_variable_set(name, val)
175 if receiver.kind_of? Module
176 return receiver.class_variable_set(name, val)
179 return current_scope.class_variable_set(name, val)
182 def class_variable_defined?(name)
183 return current_scope.class_variable_defined?(name)
187 if ss = method.staticscope
195 self.method = method.dup
203 # Look up the staticscope chain to find the one with a Script object
204 # attached to it. Return that object.
207 if ss = method.staticscope
208 while ss and !ss.script
212 return ss.script if ss
219 # Used to implement __FILE__ properly. kernel/core/compile.rb stashes
220 # the path used to load this file in the Script object located in
221 # the top staticscope.
224 if script = script_object()
225 if path = script.path
230 # If for some reason that didn't work, return the compile time filename.
235 # Used to set the module body toggles
237 attr_accessor :method_scope
239 def alias_method(name, original)
240 scope = MethodContext.current.sender.current_scope
241 scope.__send__(:alias_method, name, original)
244 # This version is trivial, and is meant to match the API of BlockContext
245 def __const_set__(name, value)
246 const_scope = MethodContext.current.sender.receiver
247 const_scope.__send__(:__const_set__, name, value)
251 # Called when 'def name' is used in userland
253 def __add_method__(name, obj)
254 s = MethodContext.current.sender
255 scope = s.method_scope || :public
257 if name == :initialize or scope == :module
258 visibility = :private
263 # All userland added methods start out with a serial of 1.
266 # Push the scoping down.
267 obj.staticscope = s.method.staticscope
269 Rubinius::VM.reset_method_cache(name)
271 obj.staticscope.module.method_table[name] = Tuple[visibility, obj]
274 s.current_scope.module_function name
277 if s.current_scope.respond_to? :method_added
278 s.current_scope.method_added(name)
281 # Return value here is the return value of the 'def' expression
288 # Stores all the information about a running NativeMethod.
290 class NativeMethodContext
297 # Stores all information about a running Block.
299 # Block context has no own receiver,
300 # static lexical scope and is unnamed
301 # so it uses receiver, scope and name
302 # of home method context, that is,
303 # method context that started it's execution.
310 def last_match=(match)
311 home.last_match = match
323 @method_scope || env.home_block.method_scope
326 # Active context (instance of MethodContext) that started
327 # execution of this block context.
332 # Name of home method.
337 # Block context has no receiver thus uses
338 # receiver from it's home method context.
343 # Block context has no own module thus uses
344 # module from it's home method context.
349 # Static scope of home method context.
351 if ss = method.staticscope
358 # instance_eval needs alternate const behavior
359 def __const_set__(name, value)
360 const_scope = env.constant_scope.module
361 const_scope.__send__(:__const_set__, name, value)
366 # Describes the environment a Block was created in. BlockEnvironment is used
367 # to create a BlockContext.
369 class BlockEnvironment
370 ivar_as_index :__ivars__ => 0, :home => 1, :initial_ip => 2, :last_ip => 3,
371 :post_send => 4, :home_block => 5, :local_count => 6, :metadata_container => 7, :method => 8
372 def __ivars__ ; @__ivars__ ; end
373 def home ; @home ; end
374 def initial_ip ; @initial_ip ; end
375 def last_ip ; @last_ip ; end
376 def post_send ; @post_send ; end
377 def home_block ; @home_block ; end
378 def local_count ; @local_count ; end
379 def method ; @method ; end
381 def metadata_container
385 def under_context(home, cmethod)
386 if home.kind_of? BlockContext
395 @last_ip = 0x10000000 # 2**28
397 @home_block = home_block
399 @local_count = cmethod.local_count
404 # Holds a Tuple of additional metadata.
405 # First field of the tuple holds a boolean indicating if the context is from
407 def metadata_container=(tup)
408 @metadata_container = tup
412 @metadata_container and @metadata_container[0]
416 @metadata_container = Tuple.new(1) unless @metadata_container
417 @metadata_container[0] = true
421 # The CompiledMethod object that we were called from
429 # These should be safe since I'm unsure how you'd have a BlockContext
430 # and have a nil CompiledMethod (something that can (and has) happened
431 # with MethodContexts)
438 method.line_from_ip(initial_ip)
451 @home_block = @home_block.dup
452 @method = @method.dup
458 env.home.receiver = obj
462 def call_on_instance(obj, *args)
463 obj = redirect_to(obj)
467 def disable_long_return!
475 # Static scope for constant lookup
476 def constant_scope=(scope)
477 @constant_scope = scope
481 @constant_scope ||= @method.staticscope
486 # Contains stack frame objects
493 attr_accessor :first_color
494 attr_accessor :kernel_color
495 attr_accessor :eval_color
500 @first_color = "\033[0;31m"
501 @kernel_color = "\033[0;34m"
502 @eval_color = "\033[0;33m"
509 def show(sep="\n", colorize = true)
511 color_config = Rubinius::RUBY_CONFIG["rbx.colorize_backtraces"]
512 if color_config == "no" or color_config == "NO"
520 fr2 = @frames.map do |ent|
523 color = color_from_loc(loc, first) if colorize
524 first = false # special handling for first line
525 times = @max - recv.size
526 times = 0 if times < 0
527 "#{color} #{' ' * times}#{recv} at #{loc}#{clear}"
536 alias_method :to_s, :show
538 def color_from_loc(loc, first)
539 return @first_color if first
542 elsif loc =~ /\(eval\)/
549 attr_reader :top_context
569 @frames << [str, ctx.location]
572 @max = MAX_WIDTH if @max > MAX_WIDTH
575 def self.backtrace(ctx=nil)
578 ctx = MethodContext.current.sender
585 @frames.each { |f| yield f.last }
590 return @top_context.calling_hierarchy(0)