syntax_tree-translator 0.1.0
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 +7 -0
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/main.yml +34 -0
- data/.gitignore +11 -0
- data/.gitmodules +6 -0
- data/CHANGELOG.md +16 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +44 -0
- data/LICENSE +21 -0
- data/README.md +74 -0
- data/Rakefile +22 -0
- data/bin/compare-p +58 -0
- data/bin/compare-rp +26 -0
- data/bin/console +10 -0
- data/bin/rubocop +32 -0
- data/lib/syntax_tree/translator/parser.rb +1269 -0
- data/lib/syntax_tree/translator/rubocop.rb +13 -0
- data/lib/syntax_tree/translator/ruby_parser.rb +1055 -0
- data/lib/syntax_tree/translator/version.rb +7 -0
- data/lib/syntax_tree/translator.rb +10 -0
- data/syntax_tree-translator.gemspec +35 -0
- metadata +176 -0
@@ -0,0 +1,1055 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SyntaxTree
|
4
|
+
module Translator
|
5
|
+
class RubyParser < Visitor
|
6
|
+
attr_reader :stack
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@stack = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def visit(node)
|
13
|
+
stack << node
|
14
|
+
result = super
|
15
|
+
stack.pop
|
16
|
+
result
|
17
|
+
end
|
18
|
+
|
19
|
+
# Visit an ARef node.
|
20
|
+
def visit_aref(node)
|
21
|
+
case node
|
22
|
+
in { index: Args[parts: [part]] }
|
23
|
+
s(:call, visit(node.collection), :[], visit(part))
|
24
|
+
in { index: nil }
|
25
|
+
s(:call, visit(node.collection), :[])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Visit an ARefField node.
|
30
|
+
def visit_aref_field(node)
|
31
|
+
case node
|
32
|
+
in { index: Args[parts: [part]] }
|
33
|
+
s(:attrasgn, visit(node.collection), :[]=, visit(part))
|
34
|
+
in { index: nil }
|
35
|
+
s(:attrasgn, visit(node.collection), :[]=)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Visit an Alias node.
|
40
|
+
def visit_alias(node)
|
41
|
+
s(:alias, visit(node.left), visit(node.right))
|
42
|
+
end
|
43
|
+
|
44
|
+
# Visit an ArgBlock node.
|
45
|
+
def visit_arg_block(node)
|
46
|
+
children = []
|
47
|
+
children << visit(node.value) if node.value
|
48
|
+
s(:block_pass, *children)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Visit an ArgParen node.
|
52
|
+
def visit_arg_paren(node)
|
53
|
+
raise
|
54
|
+
end
|
55
|
+
|
56
|
+
# Visit an ArgStar node.
|
57
|
+
def visit_arg_star(node)
|
58
|
+
case node
|
59
|
+
in { value: nil | Ident }
|
60
|
+
:"*#{visit(node.value)}"
|
61
|
+
else
|
62
|
+
s(:splat, visit(node.value))
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Visit an Args node.
|
67
|
+
def visit_args(node)
|
68
|
+
s(:args, *visit_all(node.parts))
|
69
|
+
end
|
70
|
+
|
71
|
+
# Visit an ArgsForward node.
|
72
|
+
def visit_args_forward(node)
|
73
|
+
raise
|
74
|
+
end
|
75
|
+
|
76
|
+
# Visit an ArrayLiteral node.
|
77
|
+
def visit_array(node)
|
78
|
+
case node
|
79
|
+
in { contents: nil }
|
80
|
+
s(:array)
|
81
|
+
in { contents: }
|
82
|
+
s(:array, *visit(contents)[1..])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Visit an AryPtn node.
|
87
|
+
def visit_aryptn(node)
|
88
|
+
children = [visit(node.constant)] + visit_all(node.requireds)
|
89
|
+
children << visit(node.rest) if node.rest
|
90
|
+
children += visit_all(node.posts)
|
91
|
+
s(:array_pat, *children)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Visit an Assign node.
|
95
|
+
def visit_assign(node)
|
96
|
+
s(*visit(node.target), visit(node.value))
|
97
|
+
end
|
98
|
+
|
99
|
+
# Visit an Assoc node.
|
100
|
+
def visit_assoc(node)
|
101
|
+
[visit(node.key), visit(node.value)]
|
102
|
+
end
|
103
|
+
|
104
|
+
# Visit an AssocSplat node.
|
105
|
+
def visit_assoc_splat(node)
|
106
|
+
[s(:kwsplat, visit(node.value))]
|
107
|
+
end
|
108
|
+
|
109
|
+
# Visit a Backref node.
|
110
|
+
def visit_backref(node)
|
111
|
+
node.value.to_sym
|
112
|
+
end
|
113
|
+
|
114
|
+
# Visit a Backtick node.
|
115
|
+
def visit_backtick(node)
|
116
|
+
raise
|
117
|
+
end
|
118
|
+
|
119
|
+
# Visit a BareAssocHash node.
|
120
|
+
def visit_bare_assoc_hash(node)
|
121
|
+
s(:hash, *visit_all(node.assocs).flatten(1))
|
122
|
+
end
|
123
|
+
|
124
|
+
# Visit a BEGINBlock node.
|
125
|
+
def visit_BEGIN(node)
|
126
|
+
s(:iter, s(:preexe), 0, visit(node.statements))
|
127
|
+
end
|
128
|
+
|
129
|
+
# Visit a Begin node.
|
130
|
+
def visit_begin(node)
|
131
|
+
raise
|
132
|
+
end
|
133
|
+
|
134
|
+
# Visit a Binary node.
|
135
|
+
def visit_binary(node)
|
136
|
+
case node
|
137
|
+
in { operator: :and }
|
138
|
+
s(:and, visit(node.left), visit(node.right))
|
139
|
+
in { operator: :"!~" }
|
140
|
+
s(:not, s(:call, visit(node.left), :=~, visit(node.right)))
|
141
|
+
else
|
142
|
+
s(:call, visit(node.left), node.operator, visit(node.right))
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Visit a BlockArg node.
|
147
|
+
def visit_blockarg(node)
|
148
|
+
:"&#{visit(node.name)}"
|
149
|
+
end
|
150
|
+
|
151
|
+
# Visit a BlockVar node.
|
152
|
+
def visit_block_var(node)
|
153
|
+
case node
|
154
|
+
in { locals: [] }
|
155
|
+
s(*visit(node.params))
|
156
|
+
else
|
157
|
+
s(*visit(node.params), s(:shadow, *node.locals.map { |local| visit(local) }))
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Visit a BodyStmt node.
|
162
|
+
def visit_bodystmt(node)
|
163
|
+
visit(node.statements)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Visit a BraceBlock node.
|
167
|
+
def visit_brace_block(node)
|
168
|
+
raise
|
169
|
+
end
|
170
|
+
|
171
|
+
# Visit a Break node.
|
172
|
+
def visit_break(node)
|
173
|
+
s(:break, *visit(node.arguments)[1..])
|
174
|
+
end
|
175
|
+
|
176
|
+
# Visit a Call node.
|
177
|
+
def visit_call(node)
|
178
|
+
case node
|
179
|
+
in { message: :call, arguments: ArgParen[arguments: nil] }
|
180
|
+
s(call_type(node.operator), visit(node.receiver), :call)
|
181
|
+
in { message: :call, arguments: ArgParen[arguments: { parts: }] }
|
182
|
+
s(call_type(node.operator), visit(node.receiver), :call, *visit_all(parts))
|
183
|
+
in { arguments: nil | ArgParen[arguments: nil] }
|
184
|
+
s(call_type(node.operator), visit(node.receiver), node.message.value.to_sym)
|
185
|
+
in { arguments: Args[parts:] }
|
186
|
+
s(call_type(node.operator), visit(node.receiver), node.message.value.to_sym, *visit_all(parts))
|
187
|
+
in { arguments: ArgParen[arguments: { parts: }] }
|
188
|
+
s(call_type(node.operator), visit(node.receiver), node.message.value.to_sym, *visit_all(parts))
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# Visit a Case node.
|
193
|
+
def visit_case(node)
|
194
|
+
clauses = [node.consequent]
|
195
|
+
clauses << clauses.last.consequent while clauses.last && !(clauses.last in Else)
|
196
|
+
s(:case, visit(node.value), *visit_all(clauses))
|
197
|
+
end
|
198
|
+
|
199
|
+
# Visit a CHAR node.
|
200
|
+
def visit_CHAR(node)
|
201
|
+
s(:str, node.value[1..])
|
202
|
+
end
|
203
|
+
|
204
|
+
# Visit a ClassDeclaration node.
|
205
|
+
def visit_class(node)
|
206
|
+
s(:class, visit(node.constant), visit(node.superclass), visit(node.bodystmt))
|
207
|
+
end
|
208
|
+
|
209
|
+
# Visit a Comma node.
|
210
|
+
def visit_comma(node)
|
211
|
+
raise
|
212
|
+
end
|
213
|
+
|
214
|
+
# Visit a Command node.
|
215
|
+
def visit_command(node)
|
216
|
+
s(:call, nil, node.message.value.to_sym, *visit_all(node.arguments.parts))
|
217
|
+
end
|
218
|
+
|
219
|
+
# Visit a CommandCall node.
|
220
|
+
def visit_command_call(node)
|
221
|
+
arguments =
|
222
|
+
case node
|
223
|
+
in { arguments: nil }
|
224
|
+
# do nothing
|
225
|
+
in { arguments: Args[parts:] }
|
226
|
+
visit_all(parts)
|
227
|
+
in { arguments: ArgParen[arguments: { parts: }] }
|
228
|
+
visit_all(parts)
|
229
|
+
end
|
230
|
+
|
231
|
+
s(call_type(node.operator), visit(node.receiver), visit(node.message), *arguments)
|
232
|
+
end
|
233
|
+
|
234
|
+
# Visit a Comment node.
|
235
|
+
def visit_comment(node)
|
236
|
+
raise
|
237
|
+
end
|
238
|
+
|
239
|
+
# Visit a Const node.
|
240
|
+
def visit_const(node)
|
241
|
+
s(:const, node.value.to_sym)
|
242
|
+
end
|
243
|
+
|
244
|
+
# Visit a ConstPathField node.
|
245
|
+
def visit_const_path_field(node)
|
246
|
+
s(:colon2, visit(node.parent), node.constant.value.to_sym)
|
247
|
+
end
|
248
|
+
|
249
|
+
# Visit a ConstPathRef node.
|
250
|
+
def visit_const_path_ref(node)
|
251
|
+
raise
|
252
|
+
end
|
253
|
+
|
254
|
+
# Visit a ConstRef node.
|
255
|
+
def visit_const_ref(node)
|
256
|
+
node.constant.value.to_sym
|
257
|
+
end
|
258
|
+
|
259
|
+
# Visit a CVar node.
|
260
|
+
def visit_cvar(node)
|
261
|
+
s(:cvar, node.value.to_sym)
|
262
|
+
end
|
263
|
+
|
264
|
+
# Visit a Def node.
|
265
|
+
def visit_def(node)
|
266
|
+
args = (node.params in Params) ? node.params : node.params.contents
|
267
|
+
s(:defn, node.name.value.to_sym, visit(args), visit(node.bodystmt))
|
268
|
+
end
|
269
|
+
|
270
|
+
# Visit a DefEndless node.
|
271
|
+
def visit_def_endless(node)
|
272
|
+
children = []
|
273
|
+
children << visit(node.target) if node.target
|
274
|
+
|
275
|
+
args = (node.paren in Params) ? node.paren : node.paren.contents
|
276
|
+
children += [node.name.value.to_sym, visit(args), visit(node.statement)]
|
277
|
+
|
278
|
+
s(node.target ? :defs : :defn, *children)
|
279
|
+
end
|
280
|
+
|
281
|
+
# Visit a Defined node.
|
282
|
+
def visit_defined(node)
|
283
|
+
s(:defined, visit(node.value))
|
284
|
+
end
|
285
|
+
|
286
|
+
# Visit a Defs node.
|
287
|
+
def visit_defs(node)
|
288
|
+
args = (node.params in Params) ? node.params : node.params.contents
|
289
|
+
s(:defs, visit(node.target), visit(node.name), visit(args), visit(node.bodystmt))
|
290
|
+
end
|
291
|
+
|
292
|
+
# Visit a DoBlock node.
|
293
|
+
def visit_do_block(node)
|
294
|
+
raise
|
295
|
+
end
|
296
|
+
|
297
|
+
# Visit a Dot2 node.
|
298
|
+
def visit_dot2(node)
|
299
|
+
s(:dot2, visit(node.left), visit(node.right))
|
300
|
+
end
|
301
|
+
|
302
|
+
# Visit a Dot3 node.
|
303
|
+
def visit_dot3(node)
|
304
|
+
s(:dot3, visit(node.left), visit(node.right))
|
305
|
+
end
|
306
|
+
|
307
|
+
# Visit a DynaSymbol node.
|
308
|
+
def visit_dyna_symbol(node)
|
309
|
+
case node
|
310
|
+
in { parts: [] }
|
311
|
+
s(:lit, :"")
|
312
|
+
in { parts: [TStringContent => part] }
|
313
|
+
s(:lit, part.value.to_sym)
|
314
|
+
in { parts: [StringEmbExpr => part, *parts] }
|
315
|
+
s(:dsym, "", visit(part), *visit_all(parts))
|
316
|
+
else
|
317
|
+
s(:dsym, *visit_all(node.parts))
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
# Visit an ENDBlock node.
|
322
|
+
def visit_END(node)
|
323
|
+
s(:iter, s(:postexe), 0, visit(node.statements))
|
324
|
+
end
|
325
|
+
|
326
|
+
# Visit an Else node.
|
327
|
+
def visit_else(node)
|
328
|
+
visit(node.statements)
|
329
|
+
end
|
330
|
+
|
331
|
+
# Visit an Elsif node.
|
332
|
+
def visit_elsif(node)
|
333
|
+
statements = node.statements.empty? ? nil : visit(node.statements)
|
334
|
+
s(:if, visit(node.predicate), statements, visit(node.consequent))
|
335
|
+
end
|
336
|
+
|
337
|
+
# Visit an EmbDoc node.
|
338
|
+
def visit_embdoc(node)
|
339
|
+
raise
|
340
|
+
end
|
341
|
+
|
342
|
+
# Visit an EmbExprBeg node.
|
343
|
+
def visit_embexpr_beg(node)
|
344
|
+
raise
|
345
|
+
end
|
346
|
+
|
347
|
+
# Visit an EmbExprEnd node.
|
348
|
+
def visit_embexpr_end(node)
|
349
|
+
raise
|
350
|
+
end
|
351
|
+
|
352
|
+
# Visit an EmbVar node.
|
353
|
+
def visit_embvar(node)
|
354
|
+
raise
|
355
|
+
end
|
356
|
+
|
357
|
+
# Visit an Ensure node.
|
358
|
+
def visit_ensure(node)
|
359
|
+
raise
|
360
|
+
end
|
361
|
+
|
362
|
+
# Visit an ExcessedComma node.
|
363
|
+
def visit_excessed_comma(node)
|
364
|
+
raise
|
365
|
+
end
|
366
|
+
|
367
|
+
# Visit a FCall node.
|
368
|
+
def visit_fcall(node)
|
369
|
+
case node
|
370
|
+
in { arguments: Args[parts: []] | ArgParen[arguments: nil] }
|
371
|
+
s(:call, nil, node.value.value.to_sym)
|
372
|
+
in { arguments: ArgParen[arguments: { parts: }] }
|
373
|
+
s(:call, nil, node.value.value.to_sym, *visit_all(parts))
|
374
|
+
in { arguments: ArgParen[arguments: ArgsForward] }
|
375
|
+
s(:call, nil, node.value.value.to_sym, s(:forwarded_args))
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
# Visit a Field node.
|
380
|
+
def visit_field(node)
|
381
|
+
s(:attrasgn, visit(node.parent), :"#{node.name.value}=")
|
382
|
+
end
|
383
|
+
|
384
|
+
# Visit a FloatLiteral node.
|
385
|
+
def visit_float(node)
|
386
|
+
s(:lit, node.value.to_f)
|
387
|
+
end
|
388
|
+
|
389
|
+
# Visit a FndPtn node.
|
390
|
+
def visit_fndptn(node)
|
391
|
+
raise
|
392
|
+
end
|
393
|
+
|
394
|
+
# Visit a For node.
|
395
|
+
def visit_for(node)
|
396
|
+
raise
|
397
|
+
end
|
398
|
+
|
399
|
+
# Visit a GVar node.
|
400
|
+
def visit_gvar(node)
|
401
|
+
node.value.to_sym
|
402
|
+
end
|
403
|
+
|
404
|
+
# Visit a HashLiteral node.
|
405
|
+
def visit_hash(node)
|
406
|
+
s(:hash, *visit_all(node.assocs).flatten(1))
|
407
|
+
end
|
408
|
+
|
409
|
+
# Visit a Heredoc node.
|
410
|
+
def visit_heredoc(node)
|
411
|
+
raise
|
412
|
+
end
|
413
|
+
|
414
|
+
# Visit a HeredocBeg node.
|
415
|
+
def visit_heredoc_beg(node)
|
416
|
+
raise
|
417
|
+
end
|
418
|
+
|
419
|
+
# Visit a HshPtn node.
|
420
|
+
def visit_hshptn(node)
|
421
|
+
children = [
|
422
|
+
visit(node.constant),
|
423
|
+
*node.keywords.flat_map { |(keyword, value)| [visit(keyword), visit(value)] }
|
424
|
+
]
|
425
|
+
|
426
|
+
children << visit(node.keyword_rest) if node.keyword_rest
|
427
|
+
s(:hash_pat, *children)
|
428
|
+
end
|
429
|
+
|
430
|
+
# Visit an Ident node.
|
431
|
+
def visit_ident(node)
|
432
|
+
node.value.to_sym
|
433
|
+
end
|
434
|
+
|
435
|
+
# Visit an If node.
|
436
|
+
def visit_if(node)
|
437
|
+
statements = node.statements.empty? ? nil : visit(node.statements)
|
438
|
+
s(:if, visit(node.predicate), statements, visit(node.consequent))
|
439
|
+
end
|
440
|
+
|
441
|
+
# Visit an IfMod node.
|
442
|
+
def visit_if_mod(node)
|
443
|
+
s(:if, visit(node.predicate), visit(node.statement), nil)
|
444
|
+
end
|
445
|
+
|
446
|
+
# Visit an IfOp node.
|
447
|
+
def visit_if_op(node)
|
448
|
+
s(:if, visit(node.predicate), visit(node.truthy), visit(node.falsy))
|
449
|
+
end
|
450
|
+
|
451
|
+
# Visit an Imaginary node.
|
452
|
+
def visit_imaginary(node)
|
453
|
+
s(:lit, eval(node.value))
|
454
|
+
end
|
455
|
+
|
456
|
+
# Visit an In node.
|
457
|
+
def visit_in(node)
|
458
|
+
s(:in, visit(node.pattern), visit(node.statements))
|
459
|
+
end
|
460
|
+
|
461
|
+
# Visit an Int node.
|
462
|
+
def visit_int(node)
|
463
|
+
s(:lit, node.value.to_i)
|
464
|
+
end
|
465
|
+
|
466
|
+
# Visit an IVar node.
|
467
|
+
def visit_ivar(node)
|
468
|
+
s(:ivar, node.value.to_sym)
|
469
|
+
end
|
470
|
+
|
471
|
+
# Visit a Kw node.
|
472
|
+
def visit_kw(node)
|
473
|
+
s(node.value.to_sym)
|
474
|
+
end
|
475
|
+
|
476
|
+
# Visit a KwRestParam node.
|
477
|
+
def visit_kwrest_param(node)
|
478
|
+
:"**#{visit(node.name)}"
|
479
|
+
end
|
480
|
+
|
481
|
+
# Visit a Label node.
|
482
|
+
def visit_label(node)
|
483
|
+
value = node.value.chomp(":").to_sym
|
484
|
+
(stack[-2] in Params) ? value : s(:lit, value)
|
485
|
+
end
|
486
|
+
|
487
|
+
# Visit a LabelEnd node.
|
488
|
+
def visit_label_end(node)
|
489
|
+
raise
|
490
|
+
end
|
491
|
+
|
492
|
+
# Visit a Lambda node.
|
493
|
+
def visit_lambda(node)
|
494
|
+
children = [s(:lambda)]
|
495
|
+
|
496
|
+
case node
|
497
|
+
in { params: Paren[contents: Params => params] } if params.empty?
|
498
|
+
children << s(:args)
|
499
|
+
in { params: Params => params } if params.empty?
|
500
|
+
children << 0
|
501
|
+
else
|
502
|
+
children << visit(node.params)
|
503
|
+
end
|
504
|
+
|
505
|
+
children << visit(node.statements) unless node.statements.empty?
|
506
|
+
|
507
|
+
s(:iter, *children)
|
508
|
+
end
|
509
|
+
|
510
|
+
# Visit a LBrace node.
|
511
|
+
def visit_lbrace(node)
|
512
|
+
raise
|
513
|
+
end
|
514
|
+
|
515
|
+
# Visit a LBracket node.
|
516
|
+
def visit_lbracket(node)
|
517
|
+
raise
|
518
|
+
end
|
519
|
+
|
520
|
+
# Visit a LParen node.
|
521
|
+
def visit_lparen(node)
|
522
|
+
raise
|
523
|
+
end
|
524
|
+
|
525
|
+
# Visit a MAssign node.
|
526
|
+
def visit_massign(node)
|
527
|
+
s(:masgn, s(:array, visit(node.target)), s(:to_ary, visit(node.value)))
|
528
|
+
end
|
529
|
+
|
530
|
+
# Visit a MethodAddBlock node.
|
531
|
+
def visit_method_add_block(node)
|
532
|
+
statements =
|
533
|
+
if node.block in BraceBlock
|
534
|
+
node.block.statements
|
535
|
+
else
|
536
|
+
node.block.bodystmt
|
537
|
+
end
|
538
|
+
|
539
|
+
block = statements.empty? ? nil : visit(statements)
|
540
|
+
|
541
|
+
if node.call in Break | Next | Return | Yield
|
542
|
+
type, *children = visit(node.call)
|
543
|
+
s(type, s(:iter, *children, visit(node.block.block_var), *block))
|
544
|
+
else
|
545
|
+
s(:iter, visit(node.call), visit(node.block.block_var), *block)
|
546
|
+
end
|
547
|
+
end
|
548
|
+
|
549
|
+
# Visit a MLHS node.
|
550
|
+
def visit_mlhs(node)
|
551
|
+
s(:masgn, *visit_all(node.parts))
|
552
|
+
end
|
553
|
+
|
554
|
+
# Visit a MLHSParen node.
|
555
|
+
def visit_mlhs_paren(node)
|
556
|
+
visit(node.contents)
|
557
|
+
end
|
558
|
+
|
559
|
+
# Visit a ModuleDeclaration node.
|
560
|
+
def visit_module(node)
|
561
|
+
raise
|
562
|
+
end
|
563
|
+
|
564
|
+
# Visit a MRHS node.
|
565
|
+
def visit_mrhs(node)
|
566
|
+
s(:svalue, s(:array, *visit_all(node.parts)))
|
567
|
+
end
|
568
|
+
|
569
|
+
# Visit a Next node.
|
570
|
+
def visit_next(node)
|
571
|
+
s(:next, *visit(node.arguments)[1..])
|
572
|
+
end
|
573
|
+
|
574
|
+
# Visit a Not node.
|
575
|
+
def visit_not(node)
|
576
|
+
s(:call, visit(node.statement), :"!")
|
577
|
+
end
|
578
|
+
|
579
|
+
# Visit an Op node.
|
580
|
+
def visit_op(node)
|
581
|
+
node.value.to_sym
|
582
|
+
end
|
583
|
+
|
584
|
+
# Visit an OpAssign node.
|
585
|
+
def visit_opassign(node)
|
586
|
+
case node.operator
|
587
|
+
in { value: "||=" }
|
588
|
+
s(:op_asgn_or, visit(node.target), visit(node.value))
|
589
|
+
in { value: "&&=" }
|
590
|
+
s(:op_asgn_and, visit(node.target), visit(node.value))
|
591
|
+
else
|
592
|
+
s(:op_asgn, visit(node.target), node.operator.value.chomp("=").to_sym, visit(node.value))
|
593
|
+
end
|
594
|
+
end
|
595
|
+
|
596
|
+
# Visit a Params node.
|
597
|
+
def visit_params(node)
|
598
|
+
s(
|
599
|
+
:args,
|
600
|
+
*node.requireds.map { |required| visit(required) },
|
601
|
+
*node.optionals.map { |(name, value)| s(:lasgn, visit(name), visit(value)) },
|
602
|
+
*visit(node.rest),
|
603
|
+
*node.posts.map { |post| visit(post) },
|
604
|
+
*node.keywords.map do |(name, value)|
|
605
|
+
children = [visit(name)]
|
606
|
+
children << visit(value) if value
|
607
|
+
s(:kwarg, *children)
|
608
|
+
end,
|
609
|
+
*visit(node.keyword_rest),
|
610
|
+
*visit(node.block)
|
611
|
+
)
|
612
|
+
end
|
613
|
+
|
614
|
+
# Visit a Paren node.
|
615
|
+
def visit_paren(node)
|
616
|
+
visit(node.contents)
|
617
|
+
end
|
618
|
+
|
619
|
+
# Visit a Period node.
|
620
|
+
def visit_period(node)
|
621
|
+
raise
|
622
|
+
end
|
623
|
+
|
624
|
+
# Visit a PinnedBegin node.
|
625
|
+
def visit_pinned_begin(node)
|
626
|
+
raise
|
627
|
+
end
|
628
|
+
|
629
|
+
# Visit a PinnedVarRef node.
|
630
|
+
def visit_pinned_var_ref(node)
|
631
|
+
raise
|
632
|
+
end
|
633
|
+
|
634
|
+
# Visit a Program node.
|
635
|
+
def visit_program(node)
|
636
|
+
visit(node.statements)
|
637
|
+
end
|
638
|
+
|
639
|
+
# Visit a QSymbols node.
|
640
|
+
def visit_qsymbols(node)
|
641
|
+
s(
|
642
|
+
:array,
|
643
|
+
*node.elements.map { |element| s(:lit, element.value.to_sym) }
|
644
|
+
)
|
645
|
+
end
|
646
|
+
|
647
|
+
# Visit a QSymbolsBeg node.
|
648
|
+
def visit_qsymbols_beg(node)
|
649
|
+
raise
|
650
|
+
end
|
651
|
+
|
652
|
+
# Visit a QWords node.
|
653
|
+
def visit_qwords(node)
|
654
|
+
s(:array, *visit_all(node.elements))
|
655
|
+
end
|
656
|
+
|
657
|
+
# Visit a QWordsBeg node.
|
658
|
+
def visit_qwords_beg(node)
|
659
|
+
raise
|
660
|
+
end
|
661
|
+
|
662
|
+
# Visit a RAssign node.
|
663
|
+
def visit_rassign(node)
|
664
|
+
s(:case, visit(node.value), s(:in, visit(node.pattern), nil), nil)
|
665
|
+
end
|
666
|
+
|
667
|
+
# Visit a RationalLiteral node.
|
668
|
+
def visit_rational(node)
|
669
|
+
s(:lit, node.value.to_r)
|
670
|
+
end
|
671
|
+
|
672
|
+
# Visit a RBrace node.
|
673
|
+
def visit_rbrace(node)
|
674
|
+
raise
|
675
|
+
end
|
676
|
+
|
677
|
+
# Visit a RBracket node.
|
678
|
+
def visit_rbracket(node)
|
679
|
+
raise
|
680
|
+
end
|
681
|
+
|
682
|
+
# Visit a Redo node.
|
683
|
+
def visit_redo(node)
|
684
|
+
s(:redo)
|
685
|
+
end
|
686
|
+
|
687
|
+
# Visit a RegexpBeg node.
|
688
|
+
def visit_regexp_beg(node)
|
689
|
+
raise
|
690
|
+
end
|
691
|
+
|
692
|
+
# Visit a RegexpContent node.
|
693
|
+
def visit_regexp_content(node)
|
694
|
+
raise
|
695
|
+
end
|
696
|
+
|
697
|
+
# Visit a RegexpEnd node.
|
698
|
+
def visit_regexp_end(node)
|
699
|
+
raise
|
700
|
+
end
|
701
|
+
|
702
|
+
# Visit a RegexpLiteral node.
|
703
|
+
def visit_regexp_literal(node)
|
704
|
+
raise
|
705
|
+
end
|
706
|
+
|
707
|
+
# Visit a Rescue node.
|
708
|
+
def visit_rescue(node)
|
709
|
+
raise
|
710
|
+
end
|
711
|
+
|
712
|
+
# Visit a RescueEx node.
|
713
|
+
def visit_rescue_ex(node)
|
714
|
+
raise
|
715
|
+
end
|
716
|
+
|
717
|
+
# Visit a RescueMod node.
|
718
|
+
def visit_rescue_mod(node)
|
719
|
+
s(:rescue, visit(node.statement), s(:resbody, s(:array), visit(node.value)))
|
720
|
+
end
|
721
|
+
|
722
|
+
# Visit a RestParam node.
|
723
|
+
def visit_rest_param(node)
|
724
|
+
:"*#{visit(node.name)}"
|
725
|
+
end
|
726
|
+
|
727
|
+
# Visit a Retry node.
|
728
|
+
def visit_retry(node)
|
729
|
+
s(:retry)
|
730
|
+
end
|
731
|
+
|
732
|
+
# Visit a Return node.
|
733
|
+
def visit_return(node)
|
734
|
+
s(:return, *visit(node.arguments)[1..])
|
735
|
+
end
|
736
|
+
|
737
|
+
# Visit a Return0 node.
|
738
|
+
def visit_return0(node)
|
739
|
+
s(:return)
|
740
|
+
end
|
741
|
+
|
742
|
+
# Visit a RParen node.
|
743
|
+
def visit_rparen(node)
|
744
|
+
raise
|
745
|
+
end
|
746
|
+
|
747
|
+
# Visit a SClass node.
|
748
|
+
def visit_sclass(node)
|
749
|
+
raise
|
750
|
+
end
|
751
|
+
|
752
|
+
# Visit a Statements node.
|
753
|
+
def visit_statements(node)
|
754
|
+
children = node.body.reject { |child| child in Comment | EmbDoc | EndContent | VoidStmt }
|
755
|
+
|
756
|
+
case children
|
757
|
+
in []
|
758
|
+
s(:nil)
|
759
|
+
in [child]
|
760
|
+
visit(child)
|
761
|
+
else
|
762
|
+
s(:block, *visit_all(children))
|
763
|
+
end
|
764
|
+
end
|
765
|
+
|
766
|
+
# Visit a StringConcat node.
|
767
|
+
def visit_string_concat(node)
|
768
|
+
raise
|
769
|
+
end
|
770
|
+
|
771
|
+
# Visit a StringContent node.
|
772
|
+
def visit_string_content(node)
|
773
|
+
raise
|
774
|
+
end
|
775
|
+
|
776
|
+
# Visit a StringDVar node.
|
777
|
+
def visit_string_dvar(node)
|
778
|
+
raise
|
779
|
+
end
|
780
|
+
|
781
|
+
# Visit a StringEmbExpr node.
|
782
|
+
def visit_string_embexpr(node)
|
783
|
+
s(:evstr, visit(node.statements))
|
784
|
+
end
|
785
|
+
|
786
|
+
# Visit a StringLiteral node.
|
787
|
+
def visit_string_literal(node)
|
788
|
+
children = [+""]
|
789
|
+
|
790
|
+
node.parts.each_with_index do |part, index|
|
791
|
+
if children.last in String
|
792
|
+
case part
|
793
|
+
in StringEmbExpr[statements: { body: [StringLiteral[parts: [TStringContent => tstring]]] }]
|
794
|
+
children.last << visit(tstring)
|
795
|
+
in TStringContent
|
796
|
+
children.last << visit(part)
|
797
|
+
else
|
798
|
+
children << visit(part)
|
799
|
+
end
|
800
|
+
else
|
801
|
+
children << visit(part)
|
802
|
+
end
|
803
|
+
end
|
804
|
+
|
805
|
+
case children
|
806
|
+
in [String => child]
|
807
|
+
s(:str, child)
|
808
|
+
else
|
809
|
+
s(:dstr, *children)
|
810
|
+
end
|
811
|
+
end
|
812
|
+
|
813
|
+
# Visit a Super node.
|
814
|
+
def visit_super(node)
|
815
|
+
raise
|
816
|
+
end
|
817
|
+
|
818
|
+
# Visit a SymBeg node.
|
819
|
+
def visit_symbeg(node)
|
820
|
+
raise
|
821
|
+
end
|
822
|
+
|
823
|
+
# Visit a SymbolContent node.
|
824
|
+
def visit_symbol_content(node)
|
825
|
+
raise
|
826
|
+
end
|
827
|
+
|
828
|
+
# Visit a SymbolLiteral node.
|
829
|
+
def visit_symbol_literal(node)
|
830
|
+
s(:lit, node.value.value.to_sym)
|
831
|
+
end
|
832
|
+
|
833
|
+
# Visit a Symbols node.
|
834
|
+
def visit_symbols(node)
|
835
|
+
s(:array, *visit_all(node.elements))
|
836
|
+
end
|
837
|
+
|
838
|
+
# Visit a SymbolsBeg node.
|
839
|
+
def visit_symbols_beg(node)
|
840
|
+
raise
|
841
|
+
end
|
842
|
+
|
843
|
+
# Visit a TLambda node.
|
844
|
+
def visit_tlambda(node)
|
845
|
+
raise
|
846
|
+
end
|
847
|
+
|
848
|
+
# Visit a TLamBeg node.
|
849
|
+
def visit_tlambeg(node)
|
850
|
+
raise
|
851
|
+
end
|
852
|
+
|
853
|
+
# Visit a TopConstField node.
|
854
|
+
def visit_top_const_field(node)
|
855
|
+
s(:colon3, node.constant.value.to_sym)
|
856
|
+
end
|
857
|
+
|
858
|
+
# Visit a TopConstRef node.
|
859
|
+
def visit_top_const_ref(node)
|
860
|
+
s(:colon3, node.constant.value.to_sym)
|
861
|
+
end
|
862
|
+
|
863
|
+
# Visit a TStringBeg node.
|
864
|
+
def visit_tstring_beg(node)
|
865
|
+
raise
|
866
|
+
end
|
867
|
+
|
868
|
+
# Visit a TStringContent node.
|
869
|
+
def visit_tstring_content(node)
|
870
|
+
node.value
|
871
|
+
end
|
872
|
+
|
873
|
+
# Visit a TStringEnd node.
|
874
|
+
def visit_tstring_end(node)
|
875
|
+
raise
|
876
|
+
end
|
877
|
+
|
878
|
+
# Visit an Unary node.
|
879
|
+
def visit_unary(node)
|
880
|
+
case node
|
881
|
+
in { operator: "+" }
|
882
|
+
s(:call, visit(node.statement), :+@)
|
883
|
+
in { statement: FloatLiteral[value:], operator: "-" }
|
884
|
+
s(:lit, -value.to_f)
|
885
|
+
in { statement: Int[value:], operator: "-" }
|
886
|
+
s(:lit, -value.to_i)
|
887
|
+
in { operator: "-" }
|
888
|
+
s(:call, visit(node.statement), :-@)
|
889
|
+
else
|
890
|
+
s(:call, visit(node.statement), node.operator.to_sym)
|
891
|
+
end
|
892
|
+
end
|
893
|
+
|
894
|
+
# Visit an Undef node.
|
895
|
+
def visit_undef(node)
|
896
|
+
raise
|
897
|
+
end
|
898
|
+
|
899
|
+
# Visit an Unless node.
|
900
|
+
def visit_unless(node)
|
901
|
+
raise
|
902
|
+
end
|
903
|
+
|
904
|
+
# Visit an UnlessMod node.
|
905
|
+
def visit_unless_mod(node)
|
906
|
+
s(:unless, visit(node.predicate), visit(node.statement), nil)
|
907
|
+
end
|
908
|
+
|
909
|
+
# Visit an Until node.
|
910
|
+
def visit_until(node)
|
911
|
+
s(:until, visit(node.predicate), visit(node.statements), true)
|
912
|
+
end
|
913
|
+
|
914
|
+
# Visit an UntilMod node.
|
915
|
+
def visit_until_mod(node)
|
916
|
+
s(:until, visit(node.predicate), visit(node.statement), true)
|
917
|
+
end
|
918
|
+
|
919
|
+
# Visit a VarAlias node.
|
920
|
+
def visit_var_alias(node)
|
921
|
+
s(:valias, visit(node.left), visit(node.right))
|
922
|
+
end
|
923
|
+
|
924
|
+
# Visit a VarField node.
|
925
|
+
def visit_var_field(node)
|
926
|
+
case node.value
|
927
|
+
in Const[value:] then s(:casgn, nil, value.to_sym)
|
928
|
+
in CVar[value:] then s(:cvasgn, value.to_sym)
|
929
|
+
in GVar[value:] then s(:gvasgn, value.to_sym)
|
930
|
+
in Ident[value:] then s(:lasgn, value.to_sym)
|
931
|
+
in IVar[value:] then s(:ivasgn, value.to_sym)
|
932
|
+
in VarRef[value:] then s(:lasgn, value.to_sym)
|
933
|
+
in :nil then s(:kwrest, :"**nil")
|
934
|
+
in nil then :*
|
935
|
+
end
|
936
|
+
end
|
937
|
+
|
938
|
+
# Visit a VarRef node.
|
939
|
+
def visit_var_ref(node)
|
940
|
+
visit(node.value)
|
941
|
+
end
|
942
|
+
|
943
|
+
# Visit a VCall node.
|
944
|
+
def visit_vcall(node)
|
945
|
+
s(:call, nil, node.value.value.to_sym)
|
946
|
+
end
|
947
|
+
|
948
|
+
# Visit a VoidStmt node.
|
949
|
+
def visit_void_stmt(node)
|
950
|
+
raise
|
951
|
+
end
|
952
|
+
|
953
|
+
# Visit a When node.
|
954
|
+
def visit_when(node)
|
955
|
+
cases = s(:array, *visit_all(node.arguments.parts))
|
956
|
+
statements = node.statements.empty? ? nil : visit(node.statements)
|
957
|
+
s(:when, cases, statements)
|
958
|
+
end
|
959
|
+
|
960
|
+
# Visit a While node.
|
961
|
+
def visit_while(node)
|
962
|
+
s(:while, visit(node.predicate), visit(node.statements), true)
|
963
|
+
end
|
964
|
+
|
965
|
+
# Visit a WhileMod node.
|
966
|
+
def visit_while_mod(node)
|
967
|
+
s(:while, visit(node.predicate), visit(node.statement), true)
|
968
|
+
end
|
969
|
+
|
970
|
+
# Visit a Word node.
|
971
|
+
def visit_word(node)
|
972
|
+
case stack[-2]
|
973
|
+
in Symbols
|
974
|
+
case node
|
975
|
+
in { parts: [TStringContent => part] }
|
976
|
+
s(:lit, part.value.to_sym)
|
977
|
+
in { parts: [StringEmbExpr => part, *parts] }
|
978
|
+
s(:dsym, "", visit(part), *visit_all(parts))
|
979
|
+
else
|
980
|
+
s(:dsym, *visit_all(parts))
|
981
|
+
end
|
982
|
+
in Words
|
983
|
+
case node
|
984
|
+
in { parts: [TStringContent => part] }
|
985
|
+
s(:str, visit(part))
|
986
|
+
in { parts: [StringEmbExpr => part, *parts] }
|
987
|
+
s(:dstr, "", visit(part), *visit_all(parts))
|
988
|
+
else
|
989
|
+
s(:dstr, *visit_all(parts))
|
990
|
+
end
|
991
|
+
end
|
992
|
+
end
|
993
|
+
|
994
|
+
# Visit a Words node.
|
995
|
+
def visit_words(node)
|
996
|
+
s(:array, *visit_all(node.elements))
|
997
|
+
end
|
998
|
+
|
999
|
+
# Visit a WordsBeg node.
|
1000
|
+
def visit_words_beg(node)
|
1001
|
+
raise
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
# Visit a XString node.
|
1005
|
+
def visit_xstring(node)
|
1006
|
+
raise
|
1007
|
+
end
|
1008
|
+
|
1009
|
+
# Visit a XStringLiteral node.
|
1010
|
+
def visit_xstring_literal(node)
|
1011
|
+
case node
|
1012
|
+
in { parts: [StringEmbExpr => part, *parts] }
|
1013
|
+
s(:dxstr, "", visit(part), *visit_all(parts))
|
1014
|
+
else
|
1015
|
+
s(:dxstr, *visit_all(node.parts))
|
1016
|
+
end
|
1017
|
+
end
|
1018
|
+
|
1019
|
+
# Visit a Yield node.
|
1020
|
+
def visit_yield(node)
|
1021
|
+
case node
|
1022
|
+
in { arguments: Args[parts:] }
|
1023
|
+
s(:yield, *visit_all(parts))
|
1024
|
+
in { arguments: Paren[contents: Args[parts:]] }
|
1025
|
+
s(:yield, *visit_all(parts))
|
1026
|
+
end
|
1027
|
+
end
|
1028
|
+
|
1029
|
+
# Visit a Yield0 node.
|
1030
|
+
def visit_yield0(node)
|
1031
|
+
s(:yield)
|
1032
|
+
end
|
1033
|
+
|
1034
|
+
# Visit a ZSuper node.
|
1035
|
+
def visit_zsuper(node)
|
1036
|
+
s(:zsuper)
|
1037
|
+
end
|
1038
|
+
|
1039
|
+
# Visit an EndContent node.
|
1040
|
+
def visit___end__(node)
|
1041
|
+
raise
|
1042
|
+
end
|
1043
|
+
|
1044
|
+
private
|
1045
|
+
|
1046
|
+
def call_type(operator)
|
1047
|
+
(operator in Op[value: "&."]) ? :safe_call : :call
|
1048
|
+
end
|
1049
|
+
|
1050
|
+
def s(*args)
|
1051
|
+
Sexp.new(*args)
|
1052
|
+
end
|
1053
|
+
end
|
1054
|
+
end
|
1055
|
+
end
|