syntax_tree-translator 0.1.0

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