sexp2ruby 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|