UnifiedRuby

Public Instance Methods

process(exp) click to toggle source
    # File lib/unified_ruby.rb, line 7
 7:   def process exp
 8:     exp = Sexp.from_array exp unless Sexp === exp or exp.nil?
 9:     super
10:   end
rewrite_argscat(exp) click to toggle source
    # File lib/unified_ruby.rb, line 12
12:   def rewrite_argscat exp
13:     _, ary, val = exp
14:     ary = s(:array, ary) unless ary.first == :array
15:     ary << s(:splat, val)
16:   end
rewrite_argspush(exp) click to toggle source
    # File lib/unified_ruby.rb, line 18
18:   def rewrite_argspush exp
19:     exp[0] = :arglist
20:     exp
21:   end
rewrite_attrasgn(exp) click to toggle source
    # File lib/unified_ruby.rb, line 23
23:   def rewrite_attrasgn(exp)
24:     last = exp.last
25: 
26:     if Sexp === last then
27:       last[0] = :arglist if last[0] == :array
28:     else
29:       exp << s(:arglist)
30:     end
31: 
32:     exp
33:   end
rewrite_begin(exp) click to toggle source
    # File lib/unified_ruby.rb, line 35
35:   def rewrite_begin(exp)
36:     raise "wtf: #{exp.inspect}" if exp.size > 2
37:     exp.last
38:   end
rewrite_block_pass(exp) click to toggle source
    # File lib/unified_ruby.rb, line 40
40:   def rewrite_block_pass exp
41:     case exp.size
42:     when 2 then
43:       _, block = exp
44:       case block.first
45:       when :lasgn then
46:         block[1] = :"&#{block[-1]}"
47:         exp = block
48:       else
49:         raise "huh?: #{block.inspect}"
50:       end
51:     when 3 then
52:       _, block, recv = exp
53:       case recv.first
54:       when :super then
55:         recv << s(:block_pass, block)
56:         exp = recv
57:       when :call then
58:         recv.last << s(:block_pass, block)
59:         exp = recv
60:       when :masgn then
61:         block[1] = :"&#{block[-1]}"
62:         recv.last << block
63:         exp = recv
64:       else
65:         raise "huh?: #{recv.inspect}"
66:       end
67:     end
68: 
69:     exp
70:   end
rewrite_bmethod(exp) click to toggle source
     # File lib/unified_ruby.rb, line 72
 72:   def rewrite_bmethod(exp)
 73:     _, args, body = exp
 74: 
 75:     args ||= s(:array)
 76:     body ||= s(:block)
 77: 
 78:     args = s(:args, args) unless args[0] == :array
 79: 
 80:     args = args[1] if args[1] && args[1][0] == :masgn # TODO: clean up
 81:     args = args[1] if args[1] && args[1][0] == :array
 82:     args[0] = :args
 83: 
 84:     # this is ugly because rewriters are depth first.
 85:     # TODO: maybe we could come up with some way to do both forms of rewriting.
 86:     args.map! { |s|
 87:       if Sexp === s
 88:         case s[0]
 89:         when :lasgn then
 90:           s[1]
 91:         when :splat then
 92:           :"*#{s[1][1]}"
 93:         else
 94:           raise "huh?: #{s.inspect}"
 95:         end
 96:       else
 97:         s
 98:       end
 99:     }
100: 
101:     body = s(:block, body) unless body[0] == :block
102:     body.insert 1, args
103: 
104:     s(:scope, body)
105:   end
rewrite_call(exp) click to toggle source
     # File lib/unified_ruby.rb, line 122
122:   def rewrite_call(exp)
123:     args = exp.last
124:     case args
125:     when nil
126:       exp.pop
127:     when Array
128:       case args.first
129:       when :array, :arglist then
130:         args[0] = :arglist
131:       when :argscat, :splat then
132:         exp[1] = s(:arglist, args)
133:       else
134:         raise "unknown type in call #{args.first.inspect} in #{exp.inspect}"
135:       end
136:       return exp
137:     end
138: 
139:     exp << s(:arglist)
140: 
141:     exp
142:   end
rewrite_dasgn(exp) click to toggle source
     # File lib/unified_ruby.rb, line 144
