June 2005 Archives

RubyConf, Here I Come!

| | Comments (0)

My rubyconf 2005 presentation proposal was accepted!

I plan on talking about all the technologies and toys that have spawned out of the metaruby project. The whole fam.

I plan on illustrating the family's usefulness and power through examples including: an example of RubyInline, a language extension for RubyInline, aparse tree complexity metric grapher, a simple example of ruby2c translation, amaintainable and fast profiler, a Ruby obfuscator, and a dynamic Ruby optimizer that requires zero effort to use.

For fun, here is something I scratched up tonight with Eric to play with the idea of lisp-like ruby posted on redhanded recently. Check it, real s-expressions in ruby:

require 'ruby2ruby'

class Module
  def _(sexp)
    self.module_eval RubyToRuby.new.process(sexp)
  end
end

class Foo
  _ [:defn, :example, [:args], [:call, [:lit, 1], :+, [:array, [:lit, 1]]]]
end

p Foo.new.example
=> 2

I just released ruby2c 1.0.0 beta 3! Have at it. Here are the release notes:

Ruby2C provides a pipeline of SexpProcessor classes to work with ParseTree output. Processors included:

  • Rewriter - massages the sexp into a more consistent form.
  • TypeChecker - type inferencer for the above sexps.
  • RubyToC - converts a ruby (subset) sexp to C.

    Remember folks: THIS IS BETA SOFTWARE!

    Changes:

    • 16 minor enhancements:
      • Added ivar and iasgn support. Needs more work.
      • Added limited support for self.
      • Added pipeline tests for bools, call_arglist, call_attrasgn, fbody.
      • Added process_not to RubyToC.
      • Added support for float and symbol literals.
      • Added support for gasgn, cvasgn, const (class consts, not classes).
      • Improved error handling/reporting, esp in RubyToC.
      • In TypeChecker.boostrap, pre-registered all base classes.
      • Modified process_class test to include a class const.
      • Processing :class now adds class constants to the local var scope.
      • Processing :const checks both genv and env now.
      • Rearchitected all tests into a pipeline test class.
      • Rewrite attrasgn into regular calls.
      • Rewrite fbody into a regular defn.
      • Rewrote :array inside call to :arglist.
      • Rewrote :or nodes in process_case to correctly be binary.
    • 1 bug fix:
      • Fixed a bug where single line while bodies were missing a semicolon.
  • ZenHacks 1.0.0 released

    | | Comments (0)

    I've finally gotten around to releasing ZenHacks 1.0.0. This includes ZenDebugger, ZenProfiler, ZenOptimizer, ruby2ruby, and quite a bit more.

    Check it out...

    ZenTest and unit_diff

    | | Comments (0)

    What do you do when you change something and your unit tests break? You look at what broke, right? But, what do you do when you look at it and you can't find out what is wrong because the text is just too big?

    I just had that happen. Can you quickly tell what is broken? I can't. It looks like this:

    % ruby  ./TestZenTest.rb 
    Requiring ZenTest
    Loaded suite ./TestZenTest
    Started
    .................F...............
    Finished in 0.186974 seconds.
    
      1) Failure:
    test_klasses_equals(TestZenTest) [./TestZenTest.rb:468]:
    <{"Something"=>
      {"equal?"=>true,
       "attrib="=>true,
       "self.method3"=>true,
       "method1="=>true,
       "method1?"=>true,
       "method1"=>true,
       "attrib"=>true,
       "method1!"=>true}}> expected but was
    <{"Something"=>
      {"equal?"=>true,
       "attrib="=>true,
       "self.[]"=>true,
       "self.method3"=>true,
       "method1="=>true,
       "method1?"=>true,
       "method1"=>true,
       "attrib"=>true,
       "method1!"=>true}}>.
    
    33 tests, 128 assertions, 1 failures, 0 errors

    So, this is just a small example. When we were working on ParseTree we'd have individual test failures that were probably 50-100 lines long, with a 1 to 2 line change somewhere in the middle. So what do you do about this??? Well, it'd be nice to just see the differences between the expected an actual result. How? You use unit_diff of course!

    % ruby  ./TestZenTest.rb | unit_diff
    Requiring ZenTest
    Loaded suite ./TestZenTest
    Started
    .................F...............
    Finished in 0.123412 seconds.
    
      1) Failure:
    test_klasses_equals(TestZenTest) [./TestZenTest.rb:468]:
    3a4
    >    "self.[]"=>true,
    33 tests, 128 assertions, 1 failures, 0 errors

    This one tool knocked HOURS off our debugging time. Try it now by downloading ZenTest.

    If you'd like to see ZenTest in action, check out Pat Eyler's excellent articles How to Use ZenTest with Ruby and Test-First Ruby Programming.