Module: UnifiedRuby

### Home Classes Methods

### In Files

- lib/unified_ruby.rb

### Methods

- #process
- #rewrite_argscat
- #rewrite_argspush
- #rewrite_attrasgn
- #rewrite_begin
- #rewrite_block_pass
- #rewrite_bmethod
- #rewrite_call
- #rewrite_dasgn
- #rewrite_dasgn_curr
- #rewrite_defn
- #rewrite_defs
- #rewrite_dmethod
- #rewrite_dvar
- #rewrite_fcall
- #rewrite_flip2
- #rewrite_flip3
- #rewrite_iter
- #rewrite_masgn
- #rewrite_op_asgn1
- #rewrite_resbody
- #rewrite_rescue
- #rewrite_splat
- #rewrite_super
- #rewrite_vcall
- #rewrite_yield
- #rewrite_zarray

### Files

- History.txt
- Manifest.txt
- README.txt

### Class/Module Index

Quicksearch

- Class
- ClassInclude
- Method
- Mod1
- Mod2
- Module
- ParseTree
- ParseTreeGauntlet
- ParseTreeTestCase
- PostUnifier
- PreUnifier
- Proc
- ProcStoreTmp
- R2RTestCase
- RawParseTree
- Something
- SomethingWithInitialize
- TestParseTree
- TestRawParseTree
- TestUnifier
- UnboundMethod
- UnifiedRuby
- Unifier

No matching classes.

# UnifiedRuby

### Public Instance Methods

process(exp) click to toggle source

    # File lib/unified_ruby.rb, line 7
    def process exp
      exp = Sexp.from_array exp unless Sexp === exp or exp.nil?
      super
    end

rewrite_argscat(exp) click to toggle source

    # File lib/unified_ruby.rb, line 12
    def rewrite_argscat exp
      _, ary, val = exp
      ary = s(:array, ary) unless ary.first == :array
      ary << s(:splat, val)
    end

rewrite_argspush(exp) click to toggle source

    # File lib/unified_ruby.rb, line 18
    def rewrite_argspush exp
      exp[0] = :arglist
      exp
    end

rewrite_attrasgn(exp) click to toggle source

    # File lib/unified_ruby.rb, line 23
    def rewrite_attrasgn(exp)
      last = exp.last

      if Sexp === last then
        last[0] = :arglist if last[0] == :array
      else
        exp << s(:arglist)
      end

      exp
    end

rewrite_begin(exp) click to toggle source

    # File lib/unified_ruby.rb, line 35
    def rewrite_begin(exp)
      raise "wtf: #{exp.inspect}" if exp.size > 2
      exp.last
    end

rewrite_block_pass(exp) click to toggle source

    # File lib/unified_ruby.rb, line 40
    def rewrite_block_pass exp
      case exp.size
      when 2 then
        _, block = exp
        case block.first
        when :lasgn then
          block[-1] = :"&#{block[-1]}"
          exp = block
        else
          raise "huh?: #{block.inspect}"
        end
      when 3 then
        _, block, recv = exp
        case recv.first
        when :super then
          recv << s(:block_pass, block)
          exp = recv
        when :call then
          recv.last << s(:block_pass, block)
          exp = recv
        when :masgn then
          block[-1] = :"&#{block[-1]}"
          recv.last << block
          exp = recv
        else
          raise "huh?: #{recv.inspect}"
        end
      end

      exp
    end

rewrite_bmethod(exp) click to toggle source

    # File lib/unified_ruby.rb, line 72
    def rewrite_bmethod(exp)
      _, args, body = exp

      args ||= s(:array)
      body ||= s(:block)

      args = s(:args, args) unless args[0] == :array

      args = args[1] if args[1] && args[1][0] == :masgn # TODO: clean up
      args = args[1] if args[1] && args[1][0] == :array
      args[0] = :args

      # this is ugly because rewriters are depth first.
      # TODO: maybe we could come up with some way to do both forms of rewriting.
      args.map! { |s|
        if Sexp === s
          case s[0]
          when :lasgn then
            s[1]
          when :splat then
            :"*#{s[1][1]}"
          else
            raise "huh?: #{s.inspect}"
          end
        else
          s
        end
      }

      body = s(:block, body) unless body[0] == :block
      body.insert 1, args

      s(:scope, body)
    end

