The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Refax the Automatic Refactoring Engine

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Rudi Cilibrasi

Posts: 25
Nickname: cilibrar
Registered: Aug, 2004

Rudi Cilibrasi is a longtime programmer and machine-learning researcher who loves Ruby
Refax the Automatic Refactoring Engine Posted: Feb 4, 2005 3:13 AM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Rudi Cilibrasi.
Original Post: Refax the Automatic Refactoring Engine
Feed Title: Esoteric Ruby Blog
Feed URL: http://cilibrar.com/~cilibrar/erblog.cgi/index.rss
Feed Description: A weblog made to explore some Ruby ideas in great detail and try to work out ideal solutions to real problems.
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Rudi Cilibrasi
Latest Posts From Esoteric Ruby Blog

Advertisement
Refax is an idea for an automatic refactoring system. It scans Ruby code for common redundancies and alerts the developer to what it finds. Here is the fixloops.rb code:
# Refax automatic refactoring system by Rudi Cilibrasi (cilibrar@gmail.com)
# A simple example test of the new ParseTree library.
#
# This program is meant to suggest possible refactoring opportunities
#
# to convert loops of the form
# stmt A
# stmt B
# stmt C
# while cond
#   stmt A
#   stmt B
#   stmt C
# end
#
# to
#
# begin
#   stmt A
#   stmt B
#   stmt C
# end while cond
#
# to use this system, just put
#
# require 'fixloops'
# at the bottom of your ruby source file after requiring all classes to check
#
# ParseTree notes:
# 1) How can you distinguish while loops with preconditions
# versus those with postconditional guards?  It looks like the parse tree
# is showing them the same at this moment.
# 2) Trying to parse_tree(Object) throws a nil ptr

require 'rubygems'
require 'parse_tree'

class Refax
  def refactor(c)
    fail "Must have class or module" unless c.is_a?(Module)
    p = ParseTree.new.parse_tree(c)
    recurseOn(p)
  end
  def couldPossiblyRefactor?(p, ind)
    return false unless p[ind].is_a?(Array)
    return false unless p[ind][0] == :while
    return true unless p[ind][2].is_a?(Array)
    p[ind][2][0] == :block
  end
  def howManyInsn(p)
    fail "Must be a while, not a #{p}" unless p[0] == :while
    if p[2].is_a?(Array)
      fail unless p[2][0] == :block
      p[2].size - 1
    else
      1
    end
  end
  def grabInsnArray(p)
    fail "Must be a while, not a #{p}" unless p[0] == :while
      if p[2].is_a?(Array)
        p[2][1..-1]
      else
        [p[2]]
      end
  end
  def isEquiv(a, b)
    a.to_s == b.to_s
  end
  def fixcode(p, ind)
    loopsize = howManyInsn(p[ind])
    goodcode = p.clone
    goodcode.slice!(ind-loopsize..ind-1)
    goodcode # todo : make correcter
  end
  def recurseOn(p)
    if p.is_a?(Array)
      @lastclass = p[1] if p[0] == :class
      @lastfunc = p[1] if p[0] == :defn
      p.each { |i| recurseOn(i) }
#      puts "func:#{p[1]}: #{p[2].inspect}" if p[0] == :defn
      p.each_index { |ind|
        if couldPossiblyRefactor?(p,ind)
          loopsize = howManyInsn(p[ind])
          if loopsize < ind
#            puts "The size is right."
            if isEquiv(p[ind-loopsize,loopsize], grabInsnArray(p[ind]))
#              puts "The code matches."
              goodstuff = fixcode(p, ind)
              puts "Suggest refactoring #{@lastfunc} in #{@lastclass}: #{goodstuff.inspect}"
            else
#              puts "The code doesn't match: #{grabInsnArray(p[ind]).inspect}"
#              puts p[ind-loopsize,loopsize].inspect
            end
          else
#            puts "The loop is too large."
          end
        end
      }
    end
  end

  r = Refax.new
  ObjectSpace.each_object(Module) { |c|
    r.refactor(c) unless c == Object
  }

end

And here is an example hastily.rb that can be refactored using it:

# Example Ruby program to test automatic refactoring engine based on ParseTree
# by Rudi Cilibrasi (cilibrar@gmail.com)

class HastilyWritten
  def keepgoing() rand(2) == 0 end
  def doSomethingWeird() puts "zzzzz" end
  def weirdfunc
    puts "This is a weird loop"
    doSomethingWeird()
    while keepgoing
      puts "This is a weird loop"
      doSomethingWeird()
    end
  end
  def finefunc
    begin
      puts "This is a weird loop"
      doSomethingWeird()
    end while keepgoing
  end
end

# Here is the line you need to use Refax automatic refactoring system

require 'fixloops'

And here is the output

Suggest refactoring weirdfunc in HastilyWritten: [:block, [:args], [:while, [:vcall, :keepgoing], [:block, [:fcall, :puts, [:array, [:str, "This is a weird loop"]]], [:fcall, :doSomethingWeird]]]]
Thanks for the great work Ryan!

Read: Refax the Automatic Refactoring Engine

Topic: Dynamic VHosts One-liner for Rails Previous Topic   Next Topic Topic: If You Buy One Crossstitch This Year

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use