Object
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]]]]]]]]]
# File lib/parse_tree.rb, line 191
191: def self.has_alloca
192: true
193: end
Initializes a ParseTree instance. Includes newline nodes if include_newlines which defaults to +$DEBUG+.
# File lib/parse_tree.rb, line 82
82: def initialize(include_newlines=$DEBUG)
83: @include_newlines = include_newlines
84: end
Front end translation method.
# File lib/parse_tree.rb, line 51
51: def self.translate(klass_or_str, method=nil)
52: pt = self.new(false)
53: case klass_or_str
54: when String then
55: sexp = pt.parse_tree_for_string(klass_or_str).first
56: if method then
57: # class, scope, block, *methods
58: sexp.last.last[1..1].find do |defn|
59: defn[1] == method
60: end
61: else
62: sexp
63: end
64: else
65: unless method.nil? then
66: if method.to_s =~ /^self\./ then
67: method = method.to_s[5..1].intern
68: pt.parse_tree_for_method(klass_or_str, method, true)
69: else
70: pt.parse_tree_for_method(klass_or_str, method)
71: end
72: else
73: pt.parse_tree(klass_or_str).first
74: end
75: end
76: end
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
99: def parse_tree(*klasses)
100: result = []
101: klasses.each do |klass|
102: klassname = klass.name rescue '' # HACK klass.name should never be nil
103: # Tempfile's DelegateClass(File) seems to
104: # cause this
105: klassname = "UnnamedClass_#{klass.object_id}" if klassname.empty?
106: klassname = klassname.to_sym
107:
108: code = if Class === klass then
109: sc = klass.superclass
110: sc_name = ((sc.nil? or sc.name.empty?) ? "nil" : sc.name).intern
111: [:class, klassname, [:const, sc_name]]
112: else
113: [:module, klassname]
114: end
115:
116: method_names = []
117: method_names += klass.instance_methods false
118: method_names += klass.private_instance_methods false
119: # protected methods are included in instance_methods, go figure!
120:
121: method_names.sort.each do |m|
122: r = parse_tree_for_method(klass, m.to_sym)
123: code << r
124: end
125:
126: klass.modules.each do |mod| # TODO: add a test for this damnit
127: mod.instance_methods.each do |m|
128: r = parse_tree_for_method(mod, m.to_sym)
129: code << r
130: end
131: end
132:
133: klass.singleton_methods(false).sort.each do |m|
134: code << parse_tree_for_method(klass, m.to_sym, true)
135: end
136:
137: result << code
138: end
139: return result
140: end
Returns the parse tree for just one method of a class klass.
Format:
[:defn, :name, :body]
# File lib/parse_tree.rb, line 149
149: def parse_tree_for_method(klass, method, is_cls_meth=false, verbose = true)
150: $stderr.puts "** parse_tree_for_method(#{klass}, #{method}):" if $DEBUG
151: old_verbose, $VERBOSE = $VERBOSE, verbose
152: r = parse_tree_for_meth(klass, method.to_sym, is_cls_meth)
153: r
154: ensure
155: $VERBOSE = old_verbose
156: end
Returns the parse tree for a string source.
Format:
[[sexps] ... ]
# File lib/parse_tree.rb, line 165
165: def parse_tree_for_string(source,
166: filename = '(string)', line = 1, verbose = true)
167: old_verbose, $VERBOSE = $VERBOSE, verbose
168: return parse_tree_for_str0(source, filename, line)
169: ensure
170: $VERBOSE = old_verbose
171: end
# File test/test_parse_tree.rb, line 23
23: def process(input, verbose = nil) # TODO: remove
24:
25: test_method = caller[0][/\`(.*)\'/, 1]
26: verbose = test_method =~ /mri_verbose_flag/ ? true : nil
27:
28: # um. kinda stupid, but cleaner
29: case input
30: when Array then
31: ParseTree.translate(*input)
32: else
33: self.parse_tree_for_string(input, '(string)', 1, verbose).first
34: end
35: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.