ruby-decompiler 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,619 @@
1
+ require 'internal/node'
2
+ require 'internal/node/to_a'
3
+ require 'rbconfig'
4
+
5
+ class Node
6
+ public
7
+
8
+ # Return an string describing this node as a single expression. By
9
+ # default, this just returns the name of the node's type, but some
10
+ # node types override this method to produce more meaningful output.
11
+ def as_expression(*args)
12
+ return as_expression_impl(self, *args)
13
+ end
14
+
15
+ # Return a string as with as_expression, but surround it with parens
16
+ # if it is a composite expression, so that it can be used to form more
17
+ # complex expressions.
18
+ def as_paren_expression(*args)
19
+ expr = self.as_expression(*args)
20
+ if not OMIT_PARENS[self.class] then
21
+ expr = "(#{expr})"
22
+ end
23
+ return expr
24
+ end
25
+
26
+ private
27
+
28
+ # default
29
+ def as_expression_impl(node)
30
+ return "<#{node.nd_type.to_s}>"
31
+ end
32
+
33
+ class << self
34
+ def define_expression(klass, &block)
35
+ if const_defined?(klass) then
36
+ const_get(klass).instance_eval { define_method(:as_expression_impl, &block) }
37
+ end
38
+ end
39
+ end
40
+
41
+ define_expression(:LIT) do |node|
42
+ # TODO: #inspect might not give an eval-able expression
43
+ node.lit.inspect
44
+ end
45
+
46
+ define_expression(:FCALL) do |node|
47
+ # args will either be an ARRAY or ARGSCAT
48
+ args = node.args
49
+ "#{node.mid}(#{args ? args.as_expression(false) : ''})"
50
+ end
51
+
52
+ define_expression(:VCALL) do |node|
53
+ node.mid.to_s
54
+ end
55
+
56
+ arithmetic_expressions = [
57
+ :+, :-, :*, :/, :<, :>, :<=, :>=, :==, :===, :<=>, :<<, :>>, :&, :|,
58
+ :^, :%, '!'.intern, '!='.intern
59
+ ]
60
+
61
+ # TODO: there should be a way to detect if the expressions need to be
62
+ # in parens
63
+ define_expression(:CALL) do |node|
64
+ recv_expr = node.recv.as_paren_expression
65
+
66
+ case node.mid
67
+ when *arithmetic_expressions
68
+ args = node.args
69
+ "#{recv_expr} #{node.mid} #{args ? args.as_paren_expression(false) : ''}"
70
+ when :[]
71
+ args = node.args
72
+ "#{recv_expr}[#{args ? args.as_expression(false) : ''}]"
73
+ else
74
+ args = node.args
75
+ "#{recv_expr}.#{node.mid}(#{args ? args.as_expression(false) : ''})"
76
+ end
77
+ end
78
+
79
+ define_expression(:ZSUPER) do |node|
80
+ "super"
81
+ end
82
+
83
+ define_expression(:SUPER) do |node|
84
+ "super(#{node.args ? node.args.as_expression(false) : ''})"
85
+ end
86
+
87
+ define_expression(:REDO) do |node|
88
+ "redo"
89
+ end
90
+
91
+ define_expression(:RETRY) do |node|
92
+ "retry"
93
+ end
94
+
95
+ define_expression(:NOT) do |node|
96
+ "not #{node.body.as_expression}"
97
+ end
98
+
99
+ define_expression(:AND) do |node|
100
+ "#{node.first.as_expression} and #{node.second.as_expression}"
101
+ end
102
+
103
+ define_expression(:OR) do |node|
104
+ "#{node.first.as_expression} or #{node.second.as_expression}"
105
+ end
106
+
107
+ class ARRAY < Node
108
+ def as_expression_impl(node, brackets = true)
109
+ s = brackets ? '[' : ''
110
+ s << (node.to_a.map { |n| n.as_expression }.join(', '))
111
+ s << (brackets ? ']' : '')
112
+ s
113
+ end
114
+ end
115
+
116
+ class ARGSCAT < Node
117
+ def as_expression_impl(node, brackets = true)
118
+ s = brackets ? '[' : ''
119
+ s << node.head.as_expression(false)
120
+ s << ", "
121
+ s << "*#{node.body.as_expression}"
122
+ s << (brackets ? ']' : '')
123
+ s
124
+ end
125
+ end
126
+
127
+ class ZARRAY < Node
128
+ def as_expression_impl(node, brackets = true)
129
+ brackets ? '[]' : ''
130
+ end
131
+ end
132
+
133
+ class BLOCK < Node
134
+ def as_expression_impl(node)
135
+ a = node.to_a
136
+ if a.size == 1 then
137
+ return 'nil'
138
+ end
139
+ d = a[0]
140
+ while d.class == Node::DASGN_CURR do
141
+ d = d.value
142
+ end
143
+ a.shift if not d
144
+ expressions = a.map { |n| n.as_expression }
145
+ expressions.reject! { |e| e.nil? }
146
+ if expressions.nitems == 0 then
147
+ return 'nil'
148
+ else
149
+ return expressions.join('; ')
150
+ end
151
+ end
152
+ end
153
+
154
+ define_expression(:HASH) do |node|
155
+ if not node.head then
156
+ "{}"
157
+ else
158
+ a = node.head.to_a
159
+ elems = []
160
+ i = 0
161
+ while i < a.size do
162
+ elems << "(#{a[i].as_expression})=>(#{a[i+1].as_expression})"
163
+ i += 2
164
+ end
165
+ "{#{elems.join(', ')}}"
166
+ end
167
+ end
168
+
169
+ define_expression(:IF) do |node|
170
+ if Node.const_defined?(:NEWLINE) then
171
+ bodynode = node.body.class == Node::NEWLINE ? node.body.next : node.body
172
+ elsenode = node.else.class == Node::NEWLINE ? node.else.next : node.else
173
+ else
174
+ bodynode = node.body
175
+ elsenode = node.else
176
+ end
177
+ if elsenode then
178
+ "#{node.cond.as_paren_expression} ? " +
179
+ "#{bodynode.as_paren_expression} : " +
180
+ "#{elsenode.as_paren_expression}"
181
+ else
182
+ "#{bodynode.as_paren_expression} if " +
183
+ "#{node.cond.as_paren_expression}"
184
+ end
185
+ end
186
+
187
+ define_expression(:TRUE) do |node|
188
+ "true"
189
+ end
190
+
191
+ define_expression(:FALSE) do |node|
192
+ "false"
193
+ end
194
+
195
+ define_expression(:NIL) do |node|
196
+ "nil"
197
+ end
198
+
199
+ define_expression(:SELF) do |node|
200
+ "self"
201
+ end
202
+
203
+ define_expression(:DOT2) do |node|
204
+ "#{node.beg.as_paren_expression}..#{node.end.as_paren_expression}"
205
+ end
206
+
207
+ define_expression(:DOT3) do |node|
208
+ "#{node.beg.as_paren_expression}...#{node.end.as_paren_expression}"
209
+ end
210
+
211
+ define_expression(:GVAR) do |node|
212
+ "#{node.vid}"
213
+ end
214
+
215
+ define_expression(:IVAR) do |node|
216
+ "#{node.vid}"
217
+ end
218
+
219
+ define_expression(:CVAR) do |node|
220
+ "#{node.vid}"
221
+ end
222
+
223
+ define_expression(:DVAR) do |node|
224
+ "#{node.vid}"
225
+ end
226
+
227
+ define_expression(:NTH_REF) do |node|
228
+ "$#{node.nth}"
229
+ end
230
+
231
+ define_expression(:BACK_REF) do |node|
232
+ "$`"
233
+ end
234
+
235
+ define_expression(:DASGN_CURR) do |node|
236
+ # node.value is unset for MASGN
237
+ node.value ? "#{node.vid} = #{node.value.as_expression}" : "#{node.vid}"
238
+ end
239
+
240
+ define_expression(:DASGN) do |node|
241
+ "#{node.vid} = #{node.value.as_expression}"
242
+ end
243
+
244
+ define_expression(:IASGN) do |node|
245
+ "#{node.vid} = #{node.value.as_expression}"
246
+ end
247
+
248
+ define_expression(:LASGN) do |node|
249
+ "#{node.vid} = #{node.value.as_expression}"
250
+ end
251
+
252
+ define_expression(:MASGN) do |node|
253
+ lhs = node.head.to_a.map { |n| n.as_expression }
254
+ rhs = node.value.to_a.map { |n| n.as_expression }
255
+ "#{lhs.join(', ')} = #{rhs.join(', ')}"
256
+ end
257
+
258
+ define_expression(:OP_ASGN1) do |node|
259
+ # TODO
260
+ raise "Not implemented"
261
+ end
262
+
263
+ define_expression(:OP_ASGN2) do |node|
264
+ recv = node.recv.as_expression
265
+ attr = node.next.vid # TODO: we assume it's the same as aid
266
+ op = case node.next.mid
267
+ when false then '||'
268
+ when nil then '&&'
269
+ else node.next.mid
270
+ end
271
+ value = node.value.as_expression
272
+ "#{recv}.#{attr} #{op}= #{value}"
273
+ end
274
+
275
+ define_expression(:CDECL) do |node|
276
+ "#{node.vid} = #{node.value.as_expression}"
277
+ end
278
+
279
+ define_expression(:CVDECL) do |node|
280
+ "#{node.vid} = #{node.value.as_expression}"
281
+ end
282
+
283
+ define_expression(:CVASGN) do |node|
284
+ "#{node.vid} = #{node.value.as_expression}"
285
+ end
286
+
287
+ define_expression(:ATTRASGN) do |node|
288
+ case node.mid
289
+ when :[]=
290
+ args = node.args.to_a
291
+ attrs = args[1..-2].map { |n| n.as_expression }
292
+ value = args[-1].as_expression
293
+ "#{node.recv.as_paren_expression}[#{attrs.join(', ')}] = #{value}"
294
+ else
295
+ "#{node.recv.as_paren_expression}.#{node.mid}#{node.args.as_expression(false)}"
296
+ end
297
+ end
298
+
299
+ define_expression(:CONST) do |node|
300
+ "#{node.vid}"
301
+ end
302
+
303
+ define_expression(:COLON2) do |node|
304
+ # TODO: shouldn't COLON2 have args if it's a method?
305
+ if node.head then
306
+ "#{node.head.as_expression}::#{node.mid}"
307
+ else
308
+ node.mid.to_s
309
+ end
310
+ end
311
+
312
+ define_expression(:COLON3) do |node|
313
+ "::#{node.mid}"
314
+ end
315
+
316
+ define_expression(:LVAR) do |node|
317
+ "#{node.vid}"
318
+ end
319
+
320
+ define_expression(:NEWLINE) do |node|
321
+ node.next.as_expression
322
+ end
323
+
324
+ define_expression(:STR) do |node|
325
+ "\"#{node.lit.inspect[1..-2]}\""
326
+ end
327
+
328
+ define_expression(:REGX) do |node|
329
+ # TODO: cflag
330
+ "/#{node.lit.inspect[1..-2]}/"
331
+ end
332
+
333
+ define_expression(:REGX_ONCE) do |node|
334
+ # TODO: cflag
335
+ "/#{node.lit.inspect[1..-2]}/o"
336
+ end
337
+
338
+ define_expression(:XSTR) do |node|
339
+ "`#{node.lit.inspect[1..-2]}`"
340
+ end
341
+
342
+ define_expression(:DSTR) do |node|
343
+ a = node.next.to_a
344
+ s = "\"#{node.lit.inspect[1..-2]}"
345
+ a.each do |elem|
346
+ case elem
347
+ when Node::STR then s += elem.lit
348
+ else s += elem.as_expression
349
+ end
350
+ end
351
+ s += "\""
352
+ s
353
+ end
354
+
355
+ define_expression(:DREGX) do |node|
356
+ a = node.next.to_a
357
+ s = "/#{node.lit.inspect[1..-2]}"
358
+ a.each do |elem|
359
+ case elem
360
+ when Node::STR then s += elem.lit
361
+ else s += elem.as_expression
362
+ end
363
+ end
364
+ s += "/"
365
+ # TODO: cflag
366
+ s
367
+ end
368
+
369
+ define_expression(:DREGX_ONCE) do |node|
370
+ a = node.next.to_a
371
+ s = "/#{node.lit.inspect[1..-2]}"
372
+ a.each do |elem|
373
+ case elem
374
+ when Node::STR then s += elem.lit
375
+ else s += elem.as_expression
376
+ end
377
+ end
378
+ s += "/o"
379
+ # TODO: cflag
380
+ s
381
+ end
382
+
383
+ define_expression(:DXSTR) do |node|
384
+ a = node.next.to_a
385
+ s = "`#{node.lit.inspect[1..-2]}"
386
+ a.each do |elem|
387
+ case elem
388
+ when Node::STR then s += elem.lit
389
+ else s += elem.as_expression
390
+ end
391
+ end
392
+ s += "`"
393
+ s
394
+ end
395
+
396
+ major = Config::CONFIG['MAJOR'].to_i
397
+ minor = Config::CONFIG['MINOR'].to_i
398
+ teeny = Config::CONFIG['TEENY'].to_i
399
+ ruby_version_code = major * 100 + minor * 10 + teeny
400
+
401
+ if ruby_version_code >= 180 then
402
+
403
+ define_expression(:EVSTR) do |node|
404
+ "\#\{#{node.body.as_expression}\}"
405
+ end
406
+
407
+ else
408
+
409
+ define_expression(:EVSTR) do |node|
410
+ "\#\{#{node.lit}\}"
411
+ end
412
+
413
+ end
414
+
415
+ define_expression(:ITER) do |node|
416
+ iter = node.iter.as_expression
417
+ body = node.body ? (node.body.as_expression + " ") : ""
418
+ "#{iter} { #{body} }"
419
+ end
420
+
421
+ define_expression(:WHILE) do |node|
422
+ if node.state == 1 then
423
+ "while #{node.cond.as_expression} do; #{node.body.as_expression}; end"
424
+ else
425
+ "begin; #{node.body.as_expression}; end while #{node.cond.as_expression}"
426
+ end
427
+ end
428
+
429
+ define_expression(:UNTIL) do |node|
430
+ if node.state == 1 then
431
+ "until #{node.cond.as_expression} do; #{node.body.as_expression}; end"
432
+ else
433
+ "begin; #{node.body.as_expression}; end until #{node.cond.as_expression}"
434
+ end
435
+ end
436
+
437
+ define_expression(:BREAK) do |node|
438
+ s = "break"
439
+ if node.stts then
440
+ s += " #{node.stts.as_expression}"
441
+ end
442
+ s
443
+ end
444
+
445
+ define_expression(:RETURN) do |node|
446
+ s = "return"
447
+ if node.stts then
448
+ s += " #{node.stts.as_expression}"
449
+ end
450
+ s
451
+ end
452
+
453
+ define_expression(:YIELD) do |node|
454
+ s = "yield"
455
+ if node.stts then
456
+ s += " #{node.stts.as_expression}"
457
+ end
458
+ s
459
+ end
460
+
461
+ define_expression(:BEGIN) do |node|
462
+ if node.body.class == Node::RESCUE or
463
+ node.body.class == Node::ENSURE then
464
+ "begin; #{node.body.as_expression(true)}; end"
465
+ elsif node.body then
466
+ "begin; #{node.body.as_expression}; end"
467
+ else
468
+ "begin; end"
469
+ end
470
+ end
471
+
472
+ define_expression(:ENSURE) do |node, *args|
473
+ begin_ensure = args[0] || false
474
+ if node.head then
475
+ if begin_ensure then
476
+ "#{node.head.as_expression} ensure #{node.ensr.as_expression}"
477
+ else
478
+ "begin; #{node.head.as_expression} ensure #{node.ensr.as_expression}; end"
479
+ end
480
+ else
481
+ if begin_ensure then
482
+ "ensure #{node.ensr.as_expression}"
483
+ else
484
+ "begin; ensure #{node.ensr.as_expression}; end"
485
+ end
486
+ end
487
+ end
488
+
489
+ define_expression(:RESCUE) do |node, *args|
490
+ begin_rescue = args[0] || false
491
+ if node.head then
492
+ if begin_rescue then
493
+ "#{node.head.as_expression}; rescue #{node.resq.as_expression(begin_rescue)}"
494
+ else
495
+ if not node.resq or not node.resq.body then
496
+ "begin; #{node.head.as_expression}; rescue; end"
497
+ else
498
+ "#{node.head.as_paren_expression} rescue #{node.resq.as_expression(begin_rescue)}"
499
+ end
500
+ end
501
+ else
502
+ if not node.resq or not node.resq.body then
503
+ "begin; rescue; end"
504
+ else
505
+ "rescue #{node.resq.as_expression(begin_rescue)}"
506
+ end
507
+ end
508
+ end
509
+
510
+ define_expression(:RESBODY) do |node, *args|
511
+ begin_rescue = args[0] || false
512
+ if begin_rescue then
513
+ if node.args then
514
+ a = node.args.to_a.map { |n| n.as_expression }
515
+ "#{a.join(', ')}; #{node.resq.as_expression}"
516
+ else
517
+ node.body ? "; #{node.body.as_expression}" : ''
518
+ end
519
+ else
520
+ # TODO: assuming node.args is false...
521
+ node.body ? node.body.as_expression : ''
522
+ end
523
+ end
524
+
525
+ define_expression(:CASE) do |node|
526
+ "case #{node.head.as_expression}; #{node.body.as_expression}end"
527
+ end
528
+
529
+ define_expression(:WHEN) do |node|
530
+ args = node.head.to_a.map { |n| n.as_expression }
531
+ s = ''
532
+ if node.body then
533
+ s = "when #{args.join(', ')} then #{node.body.as_expression}; "
534
+ else
535
+ s = "when #{args.join(', ')}; "
536
+ end
537
+ if node.next then
538
+ s += node.next.as_expression
539
+ end
540
+ s
541
+ end
542
+
543
+ define_expression(:ALIAS) do |node|
544
+ "alias #{node.new} #{node.old}"
545
+ end
546
+
547
+ define_expression(:VALIAS) do |node|
548
+ "alias #{node.new} #{node.old}"
549
+ end
550
+
551
+ define_expression(:UNDEF) do |node|
552
+ if defined? node.mid then
553
+ # < 1.8.5
554
+ "undef #{node.mid}"
555
+ else
556
+ # >= 1.8.5
557
+ "undef #{node.body.as_expression}"
558
+ end
559
+ end
560
+
561
+ define_expression(:CLASS) do |node|
562
+ s_super = node.super ? " < #{node.super.as_expression}" : ''
563
+ if node.respond_to?(:cpath) then
564
+ path = node.cpath.as_expression
565
+ else
566
+ path = node.cname
567
+ end
568
+ "class #{path}#{s_super}; #{node.body.as_expression}; end"
569
+ end
570
+
571
+ define_expression(:SCLASS) do |node|
572
+ "class << #{node.recv.as_expression}; #{node.body.as_expression}; end"
573
+ end
574
+
575
+ define_expression(:SCOPE) do |node|
576
+ case node.next
577
+ when nil then ''
578
+ when Node::ARGS then 'nil'
579
+ when Node::BLOCK_ARG then 'nil'
580
+ else node.next.as_expression
581
+ end
582
+ end
583
+
584
+ define_expression(:DEFN) do |node|
585
+ # TODO: what to do about noex?
586
+ "def #{node.mid}; #{node.next.as_expression}; end"
587
+ end
588
+
589
+ define_expression(:DEFS) do |node|
590
+ "def #{node.recv.as_expression}.#{node.mid}; #{node.next.as_expression}; end"
591
+ end
592
+
593
+ define_expression(:DEFINED) do |node|
594
+ "defined?(#{node.head.as_expression})"
595
+ end
596
+
597
+ define_expression(:ARGS) do |node|
598
+ nil
599
+ end
600
+
601
+ define_expression(:BLOCK_ARG) do |node|
602
+ nil
603
+ end
604
+
605
+ # TODO: MATCH3
606
+
607
+ OMIT_PARENS = {
608
+ LVAR => true,
609
+ GVAR => true,
610
+ IVAR => true,
611
+ CVAR => true,
612
+ DVAR => true,
613
+ LIT => true,
614
+ ARRAY => true,
615
+ ZARRAY => true,
616
+ HASH => true,
617
+ }
618
+ end
619
+