Class: ParseTree

Inherits:
Object show all
Defined in:
lib/parse_tree.rb

Overview

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]]]]]]]]]

Constant Summary collapse

VERSION =
'1.4.1'
NODE_NAMES =
[
 #  00
 :method, :fbody, :cfunc, :scope, :block,
 :if, :case, :when, :opt_n, :while,
 #  10
 :until, :iter, :for, :break, :next,
 :redo, :retry, :begin, :rescue, :resbody,
 #  20
 :ensure, :and, :or, :not, :masgn,
 :lasgn, :dasgn, :dasgn_curr, :gasgn, :iasgn,
 #  30
 :cdecl, :cvasgn, :cvdecl, :op_asgn1, :op_asgn2,
 :op_asgn_and, :op_asgn_or, :call, :fcall, :vcall,
 #  40
 :super, :zsuper, :array, :zarray, :hash,
 :return, :yield, :lvar, :dvar, :gvar,
 #  50
 :ivar, :const, :cvar, :nth_ref, :back_ref,
 :match, :match2, :match3, :lit, :str,
 #  60
 :dstr, :xstr, :dxstr, :evstr, :dregx,
 :dregx_once, :args, :argscat, :argspush, :splat,
 #  70
 :to_ary, :svalue, :block_arg, :block_pass, :defn,
 :defs, :alias, :valias, :undef, :class,
 #  80
 :module, :sclass, :colon2, :colon3, :cref,
 :dot2, :dot3, :flip2, :flip3, :attrset,
 #  90
 :self, :nil, :true, :false, :defined,
 #  95
 :newline, :postexe, :alloca, :dmethod, :bmethod,
 # 100
 :memo, :ifunc, :dsym, :attrasgn,
 # 104
 :last
]

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(include_newlines = $DEBUG) ⇒ ParseTree

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



34
35
36
37
38
39
# File 'lib/parse_tree.rb', line 34

def initialize(include_newlines=$DEBUG)
  if include_newlines then
    warn "WARNING: include_newlines=true from #{caller[0..9].join(', ')}"
  end
  @include_newlines = include_newlines
end

Class Method Details

.has_allocaObject



112
113
114
# File 'lib/parse_tree.rb', line 112

def self.has_alloca
  true
end

Instance Method Details

#parse_tree(*klasses) ⇒ Object

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.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/parse_tree.rb', line 54

def parse_tree(*klasses)
  result = []
  klasses.each do |klass|
    # TODO: remove this on v 1.1
    raise "You should call parse_tree_for_method(#{klasses.first}, #{klass}) instead of parse_tree" if Symbol === klass or String === 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, 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|
      $stderr.puts "parse_tree_for_method(#{klass}, #{m}):" if $DEBUG
      code << parse_tree_for_method(klass, m.to_sym)
    end
    result << code
  end
  return result
end

#parse_tree_for_method(klass, method) ⇒ Object

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

Format:

[:defn, :name, :body]


94
95
96
# File 'lib/parse_tree.rb', line 94

def parse_tree_for_method(klass, method)
  parse_tree_for_meth(klass, method.to_sym, @include_newlines)
end