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.
@@ -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