module YARP::Debug

def self.cruby_locals(source)

sets of local variables that were encountered.
For the given source, compiles with CRuby and returns a list of all of the
def self.cruby_locals(source)
  verbose = $VERBOSE
  $VERBOSE = nil
  begin
    locals = []
    stack = [ISeq.new(RubyVM::InstructionSequence.compile(source).to_a)]
    while (iseq = stack.pop)
      if iseq.type != :once
        names = iseq.local_table
        # CRuby will push on a special local variable when there are keyword
        # arguments. We get rid of that here.
        names = names.grep_v(Integer)
        # TODO: We don't support numbered local variables yet, so we get rid
        # of those here.
        names = names.grep_v(/^_\d$/)
        # For some reason, CRuby occasionally pushes this special local
        # variable when there are splat arguments. We get rid of that here.
        names = names.grep_v(:"#arg_rest")
        # Now push them onto the list of locals.
        locals << names
      end
      iseq.each_child { |child| stack << child }
    end
    locals
  ensure
    $VERBOSE = verbose
  end
end