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.