sexp2ruby 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rspec +3 -0
- data/.travis.yml +1 -2
- data/README.md +9 -0
- data/lib/{sexp2ruby/core_extensions → core_extensions}/regexp.rb +0 -0
- data/lib/sexp2ruby/node/alias.rb +9 -0
- data/lib/sexp2ruby/node/and.rb +9 -0
- data/lib/sexp2ruby/node/arglist.rb +16 -0
- data/lib/sexp2ruby/node/args.rb +33 -0
- data/lib/sexp2ruby/node/array.rb +9 -0
- data/lib/sexp2ruby/node/attrasgn.rb +27 -0
- data/lib/sexp2ruby/node/back_ref.rb +9 -0
- data/lib/sexp2ruby/node/base.rb +36 -0
- data/lib/sexp2ruby/node/begin.rb +19 -0
- data/lib/sexp2ruby/node/block.rb +24 -0
- data/lib/sexp2ruby/node/block_pass.rb +10 -0
- data/lib/sexp2ruby/node/break.rb +14 -0
- data/lib/sexp2ruby/node/call.rb +70 -0
- data/lib/sexp2ruby/node/case.rb +27 -0
- data/lib/sexp2ruby/node/cdecl.rb +17 -0
- data/lib/sexp2ruby/node/class.rb +9 -0
- data/lib/sexp2ruby/node/colon2.rb +9 -0
- data/lib/sexp2ruby/node/colon3.rb +9 -0
- data/lib/sexp2ruby/node/const.rb +9 -0
- data/lib/sexp2ruby/node/cvar.rb +9 -0
- data/lib/sexp2ruby/node/cvasgn.rb +9 -0
- data/lib/sexp2ruby/node/cvdecl.rb +9 -0
- data/lib/sexp2ruby/node/defined.rb +9 -0
- data/lib/sexp2ruby/node/defn.rb +66 -0
- data/lib/sexp2ruby/node/defs.rb +17 -0
- data/lib/sexp2ruby/node/dot2.rb +9 -0
- data/lib/sexp2ruby/node/dot3.rb +9 -0
- data/lib/sexp2ruby/node/dregx.rb +19 -0
- data/lib/sexp2ruby/node/dregx_once.rb +9 -0
- data/lib/sexp2ruby/node/dstr.rb +9 -0
- data/lib/sexp2ruby/node/dsym.rb +9 -0
- data/lib/sexp2ruby/node/dxstr.rb +9 -0
- data/lib/sexp2ruby/node/ensure.rb +18 -0
- data/lib/sexp2ruby/node/evstr.rb +9 -0
- data/lib/sexp2ruby/node/false.rb +9 -0
- data/lib/sexp2ruby/node/flip2.rb +9 -0
- data/lib/sexp2ruby/node/flip3.rb +9 -0
- data/lib/sexp2ruby/node/for.rb +17 -0
- data/lib/sexp2ruby/node/gasgn.rb +9 -0
- data/lib/sexp2ruby/node/gvar.rb +9 -0
- data/lib/sexp2ruby/node/hash.rb +53 -0
- data/lib/sexp2ruby/node/iasgn.rb +14 -0
- data/lib/sexp2ruby/node/if.rb +41 -0
- data/lib/sexp2ruby/node/iter.rb +50 -0
- data/lib/sexp2ruby/node/ivar.rb +9 -0
- data/lib/sexp2ruby/node/kwsplat.rb +9 -0
- data/lib/sexp2ruby/node/lasgn.rb +11 -0
- data/lib/sexp2ruby/node/lit.rb +15 -0
- data/lib/sexp2ruby/node/lvar.rb +9 -0
- data/lib/sexp2ruby/node/masgn.rb +46 -0
- data/lib/sexp2ruby/node/match.rb +9 -0
- data/lib/sexp2ruby/node/match2.rb +11 -0
- data/lib/sexp2ruby/node/match3.rb +17 -0
- data/lib/sexp2ruby/node/module.rb +9 -0
- data/lib/sexp2ruby/node/next.rb +14 -0
- data/lib/sexp2ruby/node/nil.rb +9 -0
- data/lib/sexp2ruby/node/not.rb +9 -0
- data/lib/sexp2ruby/node/nth_ref.rb +9 -0
- data/lib/sexp2ruby/node/op_asgn1.rb +16 -0
- data/lib/sexp2ruby/node/op_asgn2.rb +17 -0
- data/lib/sexp2ruby/node/op_asgn_and.rb +13 -0
- data/lib/sexp2ruby/node/op_asgn_or.rb +13 -0
- data/lib/sexp2ruby/node/or.rb +9 -0
- data/lib/sexp2ruby/node/postexe.rb +9 -0
- data/lib/sexp2ruby/node/redo.rb +9 -0
- data/lib/sexp2ruby/node/resbody.rb +19 -0
- data/lib/sexp2ruby/node/rescue.rb +32 -0
- data/lib/sexp2ruby/node/retry.rb +9 -0
- data/lib/sexp2ruby/node/return.rb +13 -0
- data/lib/sexp2ruby/node/sclass.rb +9 -0
- data/lib/sexp2ruby/node/self.rb +9 -0
- data/lib/sexp2ruby/node/splat.rb +13 -0
- data/lib/sexp2ruby/node/str.rb +9 -0
- data/lib/sexp2ruby/node/super.rb +10 -0
- data/lib/sexp2ruby/node/svalue.rb +13 -0
- data/lib/sexp2ruby/node/to_ary.rb +9 -0
- data/lib/sexp2ruby/node/true.rb +9 -0
- data/lib/sexp2ruby/node/undef.rb +9 -0
- data/lib/sexp2ruby/node/until.rb +9 -0
- data/lib/sexp2ruby/node/valias.rb +9 -0
- data/lib/sexp2ruby/node/when.rb +24 -0
- data/lib/sexp2ruby/node/while.rb +9 -0
- data/lib/sexp2ruby/node/xstr.rb +9 -0
- data/lib/sexp2ruby/node/yield.rb +18 -0
- data/lib/sexp2ruby/node/zsuper.rb +9 -0
- data/lib/sexp2ruby/processor.rb +121 -912
- data/lib/sexp2ruby/version.rb +1 -1
- data/lib/sexp2ruby.rb +88 -1
- data/sexp2ruby.gemspec +1 -0
- data/spec/lib/processor_spec.rb +478 -1
- metadata +104 -8
- data/Rakefile +0 -92
- data/test/test_ruby2ruby.rb +0 -496
data/lib/sexp2ruby/processor.rb
CHANGED
|
@@ -4,14 +4,8 @@ module Sexp2Ruby
|
|
|
4
4
|
|
|
5
5
|
# Generate ruby code from a sexp.
|
|
6
6
|
class Processor < SexpProcessor
|
|
7
|
+
LF = "\n"
|
|
7
8
|
|
|
8
|
-
# cutoff for one-liners
|
|
9
|
-
LINE_LENGTH = 78
|
|
10
|
-
|
|
11
|
-
# binary operation messages
|
|
12
|
-
BINARY = [:<=>, :==, :<, :>, :<=, :>=, :-, :+, :*, :/, :%, :<<, :>>, :**, :'!=']
|
|
13
|
-
|
|
14
|
-
##
|
|
15
9
|
# Nodes that represent assignment and probably need () around them.
|
|
16
10
|
#
|
|
17
11
|
# TODO: this should be replaced with full precedence support :/
|
|
@@ -32,32 +26,100 @@ module Sexp2Ruby
|
|
|
32
26
|
:rescue,
|
|
33
27
|
]
|
|
34
28
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
#
|
|
40
|
-
# { :foo => (bar("baz")) } # The outer parens are unnecessary
|
|
41
|
-
# { :foo => bar("baz") } # This is the normal code style
|
|
29
|
+
HASH_SYNTAXES = [:ruby18, :ruby19]
|
|
30
|
+
RUBY_19_HASH_KEY = /\A[a-z][_a-zA-Z0-9]+\Z/
|
|
31
|
+
|
|
32
|
+
CONSTRUCTOR_OPTIONS = [:hash_syntax]
|
|
42
33
|
|
|
43
|
-
|
|
34
|
+
NODES = [
|
|
35
|
+
:alias,
|
|
36
|
+
:and,
|
|
37
|
+
:arglist,
|
|
38
|
+
:args,
|
|
39
|
+
:array,
|
|
40
|
+
:attrasgn,
|
|
41
|
+
:back_ref,
|
|
42
|
+
:begin,
|
|
43
|
+
:block,
|
|
44
|
+
:block_pass,
|
|
45
|
+
:break,
|
|
44
46
|
:call,
|
|
47
|
+
:case,
|
|
48
|
+
:cdecl,
|
|
49
|
+
:class,
|
|
50
|
+
:colon2,
|
|
51
|
+
:colon3,
|
|
52
|
+
:const,
|
|
53
|
+
:cvar,
|
|
54
|
+
:cvasgn,
|
|
55
|
+
:cvdecl,
|
|
56
|
+
:defined,
|
|
57
|
+
:defn,
|
|
58
|
+
:defs,
|
|
59
|
+
:dot2,
|
|
60
|
+
:dot3,
|
|
61
|
+
:dregx,
|
|
62
|
+
:dregx_once,
|
|
63
|
+
:dstr,
|
|
64
|
+
:dsym,
|
|
65
|
+
:dxstr,
|
|
66
|
+
:ensure,
|
|
67
|
+
:evstr,
|
|
45
68
|
:false,
|
|
69
|
+
:flip2,
|
|
70
|
+
:flip3,
|
|
71
|
+
:for,
|
|
72
|
+
:gasgn,
|
|
73
|
+
:gvar,
|
|
74
|
+
:hash,
|
|
75
|
+
:iasgn,
|
|
76
|
+
:if,
|
|
77
|
+
:iter,
|
|
78
|
+
:ivar,
|
|
79
|
+
:kwsplat,
|
|
80
|
+
:lasgn,
|
|
46
81
|
:lit,
|
|
47
82
|
:lvar,
|
|
83
|
+
:masgn,
|
|
84
|
+
:match,
|
|
85
|
+
:match2,
|
|
86
|
+
:match3,
|
|
87
|
+
:module,
|
|
88
|
+
:next,
|
|
48
89
|
:nil,
|
|
90
|
+
:not,
|
|
91
|
+
:nth_ref,
|
|
92
|
+
:op_asgn1,
|
|
93
|
+
:op_asgn2,
|
|
94
|
+
:op_asgn_and,
|
|
95
|
+
:op_asgn_or,
|
|
96
|
+
:or,
|
|
97
|
+
:postexe,
|
|
98
|
+
:redo,
|
|
99
|
+
:resbody,
|
|
100
|
+
:rescue,
|
|
101
|
+
:retry,
|
|
102
|
+
:return,
|
|
103
|
+
:sclass,
|
|
104
|
+
:self,
|
|
105
|
+
:splat,
|
|
49
106
|
:str,
|
|
50
|
-
:
|
|
107
|
+
:super,
|
|
108
|
+
:svalue,
|
|
109
|
+
:to_ary,
|
|
110
|
+
:true,
|
|
111
|
+
:undef,
|
|
112
|
+
:until,
|
|
113
|
+
:valias,
|
|
114
|
+
:when,
|
|
115
|
+
:while,
|
|
116
|
+
:xstr,
|
|
117
|
+
:yield,
|
|
118
|
+
:zsuper
|
|
51
119
|
]
|
|
52
120
|
|
|
53
|
-
|
|
54
|
-
RUBY_19_HASH_KEY = /\A[a-z][_a-zA-Z0-9]+\Z/
|
|
55
|
-
|
|
56
|
-
CONSTRUCTOR_OPTIONS = [:hash_syntax]
|
|
57
|
-
|
|
58
|
-
attr_reader :hash_syntax
|
|
121
|
+
attr_reader :hash_syntax, :indent_lvl
|
|
59
122
|
|
|
60
|
-
##
|
|
61
123
|
# Options:
|
|
62
124
|
#
|
|
63
125
|
# - `:hash_syntax` - either `:ruby18` or `:ruby19`
|
|
@@ -66,864 +128,44 @@ module Sexp2Ruby
|
|
|
66
128
|
super()
|
|
67
129
|
check_option_keys(option)
|
|
68
130
|
@hash_syntax = extract_option(HASH_SYNTAXES, option[:hash_syntax], :ruby18)
|
|
69
|
-
@
|
|
131
|
+
@indent_lvl = " "
|
|
70
132
|
self.auto_shift_type = true
|
|
71
133
|
self.strict = true
|
|
72
134
|
self.expected = String
|
|
73
|
-
|
|
74
135
|
@calls = []
|
|
75
|
-
|
|
76
|
-
# self.debug[:defn] = /zsuper/
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
############################################################
|
|
80
|
-
# Processors
|
|
81
|
-
|
|
82
|
-
def process_alias(exp) # :nodoc:
|
|
83
|
-
parenthesize "alias #{process(exp.shift)} #{process(exp.shift)}"
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def process_and(exp) # :nodoc:
|
|
87
|
-
parenthesize "#{process exp.shift} and #{process exp.shift}"
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def process_arglist(exp) # custom made node # :nodoc:
|
|
91
|
-
code = []
|
|
92
|
-
until exp.empty? do
|
|
93
|
-
arg = exp.shift
|
|
94
|
-
to_wrap = arg.first == :rescue
|
|
95
|
-
arg_code = process arg
|
|
96
|
-
code << (to_wrap ? "(#{arg_code})" : arg_code)
|
|
97
|
-
end
|
|
98
|
-
code.join ', '
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def process_args(exp) # :nodoc:
|
|
102
|
-
args = []
|
|
103
|
-
|
|
104
|
-
until exp.empty? do
|
|
105
|
-
arg = exp.shift
|
|
106
|
-
case arg
|
|
107
|
-
when Symbol then
|
|
108
|
-
args << arg
|
|
109
|
-
when Sexp then
|
|
110
|
-
case arg.first
|
|
111
|
-
when :lasgn then
|
|
112
|
-
args << process(arg)
|
|
113
|
-
when :masgn then
|
|
114
|
-
args << process(arg)
|
|
115
|
-
when :kwarg then
|
|
116
|
-
_, k, v = arg
|
|
117
|
-
args << "#{k}: #{process v}"
|
|
118
|
-
else
|
|
119
|
-
raise "unknown arg type #{arg.first.inspect}"
|
|
120
|
-
end
|
|
121
|
-
else
|
|
122
|
-
raise "unknown arg type #{arg.inspect}"
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
"(#{args.join ', '})"
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def process_array(exp) # :nodoc:
|
|
130
|
-
"[#{process_arglist(exp)}]"
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
def process_attrasgn(exp) # :nodoc:
|
|
134
|
-
receiver = process exp.shift
|
|
135
|
-
name = exp.shift
|
|
136
|
-
rhs = exp.pop
|
|
137
|
-
args = s(:array, *exp)
|
|
138
|
-
exp.clear
|
|
139
|
-
|
|
140
|
-
case name
|
|
141
|
-
when :[]= then
|
|
142
|
-
args = process args
|
|
143
|
-
"#{receiver}#{args} = #{process rhs}"
|
|
144
|
-
else
|
|
145
|
-
raise "dunno what to do: #{args.inspect}" unless args.size == 1 # s(:array)
|
|
146
|
-
name = name.to_s.sub(/=$/, '')
|
|
147
|
-
if rhs && rhs != s(:arglist) then
|
|
148
|
-
"#{receiver}.#{name} = #{process(rhs)}"
|
|
149
|
-
else
|
|
150
|
-
raise "dunno what to do: #{rhs.inspect}"
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
136
|
end
|
|
154
137
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
#
|
|
160
|
-
def process_begin(exp) # :nodoc:
|
|
161
|
-
code = []
|
|
162
|
-
code << "begin"
|
|
163
|
-
until exp.empty?
|
|
164
|
-
src = process(exp.shift)
|
|
165
|
-
src = indent(src) unless src =~ /(^|\n)(rescue|ensure)/ # ensure no level 0 rescues
|
|
166
|
-
code << src
|
|
167
|
-
end
|
|
168
|
-
code << "end"
|
|
169
|
-
return code.join("\n")
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
def process_block(exp) # :nodoc:
|
|
173
|
-
result = []
|
|
174
|
-
|
|
175
|
-
exp << nil if exp.empty?
|
|
176
|
-
until exp.empty? do
|
|
177
|
-
code = exp.shift
|
|
178
|
-
if code.nil? or code.first == :nil then
|
|
179
|
-
result << "# do nothing\n"
|
|
180
|
-
else
|
|
181
|
-
result << process(code)
|
|
182
|
-
end
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
result = parenthesize result.join "\n"
|
|
186
|
-
result += "\n" unless result.start_with? "("
|
|
187
|
-
|
|
188
|
-
return result
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
def process_block_pass exp # :nodoc:
|
|
192
|
-
raise "huh?: #{exp.inspect}" if exp.size > 1
|
|
193
|
-
|
|
194
|
-
"&#{process exp.shift}"
|
|
195
|
-
end
|
|
138
|
+
# Process Methods
|
|
139
|
+
# ---------------
|
|
140
|
+
#
|
|
141
|
+
# For each node that a SexpProcessor visits, it will call a
|
|
142
|
+
# method `#process_X` where X is is the node's `sexp_type`.
|
|
196
143
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
end
|
|
144
|
+
NODES.each do |p|
|
|
145
|
+
define_method("process_#{p}") { |exp|
|
|
146
|
+
"::Sexp2Ruby::Node::#{p.to_s.camelize}".
|
|
147
|
+
constantize.
|
|
148
|
+
new(self).
|
|
149
|
+
to_s(exp)
|
|
150
|
+
}
|
|
205
151
|
end
|
|
206
152
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
receiver = process exp.shift
|
|
210
|
-
receiver = "(#{receiver})" if ASSIGN_NODES.include? receiver_node_type
|
|
153
|
+
# State
|
|
154
|
+
# -----
|
|
211
155
|
|
|
212
|
-
|
|
213
|
-
args = []
|
|
214
|
-
|
|
215
|
-
# this allows us to do both old and new sexp forms:
|
|
216
|
-
exp.push(*exp.pop[1..-1]) if exp.size == 1 && exp.first.first == :arglist
|
|
217
|
-
|
|
218
|
-
@calls.push name
|
|
219
|
-
|
|
220
|
-
in_context :arglist do
|
|
221
|
-
until exp.empty? do
|
|
222
|
-
arg_type = exp.first.sexp_type
|
|
223
|
-
is_empty_hash = (exp.first == s(:hash))
|
|
224
|
-
arg = process exp.shift
|
|
225
|
-
|
|
226
|
-
next if arg.empty?
|
|
227
|
-
|
|
228
|
-
strip_hash = (arg_type == :hash and
|
|
229
|
-
not BINARY.include? name and
|
|
230
|
-
not is_empty_hash and
|
|
231
|
-
(exp.empty? or exp.first.sexp_type == :splat))
|
|
232
|
-
wrap_arg = ASSIGN_NODES.include? arg_type
|
|
233
|
-
|
|
234
|
-
arg = arg[2..-3] if strip_hash
|
|
235
|
-
arg = "(#{arg})" if wrap_arg
|
|
236
|
-
|
|
237
|
-
args << arg
|
|
238
|
-
end
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
case name
|
|
242
|
-
when *BINARY then
|
|
243
|
-
"(#{receiver} #{name} #{args.join(', ')})"
|
|
244
|
-
when :[] then
|
|
245
|
-
receiver ||= "self"
|
|
246
|
-
"#{receiver}[#{args.join(', ')}]"
|
|
247
|
-
when :[]= then
|
|
248
|
-
receiver ||= "self"
|
|
249
|
-
rhs = args.pop
|
|
250
|
-
"#{receiver}[#{args.join(', ')}] = #{rhs}"
|
|
251
|
-
when :"!" then
|
|
252
|
-
"(not #{receiver})"
|
|
253
|
-
when :"-@" then
|
|
254
|
-
"-#{receiver}"
|
|
255
|
-
when :"+@" then
|
|
256
|
-
"+#{receiver}"
|
|
257
|
-
else
|
|
258
|
-
args = nil if args.empty?
|
|
259
|
-
args = "(#{args.join(', ')})" if args
|
|
260
|
-
receiver = "#{receiver}." if receiver
|
|
261
|
-
|
|
262
|
-
"#{receiver}#{name}#{args}"
|
|
263
|
-
end
|
|
264
|
-
ensure
|
|
156
|
+
def call_pop
|
|
265
157
|
@calls.pop
|
|
266
158
|
end
|
|
267
159
|
|
|
268
|
-
def
|
|
269
|
-
|
|
270
|
-
expr = process exp.shift
|
|
271
|
-
if expr then
|
|
272
|
-
result << "case #{expr}"
|
|
273
|
-
else
|
|
274
|
-
result << "case"
|
|
275
|
-
end
|
|
276
|
-
until exp.empty?
|
|
277
|
-
pt = exp.shift
|
|
278
|
-
if pt and pt.first == :when
|
|
279
|
-
result << "#{process(pt)}"
|
|
280
|
-
else
|
|
281
|
-
code = indent(process(pt))
|
|
282
|
-
code = indent("# do nothing") if code =~ /^\s*$/
|
|
283
|
-
result << "else\n#{code}"
|
|
284
|
-
end
|
|
285
|
-
end
|
|
286
|
-
result << "end"
|
|
287
|
-
result.join("\n")
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
def process_cdecl(exp) # :nodoc:
|
|
291
|
-
lhs = exp.shift
|
|
292
|
-
lhs = process lhs if Sexp === lhs
|
|
293
|
-
unless exp.empty? then
|
|
294
|
-
rhs = process(exp.shift)
|
|
295
|
-
"#{lhs} = #{rhs}"
|
|
296
|
-
else
|
|
297
|
-
lhs.to_s
|
|
298
|
-
end
|
|
299
|
-
end
|
|
300
|
-
|
|
301
|
-
def process_class(exp) # :nodoc:
|
|
302
|
-
"#{exp.comments}class #{util_module_or_class(exp, true)}"
|
|
303
|
-
end
|
|
304
|
-
|
|
305
|
-
def process_colon2(exp) # :nodoc:
|
|
306
|
-
"#{process(exp.shift)}::#{exp.shift}"
|
|
307
|
-
end
|
|
308
|
-
|
|
309
|
-
def process_colon3(exp) # :nodoc:
|
|
310
|
-
"::#{exp.shift}"
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
def process_const(exp) # :nodoc:
|
|
314
|
-
exp.shift.to_s
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
def process_cvar(exp) # :nodoc:
|
|
318
|
-
"#{exp.shift}"
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
def process_cvasgn(exp) # :nodoc:
|
|
322
|
-
"#{exp.shift} = #{process(exp.shift)}"
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
def process_cvdecl(exp) # :nodoc:
|
|
326
|
-
"#{exp.shift} = #{process(exp.shift)}"
|
|
327
|
-
end
|
|
328
|
-
|
|
329
|
-
def process_defined(exp) # :nodoc:
|
|
330
|
-
"defined? #{process(exp.shift)}"
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
def process_defn(exp) # :nodoc:
|
|
334
|
-
type1 = exp[1].first
|
|
335
|
-
type2 = exp[2].first rescue nil
|
|
336
|
-
expect = [:ivar, :iasgn, :attrset]
|
|
337
|
-
|
|
338
|
-
# s(name, args, ivar|iasgn|attrset)
|
|
339
|
-
if exp.size == 3 and type1 == :args and expect.include? type2 then
|
|
340
|
-
name = exp.first # don't shift in case we pass through
|
|
341
|
-
case type2
|
|
342
|
-
when :ivar then
|
|
343
|
-
ivar_name = exp.ivar.last
|
|
344
|
-
|
|
345
|
-
meth_name = ivar_name.to_s[1..-1].to_sym
|
|
346
|
-
expected = s(meth_name, s(:args), s(:ivar, ivar_name))
|
|
347
|
-
|
|
348
|
-
if exp == expected then
|
|
349
|
-
exp.clear
|
|
350
|
-
return "attr_reader #{name.inspect}"
|
|
351
|
-
end
|
|
352
|
-
when :attrset then
|
|
353
|
-
# TODO: deprecate? this is a PT relic
|
|
354
|
-
exp.clear
|
|
355
|
-
return "attr_writer :#{name.to_s[0..-2]}"
|
|
356
|
-
when :iasgn then
|
|
357
|
-
ivar_name = exp.iasgn[1]
|
|
358
|
-
meth_name = "#{ivar_name.to_s[1..-1]}=".to_sym
|
|
359
|
-
arg_name = exp.args.last
|
|
360
|
-
expected = s(meth_name, s(:args, arg_name),
|
|
361
|
-
s(:iasgn, ivar_name, s(:lvar, arg_name)))
|
|
362
|
-
|
|
363
|
-
if exp == expected then
|
|
364
|
-
exp.clear
|
|
365
|
-
return "attr_writer :#{name.to_s[0..-2]}"
|
|
366
|
-
end
|
|
367
|
-
else
|
|
368
|
-
raise "Unknown defn type: #{exp.inspect}"
|
|
369
|
-
end
|
|
370
|
-
end
|
|
371
|
-
|
|
372
|
-
comm = exp.comments
|
|
373
|
-
name = exp.shift
|
|
374
|
-
args = process exp.shift
|
|
375
|
-
args = "" if args == "()"
|
|
376
|
-
|
|
377
|
-
exp.shift if exp == s(s(:nil)) # empty it out of a default nil expression
|
|
378
|
-
|
|
379
|
-
# REFACTOR: use process_block but get it happier wrt parenthesize
|
|
380
|
-
body = []
|
|
381
|
-
until exp.empty? do
|
|
382
|
-
body << process(exp.shift)
|
|
383
|
-
end
|
|
384
|
-
|
|
385
|
-
body << "# do nothing" if body.empty?
|
|
386
|
-
body = body.join("\n")
|
|
387
|
-
body = body.lines.to_a[1..-2].join("\n") if
|
|
388
|
-
body =~ /^\Abegin/ && body =~ /^end\z/
|
|
389
|
-
body = indent(body) unless body =~ /(^|\n)rescue/
|
|
390
|
-
|
|
391
|
-
return "#{comm}def #{name}#{args}\n#{body}\nend".gsub(/\n\s*\n+/, "\n")
|
|
392
|
-
end
|
|
393
|
-
|
|
394
|
-
def process_defs(exp) # :nodoc:
|
|
395
|
-
lhs = exp.shift
|
|
396
|
-
var = [:self, :cvar, :dvar, :ivar, :gvar, :lvar].include? lhs.first
|
|
397
|
-
name = exp.shift
|
|
398
|
-
|
|
399
|
-
lhs = process(lhs)
|
|
400
|
-
lhs = "(#{lhs})" unless var
|
|
401
|
-
|
|
402
|
-
exp.unshift "#{lhs}.#{name}"
|
|
403
|
-
process_defn(exp)
|
|
404
|
-
end
|
|
405
|
-
|
|
406
|
-
def process_dot2(exp) # :nodoc:
|
|
407
|
-
"(#{process exp.shift}..#{process exp.shift})"
|
|
408
|
-
end
|
|
409
|
-
|
|
410
|
-
def process_dot3(exp) # :nodoc:
|
|
411
|
-
"(#{process exp.shift}...#{process exp.shift})"
|
|
412
|
-
end
|
|
413
|
-
|
|
414
|
-
def process_dregx(exp) # :nodoc:
|
|
415
|
-
options = re_opt exp.pop if Fixnum === exp.last
|
|
416
|
-
"/" << util_dthing(:dregx, exp) << "/#{options}"
|
|
417
|
-
end
|
|
418
|
-
|
|
419
|
-
def process_dregx_once(exp) # :nodoc:
|
|
420
|
-
process_dregx(exp) + "o"
|
|
160
|
+
def call_push(name)
|
|
161
|
+
@calls.push(name)
|
|
421
162
|
end
|
|
422
163
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
end
|
|
426
|
-
|
|
427
|
-
def process_dsym(exp) # :nodoc:
|
|
428
|
-
":\"#{util_dthing(:dsym, exp)}\""
|
|
429
|
-
end
|
|
164
|
+
# Rewriters
|
|
165
|
+
# ---------
|
|
430
166
|
|
|
431
|
-
def
|
|
432
|
-
|
|
433
|
-
end
|
|
434
|
-
|
|
435
|
-
def process_ensure(exp) # :nodoc:
|
|
436
|
-
body = process exp.shift
|
|
437
|
-
ens = exp.shift
|
|
438
|
-
ens = nil if ens == s(:nil)
|
|
439
|
-
ens = process(ens) || "# do nothing"
|
|
440
|
-
ens = "begin\n#{ens}\nend\n" if ens =~ /(^|\n)rescue/
|
|
441
|
-
|
|
442
|
-
body.sub!(/\n\s*end\z/, '')
|
|
443
|
-
body = indent(body) unless body =~ /(^|\n)rescue/
|
|
444
|
-
|
|
445
|
-
return "#{body}\nensure\n#{indent ens}"
|
|
446
|
-
end
|
|
447
|
-
|
|
448
|
-
def process_evstr(exp) # :nodoc:
|
|
449
|
-
exp.empty? ? '' : process(exp.shift)
|
|
450
|
-
end
|
|
451
|
-
|
|
452
|
-
def process_false(exp) # :nodoc:
|
|
453
|
-
"false"
|
|
454
|
-
end
|
|
455
|
-
|
|
456
|
-
def process_flip2(exp) # :nodoc:
|
|
457
|
-
"#{process(exp.shift)}..#{process(exp.shift)}"
|
|
458
|
-
end
|
|
459
|
-
|
|
460
|
-
def process_flip3(exp) # :nodoc:
|
|
461
|
-
"#{process(exp.shift)}...#{process(exp.shift)}"
|
|
462
|
-
end
|
|
463
|
-
|
|
464
|
-
def process_for(exp) # :nodoc:
|
|
465
|
-
recv = process exp.shift
|
|
466
|
-
iter = process exp.shift
|
|
467
|
-
body = exp.empty? ? nil : process(exp.shift)
|
|
468
|
-
|
|
469
|
-
result = ["for #{iter} in #{recv} do"]
|
|
470
|
-
result << indent(body ? body : "# do nothing")
|
|
471
|
-
result << "end"
|
|
472
|
-
|
|
473
|
-
result.join("\n")
|
|
474
|
-
end
|
|
475
|
-
|
|
476
|
-
def process_gasgn(exp) # :nodoc:
|
|
477
|
-
process_iasgn(exp)
|
|
478
|
-
end
|
|
479
|
-
|
|
480
|
-
def process_gvar(exp) # :nodoc:
|
|
481
|
-
return exp.shift.to_s
|
|
482
|
-
end
|
|
483
|
-
|
|
484
|
-
def process_hash(exp) # :nodoc:
|
|
485
|
-
result = []
|
|
486
|
-
|
|
487
|
-
until exp.empty?
|
|
488
|
-
s = exp.shift
|
|
489
|
-
t = s.sexp_type
|
|
490
|
-
ruby19_key = ruby19_hash_key?(s)
|
|
491
|
-
lhs = process s
|
|
492
|
-
|
|
493
|
-
case t
|
|
494
|
-
when :kwsplat then
|
|
495
|
-
result << lhs
|
|
496
|
-
else
|
|
497
|
-
rhs = exp.shift
|
|
498
|
-
t = rhs.first
|
|
499
|
-
rhs = process rhs
|
|
500
|
-
rhs = "(#{rhs})" unless HASH_VAL_NO_PAREN.include? t
|
|
501
|
-
|
|
502
|
-
if hash_syntax == :ruby19 && ruby19_key
|
|
503
|
-
lhs.gsub!(/\A:/, "")
|
|
504
|
-
result << "#{lhs}: #{rhs}"
|
|
505
|
-
else
|
|
506
|
-
result << "#{lhs} => #{rhs}"
|
|
507
|
-
end
|
|
508
|
-
end
|
|
509
|
-
end
|
|
510
|
-
|
|
511
|
-
return result.empty? ? "{}" : "{ #{result.join(', ')} }"
|
|
512
|
-
end
|
|
513
|
-
|
|
514
|
-
def process_iasgn(exp) # :nodoc:
|
|
515
|
-
lhs = exp.shift
|
|
516
|
-
if exp.empty? then # part of an masgn
|
|
517
|
-
lhs.to_s
|
|
518
|
-
else
|
|
519
|
-
"#{lhs} = #{process exp.shift}"
|
|
520
|
-
end
|
|
521
|
-
end
|
|
522
|
-
|
|
523
|
-
def process_if(exp) # :nodoc:
|
|
524
|
-
expand = ASSIGN_NODES.include? exp.first.first
|
|
525
|
-
c = process exp.shift
|
|
526
|
-
t = process exp.shift
|
|
527
|
-
f = process exp.shift
|
|
528
|
-
|
|
529
|
-
c = "(#{c.chomp})" if c =~ /\n/
|
|
530
|
-
|
|
531
|
-
if t then
|
|
532
|
-
unless expand then
|
|
533
|
-
if f then
|
|
534
|
-
r = "#{c} ? (#{t}) : (#{f})"
|
|
535
|
-
r = nil if r =~ /return/ # HACK - need contextual awareness or something
|
|
536
|
-
else
|
|
537
|
-
r = "#{t} if #{c}"
|
|
538
|
-
end
|
|
539
|
-
return r if r and (@indent+r).size < LINE_LENGTH and r !~ /\n/
|
|
540
|
-
end
|
|
541
|
-
|
|
542
|
-
r = "if #{c} then\n#{indent(t)}\n"
|
|
543
|
-
r << "else\n#{indent(f)}\n" if f
|
|
544
|
-
r << "end"
|
|
545
|
-
|
|
546
|
-
r
|
|
547
|
-
elsif f
|
|
548
|
-
unless expand then
|
|
549
|
-
r = "#{f} unless #{c}"
|
|
550
|
-
return r if (@indent+r).size < LINE_LENGTH and r !~ /\n/
|
|
551
|
-
end
|
|
552
|
-
"unless #{c} then\n#{indent(f)}\nend"
|
|
553
|
-
else
|
|
554
|
-
# empty if statement, just do it in case of side effects from condition
|
|
555
|
-
"if #{c} then\n#{indent '# do nothing'}\nend"
|
|
556
|
-
end
|
|
557
|
-
end
|
|
558
|
-
|
|
559
|
-
def process_iter(exp) # :nodoc:
|
|
560
|
-
iter = process exp.shift
|
|
561
|
-
args = exp.shift
|
|
562
|
-
body = exp.empty? ? nil : process(exp.shift)
|
|
563
|
-
|
|
564
|
-
args = case args
|
|
565
|
-
when 0 then
|
|
566
|
-
" ||"
|
|
567
|
-
else
|
|
568
|
-
a = process(args)[1..-2]
|
|
569
|
-
a = " |#{a}|" unless a.empty?
|
|
570
|
-
a
|
|
571
|
-
end
|
|
572
|
-
|
|
573
|
-
b, e = if iter == "END" then
|
|
574
|
-
[ "{", "}" ]
|
|
575
|
-
else
|
|
576
|
-
[ "do", "end" ]
|
|
577
|
-
end
|
|
578
|
-
|
|
579
|
-
iter.sub!(/\(\)$/, '')
|
|
580
|
-
|
|
581
|
-
# REFACTOR: ugh
|
|
582
|
-
result = []
|
|
583
|
-
result << "#{iter} {"
|
|
584
|
-
result << args
|
|
585
|
-
if body then
|
|
586
|
-
result << " #{body.strip} "
|
|
587
|
-
else
|
|
588
|
-
result << ' '
|
|
589
|
-
end
|
|
590
|
-
result << "}"
|
|
591
|
-
result = result.join
|
|
592
|
-
return result if result !~ /\n/ and result.size < LINE_LENGTH
|
|
593
|
-
|
|
594
|
-
result = []
|
|
595
|
-
result << "#{iter} #{b}"
|
|
596
|
-
result << args
|
|
597
|
-
result << "\n"
|
|
598
|
-
if body then
|
|
599
|
-
result << indent(body.strip)
|
|
600
|
-
result << "\n"
|
|
601
|
-
end
|
|
602
|
-
result << e
|
|
603
|
-
result.join
|
|
604
|
-
end
|
|
605
|
-
|
|
606
|
-
def process_ivar(exp) # :nodoc:
|
|
607
|
-
exp.shift.to_s
|
|
608
|
-
end
|
|
609
|
-
|
|
610
|
-
def process_kwsplat(exp)
|
|
611
|
-
"**#{process exp.shift}"
|
|
612
|
-
end
|
|
613
|
-
|
|
614
|
-
def process_lasgn(exp) # :nodoc:
|
|
615
|
-
s = "#{exp.shift}"
|
|
616
|
-
s += " = #{process exp.shift}" unless exp.empty?
|
|
617
|
-
s
|
|
618
|
-
end
|
|
619
|
-
|
|
620
|
-
def process_lit(exp) # :nodoc:
|
|
621
|
-
obj = exp.shift
|
|
622
|
-
case obj
|
|
623
|
-
when Range then
|
|
624
|
-
"(#{obj.inspect})"
|
|
625
|
-
else
|
|
626
|
-
obj.inspect
|
|
627
|
-
end
|
|
628
|
-
end
|
|
629
|
-
|
|
630
|
-
def process_lvar(exp) # :nodoc:
|
|
631
|
-
exp.shift.to_s
|
|
632
|
-
end
|
|
633
|
-
|
|
634
|
-
def process_masgn(exp) # :nodoc:
|
|
635
|
-
# s(:masgn, s(:array, s(:lasgn, :var), ...), s(:to_ary, <val>, ...))
|
|
636
|
-
# s(:iter, <call>, s(:args, s(:masgn, :a, :b)), <body>)
|
|
637
|
-
|
|
638
|
-
case exp.first
|
|
639
|
-
when Sexp then
|
|
640
|
-
lhs = exp.shift
|
|
641
|
-
rhs = exp.empty? ? nil : exp.shift
|
|
642
|
-
|
|
643
|
-
case lhs.first
|
|
644
|
-
when :array then
|
|
645
|
-
lhs.shift # node type
|
|
646
|
-
lhs = lhs.map do |l|
|
|
647
|
-
case l.first
|
|
648
|
-
when :masgn then
|
|
649
|
-
"(#{process(l)})"
|
|
650
|
-
else
|
|
651
|
-
process(l)
|
|
652
|
-
end
|
|
653
|
-
end
|
|
654
|
-
else
|
|
655
|
-
raise "no clue: #{lhs.inspect}"
|
|
656
|
-
end
|
|
657
|
-
|
|
658
|
-
unless rhs.nil? then
|
|
659
|
-
t = rhs.first
|
|
660
|
-
rhs = process rhs
|
|
661
|
-
rhs = rhs[1..-2] if t == :array # FIX: bad? I dunno
|
|
662
|
-
return "#{lhs.join(", ")} = #{rhs}"
|
|
663
|
-
else
|
|
664
|
-
return lhs.join(", ")
|
|
665
|
-
end
|
|
666
|
-
when Symbol then # block arg list w/ masgn
|
|
667
|
-
result = exp.join ", "
|
|
668
|
-
exp.clear
|
|
669
|
-
"(#{result})"
|
|
670
|
-
else
|
|
671
|
-
raise "unknown masgn: #{exp.inspect}"
|
|
672
|
-
end
|
|
673
|
-
end
|
|
674
|
-
|
|
675
|
-
def process_match(exp) # :nodoc:
|
|
676
|
-
"#{process(exp.shift)}"
|
|
677
|
-
end
|
|
678
|
-
|
|
679
|
-
def process_match2(exp) # :nodoc:
|
|
680
|
-
lhs = process(exp.shift)
|
|
681
|
-
rhs = process(exp.shift)
|
|
682
|
-
"#{lhs} =~ #{rhs}"
|
|
683
|
-
end
|
|
684
|
-
|
|
685
|
-
def process_match3(exp) # :nodoc:
|
|
686
|
-
rhs = process(exp.shift)
|
|
687
|
-
left_type = exp.first.sexp_type
|
|
688
|
-
lhs = process(exp.shift)
|
|
689
|
-
|
|
690
|
-
if ASSIGN_NODES.include? left_type then
|
|
691
|
-
"(#{lhs}) =~ #{rhs}"
|
|
692
|
-
else
|
|
693
|
-
"#{lhs} =~ #{rhs}"
|
|
694
|
-
end
|
|
695
|
-
end
|
|
696
|
-
|
|
697
|
-
def process_module(exp) # :nodoc:
|
|
698
|
-
"#{exp.comments}module #{util_module_or_class(exp)}"
|
|
699
|
-
end
|
|
700
|
-
|
|
701
|
-
def process_next(exp) # :nodoc:
|
|
702
|
-
val = exp.empty? ? nil : process(exp.shift)
|
|
703
|
-
if val then
|
|
704
|
-
"next #{val}"
|
|
705
|
-
else
|
|
706
|
-
"next"
|
|
707
|
-
end
|
|
708
|
-
end
|
|
709
|
-
|
|
710
|
-
def process_nil(exp) # :nodoc:
|
|
711
|
-
"nil"
|
|
712
|
-
end
|
|
713
|
-
|
|
714
|
-
def process_not(exp) # :nodoc:
|
|
715
|
-
"(not #{process exp.shift})"
|
|
716
|
-
end
|
|
717
|
-
|
|
718
|
-
def process_nth_ref(exp) # :nodoc:
|
|
719
|
-
"$#{exp.shift}"
|
|
720
|
-
end
|
|
721
|
-
|
|
722
|
-
def process_op_asgn1(exp) # :nodoc:
|
|
723
|
-
# [[:lvar, :b], [:arglist, [:lit, 1]], :"||", [:lit, 10]]
|
|
724
|
-
lhs = process(exp.shift)
|
|
725
|
-
index = process(exp.shift)
|
|
726
|
-
msg = exp.shift
|
|
727
|
-
rhs = process(exp.shift)
|
|
728
|
-
|
|
729
|
-
"#{lhs}[#{index}] #{msg}= #{rhs}"
|
|
730
|
-
end
|
|
731
|
-
|
|
732
|
-
def process_op_asgn2(exp) # :nodoc:
|
|
733
|
-
# [[:lvar, :c], :var=, :"||", [:lit, 20]]
|
|
734
|
-
lhs = process(exp.shift)
|
|
735
|
-
index = exp.shift.to_s[0..-2]
|
|
736
|
-
msg = exp.shift
|
|
737
|
-
|
|
738
|
-
rhs = process(exp.shift)
|
|
739
|
-
|
|
740
|
-
"#{lhs}.#{index} #{msg}= #{rhs}"
|
|
741
|
-
end
|
|
742
|
-
|
|
743
|
-
def process_op_asgn_and(exp) # :nodoc:
|
|
744
|
-
# a &&= 1
|
|
745
|
-
# [[:lvar, :a], [:lasgn, :a, [:lit, 1]]]
|
|
746
|
-
exp.shift
|
|
747
|
-
process(exp.shift).sub(/\=/, '&&=')
|
|
748
|
-
end
|
|
749
|
-
|
|
750
|
-
def process_op_asgn_or(exp) # :nodoc:
|
|
751
|
-
# a ||= 1
|
|
752
|
-
# [[:lvar, :a], [:lasgn, :a, [:lit, 1]]]
|
|
753
|
-
exp.shift
|
|
754
|
-
process(exp.shift).sub(/\=/, '||=')
|
|
755
|
-
end
|
|
756
|
-
|
|
757
|
-
def process_or(exp) # :nodoc:
|
|
758
|
-
"(#{process exp.shift} or #{process exp.shift})"
|
|
759
|
-
end
|
|
760
|
-
|
|
761
|
-
def process_postexe(exp) # :nodoc:
|
|
762
|
-
"END"
|
|
763
|
-
end
|
|
764
|
-
|
|
765
|
-
def process_redo(exp) # :nodoc:
|
|
766
|
-
"redo"
|
|
767
|
-
end
|
|
768
|
-
|
|
769
|
-
def process_resbody exp # :nodoc:
|
|
770
|
-
args = exp.shift
|
|
771
|
-
body = finish(exp)
|
|
772
|
-
body << "# do nothing" if body.empty?
|
|
773
|
-
|
|
774
|
-
name = args.lasgn true
|
|
775
|
-
name ||= args.iasgn true
|
|
776
|
-
args = process(args)[1..-2]
|
|
777
|
-
args = " #{args}" unless args.empty?
|
|
778
|
-
args += " => #{name[1]}" if name
|
|
779
|
-
|
|
780
|
-
"rescue#{args}\n#{indent body.join("\n")}"
|
|
781
|
-
end
|
|
782
|
-
|
|
783
|
-
def process_rescue exp # :nodoc:
|
|
784
|
-
body = process(exp.shift) unless exp.first.first == :resbody
|
|
785
|
-
els = process(exp.pop) unless exp.last.first == :resbody
|
|
786
|
-
|
|
787
|
-
body ||= "# do nothing"
|
|
788
|
-
simple = exp.size == 1 && exp.resbody.size <= 3 &&
|
|
789
|
-
!exp.resbody.block &&
|
|
790
|
-
!exp.resbody.return
|
|
791
|
-
|
|
792
|
-
resbodies = []
|
|
793
|
-
until exp.empty? do
|
|
794
|
-
resbody = exp.shift
|
|
795
|
-
simple &&= resbody[1] == s(:array)
|
|
796
|
-
simple &&= resbody[2] != nil && resbody[2].node_type != :block
|
|
797
|
-
resbodies << process(resbody)
|
|
798
|
-
end
|
|
799
|
-
|
|
800
|
-
if els then
|
|
801
|
-
"#{indent body}\n#{resbodies.join("\n")}\nelse\n#{indent els}"
|
|
802
|
-
elsif simple then
|
|
803
|
-
resbody = resbodies.first.sub(/\n\s*/, ' ')
|
|
804
|
-
"#{body} #{resbody}"
|
|
805
|
-
else
|
|
806
|
-
"#{indent body}\n#{resbodies.join("\n")}"
|
|
807
|
-
end
|
|
808
|
-
end
|
|
809
|
-
|
|
810
|
-
def process_retry(exp) # :nodoc:
|
|
811
|
-
"retry"
|
|
812
|
-
end
|
|
813
|
-
|
|
814
|
-
def process_return(exp) # :nodoc:
|
|
815
|
-
# HACK return "return" + (exp.empty? ? "" : " #{process exp.shift}")
|
|
816
|
-
|
|
817
|
-
if exp.empty? then
|
|
818
|
-
return "return"
|
|
819
|
-
else
|
|
820
|
-
return "return #{process exp.shift}"
|
|
821
|
-
end
|
|
822
|
-
end
|
|
823
|
-
|
|
824
|
-
def process_sclass(exp) # :nodoc:
|
|
825
|
-
"class << #{process(exp.shift)}\n#{indent(process_block(exp))}\nend"
|
|
826
|
-
end
|
|
827
|
-
|
|
828
|
-
def process_self(exp) # :nodoc:
|
|
829
|
-
"self"
|
|
830
|
-
end
|
|
831
|
-
|
|
832
|
-
def process_splat(exp) # :nodoc:
|
|
833
|
-
if exp.empty? then
|
|
834
|
-
"*"
|
|
835
|
-
else
|
|
836
|
-
"*#{process(exp.shift)}"
|
|
837
|
-
end
|
|
838
|
-
end
|
|
839
|
-
|
|
840
|
-
def process_str(exp) # :nodoc:
|
|
841
|
-
return exp.shift.dump
|
|
842
|
-
end
|
|
843
|
-
|
|
844
|
-
def process_super(exp) # :nodoc:
|
|
845
|
-
args = finish exp
|
|
846
|
-
|
|
847
|
-
"super(#{args.join(', ')})"
|
|
848
|
-
end
|
|
849
|
-
|
|
850
|
-
def process_svalue(exp) # :nodoc:
|
|
851
|
-
code = []
|
|
852
|
-
until exp.empty? do
|
|
853
|
-
code << process(exp.shift)
|
|
854
|
-
end
|
|
855
|
-
code.join(", ")
|
|
856
|
-
end
|
|
857
|
-
|
|
858
|
-
def process_to_ary(exp) # :nodoc:
|
|
859
|
-
process(exp.shift)
|
|
860
|
-
end
|
|
861
|
-
|
|
862
|
-
def process_true(exp) # :nodoc:
|
|
863
|
-
"true"
|
|
864
|
-
end
|
|
865
|
-
|
|
866
|
-
def process_undef(exp) # :nodoc:
|
|
867
|
-
"undef #{process(exp.shift)}"
|
|
868
|
-
end
|
|
869
|
-
|
|
870
|
-
def process_until(exp) # :nodoc:
|
|
871
|
-
cond_loop(exp, 'until')
|
|
872
|
-
end
|
|
873
|
-
|
|
874
|
-
def process_valias(exp) # :nodoc:
|
|
875
|
-
"alias #{exp.shift} #{exp.shift}"
|
|
876
|
-
end
|
|
877
|
-
|
|
878
|
-
def process_when(exp) # :nodoc:
|
|
879
|
-
src = []
|
|
880
|
-
|
|
881
|
-
if self.context[1] == :array then # ugh. matz! why not an argscat?!?
|
|
882
|
-
val = process(exp.shift)
|
|
883
|
-
exp.shift # empty body
|
|
884
|
-
return "*#{val}"
|
|
885
|
-
end
|
|
886
|
-
|
|
887
|
-
until exp.empty?
|
|
888
|
-
cond = process(exp.shift).to_s[1..-2]
|
|
889
|
-
code = indent(finish(exp).join("\n"))
|
|
890
|
-
code = indent "# do nothing" if code =~ /\A\s*\Z/
|
|
891
|
-
src << "when #{cond} then\n#{code.chomp}"
|
|
892
|
-
end
|
|
893
|
-
|
|
894
|
-
src.join("\n")
|
|
895
|
-
end
|
|
896
|
-
|
|
897
|
-
def process_while(exp) # :nodoc:
|
|
898
|
-
cond_loop(exp, 'while')
|
|
899
|
-
end
|
|
900
|
-
|
|
901
|
-
def process_xstr(exp) # :nodoc:
|
|
902
|
-
"`#{process_str(exp)[1..-2]}`"
|
|
903
|
-
end
|
|
904
|
-
|
|
905
|
-
def process_yield(exp) # :nodoc:
|
|
906
|
-
args = []
|
|
907
|
-
until exp.empty? do
|
|
908
|
-
args << process(exp.shift)
|
|
909
|
-
end
|
|
910
|
-
|
|
911
|
-
unless args.empty? then
|
|
912
|
-
"yield(#{args.join(', ')})"
|
|
913
|
-
else
|
|
914
|
-
"yield"
|
|
915
|
-
end
|
|
916
|
-
end
|
|
917
|
-
|
|
918
|
-
def process_zsuper(exp) # :nodoc:
|
|
919
|
-
"super"
|
|
920
|
-
end
|
|
921
|
-
|
|
922
|
-
############################################################
|
|
923
|
-
# Rewriters:
|
|
924
|
-
|
|
925
|
-
def rewrite_attrasgn exp # :nodoc:
|
|
926
|
-
if context.first(2) == [:array, :masgn] then
|
|
167
|
+
def rewrite_attrasgn exp
|
|
168
|
+
if context.first(2) == [:array, :masgn]
|
|
927
169
|
exp[0] = :call
|
|
928
170
|
exp[2] = exp[2].to_s.sub(/=$/, '').to_sym
|
|
929
171
|
end
|
|
@@ -931,19 +173,19 @@ module Sexp2Ruby
|
|
|
931
173
|
exp
|
|
932
174
|
end
|
|
933
175
|
|
|
934
|
-
def rewrite_ensure exp
|
|
176
|
+
def rewrite_ensure exp
|
|
935
177
|
exp = s(:begin, exp) unless context.first == :begin
|
|
936
178
|
exp
|
|
937
179
|
end
|
|
938
180
|
|
|
939
|
-
def rewrite_resbody exp
|
|
181
|
+
def rewrite_resbody exp
|
|
940
182
|
raise "no exception list in #{exp.inspect}" unless exp.size > 2 && exp[1]
|
|
941
183
|
raise exp[1].inspect if exp[1][0] != :array
|
|
942
184
|
# for now, do nothing, just check and freak if we see an errant structure
|
|
943
185
|
exp
|
|
944
186
|
end
|
|
945
187
|
|
|
946
|
-
def rewrite_rescue exp
|
|
188
|
+
def rewrite_rescue exp
|
|
947
189
|
complex = false
|
|
948
190
|
complex ||= exp.size > 3
|
|
949
191
|
complex ||= exp.resbody.block
|
|
@@ -959,7 +201,7 @@ module Sexp2Ruby
|
|
|
959
201
|
exp
|
|
960
202
|
end
|
|
961
203
|
|
|
962
|
-
def rewrite_svalue(exp)
|
|
204
|
+
def rewrite_svalue(exp)
|
|
963
205
|
case exp.last.first
|
|
964
206
|
when :array
|
|
965
207
|
s(:svalue, *exp[1][1..-1])
|
|
@@ -970,8 +212,8 @@ module Sexp2Ruby
|
|
|
970
212
|
end
|
|
971
213
|
end
|
|
972
214
|
|
|
973
|
-
|
|
974
|
-
#
|
|
215
|
+
# Utility Methods
|
|
216
|
+
# ---------------
|
|
975
217
|
|
|
976
218
|
def check_option_keys(option)
|
|
977
219
|
diff = option.keys - CONSTRUCTOR_OPTIONS
|
|
@@ -980,9 +222,7 @@ module Sexp2Ruby
|
|
|
980
222
|
end
|
|
981
223
|
end
|
|
982
224
|
|
|
983
|
-
##
|
|
984
225
|
# Generate a post-or-pre conditional loop.
|
|
985
|
-
|
|
986
226
|
def cond_loop(exp, name)
|
|
987
227
|
cond = process(exp.shift)
|
|
988
228
|
body = process(exp.shift)
|
|
@@ -991,7 +231,7 @@ module Sexp2Ruby
|
|
|
991
231
|
body = indent(body).chomp if body
|
|
992
232
|
|
|
993
233
|
code = []
|
|
994
|
-
if head_controlled
|
|
234
|
+
if head_controlled
|
|
995
235
|
code << "#{name} #{cond} do"
|
|
996
236
|
code << body if body
|
|
997
237
|
code << "end"
|
|
@@ -1000,12 +240,10 @@ module Sexp2Ruby
|
|
|
1000
240
|
code << body if body
|
|
1001
241
|
code << "end #{name} #{cond}"
|
|
1002
242
|
end
|
|
1003
|
-
code.join(
|
|
243
|
+
code.join(LF)
|
|
1004
244
|
end
|
|
1005
245
|
|
|
1006
|
-
|
|
1007
|
-
# Utility method to escape something interpolated.
|
|
1008
|
-
|
|
246
|
+
# Escape something interpolated.
|
|
1009
247
|
def dthing_escape type, lit
|
|
1010
248
|
lit = lit.gsub(/\n/, '\n')
|
|
1011
249
|
case type
|
|
@@ -1020,10 +258,8 @@ module Sexp2Ruby
|
|
|
1020
258
|
end
|
|
1021
259
|
end
|
|
1022
260
|
|
|
1023
|
-
##
|
|
1024
261
|
# Check that `value` is in `array` of valid option values,
|
|
1025
262
|
# or raise InvalidOption. If `value` is nil, return `default`.
|
|
1026
|
-
|
|
1027
263
|
def extract_option(array, value, default)
|
|
1028
264
|
if value.nil?
|
|
1029
265
|
default
|
|
@@ -1034,10 +270,8 @@ module Sexp2Ruby
|
|
|
1034
270
|
end
|
|
1035
271
|
end
|
|
1036
272
|
|
|
1037
|
-
##
|
|
1038
273
|
# Process all the remaining stuff in +exp+ and return the results
|
|
1039
274
|
# sans-nils.
|
|
1040
|
-
|
|
1041
275
|
def finish exp # REFACTOR: work this out of the rest of the processors
|
|
1042
276
|
body = []
|
|
1043
277
|
until exp.empty? do
|
|
@@ -1046,27 +280,21 @@ module Sexp2Ruby
|
|
|
1046
280
|
body.compact
|
|
1047
281
|
end
|
|
1048
282
|
|
|
1049
|
-
##
|
|
1050
283
|
# Given `exp` representing the left side of a hash pair, return true
|
|
1051
284
|
# if it is compatible with the ruby 1.9 hash syntax. For example,
|
|
1052
285
|
# the symbol `:foo` is compatible, but the literal `7` is not. Note
|
|
1053
286
|
# that strings are not considered "compatible". If we converted string
|
|
1054
287
|
# keys to symbol keys, we wouldn't be faithfully representing the input.
|
|
1055
|
-
|
|
1056
288
|
def ruby19_hash_key?(exp)
|
|
1057
289
|
exp.sexp_type == :lit && exp.length == 2 && RUBY_19_HASH_KEY === exp[1].to_s
|
|
1058
290
|
end
|
|
1059
291
|
|
|
1060
|
-
##
|
|
1061
292
|
# Indent all lines of +s+ to the current indent level.
|
|
1062
|
-
|
|
1063
293
|
def indent(s)
|
|
1064
|
-
s.to_s.split(/\n/).map{|line| @
|
|
294
|
+
s.to_s.split(/\n/).map{|line| @indent_lvl + line}.join(LF)
|
|
1065
295
|
end
|
|
1066
296
|
|
|
1067
|
-
##
|
|
1068
297
|
# Wrap appropriate expressions in matching parens.
|
|
1069
|
-
|
|
1070
298
|
def parenthesize exp
|
|
1071
299
|
case self.context[1]
|
|
1072
300
|
when nil, :defn, :defs, :class, :sclass, :if, :iter, :resbody, :when, :while then
|
|
@@ -1076,25 +304,12 @@ module Sexp2Ruby
|
|
|
1076
304
|
end
|
|
1077
305
|
end
|
|
1078
306
|
|
|
1079
|
-
##
|
|
1080
|
-
# Return the appropriate regexp flags for a given numeric code.
|
|
1081
|
-
|
|
1082
|
-
def re_opt options
|
|
1083
|
-
bits = (0..8).map { |n| options[n] * 2**n }
|
|
1084
|
-
bits.delete 0
|
|
1085
|
-
bits.map { |n| Regexp::CODES[n] }.join
|
|
1086
|
-
end
|
|
1087
|
-
|
|
1088
|
-
##
|
|
1089
307
|
# Return a splatted symbol for +sym+.
|
|
1090
|
-
|
|
1091
308
|
def splat(sym)
|
|
1092
309
|
:"*#{sym}"
|
|
1093
310
|
end
|
|
1094
311
|
|
|
1095
|
-
|
|
1096
|
-
# Utility method to generate something interpolated.
|
|
1097
|
-
|
|
312
|
+
# Generate something interpolated.
|
|
1098
313
|
def util_dthing(type, exp)
|
|
1099
314
|
s = []
|
|
1100
315
|
|
|
@@ -1121,9 +336,7 @@ module Sexp2Ruby
|
|
|
1121
336
|
s.join
|
|
1122
337
|
end
|
|
1123
338
|
|
|
1124
|
-
##
|
|
1125
339
|
# Utility method to generate ether a module or class.
|
|
1126
|
-
|
|
1127
340
|
def util_module_or_class(exp, is_class=false)
|
|
1128
341
|
result = []
|
|
1129
342
|
|
|
@@ -1132,12 +345,12 @@ module Sexp2Ruby
|
|
|
1132
345
|
|
|
1133
346
|
result << name
|
|
1134
347
|
|
|
1135
|
-
if is_class
|
|
348
|
+
if is_class
|
|
1136
349
|
superk = process(exp.shift)
|
|
1137
350
|
result << " < #{superk}" if superk
|
|
1138
351
|
end
|
|
1139
352
|
|
|
1140
|
-
result <<
|
|
353
|
+
result << LF
|
|
1141
354
|
|
|
1142
355
|
body = []
|
|
1143
356
|
begin
|
|
@@ -1145,11 +358,7 @@ module Sexp2Ruby
|
|
|
1145
358
|
body << code.chomp unless code.nil? or code.chomp.empty?
|
|
1146
359
|
end until exp.empty?
|
|
1147
360
|
|
|
1148
|
-
|
|
1149
|
-
body = indent(body.join("\n\n")) + "\n"
|
|
1150
|
-
else
|
|
1151
|
-
body = ""
|
|
1152
|
-
end
|
|
361
|
+
body = body.empty? ? "" : indent(body.join("\n\n")) + LF
|
|
1153
362
|
result << body
|
|
1154
363
|
result << "end"
|
|
1155
364
|
|