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,160 @@
1
+ class Node
2
+ # pre-YARV
3
+ class SCOPE
4
+ include MethodSig
5
+
6
+ def local_vars
7
+ return self.tbl || []
8
+ end
9
+
10
+ def argument_names
11
+ local_vars = self.local_vars
12
+ args = self.args_node
13
+ num_required_args = args.cnt
14
+ num_optional_args = 0
15
+ opt = args.opt
16
+ while opt do
17
+ num_optional_args += 1
18
+ opt = opt.next
19
+ end
20
+ num_args = \
21
+ num_required_args + \
22
+ num_optional_args + \
23
+ (rest_arg ? 1 : 0) + \
24
+ (block_arg ? 1 : 0)
25
+ return local_vars[0...num_args]
26
+ end
27
+
28
+ def args_node
29
+ if self.next.class == Node::ARGS then
30
+ return self.next
31
+ elsif self.next.head.class == Node::ARGS then
32
+ return self.next.head
33
+ else
34
+ raise "Could not find method arguments"
35
+ end
36
+ end
37
+
38
+ def rest_arg
39
+ args_node = args_node()
40
+ rest = args_node.rest()
41
+ if rest.class == Node::LASGN then
42
+ # subtract 2 to account for implicit vars
43
+ return rest.cnt - 2
44
+ elsif not rest
45
+ return nil
46
+ else
47
+ return rest > 0 ? rest - 2 : nil
48
+ end
49
+ end
50
+
51
+ def block_arg
52
+ block = self.next
53
+ if block.class == Node::BLOCK and
54
+ block.next.head.class == Node::BLOCK_ARG then
55
+ # subtract 2 to account for implicit vars
56
+ return block.next.head.cnt - 2
57
+ else
58
+ return nil
59
+ end
60
+ end
61
+
62
+ def set_optional_args(args, args_node, names)
63
+ opt = args_node.opt
64
+ while opt do
65
+ head = opt.head
66
+ if head.class == Node::LASGN then
67
+ args[head.vid] = NodeOptionalArgument.new(
68
+ head.vid, head.value.as_expression, head.value, false, false)
69
+ else
70
+ raise "Unexpected node type: #{opt.class}"
71
+ end
72
+ opt = opt.next
73
+ end
74
+ end
75
+ end
76
+
77
+ # Pre-YARV, I think
78
+ class BMETHOD
79
+ def local_vars
80
+ raise "TODO: Not implemented yet"
81
+ end
82
+
83
+ def argument_names
84
+ return self.cval.arguments.names
85
+ end
86
+
87
+ def arguments
88
+ return self.cval.arguments
89
+ end
90
+
91
+ def args_node
92
+ raise "TODO: Not implemented yet"
93
+ end
94
+
95
+ def rest_arg
96
+ raise "TODO: Not implemented yet"
97
+ end
98
+
99
+ def block_arg
100
+ raise "TODO: Not implemented yet"
101
+ end
102
+
103
+ def set_optional_args(args, args_node, names)
104
+ raise "TODO: Not implemented yet"
105
+ end
106
+ end
107
+
108
+ # YARV up to 1.9.1
109
+ class METHOD
110
+ include MethodSig
111
+
112
+ def local_vars
113
+ iseq = self.body
114
+ local_vars = iseq.local_table
115
+ return local_vars
116
+ end
117
+
118
+ def argument_names
119
+ local_vars = self.local_vars
120
+ iseq = self.body
121
+ opt_args = iseq.arg_opt_table
122
+ opt_args.pop # last arg is a pointer to the start of the code
123
+ num_args = \
124
+ iseq.argc + \
125
+ opt_args.size + \
126
+ (rest_arg ? 1 : 0) + \
127
+ (block_arg ? 1 : 0)
128
+ return local_vars[0...num_args]
129
+ end
130
+
131
+ def args_node
132
+ return nil
133
+ end
134
+
135
+ def rest_arg
136
+ arg_rest = self.body.arg_rest
137
+ return arg_rest >= 0 ? arg_rest : nil
138
+ end
139
+
140
+ def block_arg
141
+ arg_block = self.body.arg_block
142
+ return arg_block >= 0 ? arg_block : nil
143
+ end
144
+
145
+ def set_optional_args(args, args_node, names)
146
+ opt_table = self.body.arg_opt_table
147
+ opt_table.pop
148
+ first_opt_idx =
149
+ names.size -
150
+ opt_table.size -
151
+ (self.rest_arg ? 1 : 0) -
152
+ (self.block_arg ? 1 : 0)
153
+ opt_table.each_with_index do |pc, idx|
154
+ name = names[first_opt_idx + idx]
155
+ args[name] = YarvOptionalArgument.new(name, self.body, pc, idx, false, false)
156
+ end
157
+ end
158
+ end
159
+ end
160
+
@@ -0,0 +1,23 @@
1
+ module MethodSig
2
+ # An abstraction for a method signature.
3
+ class Signature
4
+ attr_reader :origin_class, :name, :arg_names, :args
5
+
6
+ def initialize(origin_class, name, arg_names, args)
7
+ @origin_class = origin_class
8
+ @name = name
9
+ @arg_names = arg_names
10
+ @args = args
11
+ end
12
+
13
+ def to_s
14
+ return "#{@origin_class}\##{@name}(#{param_list})"
15
+ end
16
+
17
+ def param_list
18
+ params = @arg_names.map{ |n| args[n].to_s }
19
+ return params.join(', ')
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,45 @@
1
+ require 'internal/node/as_code'
2
+ require 'internal/module'
3
+
4
+ class Module
5
+ # TODO: it would be nice if we could go back and find the AST
6
+ # for the class instead of recreating the code from the class's
7
+ # current state.
8
+ def as_code(indent=0)
9
+ imethods = self.instance_methods - self.superclass.instance_methods
10
+ cmethods = self.instance_methods - self.superclass.instance_methods
11
+ constants = self.constants - self.superclass.constants
12
+ name = self.name.gsub(/.*::/, '')
13
+
14
+ # TODO: included modules?
15
+ if self.class == Class then
16
+ s = "#{' '*indent}class #{name} < #{self.superclass}\n"
17
+ else
18
+ s = "#{' '*indent}module #{name}\n"
19
+ end
20
+
21
+ constants.each do |constant|
22
+ s += "#{' '*indent} #{constant}=#{self.const_get(constant).as_code}\n"
23
+ end
24
+
25
+ # TODO: protected/private
26
+ imethods.each do |method|
27
+ s += self.instance_method(method).as_code(indent+1)
28
+ s += "\n"
29
+ end
30
+
31
+ cmethods.each do |method|
32
+ s += self.instance_method(method).as_code(indent+1, "self.#{method}")
33
+ s += "\n"
34
+ end
35
+
36
+ # TODO: singleton class constants
37
+ # TODO: class variables
38
+ # TODO: singleton instance variables
39
+
40
+ s += "#{' '*indent}end"
41
+
42
+ return s
43
+ end
44
+ end
45
+
@@ -0,0 +1,233 @@
1
+ require 'internal/node'
2
+ require 'internal/node/as_expression'
3
+ require 'internal/object/as_code'
4
+ require 'rbconfig'
5
+
6
+ class Node
7
+ public
8
+
9
+ def as_code(indent=0, *args)
10
+ return as_code_impl(self, indent, *args)
11
+ end
12
+
13
+ private
14
+
15
+ def as_code_impl(node, indent, *args)
16
+ # default -- most code is just an expression
17
+ expression = node.as_expression(*args)
18
+ if not expression.nil? then
19
+ return "#{' '*indent}#{expression}"
20
+ else
21
+ return nil
22
+ end
23
+ end
24
+
25
+ class << self
26
+ def define_code(klass, &block)
27
+ if const_defined?(klass) then
28
+ const_get(klass).instance_eval { define_method(:as_code_impl, &block) }
29
+ end
30
+ end
31
+ end
32
+
33
+ define_code(:IF) do |node, indent|
34
+ if node.body.class == Node::BLOCK or
35
+ node.else.class == Node::BLOCK then
36
+ s = "#{' '*indent}if #{node.cond.as_expression} then\n"
37
+ s << "#{' '*indent}#{node.body.as_code(indent+1)}\n"
38
+ if node.else then
39
+ s << "#{' '*indent}else\n"
40
+ s << "#{' '*indent}#{node.else.as_code(indent+1)}\n"
41
+ end
42
+ s << "#{' '*indent}end"
43
+ s
44
+ else
45
+ "#{' '*indent}#{node.as_expression}"
46
+ end
47
+ end
48
+
49
+ define_code(:BLOCK) do |node, indent|
50
+ a = node.to_a
51
+ if a[0].class == Node::DASGN_CURR then
52
+ vardefs = a[0]
53
+ while vardefs.class == Node::DASGN_CURR do
54
+ vardefs = vardefs.value
55
+ end
56
+ if not vardefs then
57
+ # ignore variable definitions
58
+ a.shift
59
+ end
60
+ end
61
+ lines = a.map { |n| n.as_code(indent) }
62
+ lines.reject! { |e| e.nil? }
63
+ if lines.size == 0 then
64
+ "#{' '*indent}nil"
65
+ else
66
+ lines.join("\n")
67
+ end
68
+ end
69
+
70
+ define_code(:ITER) do |node, indent|
71
+ "#{' '*indent}#{node.iter.as_expression} {\n" +
72
+ "#{' '*indent}#{node.body.as_code(indent+1)}\n" +
73
+ "#{' '*indent}}"
74
+ end
75
+
76
+ define_code(:WHILE) do |node, indent|
77
+ if node.state == 1 then
78
+ "#{' '*indent}while #{node.cond.as_expression} do\n" +
79
+ "#{' '*indent}#{node.body.as_code(indent+1)}\n" +
80
+ "#{' '*indent}end"
81
+ else
82
+ "#{' '*indent}begin\n" +
83
+ "#{' '*indent}#{node.body.as_code(indent+1)}\n" +
84
+ "#{' '*indent}end while #{node.cond.as_expression}"
85
+ end
86
+ end
87
+
88
+ define_code(:UNTIL) do |node, indent|
89
+ if node.state == 1 then
90
+ "#{' '*indent}until #{node.cond.as_expression} do\n" +
91
+ "#{' '*indent}#{node.body.as_code(indent+1)}\n" +
92
+ "#{' '*indent}end"
93
+ else
94
+ "#{' '*indent}begin\n" +
95
+ "#{' '*indent}#{node.body.as_code(indent+1)}\n" +
96
+ "#{' '*indent}end until #{node.cond.as_expression}"
97
+ end
98
+ end
99
+
100
+ define_code(:BEGIN) do |node, indent|
101
+ if node.body.class == Node::RESCUE or
102
+ node.body.class == Node::ENSURE then
103
+ s = "#{' '*indent}begin\n" +
104
+ "#{node.body.as_code(indent+1, true)}\n" +
105
+ "#{' '*indent}end"
106
+ elsif node.body then
107
+ "#{' '*indent}begin\n" +
108
+ "#{' '*indent}#{node.body.as_code(indent+1)}\n" +
109
+ "#{' '*indent}end"
110
+ else
111
+ "#{' '*indent}begin\n" +
112
+ "#{' '*indent}end\n"
113
+ end
114
+ end
115
+
116
+ def self.begin_end(indent, have_begin)
117
+ s = ''
118
+ if not have_begin then
119
+ s << "#{' '*indent}begin\n"
120
+ indent += 1
121
+ end
122
+ yield s, indent, true
123
+ if not have_begin then
124
+ indent -= 1
125
+ s << "\n#{' '*indent}end"
126
+ end
127
+ return s
128
+ end
129
+
130
+ define_code(:ENSURE) do |node, indent, *args|
131
+ begin_ensure = args[0] || false
132
+ Node.begin_end(indent, begin_ensure) do |s, indent_, begin_ensure|
133
+ if node.head then
134
+ s << "#{node.head.as_code(indent_)}\n"
135
+ end
136
+ s << "#{' '*(indent_-1)}ensure\n"
137
+ s << "#{node.ensr.as_code(indent_)}"
138
+ end
139
+ end
140
+
141
+ define_code(:RESCUE) do |node, indent, *args|
142
+ begin_rescue = args[0] || false
143
+ Node.begin_end(indent, begin_rescue) do |s, indent_, begin_rescue|
144
+ if node.head then
145
+ if begin_rescue then
146
+ s << "#{node.head.as_code(indent_)}\n"
147
+ s << "#{' '*(indent_-1)}rescue #{node.resq.as_code(indent_+1, begin_rescue)}"
148
+ else
149
+ s << "#{node.head.as_expression} rescue #{node.resq.as_expression(begin_rescue)}"
150
+ end
151
+ else
152
+ s << "rescue #{node.resq.as_expression(begin_rescue)}"
153
+ end
154
+ end
155
+ end
156
+
157
+ define_code(:RESBODY) do |node, indent, *args|
158
+ begin_rescue = args[0] || false
159
+ if begin_rescue then
160
+ if node.args then
161
+ a = node.args.to_a.map { |n| n.as_expression }
162
+ "#{a.join(', ')}\n" +
163
+ "#{' '*indent}#{node.body.as_code(indent+1)}"
164
+ else
165
+ node.body ? "\n#{' '*indent}#{node.body.as_code(indent+1)}" : ''
166
+ end
167
+ else
168
+ # TODO: assuming node.args is false...
169
+ node.body ? node.body.as_code : ''
170
+ end
171
+ end
172
+
173
+ define_code(:NEWLINE) do |node, indent|
174
+ node.next.as_code(indent)
175
+ end
176
+
177
+ define_code(:CASE) do |node, indent|
178
+ "#{' '*indent}case #{node.head.as_expression}\n" +
179
+ "#{node.body.as_code(indent)}end"
180
+ end
181
+
182
+ define_code(:WHEN) do |node, indent|
183
+ args = node.head.to_a.map { |n| n.as_expression }
184
+ s = "#{' '*indent}when #{args.join(', ')}\n"
185
+ if node.body then
186
+ s << "#{' '*indent}#{node.body.as_code(indent+1)}; "
187
+ end
188
+ if node.next then
189
+ s << node.next.as_code
190
+ end
191
+ s
192
+ end
193
+
194
+ define_code(:CLASS) do |node, indent|
195
+ s_super = node.super ? " < #{node.super.as_expression}" : ''
196
+ if node.respond_to?(:cpath) then
197
+ path = node.cpath.as_expression
198
+ else
199
+ path = node.cname
200
+ end
201
+ "#{' '*indent}class #{path}#{s_super}\n" +
202
+ "#{' '*indent}#{node.body.as_code(indent+1)}\n" +
203
+ "#{' '*indent}end"
204
+ end
205
+
206
+ define_code(:SCLASS) do |node, indent|
207
+ "#{' '*indent}class << #{node.recv.as_expression}\n" +
208
+ "#{' '*indent}#{node.body.as_code(indent+1)}\n" +
209
+ "#{' '*indent}end"
210
+ end
211
+
212
+ define_code(:DEFN) do |node, indent|
213
+ # TODO: what to do about noex?
214
+ "#{' '*indent}def #{node.mid}\n" +
215
+ "#{' '*indent}#{node.next.as_code(indent+1)}\n" +
216
+ "#{' '*indent}end"
217
+ end
218
+
219
+ define_code(:DEFS) do |node, indent|
220
+ "#{' '*indent}def #{node.recv.as_expression}.#{node.mid}\n" +
221
+ "#{' '*indent}#{node.next.as_code(indent+1)}\n" +
222
+ "#{' '*indent}end"
223
+ end
224
+
225
+ define_code(:SCOPE) do |node, indent|
226
+ case node.next
227
+ when nil then ''
228
+ when Node::ARGS then "#{' '*indent}nil"
229
+ when Node::BLOCK_ARG then "#{' '*indent}nil"
230
+ else node.next.as_code(indent)
231
+ end
232
+ end
233
+ end