ParseTree 2.0.0 Released


#1

ParseTree version 2.0.0 has been released!

ParseTree is a C extension (using RubyInline) that extracts the parse
tree for an entire class or a specific method and returns it as a
s-expression (aka sexp) using ruby’s arrays, strings, symbols, and
integers.

As an example:

def conditional1(arg1)
if arg1 == 0 then
return 1
end
return 0
end

becomes:

[:defn,
:conditional1,
[:scope,
[:block,
[:args, :arg1],
[:if,
[:call, [:lvar, :arg1], :==, [:array, [:lit, 0]]],
[:return, [:lit, 1]],
nil],
[:return, [:lit, 0]]]]]

  • Uses RubyInline, so it just drops in.
  • Includes SexpProcessor and CompositeSexpProcessor.
    • Allows you to write very clean filters.
  • Includes UnifiedRuby, allowing you to automatically rewrite ruby
    quirks.
  • ParseTree#parse_tree_for_string lets you parse arbitrary strings of
    ruby.
  • Includes parse_tree_show, which lets you quickly snoop code.
    • echo “1+1” | parse_tree_show -f for quick snippet output.
  • Includes parse_tree_abc, which lets you get abc metrics on code.
    • abc metrics = numbers of assignments, branches, and calls.
    • whitespace independent metric for method complexity.
  • Includes parse_tree_deps, which shows you basic class level
    dependencies.
  • Does not work on the core classes, as they are not ruby (yet).

Changes:

  • 2 major enhancements:

    • Rewrite methods completely rewritten. Rewriters:
      • are no longer recursive.
      • are no longer required to empty the sexp coming in.
      • are depth first, so rewriter gets passed everything already
        normalized.
      • keep rewriting until type doesn’t change.
      • are magical goodness.
    • Added UnifiedRuby module to aid others in writing clean
      SexpProcessors:
      • bmethod/dmethod/fbody unified with defn
      • fcall/vcall unified with call
      • resbody unified with itself (lots of different forms)
  • 5 minor enhancements:

    • Add #modules to Module.
    • Add Sexp::for shortcut for Sexp.from_array ParseTree.translate
      (…).
    • Add parens for :block nodes as appropriate. May be overzealous.
    • Made add_to_parse_tree global for reuse by other C extensions.
    • Made test_ruby2ruby MUCH more rigorous with circular testing.
  • 6 bug fixes:

    • Added $TESTING = true to pt_testcase.rb. OOPS!
    • Fixed some circular bugs, mostly by hacking them out, wrt
      operator precidence.
    • Fixed splat arg processing when arg has no name.
    • Fixed trinary operator.
    • Fixed BMETHOD with no arguments.
    • Removed hacky “self.” thing for defs at top level PT use.
  • http://www.zenspider.com/ZSS/Products/ParseTree/


#2

2007/8/1, Ryan D. removed_email_address@domain.invalid:

ParseTree version 2.0.0 has been released!
(…)

Ryan, thank you for your continuous work on those libraries. I have a
question concerning Ruby’s ASTs: do you know a way to get at the parse
tree of the calling method / block and at the node of the call? For
example:

def look_at_callers_parse_tree
# what to do here?
end

def calling_from_method
look_at_callers_parse_tree # should get this node…
end

def calling_from_block
yield
end

calling_from_block { look_at_callers_parse_tree } # …and the one
in this block

Regards,
Pit


#3

On Aug 1, 2007, at 12:55 , Pit C. wrote:

# what to do here?

calling_from_block { look_at_callers_parse_tree } # …and the one
in this block

not without doing the usual caller() manipulation stuffs, no.
Rubinius might be easier in that regard tho.


#4

2007/8/1, Ryan D. removed_email_address@domain.invalid:

On Aug 1, 2007, at 12:55 , Pit C. wrote:

(…) do you know a way to get at the parse
tree of the calling method / block and at the node of the call?

not without doing the usual caller() manipulation stuffs, no.
Rubinius might be easier in that regard tho.

OK. Thanks.

Regards,
Pit


#5

May I kindly ask if you could give an example for how to use
parse_tree_for_method? Is there an example available for how to parse a
method, modify the sexpr and feed the result back to the ruby
interpreter, thereby replacing the original method with the patched
version?

Regards,
Thomas.


#6

On Aug 1, 2007, at 12:55, Pit C. wrote:

# what to do here?

calling_from_block { look_at_callers_parse_tree } # …and the one
in this block

SuperCaller can do this. It was waiting on a release of PT, because
add_to_parse_tree was static.

I need to polish the documentation a bit before I can release.


#7

2007/8/4, Eric H. removed_email_address@domain.invalid:

SuperCaller can do this. It was waiting on a release of PT, because
add_to_parse_tree was static.

I need to polish the documentation a bit before I can release.

Thanks Eric, I’m looking forward to the relase. But maybe I don’t need
it anymore, because, while searching the web for SuperCaller, I’ve
seen on your blog that you seem to work on some of the same ideas as I
do with your inliner experiments :slight_smile:

Regards,
Pit


#8

On Aug 2, 2007, at 04:29 , Tom L. wrote:

May I kindly ask if you could give an example for how to use
parse_tree_for_method? Is there an example available for how to
parse a
method, modify the sexpr and feed the result back to the ruby
interpreter, thereby replacing the original method with the patched
version?

ParseTree is one way. You have to use ruby2ruby + eval to feed the
results back in.