144:   def rewrite_dasgn(exp)
145:     exp[0] = :lasgn
146:     exp
147:   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
182:   def rewrite_defn(exp)
183:     weirdo = exp.ivar || exp.attrset
184:     fbody  = exp.fbody(true)
185: 
186:     weirdo ||= fbody.cfunc if fbody
187: 
188:     exp.push(fbody.scope) if fbody unless weirdo
189: 
190:     args = exp.scope.block.args(true) unless weirdo if exp.scope
191:     exp.insert 2, args if args
192: 
193:     # move block_arg up and in
194:     block_arg = exp.scope.block.block_arg(true) rescue nil
195:     if block_arg
196:       block = args.block(true)
197:       args << :"&#{block_arg.last}"
198:       args << block if block
199:     end
200: 
201:     # patch up attr_accessor methods
202:     if weirdo then
203:       case
204:       when fbody && fbody.cfunc then
205:         exp.insert 2, s(:args, :"*args")
206:       when exp.ivar then
207:         exp.insert 2, s(:args)
208:       when exp.attrset then
209:         exp.insert 2, s(:args, :arg)
210:       else
211:         raise "unknown wierdo: #{wierdo.inpsect}"
212:       end
213:     end
214: 
215:     exp
216:   end
rewrite_defs(exp) click to toggle source
     # File lib/unified_ruby.rb, line 218
218:   def rewrite_defs(exp)
219:     receiver = exp.delete_at 1
220: 
221:     # TODO: I think this would be better as rewrite_scope, but that breaks others
222:     exp = s(exp.shift, exp.shift,
223:             s(:scope,
224:               s(:block, exp.scope.args))) if exp.scope && exp.scope.args
225: 
226:     result = rewrite_defn(exp)
227:     result.insert 1, receiver
228: 
229:     result
230:   end
rewrite_dmethod(exp) click to toggle source
     # File lib/unified_ruby.rb, line 232
232:   def rewrite_dmethod(exp)
233:     exp.shift # type
234:     exp.shift # dmethod name
235:     exp.shift # scope / block / body
236:   end
rewrite_dvar(exp) click to toggle source
     # File lib/unified_ruby.rb, line 238
238:   def rewrite_dvar(exp)
239:     exp[0] = :lvar
240:     exp
241:   end
rewrite_fcall(exp) click to toggle source
     # File lib/unified_ruby.rb, line 243
243:   def rewrite_fcall(exp)
244:     exp[0] = :call
245:     exp.insert 1, nil
246: 
247:     rewrite_call(exp)
248:   end
rewrite_flip2(exp) click to toggle source
     # File lib/unified_ruby.rb, line 250
250:   def rewrite_flip2(exp)
251:     # from:
252:     # s(:flip2,
253:     #   s(:call, s(:lit, 1), :==, s(:arglist, s(:gvar, :$.))),
254:     #   s(:call, s(:lit, 2), :a?, s(:arglist, s(:call, nil, :b, s(:arglist)))))
255:     # to:
256:     # s(:flip2,
257:     #   s(:lit, 1),
258:     #   s(:call, s(:lit, 2), :a?, s(:arglist, s(:call, nil, :b, s(:arglist)))))
259:     exp[1] = exp[1][1] if exp[1][0] == :call && exp[1][1][0] == :lit
260:     exp
261:   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
107:   def rewrite_iter(exp)
108:     t, recv, args, body = exp
109: 
110:     # unwrap masgn args if there is only 1 thing to assign and it isn't splat
111:     if Sexp === args and args.sexp_type == :masgn and args.array.size == 2 then
112:       if args.array.last.sexp_type != :splat then
113:         args = args.array.last
114:       end
115:     end
116: 
117:     r = s(t, recv, args, body)
118:     r.delete_at 3 unless body # HACK omg this sucks
119:     r
120:   end
rewrite_masgn(exp) click to toggle source
     # File lib/unified_ruby.rb, line 265