rewrite_call(exp) click to toggle source

    # File lib/unified_ruby.rb, line 122
    def rewrite_call(exp)
      args = exp.last
      case args
      when nil
        exp.pop
      when Array
        case args.first
        when :array, :arglist then
          args[0] = :arglist
        when :argscat, :splat then
          exp[-1] = s(:arglist, args)
        else
          raise "unknown type in call #{args.first.inspect} in #{exp.inspect}"
        end
        return exp
      end

      exp << s(:arglist)

      exp
    end

rewrite_dasgn(exp) click to toggle source

    # File lib/unified_ruby.rb, line 144
    def rewrite_dasgn(exp)
      exp[0] = :lasgn
      exp
    end

Also aliased as: rewrite_dasgn_curr
rewrite_dasgn_curr(exp) click to toggle source
Alias for: rewrite_dasgn
rewrite_defn(exp) click to toggle source

:defn is one of the most complex of all the ASTs in ruby. We do one of 3 different translations:

1) From:

    s(:defn, :name, s(:scope, s(:block, s(:args, ...), ...)))
    s(:defn, :name, s(:bmethod, s(:masgn, s(:dasgn_curr, :args)), s(:block, ...)))
    s(:defn, :name, s(:fbody, s(:bmethod, s(:masgn, s(:dasgn_curr, :splat)), s(:block, ...))))

to:

    s(:defn, :name, s(:args, ...), s(:scope, s:(block, ...)))

2) From:

    s(:defn, :writer=, s(:attrset, :@name))

to:

    s(:defn, :writer=, s(:args), s(:attrset, :@name))

3) From:

    s(:defn, :reader, s(:ivar, :@name))

to:

    s(:defn, :reader, s(:args), s(:ivar, :@name))

    # File lib/unified_ruby.rb, line 182
    def rewrite_defn(exp)
      weirdo = exp.ivar || exp.attrset
      fbody  = exp.fbody(true)

      weirdo ||= fbody.cfunc if fbody

      exp.push(fbody.scope) if fbody unless weirdo

      args = exp.scope.block.args(true) unless weirdo if exp.scope
      exp.insert 2, args if args

      # move block_arg up and in
      block_arg = exp.scope.block.block_arg(true) rescue nil
      if block_arg
        block = args.block(true)
        args << :"&#{block_arg.last}"
        args << block if block
      end

      # patch up attr_accessor methods
      if weirdo then
        case
        when fbody && fbody.cfunc then
          exp.insert 2, s(:args, :"*args")
        when exp.ivar then
          exp.insert 2, s(:args)
        when exp.attrset then
          exp.insert 2, s(:args, :arg)
        else
          raise "unknown wierdo: #{wierdo.inpsect}"
        end
      end

      exp
    end

rewrite_defs(exp) click to toggle source

    # File lib/unified_ruby.rb, line 218
    def rewrite_defs(exp)
      receiver = exp.delete_at 1

      # TODO: I think this would be better as rewrite_scope, but that breaks others
      exp = s(exp.shift, exp.shift,
              s(:scope,
                s(:block, exp.scope.args))) if exp.scope && exp.scope.args

      result = rewrite_defn(exp)
      result.insert 1, receiver

      result
    end

rewrite_dmethod(exp) click to toggle source

    # File lib/unified_ruby.rb, line 232
    def rewrite_dmethod(exp)
      exp.shift # type
      exp.shift # dmethod name
      exp.shift # scope / block / body
    end

rewrite_dvar(exp) click to toggle source

    # File lib/unified_ruby.rb, line 238
    def rewrite_dvar(exp)
      exp[0] = :lvar
      exp
    end

rewrite_fcall(exp) click to toggle source

    # File lib/unified_ruby.rb, line 243
    def rewrite_fcall(exp)
      exp[0] = :call
      exp.insert 1, nil

      rewrite_call(exp)
    end

rewrite_flip2(exp) click to toggle source

    # File lib/unified_ruby.rb, line 250
    def rewrite_flip2(exp)
      # from:
      # s(:flip2,
      #   s(:call, s(:lit, 1), :==, s(:arglist, s(:gvar, :$.))),
      #   s(:call, s(:lit, 2), :a?, s(:arglist, s(:call, nil, :b, s(:arglist)))))
      # to:
      # s(:flip2,
      #   s(:lit, 1),
      #   s(:call, s(:lit, 2), :a?, s(:arglist, s(:call, nil, :b, s(:arglist)))))
      exp[1] = exp[1][1] if exp[1][0] == :call && exp[1][1][0] == :lit
      exp
    end

