Parent

RawParseTree

ParseTree is a RubyInline-style extension that accesses and traverses the internal parse tree created by ruby.

class Example
  def blah
    return 1 + 1
  end
end

ParseTree.new.parse_tree(Example)
=> [[:class, :Example, :Object,
       [:defn,
         "blah",
         [:scope,
           [:block,
             [:args],
             [:return, [:call, [:lit, 1], "+", [:array, [:lit, 1]]]]]]]]]

Constants

NODE_NAMES
VERSION

Public Class Methods

has_alloca() click to toggle source
# File lib/parse_tree.rb, line 191
def self.has_alloca
  true
end
new(include_newlines=$DEBUG) click to toggle source

Initializes a ParseTree instance. Includes newline nodes if include_newlines which defaults to +$DEBUG+.

# File lib/parse_tree.rb, line 82
def initialize(include_newlines=$DEBUG)
  @include_newlines = include_newlines
end
translate(klass_or_str, method=nil) click to toggle source

Front end translation method.

# File lib/parse_tree.rb, line 51
def self.translate(klass_or_str, method=nil)
  pt = self.new(false)
  case klass_or_str
  when String then
    sexp = pt.parse_tree_for_string(klass_or_str).first
    if method then
      # class, scope, block, *methods
      sexp.last.last[1..-1].find do |defn|
        defn[1] == method
      end
    else
      sexp
    end
  else
    unless method.nil? then
      if method.to_s =~ /^self\./ then
        method = method.to_s[5..-1].intern
        pt.parse_tree_for_method(klass_or_str, method, true)
      else
        pt.parse_tree_for_method(klass_or_str, method)
      end
    else
      pt.parse_tree(klass_or_str).first
    end
  end
end

Public Instance Methods

parse_tree(*klasses) click to toggle source

Main driver for ParseTree. Returns an array of arrays containing the parse tree for klasses.

Structure:

[[:class, classname, superclassname, [:defn :method1, ...], ...], ...]

NOTE: v1.0 - v1.1 had the signature (klass, meth=nil). This wasn’t used much at all and since parse_tree_for_method already existed, it was deemed more useful to expand this method to do multiple classes.

# File lib/parse_tree.rb, line 99
def parse_tree(*klasses)
  result = []
  klasses.each do |klass|
    klassname = klass.name rescue '' # HACK klass.name should never be nil
                                 # Tempfile's DelegateClass(File) seems to
                                 # cause this
    klassname = "UnnamedClass_#{klass.object_id}" if klassname.empty?
    klassname = klassname.to_sym

    code = if Class === klass then
             sc = klass.superclass
             sc_name = ((sc.nil? or sc.name.empty?) ? "nil" : sc.name).intern
             [:class, klassname, [:const, sc_name]]
           else
             [:module, klassname]
           end

    method_names = []
    method_names += klass.instance_methods false
    method_names += klass.private_instance_methods false
    # protected methods are included in instance_methods, go figure!

    method_names.sort.each do |m|
      r = parse_tree_for_method(klass, m.to_sym)
      code << r
    end

    mods = klass.modules
    mods -= mods.map { |mod| mod.modules }.flatten

    mods.each do |mod| # TODO: add a test for this damnit
      code << process("include #{mod}")
    end

    klass.singleton_methods(false).sort.each do |m|
      code << parse_tree_for_method(klass, m.to_sym, true)
    end

    result << code
  end
  return result
end
parse_tree_for_method(klass, method, is_cls_meth=false, verbose = true) click to toggle source

Returns the parse tree for just one method of a class klass.

Format:

[:defn, :name, :body]
# File lib/parse_tree.rb, line 149
def parse_tree_for_method(klass, method, is_cls_meth=false, verbose = true)
  $stderr.puts "** parse_tree_for_method(#{klass}, #{method}):" if $DEBUG
  old_verbose, $VERBOSE = $VERBOSE, verbose
  r = parse_tree_for_meth(klass, method.to_sym, is_cls_meth)
  r
ensure
  $VERBOSE = old_verbose
end
parse_tree_for_string(source, filename = '(string)', line = 1, verbose = true) click to toggle source

Returns the parse tree for a string source.

Format:

[[sexps] ... ]
# File lib/parse_tree.rb, line 165
def parse_tree_for_string(source,
                          filename = '(string)', line = 1, verbose = true)
  old_verbose, $VERBOSE = $VERBOSE, verbose
  return parse_tree_for_str0(source, filename, line)
ensure
  $VERBOSE = old_verbose
end
process(input, verbose = nil) click to toggle source
# File test/test_parse_tree.rb, line 36
def process(input, verbose = nil) # TODO: remove

  test_method = caller[0][/\`(.*)\'/, 1]
  verbose = test_method =~ /mri_verbose_flag/ ? true : nil

  # um. kinda stupid, but cleaner
  case input
  when Array then
    ParseTree.translate(*input)
  else
    self.parse_tree_for_string(input, '(string)', 1, verbose).first
  end
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.