265:   def rewrite_masgn(exp)
266:     t, lhs, lhs_splat, rhs = exp
267: 
268:     lhs ||= s(:array)
269: 
270:     if lhs_splat then
271:       case lhs_splat.first
272:       when :array then
273:         lhs_splat = lhs_splat.last if lhs_splat.last.first == :splat
274:       when :splat then
275:         # do nothing
276:       else
277:         lhs_splat = s(:splat, lhs_splat)
278:       end
279:       lhs << lhs_splat
280:     end
281: 
282:     # unwrap RHS from array IF it is only a splat node
283:     rhs = rhs.last if rhs && # TODO: rhs.structure =~ s(:array, s(:splat))
284:       rhs.size == 2 && rhs.structure.flatten.first(2) == [:array, :splat]
285: 
286:     s(t, lhs, rhs).compact
287:   end
rewrite_op_asgn1(exp) click to toggle source
     # File lib/unified_ruby.rb, line 289
289:   def rewrite_op_asgn1(exp)
290:     exp[2][0] = :arglist # if exp[2][0] == :array
291:     exp
292:   end
rewrite_resbody(exp) click to toggle source
     # File lib/unified_ruby.rb, line 294
294:   def rewrite_resbody(exp)
295:     exp[1] ||= s(:array)        # no args
296: 
297:     body = exp[2]
298:     if body then
299:       case body.first
300:       when :lasgn, :iasgn then
301:         exp[1] << exp.delete_at(2) if body[1] == s(:gvar, :$!)
302:       when :block then
303:         exp[1] << body.delete_at(1) if [:lasgn, :iasgn].include?(body[1][0]) &&
304:           body[1][1] == s(:gvar, :$!)
305:       end
306:     end
307: 
308:     exp << nil if exp.size == 2 # no body
309: 
310:     exp
311:   end
rewrite_rescue(exp) click to toggle source
     # File lib/unified_ruby.rb, line 313
313:   def rewrite_rescue(exp)
314:     # SKETCHY HACK return exp if exp.size > 4
315:     ignored = exp.shift
316:     body    = exp.shift unless exp.first.first == :resbody
317:     resbody = exp.shift
318:     els     = exp.shift unless exp.first.first == :resbody unless exp.empty?
319:     rest    = exp.empty? ? nil : exp # graceful re-rewriting (see rewrite_begin)
320: 
321:     resbodies = []
322: 
323:     unless rest then
324:       while resbody do
325:         resbodies << resbody
326:         resbody = resbody.resbody(true)
327:       end
328: 
329:       resbodies.each do |resbody|
330:         if resbody[2] && resbody[2][0] == :block && resbody[2].size == 2 then
331:           resbody[2] = resbody[2][1]
332:         end
333:       end
334:     else
335:       resbodies = [resbody] + rest
336:     end
337: 
338:     resbodies << els if els
339: 
340:     s(:rescue, body, *resbodies).compact
341:   end
rewrite_splat(exp) click to toggle source
     # File lib/unified_ruby.rb, line 343
343:   def rewrite_splat(exp)
344:     good = [:arglist, :argspush, :array, :svalue, :yield, :super].include? context.first
345:     exp = s(:array, exp) unless good
346:     exp
347:   end
rewrite_super(exp) click to toggle source
     # File lib/unified_ruby.rb, line 349
349:   def rewrite_super(exp)
350:     return exp if exp.structure.flatten.first(3) == [:super, :array, :splat]
351:     exp.push(*exp.pop[1..1]) if exp.size == 2 && exp.last.first == :array
352:     exp
353:   end
rewrite_vcall(exp) click to toggle source
     # File lib/unified_ruby.rb, line 355
355:   def rewrite_vcall(exp)
356:     exp.push nil
357:     rewrite_fcall(exp)
358:   end
rewrite_yield(exp) click to toggle source
     # File lib/unified_ruby.rb, line 360
360:   def rewrite_yield(exp)
361:     real_array = exp.pop if exp.size == 3
362: 
363:     if exp.size == 2 then
364:       if real_array then
365:         exp[1] = s(:array, exp[1]) if exp[1][0] != :array
366:       else
367:         exp.push(*exp.pop[1..1]) if exp.last.first == :array
368:       end
369:     end
370: 
371:     exp
372:   end
rewrite_zarray(exp) click to toggle source
     # File lib/unified_ruby.rb, line 374
374:   def rewrite_zarray(exp)
375:     exp[0] = :array
376:     exp
377:   end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.