Also aliased as: rewrite_flip3
rewrite_flip3(exp) click to toggle source
Alias for: rewrite_flip2
rewrite_iter(exp) click to toggle source

    # File lib/unified_ruby.rb, line 107
    def rewrite_iter(exp)
      t, recv, args, body = exp

      # unwrap masgn args if there is only 1 thing to assign and it isn't splat
      if Sexp === args and args.sexp_type == :masgn and args.array.size == 2 then
        if args.array.last.sexp_type != :splat then
          args = args.array.last
        end
      end

      r = s(t, recv, args, body)
      r.delete_at 3 unless body # HACK omg this sucks
      r
    end

rewrite_masgn(exp) click to toggle source

    # File lib/unified_ruby.rb, line 265
    def rewrite_masgn(exp)
      t, lhs, lhs_splat, rhs = exp

      lhs ||= s(:array)

      if lhs_splat then
        case lhs_splat.first
        when :array then
          lhs_splat = lhs_splat.last if lhs_splat.last.first == :splat
        when :splat then
          # do nothing
        else
          lhs_splat = s(:splat, lhs_splat)
        end
        lhs << lhs_splat
      end

      # unwrap RHS from array IF it is only a splat node
      rhs = rhs.last if rhs && # TODO: rhs.structure =~ s(:array, s(:splat))
        rhs.size == 2 && rhs.structure.flatten.first(2) == [:array, :splat]

      s(t, lhs, rhs).compact
    end

rewrite_op_asgn1(exp) click to toggle source

    # File lib/unified_ruby.rb, line 289
    def rewrite_op_asgn1(exp)
      exp[2][0] = :arglist # if exp[2][0] == :array
      exp
    end

rewrite_resbody(exp) click to toggle source

    # File lib/unified_ruby.rb, line 294
    def rewrite_resbody(exp)
      exp[1] ||= s(:array)        # no args

      body = exp[2]
      if body then
        case body.first
        when :lasgn, :iasgn then
          exp[1] << exp.delete_at(2) if body[-1] == s(:gvar, :$!)
        when :block then
          exp[1] << body.delete_at(1) if [:lasgn, :iasgn].include?(body[1][0]) &&
            body[1][-1] == s(:gvar, :$!)
        end
      end

      exp << nil if exp.size == 2 # no body

      exp
    end

rewrite_rescue(exp) click to toggle source

    # File lib/unified_ruby.rb, line 313
    def rewrite_rescue(exp)
      # SKETCHY HACK return exp if exp.size > 4
      ignored = exp.shift
      body    = exp.shift unless exp.first.first == :resbody
      resbody = exp.shift
      els     = exp.shift unless exp.first.first == :resbody unless exp.empty?
      rest    = exp.empty? ? nil : exp # graceful re-rewriting (see rewrite_begin)

      resbodies = []

      unless rest then
        while resbody do
          resbodies << resbody
          resbody = resbody.resbody(true)
        end

        resbodies.each do |resbody|
          if resbody[2] && resbody[2][0] == :block && resbody[2].size == 2 then
            resbody[2] = resbody[2][-1]
          end
        end
      else
        resbodies = [resbody] + rest
      end

      resbodies << els if els

      s(:rescue, body, *resbodies).compact
    end

rewrite_splat(exp) click to toggle source

    # File lib/unified_ruby.rb, line 343
    def rewrite_splat(exp)
      good = [:arglist, :argspush, :array, :svalue, :yield, :super].include? context.first
      exp = s(:array, exp) unless good
      exp
    end

rewrite_super(exp) click to toggle source

    # File lib/unified_ruby.rb, line 349
    def rewrite_super(exp)
      return exp if exp.structure.flatten.first(3) == [:super, :array, :splat]
      exp.push(*exp.pop[1..-1]) if exp.size == 2 && exp.last.first == :array
      exp
    end

rewrite_vcall(exp) click to toggle source

    # File lib/unified_ruby.rb, line 355
    def rewrite_vcall(exp)
      exp.push nil
      rewrite_fcall(exp)
    end

rewrite_yield(exp) click to toggle source

    # File lib/unified_ruby.rb, line 360
    def rewrite_yield(exp)
      real_array = exp.pop if exp.size == 3

      if exp.size == 2 then
        if real_array then
          exp[-1] = s(:array, exp[-1]) if exp[-1][0] != :array
        else
          exp.push(*exp.pop[1..-1]) if exp.last.first == :array
        end
      end

      exp
    end

rewrite_zarray(exp) click to toggle source

    # File lib/unified_ruby.rb, line 374
    def rewrite_zarray(exp)
      exp[0] = :array
      exp
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.