gloss 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a1461d26e97ea9693ee00d63016e0fa1e34ea719de672ae0d4c303e4efb5144
4
- data.tar.gz: 2370827768056a2575c1987d661a140d7247b68629e049aa58b0bc9d1de0bc31
3
+ metadata.gz: 3a630a77074bd1fa44113b542bd04b312957e3d59834dc9dec0282466e60d50a
4
+ data.tar.gz: 653fc89b0793a114f9d6a04348a63d76368db464bf93a713268467140551680c
5
5
  SHA512:
6
- metadata.gz: 17d5c598e8199b375599112a4365cb14691e651783a86880844dd35ff312dc2ca2ed0bb632e0a51897dcd3ba774231ae9c547710f19ed134318a39e098224a37
7
- data.tar.gz: 6626ff60cab24dacfc6e6780368a719e04c45c80c1f4e8b89db76bfdc0848f725e33d907058b6c9991fc80c1b97b518503eb42a47435c733f43a4e0d0d49eb0e
6
+ metadata.gz: 0f8573f5596495a00d31c102edf033f010f07092a6441a26809dc7d0044e906651058191ff9b37a87d840cae4fb16916aad76e27d219688824cd06366ef46c3c
7
+ data.tar.gz: 22a085469dd74a3c88d3334ac8c75c44ea8e43fbca211acc5e25cd83230bc435b48b262787d6eccacf2efff2f4ed5324aa11a3e102e1aa9bc0ebe1dba04d2564
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gloss (0.0.3)
4
+ gloss (0.0.4)
5
5
  fast_blank
6
6
  listen
7
7
  rbs
@@ -22,7 +22,7 @@ GEM
22
22
  thor (>= 0.19)
23
23
  byebug (11.1.3)
24
24
  coderay (1.1.3)
25
- concurrent-ruby (1.1.7)
25
+ concurrent-ruby (1.1.8)
26
26
  diff-lcs (1.4.4)
27
27
  fast_blank (1.0.0)
28
28
  ffi (1.14.2)
@@ -50,7 +50,7 @@ GEM
50
50
  rb-fsevent (0.10.4)
51
51
  rb-inotify (0.10.1)
52
52
  ffi (~> 1.0)
53
- rbs (1.0.0)
53
+ rbs (1.0.3)
54
54
  regexp_parser (2.0.3)
55
55
  rexml (3.2.4)
56
56
  rspec (3.10.0)
@@ -86,7 +86,7 @@ GEM
86
86
  parser (~> 2.7.0)
87
87
  rainbow (>= 2.2.2, < 4.0)
88
88
  rbs (~> 1.0.0)
89
- thor (1.0.1)
89
+ thor (1.1.0)
90
90
  tzinfo (2.0.4)
91
91
  concurrent-ruby (~> 1.0)
92
92
  unicode-display_width (1.7.0)
File without changes
@@ -0,0 +1,3 @@
1
+ module Gloss
2
+ class Any; end
3
+ end
@@ -104,8 +104,19 @@ module Crystal
104
104
 
105
105
  class Def < ASTNode
106
106
  def to_rb
107
- Rb::AST::DefNode.new(@name, @args.map(&.to_rb), @body.to_rb, receiver.try(&.to_rb),
108
- return_type.try(&.to_rb), @double_splat.try(&.to_rb))
107
+ positional_args = args.dup
108
+ splat = @splat_index ? positional_args.delete_at(@splat_index.as(Int32)) : nil
109
+ Rb::AST::DefNode.new(
110
+ receiver.try(&.to_rb),
111
+ @name,
112
+ positional_args.map(&.to_rb),
113
+ splat.try(&.to_rb),
114
+ @double_splat.try(&.to_rb),
115
+ @body.to_rb,
116
+ return_type.try(&.to_rb),
117
+ @yields,
118
+ @block_arg.try &.to_rb
119
+ )
109
120
  end
110
121
  end
111
122
 
@@ -141,7 +152,8 @@ module Crystal
141
152
  @args.map(&.to_rb),
142
153
  @named_args.try(&.map(&.to_rb.as(Rb::AST::Arg))),
143
154
  @block.try(&.to_rb),
144
- @block_arg.try(&.to_rb)
155
+ @block_arg.try(&.to_rb),
156
+ @has_parentheses
145
157
  )
146
158
  end
147
159
  end
@@ -187,7 +199,7 @@ module Crystal
187
199
 
188
200
  class MultiAssign < ASTNode
189
201
  def to_rb
190
- Rb::AST::EmptyNode.new(self.class.name)
202
+ Rb::AST::MultiAssign.new(@targets.map(&.to_rb), @values.map(&.to_rb))
191
203
  end
192
204
  end
193
205
 
@@ -424,14 +436,35 @@ module Crystal
424
436
  [@const.to_rb],
425
437
  nil,
426
438
  nil,
427
- nil
439
+ nil,
440
+ false
441
+ )
442
+ end
443
+ end
444
+
445
+ class VisibilityModifier < ASTNode
446
+ def to_rb
447
+ Rb::AST::VisibilityModifier.new(@modifier, @exp.to_rb)
448
+ end
449
+ end
450
+
451
+ class Yield < ASTNode
452
+ def to_rb
453
+ Rb::AST::Call.new(
454
+ nil,
455
+ "yield",
456
+ @exps.map(&.to_rb),
457
+ nil,
458
+ nil,
459
+ nil,
460
+ !@exps.empty?
428
461
  )
429
462
  end
430
463
  end
431
464
 
432
- {% for class_name in %w[ProcNotation Macro OffsetOf VisibilityModifier RespondsTo
465
+ {% for class_name in %w[ProcNotation Macro OffsetOf RespondsTo
433
466
  Select ImplicitObj AnnotationDef While Until UninitializedVar
434
- ProcPointer Self Yield LibDef FunDef TypeDef CStructOrUnionDef
467
+ ProcPointer Self LibDef FunDef TypeDef CStructOrUnionDef
435
468
  ExternalVar Alias Metaclass Cast NilableCast TypeOf Annotation
436
469
  Underscore MagicConstant Asm AsmOperand] %}
437
470
  class {{class_name.id}} < ASTNode
@@ -441,7 +474,7 @@ module Crystal
441
474
  end
442
475
  {% end %}
443
476
 
444
- {% for class_name in %w[PointerOf SizeOf InstanceSizeOf Out MacroVerbatim DoubleSplat] %}
477
+ {% for class_name in %w[PointerOf SizeOf InstanceSizeOf Out MacroVerbatim] %}
445
478
  class {{class_name.id}} < UnaryExpression
446
479
  def to_rb
447
480
  Rb::AST::EmptyNode.new(self.class.name)
@@ -1,4 +1,5 @@
1
- require "./lib/cr_ruby"
1
+ require "../lib/cr_ruby"
2
+ require "../lib/rbs_types"
2
3
  require "./cr_ast"
3
4
  require "./rb_ast"
4
5
  require "./parser"
@@ -115,7 +115,7 @@ module Crystal
115
115
  case next_char
116
116
  when '='
117
117
  next_char :"<<="
118
- when '-'
118
+ when '-', '~'
119
119
  has_single_quote = false
120
120
  found_closing_single_quote = false
121
121
 
@@ -1182,5 +1182,63 @@ module Crystal
1182
1182
 
1183
1183
  @token
1184
1184
  end
1185
+
1186
+ def check_heredoc_start
1187
+ return nil unless current_char == '<' && next_char == '<' && {'-', '~'}.includes?(next_char)
1188
+
1189
+ has_single_quote = false
1190
+ found_closing_single_quote = false
1191
+
1192
+ char = next_char
1193
+ start_here = current_pos
1194
+
1195
+ if char == '\''
1196
+ has_single_quote = true
1197
+ char = next_char
1198
+ start_here = current_pos
1199
+ end
1200
+
1201
+ return nil unless ident_part?(char)
1202
+
1203
+ end_here = 0
1204
+
1205
+ while true
1206
+ char = next_char
1207
+ case
1208
+ when char == '\r'
1209
+ if peek_next_char == '\n'
1210
+ end_here = current_pos
1211
+ next_char
1212
+ break
1213
+ else
1214
+ return nil
1215
+ end
1216
+ when char == '\n'
1217
+ end_here = current_pos
1218
+ break
1219
+ when ident_part?(char)
1220
+ # ok
1221
+ when char == '\0'
1222
+ return nil
1223
+ else
1224
+ if char == '\'' && has_single_quote
1225
+ found_closing_single_quote = true
1226
+ end_here = current_pos
1227
+ next_char
1228
+ break
1229
+ elsif has_single_quote
1230
+ # wait until another quote
1231
+ else
1232
+ end_here = current_pos
1233
+ break
1234
+ end
1235
+ end
1236
+ end
1237
+
1238
+ return nil if has_single_quote && !found_closing_single_quote
1239
+
1240
+ here = string_range(start_here, end_here)
1241
+ Token::DelimiterState.new(:heredoc, here, here, allow_escapes: !has_single_quote)
1242
+ end
1185
1243
  end
1186
1244
  end
@@ -94,18 +94,31 @@ module Rb
94
94
  end
95
95
 
96
96
  class DefNode < Node
97
- @info : NamedTuple(type: String, name: String, body: Node, rp_args: Array(Arg), receiver: Node?,
98
- return_type: Node?, rest_kw_args: Arg?)
97
+ @info : NamedTuple(type: String, name: String, body: Node, positional_args: Array(Arg), receiver: Node?,
98
+ return_type: Node?, rest_kw_args: Arg?, rest_p_args: Arg?, block_arg: Node?, yield_arg_count: Int32?)
99
99
 
100
- def initialize(name : String, rp_args : Array(Arg), body : Node, receiver : Node?, return_type : Node?, rest_kw_args)
100
+ def initialize(
101
+ receiver : Node?,
102
+ name : String,
103
+ positional_args : Array(Arg),
104
+ splat,
105
+ rest_kw_args,
106
+ body : Node,
107
+ return_type : Node?,
108
+ yields : Int32?,
109
+ block_arg : Node?
110
+ )
101
111
  @info = {
102
- type: self.class.name.split("::").last,
103
- name: name,
104
- body: body,
105
- rp_args: rp_args,
106
- rest_kw_args: rest_kw_args,
107
- receiver: receiver,
108
- return_type: return_type,
112
+ type: self.class.name.split("::").last,
113
+ name: name,
114
+ body: body,
115
+ positional_args: positional_args,
116
+ rest_kw_args: rest_kw_args,
117
+ receiver: receiver,
118
+ return_type: return_type,
119
+ rest_p_args: splat,
120
+ yield_arg_count: yields,
121
+ block_arg: block_arg
109
122
  }
110
123
  end
111
124
 
@@ -116,15 +129,14 @@ module Rb
116
129
  @info : NamedTuple(type: String, name: String, external_name: String, value: Node?,
117
130
  restriction: Node?, keyword_arg: Bool)
118
131
 
119
- def initialize(name : String, external_name : String, restriction : Node?, value :
120
- Node?, keyword_arg)
132
+ def initialize(name : String, external_name : String, restriction : Node?, value : Node?, keyword_arg)
121
133
  @info = {
122
134
  type: self.class.name.split("::").last,
123
135
  name: name,
124
136
  restriction: restriction,
125
- value: value,
137
+ value: value,
126
138
  external_name: external_name,
127
- keyword_arg: keyword_arg
139
+ keyword_arg: keyword_arg,
128
140
  }
129
141
  end
130
142
 
@@ -318,18 +330,19 @@ module Rb
318
330
  end
319
331
 
320
332
  class Call < Node
321
- @info : NamedTuple(type: String, name: String, args: Array(Node), object: Node?, block:
322
- Block?, block_arg: Node?, named_args: Array(Arg)?)
333
+ @info : NamedTuple(type: String, name: String, args: Array(Node), object: Node?, block: Block?, block_arg: Node?, named_args: Array(Arg)?, has_parentheses: Bool)
323
334
 
324
- def initialize(object : Node?, name : String, args : Array(Node), named_args, block, block_arg)
335
+ def initialize(object : Node?, name : String, args : Array(Node), named_args, block,
336
+ block_arg, has_parentheses)
325
337
  @info = {
326
- type: self.class.name.split("::").last,
327
- name: name,
328
- args: args,
329
- object: object,
330
- block: block,
331
- block_arg: block_arg,
332
- named_args: named_args,
338
+ type: self.class.name.split("::").last,
339
+ name: name,
340
+ args: args,
341
+ object: object,
342
+ block: block,
343
+ block_arg: block_arg,
344
+ named_args: named_args,
345
+ has_parentheses: has_parentheses || false,
333
346
  }
334
347
  end
335
348
 
@@ -400,6 +413,20 @@ module Rb
400
413
  delegate :to_json, to: @info
401
414
  end
402
415
 
416
+ class MultiAssign < Node
417
+ @info : NamedTuple(type: String, targets: Array(Node), values: Array(Node))
418
+
419
+ def initialize(targets, values)
420
+ @info = {
421
+ type: self.class.name.split("::").last,
422
+ targets: targets,
423
+ values: values,
424
+ }
425
+ end
426
+
427
+ delegate :to_json, to: @info
428
+ end
429
+
403
430
  class TypeDeclaration < Node
404
431
  @info : NamedTuple(type: String, var: Node, declared_type: Node, value: Node?, var_type: String)
405
432
 
@@ -511,7 +538,7 @@ module Rb
511
538
  def initialize(types)
512
539
  @info = {
513
540
  type: self.class.name.split("::").last,
514
- types: types
541
+ types: types,
515
542
  }
516
543
  end
517
544
 
@@ -523,9 +550,9 @@ module Rb
523
550
 
524
551
  def initialize(name, args)
525
552
  @info = {
526
- type: self.class.name.split("::").last,
553
+ type: self.class.name.split("::").last,
527
554
  name: name,
528
- args: args
555
+ args: args,
529
556
  }
530
557
  end
531
558
 
@@ -537,8 +564,8 @@ module Rb
537
564
 
538
565
  def initialize(function)
539
566
  @info = {
540
- type: self.class.name.split("::").last,
541
- function: function
567
+ type: self.class.name.split("::").last,
568
+ function: function,
542
569
  }
543
570
  end
544
571
 
@@ -550,8 +577,8 @@ module Rb
550
577
 
551
578
  def initialize(name)
552
579
  @info = {
553
- type: self.class.name.split("::").last,
554
- name: name
580
+ type: self.class.name.split("::").last,
581
+ name: name,
555
582
  }
556
583
  end
557
584
 
@@ -563,5 +590,27 @@ module Rb
563
590
 
564
591
  class Include < NodeWithNameNode
565
592
  end
593
+
594
+ class VisibilityModifier < Node
595
+ @info : NamedTuple(type: String, visibility: String, exp: Node)
596
+
597
+ def initialize(visibility : Crystal::Visibility, exp : Node)
598
+ vis = case visibility
599
+ when Crystal::Visibility::Public
600
+ "public"
601
+ when Crystal::Visibility::Protected
602
+ "protected"
603
+ when Crystal::Visibility::Private
604
+ "private"
605
+ end
606
+ @info = {
607
+ type: self.class.name.split("::").last,
608
+ visibility: vis.as(String),
609
+ exp: exp,
610
+ }
611
+ end
612
+
613
+ delegate :to_json, to: @info
614
+ end
566
615
  end
567
616
  end
@@ -1,9 +1,11 @@
1
- # frozen_string_literal: true
1
+ # frozen_string_literal: true
2
2
 
3
- module Gloss
4
- class Builder
5
- attr_reader :tree
3
+ ##### This file was generated by Gloss; any changes made here will be overwritten.
4
+ ##### See src/ to make changes
6
5
 
6
+ module Gloss
7
+ class Builder
8
+ attr_reader(:"tree")
7
9
  def initialize(tree_hash, type_checker = nil)
8
10
  @indent_level = 0
9
11
  @inside_macro = false
@@ -12,436 +14,603 @@ module Gloss
12
14
  @tree = tree_hash
13
15
  @type_checker = type_checker
14
16
  end
15
-
16
- def run
17
+ def run()
17
18
  rb_output = visit_node(@tree)
18
- <<~RUBY
19
- #{"# frozen_string_literal: true\n" if Config.frozen_string_literals}
20
- ##### This file was generated by Gloss; any changes made here will be overwritten.
21
- ##### See #{Config.src_dir}/ to make changes
22
-
23
- #{rb_output}
24
- RUBY
19
+ " #{(if Config.frozen_string_literals
20
+ "# frozen_string_literal: true\n"
21
+ end)}\n ##### This file was generated by Gloss; any changes made here will be overwritten.\n ##### See #{Config.src_dir}/ to make changes\n\n #{rb_output}"
25
22
  end
26
-
27
23
  def visit_node(node, scope = Scope.new)
28
24
  src = Source.new(@indent_level)
29
- case node[:type]
30
- when "ClassNode"
31
- class_name = visit_node(node[:name])
32
- current_namespace = @current_scope ? @current_scope.name.to_namespace : RBS::Namespace.root
33
- superclass_type = nil
34
- superclass_output = nil
35
- if node[:superclass]
36
- @eval_vars = true
37
- superclass_output = visit_node(node[:superclass])
38
- @eval_vars = false
39
- ns = if superclass_output.start_with? '::'
40
- RBS::Namespace.root
41
- elsif superclass_output.include? '::'
42
- current_namespace
43
- else
44
- RBS::Namespace.empty
45
- end
46
- superclass_type = RBS::AST::Declarations::Class::Super.new(
47
- name: RBS::TypeName.new(
48
- name: superclass_output.to_sym,
49
- namespace: ns
50
- ),
51
- args: [],
52
- location: nil
53
- )
54
- end
55
-
56
- src.write_ln "class #{class_name}#{" < #{superclass_output}" if superclass_output}"
57
-
58
- class_type = RBS::AST::Declarations::Class.new(
59
- name: RBS::TypeName.new(
60
- namespace: current_namespace,
61
- name: class_name.to_sym
62
- ),
63
- type_params: RBS::AST::Declarations::ModuleTypeParams.new, # responds to #add to add params
64
- super_class: superclass_type,
65
- members: [],
66
- annotations: [],
67
- location: node[:location],
68
- comment: node[:comment]
69
- )
70
- old_parent_scope = @current_scope
71
- @current_scope = class_type
72
-
73
- indented(src) { src.write_ln visit_node(node[:body]) if node[:body] }
74
-
75
- src.write_ln "end"
76
-
77
- @current_scope = old_parent_scope
78
-
79
- @current_scope.members << class_type if @current_scope
80
-
81
- if @type_checker
82
- @type_checker.top_level_decls[class_type.name.name] = class_type unless @current_scope
83
- end
84
- when "ModuleNode"
85
- module_name = visit_node node[:name]
86
- src.write_ln "module #{module_name}"
87
-
88
- current_namespace = @current_scope ? @current_scope.name.to_namespace : RBS::Namespace.root
89
-
90
- module_type = RBS::AST::Declarations::Module.new(
91
- name: RBS::TypeName.new(
92
- namespace: current_namespace,
93
- name: module_name.to_sym
94
- ),
95
- type_params: RBS::AST::Declarations::ModuleTypeParams.new, # responds to #add to add params
96
- self_types: [],
97
- members: [],
98
- annotations: [],
99
- location: node[:location],
100
- comment: node[:comment]
101
- )
102
- old_parent_scope = @current_scope
103
- @current_scope = module_type
104
-
105
- indented(src) { src.write_ln visit_node(node[:body]) if node[:body] }
106
-
107
- @current_scope = old_parent_scope
108
-
109
- @current_scope.members << module_type if @current_scope
110
-
111
- if @type_checker
112
- @type_checker.top_level_decls[module_type.name.name] = module_type unless @current_scope
113
- end
114
- src.write_ln "end"
115
- when "DefNode"
116
- args = render_args(node)
117
- src.write_ln "def #{node[:name]}#{args}"
118
-
119
- return_type = if node[:return_type]
120
- RBS::Types::ClassInstance.new(
121
- name: RBS::TypeName.new(
122
- name: eval(visit_node(node[:return_type])).to_s.to_sym,
123
- namespace: RBS::Namespace.root
124
- ),
125
- args: [],
126
- location: nil
127
- )
128
- else
129
- RBS::Types::Bases::Any.new(location: nil)
130
- end
131
-
132
- method_types = [
133
- RBS::MethodType.new(
134
- type_params: [],
135
- type: RBS::Types::Function.new(
136
- required_positionals: node[:rp_args]&.map do |a|
137
- RBS::Types::Function::Param.new(
138
- name: visit_node(a).to_sym,
139
- type: RBS::Types::Bases::Any.new(location: nil)
140
- )
141
- end || EMPTY_ARRAY,
142
- optional_positionals: node[:op_args] || EMPTY_ARRAY,
143
- rest_positionals: node[:rest_p_args],
144
- trailing_positionals: [],
145
- required_keywords: node[:req_kw_args] || EMPTY_HASH,
146
- optional_keywords: node[:opt_kw_args] || EMPTY_HASH,
147
- rest_keywords: node[:rest_kw_args] ?
148
- RBS::Types::Function::Param.new(
149
- name: visit_node(node[:rest_kw_args]).to_sym,
150
- type: RBS::Types::Bases::Any.new(location: nil)
151
- ) : nil,
152
- return_type: return_type
153
- ),
154
- block: nil,
155
- location: nil
156
- )
157
- ]
158
- method_definition = RBS::AST::Members::MethodDefinition.new(
159
- name: node[:name].to_sym,
160
- kind: :instance,
161
- types: method_types,
162
- annotations: [],
163
- location: node[:location],
164
- comment: node[:comment],
165
- overload: false
166
- )
167
-
168
- if @current_scope
169
- @current_scope.members << method_definition
170
- else
171
- @type_checker.type_env << method_definition if @type_checker # should be new class declaration for Object with method_definition as private method
172
- end
173
-
174
- indented(src) { src.write_ln visit_node(node[:body]) if node[:body] }
175
-
176
- src.write_ln "end"
177
- when "CollectionNode"
178
- src.write(*node[:children].map { |a| visit_node(a, scope) })
179
- when "Call"
180
- obj = node[:object] ? "#{visit_node(node[:object], scope)}." : ""
181
- args = node[:args] || EMPTY_ARRAY
182
- args += node[:named_args] if node[:named_args]
183
- args = if !args.empty? || node[:block_arg]
184
- "(#{args.map { |a| visit_node(a, scope).strip }.reject(&:blank?).join(", ")}#{"&#{visit_node(node[:block_arg]).strip}" if node[:block_arg]})"
185
- else
186
- nil
187
- end
188
- block = node[:block] ? " #{visit_node(node[:block])}" : nil
189
- src.write_ln "#{obj}#{node[:name]}#{args}#{block}"
190
-
191
- when "Block"
192
-
193
- src.write "{ |#{node[:args].map { |a| visit_node a }.join(", ")}|\n"
194
-
195
- indented(src) { src.write visit_node(node[:body]) }
196
-
197
- src.write_ln "}"
198
-
199
- when "RangeLiteral"
200
- dots = node[:exclusive] ? "..." : ".."
201
-
202
- # parentheses help the compatibility with precendence of operators in some situations
203
- # eg. (1..3).cover? 2 vs. 1..3.cover? 2
204
- src.write "(", visit_node(node[:from]), dots, visit_node(node[:to]), ")"
205
-
206
- when "LiteralNode"
207
-
208
- src.write node[:value]
209
-
210
- when "ArrayLiteral"
211
-
212
- src.write("[", *node[:elements].map { |e| visit_node e }.join(", "), "]")
213
- src.write ".freeze" if node[:frozen]
214
-
215
- when "StringInterpolation"
216
-
217
- contents = node[:contents].inject(String.new) do |str, c|
218
- str << case c[:type]
219
- when "LiteralNode"
220
- c[:value][1...-1]
221
- else
222
- "\#{#{visit_node(c).strip}}"
223
- end
224
- end
225
- src.write '"', contents, '"'
226
-
227
- when "Path"
228
-
229
- src.write node[:value]
230
-
231
- when "Require"
232
-
233
- src.write_ln %(require "#{node[:value]}")
234
-
235
- when "Assign", "OpAssign"
236
-
237
- src.write_ln "#{visit_node(node[:target])} #{node[:op]}= #{visit_node(node[:value]).strip}"
238
-
239
- when "Var"
240
-
241
- if @eval_vars
242
- src.write scope[node[:name]]
243
- else
244
- src.write node[:name]
245
- end
246
-
247
- when "InstanceVar"
248
-
249
- src.write node[:name]
250
-
251
- when "GlobalVar"
252
-
253
- src.write node[:name]
254
-
255
- when "Arg"
256
- val = node[:external_name]
257
- if node[:keyword_arg]
258
- val += ":"
259
- val += " #{visit_node(node[:value])}" if node[:value]
260
- elsif node[:value]
261
- val += " = #{visit_node(node[:value])}"
262
- end
263
-
264
- src.write val
265
-
266
- when "UnaryExpr"
267
-
268
- src.write "#{node[:op]}#{visit_node(node[:value]).strip}"
269
-
270
- when "BinaryOp"
271
-
272
- src.write visit_node(node[:left]).strip, " #{node[:op]} ", visit_node(node[:right]).strip
273
-
274
- when "HashLiteral"
275
-
276
- contents = node[:elements].map do |k, v|
277
- key = case k
278
- when String
279
- k.to_sym
280
- else
281
- visit_node k
282
- end
283
- value = visit_node v
284
- "#{key.inspect} => #{value}"
285
- end
286
-
287
- src.write "{#{contents.join(",\n")}}"
288
- src.write ".freeze" if node[:frozen]
289
-
290
- when "Enum"
291
- src.write_ln "module #{node[:name]}"
292
- node[:members].each_with_index do |m, i|
293
- indented(src) { src.write_ln(visit_node(m) + (!m[:value] ? " = #{i}" : "")) }
294
- end
295
- src.write_ln "end"
296
- when "If"
297
- src.write_ln "(if #{visit_node(node[:condition]).strip}"
298
-
299
- indented(src) { src.write_ln visit_node(node[:then]) }
300
-
301
- if node[:else]
302
- src.write_ln "else"
303
- indented(src) { src.write_ln visit_node(node[:else]) }
304
- end
305
-
306
- src.write_ln "end)"
307
- when "Unless"
308
- src.write_ln "unless #{visit_node node[:condition]}"
309
- indented(src) { src.write_ln visit_node(node[:then]) }
310
-
311
- if node[:else]
312
- src.write_ln "else"
313
- indented(src) { src.write_ln visit_node(node[:else]) }
314
- end
315
-
316
- src.write_ln "end"
317
- when "Case"
318
- src.write "case"
319
- src.write " #{visit_node(node[:condition]).strip}\n" if node[:condition]
320
- indented(src) do
321
- node[:whens].each do |w|
322
- src.write_ln visit_node(w)
323
- end
324
- end
325
- src.write_ln "end"
326
- when "When"
327
- src.write_ln "when #{node[:conditions].map { |n| visit_node(n) }.join(", ")}"
328
-
329
- indented(src) { src.write_ln visit_node(node[:body]) }
330
- when "MacroFor"
331
- vars, expr, body = node[:vars], node[:expr], node[:body]
332
- var_names = vars.map { |v| visit_node v }
333
- @inside_macro = true
334
- indent_level = @indent_level
335
- @indent_level -= 1 unless indent_level.zero?
336
- expanded = eval(visit_node(expr)).map do |*a|
337
- locals = Hash[[var_names.join(%(", "))].zip(a)]
338
- locals.merge!(scope) if @inside_macro
339
- visit_node(body, locals)
340
- end.flatten
341
- @indent_level += 1 unless indent_level.zero?
342
- src.write(*expanded)
343
- @inside_macro = false
344
- when "MacroLiteral"
345
- src.write node[:value]
346
- when "MacroExpression"
347
- if node[:output]
348
- expr = visit_node node[:expr], scope
349
- val = scope[expr]
350
- src.write val
351
- end
352
- when "MacroIf"
353
- if evaluate_macro_condition(node[:condition], scope)
354
- src.write_ln visit_node(node[:then], scope) if node[:then]
355
- else
356
- src.write_ln visit_node(node[:else], scope) if node[:else]
357
- end
358
- when "Return"
359
- val = node[:value] ? " #{visit_node(node[:value]).strip}" : nil
360
- src.write "return#{val}"
361
- when "TypeDeclaration"
362
- src.write_ln "# @type var #{visit_node(node[:var])}: #{visit_node(node[:declared_type])}"
363
- src.write_ln "#{visit_node(node[:var])} = #{visit_node(node[:value])}"
364
- when "ExceptionHandler"
365
- src.write_ln "begin"
366
- indented src do
367
- src.write_ln visit_node(node[:body])
368
- end
369
- node[:rescues]&.each do |r|
370
- src.write_ln "rescue #{r[:types].map { |n| visit_node n }.join(", ") if r[:types]}#{" => #{r[:name]}" if r[:name]}"
371
- indented(src) { src.write_ln visit_node(r[:body]) } if r[:body]
372
- end
373
- if node[:else]
374
- src.write_ln "else"
375
- indented(src) { src.write_ln visit_node(node[:else]) }
25
+ case node.[](:"type")
26
+ when "ClassNode"
27
+ class_name = visit_node(node.[](:"name"))
28
+ current_namespace = (if @current_scope
29
+ @current_scope.name
30
+ .to_namespace
31
+ else
32
+ RBS::Namespace.root
33
+ end)
34
+ superclass_type = nil
35
+ superclass_output = nil
36
+ (if node.[](:"superclass")
37
+ @eval_vars = true
38
+ superclass_output = visit_node(node.[](:"superclass"))
39
+ @eval_vars = false
40
+ superclass_type = RBS::Parser.parse_type(superclass_output)
41
+ (if node.dig(:"superclass", :"type")
42
+ .==("Generic")
43
+ superclass_output = superclass_output.[](/^[^\[]+/)
44
+ end)
45
+ end)
46
+ src.write_ln("class #{class_name}#{(if superclass_output
47
+ " < #{superclass_output}"
48
+ end)}")
49
+ class_type = RBS::AST::Declarations::Class.new(name: RBS::TypeName.new(namespace: current_namespace, name: class_name.to_sym), type_params: RBS::AST::Declarations::ModuleTypeParams.new, super_class: superclass_type, members: Array.new, annotations: Array.new, location: node.[](:"location"), comment: node.[](:"comment"))
50
+ old_parent_scope = @current_scope
51
+ @current_scope = class_type
52
+ indented(src) { ||
53
+ (if node.[](:"body")
54
+ src.write_ln(visit_node(node.[](:"body")))
55
+ end)
56
+ }
57
+ src.write_ln("end")
58
+ @current_scope = old_parent_scope
59
+ (if @current_scope
60
+ @current_scope.members
61
+ .<<(class_type)
62
+ end)
63
+ (if @type_checker
64
+ unless @current_scope
65
+ @type_checker.top_level_decls
66
+ .[]=(class_type.name
67
+ .name, class_type)
68
+ end
69
+ end)
70
+ when "ModuleNode"
71
+ module_name = visit_node(node.[](:"name"))
72
+ src.write_ln("module #{module_name}")
73
+ current_namespace = (if @current_scope
74
+ @current_scope.name
75
+ .to_namespace
76
+ else
77
+ RBS::Namespace.root
78
+ end)
79
+ module_type = RBS::AST::Declarations::Module.new(name: RBS::TypeName.new(namespace: current_namespace, name: module_name.to_sym), type_params: RBS::AST::Declarations::ModuleTypeParams.new, self_types: Array.new, members: Array.new, annotations: Array.new, location: node.[](:"location"), comment: node.[](:"comment"))
80
+ old_parent_scope = @current_scope
81
+ @current_scope = module_type
82
+ indented(src) { ||
83
+ (if node.[](:"body")
84
+ src.write_ln(visit_node(node.[](:"body")))
85
+ end)
86
+ }
87
+ @current_scope = old_parent_scope
88
+ (if @current_scope
89
+ @current_scope.members
90
+ .<<(module_type)
91
+ end)
92
+ (if @type_checker
93
+ unless @current_scope
94
+ @type_checker.top_level_decls
95
+ .[]=(module_type.name
96
+ .name, module_type)
97
+ end
98
+ end)
99
+ src.write_ln("end")
100
+ when "DefNode"
101
+ args = render_args(node)
102
+ src.write_ln("def #{node.[](:"name")}#{args}")
103
+ return_type = (if node.[](:"return_type")
104
+ RBS::Types::ClassInstance.new(name: RBS::TypeName.new(name: eval(visit_node(node.[](:"return_type")))
105
+ .to_s
106
+ .to_sym, namespace: RBS::Namespace.root), args: EMPTY_ARRAY, location: node.[](:"location"))
107
+ else
108
+ RBS::Types::Bases::Any.new(location: node.[](:"location"))
109
+ end)
110
+ # @type var rp: Array[Hash[Symbol, Any]]
111
+ rp = node.fetch(:"positional_args") { ||
112
+ EMPTY_ARRAY }
113
+ .filter() { |a|
114
+ !a.[](:"value") }
115
+ # @type var op: Array[Hash[Symbol, Any]]
116
+ op = node.fetch(:"positional_args") { ||
117
+ EMPTY_ARRAY }
118
+ .filter() { |a|
119
+ a.[](:"value")
120
+ }
121
+ method_types = [RBS::MethodType.new(type_params: EMPTY_ARRAY, type: RBS::Types::Function.new(required_positionals: rp.map() { |a|
122
+ RBS::Types::Function::Param.new(name: visit_node(a)
123
+ .to_sym, type: RBS::Types::Bases::Any.new(location: a.[](:"location")))
124
+ }, optional_positionals: op.map() { |a|
125
+ RBS::Types::Function::Param.new(name: visit_node(a)
126
+ .to_sym, type: RBS::Types::Bases::Any.new(location: a.[](:"location")))
127
+ }, rest_positionals: (if rpa = node.[](:"rest_p_args")
128
+ RBS::Types::Function::Param.new(name: visit_node(rpa)
129
+ .to_sym, type: RBS::Types::Bases::Any.new(location: node.[](:"location")))
130
+ else
131
+ nil
132
+ end), trailing_positionals: EMPTY_ARRAY, required_keywords: node.[](:"req_kw_args") || EMPTY_HASH, optional_keywords: node.[](:"opt_kw_args") || EMPTY_HASH, rest_keywords: (if node.[](:"rest_kw_args")
133
+ RBS::Types::Function::Param.new(name: visit_node(node.[](:"rest_kw_args"))
134
+ .to_sym, type: RBS::Types::Bases::Any.new(location: node.[](:"location")))
135
+ else
136
+ nil
137
+ end), return_type: return_type), block: (if node.[](:"yield_arg_count")
138
+ RBS::Types::Block.new(type: RBS::Types::Function.new(required_positionals: Array.new, optional_positionals: Array.new, rest_positionals: nil, trailing_positionals: Array.new, required_keywords: Hash.new, optional_keywords: Hash.new, rest_keywords: nil, return_type: RBS::Types::Bases::Any.new(location: node.[](:"location"))), required: !!node.[](:"block_arg") || node.[](:"yield_arg_count"))
139
+ else
140
+ nil
141
+ end), location: node.[](:"location"))]
142
+ method_definition = RBS::AST::Members::MethodDefinition.new(name: node.[](:"name")
143
+ .to_sym, kind: :"instance", types: method_types, annotations: EMPTY_ARRAY, location: node.[](:"location"), comment: node.[](:"comment"), overload: false)
144
+ (if @current_scope
145
+ @current_scope.members
146
+ .<<(method_definition)
147
+ else
148
+ (if @type_checker
149
+ @type_checker.type_env
150
+ .<<(method_definition)
151
+ end)
152
+ end)
153
+ indented(src) { ||
154
+ (if node.[](:"body")
155
+ src.write_ln(visit_node(node.[](:"body")))
156
+ end)
157
+ }
158
+ src.write_ln("end")
159
+ when "VisibilityModifier"
160
+ src.write_ln("#{node.[](:"visibility")} #{visit_node(node.[](:"exp"))}")
161
+ when "CollectionNode"
162
+ node.[](:"children")
163
+ .each() { |a|
164
+ src.write(visit_node(a, scope))
165
+ }
166
+ when "Call"
167
+ obj = (if node.[](:"object")
168
+ "#{visit_node(node.[](:"object"), scope)}."
169
+ else
170
+ ""
171
+ end)
172
+ arg_arr = node.fetch(:"args") { ||
173
+ EMPTY_ARRAY }
174
+ (if node.[](:"named_args")
175
+ arg_arr += node.[](:"named_args")
176
+ end)
177
+ args = (if !arg_arr.empty? || node.[](:"block_arg")
178
+ "#{arg_arr.map() { |a|
179
+ visit_node(a, scope)
180
+ .strip
181
+ }
182
+ .reject(&:"blank?")
183
+ .join(", ")}#{(if node.[](:"block_arg")
184
+ "&#{visit_node(node.[](:"block_arg"))
185
+ .strip}"
186
+ end)}"
187
+ else
188
+ nil
189
+ end)
190
+ block = (if node.[](:"block")
191
+ " #{visit_node(node.[](:"block"))}"
192
+ else
193
+ nil
194
+ end)
195
+ has_parens = !!node.[](:"has_parentheses") || args || block
196
+ opening_delimiter = (if has_parens
197
+ "("
198
+ else
199
+ nil
200
+ end)
201
+ call = "#{obj}#{node.[](:"name")}#{opening_delimiter}#{args}#{(if has_parens
202
+ ")"
203
+ end)}#{block}"
204
+ src.write_ln(call)
205
+ when "Block"
206
+ src.write("{ |#{node.[](:"args")
207
+ .map() { |a|
208
+ visit_node(a)
209
+ }
210
+ .join(", ")}|\n")
211
+ indented(src) { ||
212
+ src.write(visit_node(node.[](:"body")))
213
+ }
214
+ src.write_ln("}")
215
+ when "RangeLiteral"
216
+ dots = (if node.[](:"exclusive")
217
+ "..."
218
+ else
219
+ ".."
220
+ end)
221
+ src.write("(", visit_node(node.[](:"from")), dots, visit_node(node.[](:"to")), ")")
222
+ when "LiteralNode"
223
+ src.write(node.[](:"value"))
224
+ when "ArrayLiteral"
225
+ src.write("[", node.[](:"elements")
226
+ .map() { |e|
227
+ visit_node(e)
228
+ .strip
229
+ }
230
+ .join(", "), "]")
231
+ (if node.[](:"frozen")
232
+ src.write(".freeze")
233
+ end)
234
+ when "StringInterpolation"
235
+ contents = node.[](:"contents")
236
+ .inject(String.new) { |str, c|
237
+ str.<<(case c.[](:"type")
238
+ when "LiteralNode"
239
+ c.[](:"value")
240
+ .[]((1...-1))
241
+ else
242
+ ["\#{", visit_node(c)
243
+ .strip, "}"].join
244
+ end)
245
+ }
246
+ src.write("\"", contents, "\"")
247
+ when "Path"
248
+ src.write(node.[](:"value"))
249
+ when "Require"
250
+ src.write_ln("require \"#{node.[](:"value")}\"")
251
+ when "Assign", "OpAssign"
252
+ src.write_ln("#{visit_node(node.[](:"target"))} #{node.[](:"op")}= #{visit_node(node.[](:"value"))
253
+ .strip}")
254
+ when "MultiAssign"
255
+ src.write_ln("#{node.[](:"targets")
256
+ .map() { |t|
257
+ visit_node(t)
258
+ .strip
259
+ }
260
+ .join(", ")} = #{node.[](:"values")
261
+ .map() { |v|
262
+ visit_node(v)
263
+ .strip
264
+ }
265
+ .join(", ")}")
266
+ when "Var"
267
+ (if @eval_vars
268
+ src.write(scope.[](node.[](:"name")))
269
+ else
270
+ src.write(node.[](:"name"))
271
+ end)
272
+ when "InstanceVar"
273
+ src.write(node.[](:"name"))
274
+ when "GlobalVar"
275
+ src.write(node.[](:"name"))
276
+ when "Arg"
277
+ val = node.[](:"external_name")
278
+ (if node.[](:"keyword_arg")
279
+ val += ":"
280
+ (if node.[](:"value")
281
+ val += " #{visit_node(node.[](:"value"))}"
282
+ end)
283
+ else
284
+ (if node.[](:"value")
285
+ val += " = #{visit_node(node.[](:"value"))}"
286
+ end)
287
+ end)
288
+ src.write(val)
289
+ when "UnaryExpr"
290
+ src.write("#{node.[](:"op")}#{visit_node(node.[](:"value"))
291
+ .strip}")
292
+ when "BinaryOp"
293
+ src.write(visit_node(node.[](:"left"))
294
+ .strip, " #{node.[](:"op")} ", visit_node(node.[](:"right"))
295
+ .strip)
296
+ when "HashLiteral"
297
+ contents = node.[](:"elements")
298
+ .map() { |k, v|
299
+ key = case k
300
+ when String
301
+ k.to_sym
302
+ else
303
+ visit_node(k)
304
+ end
305
+ value = visit_node(v)
306
+ "#{key.inspect} => #{value}" }
307
+ src.write("{#{contents.join(",\n")}}")
308
+ (if node.[](:"frozen")
309
+ src.write(".freeze")
310
+ end)
311
+ when "Enum"
312
+ src.write_ln("module #{node.[](:"name")}")
313
+ node.[](:"members")
314
+ .each_with_index() { |m, i|
315
+ indented(src) { ||
316
+ src.write_ln(visit_node(m)
317
+ .+((if !m.[](:"value")
318
+ " = #{i}"
319
+ else
320
+ ""
321
+ end)))
322
+ }
323
+ }
324
+ src.write_ln("end")
325
+ when "If"
326
+ src.write_ln("(if #{visit_node(node.[](:"condition"))
327
+ .strip}")
328
+ indented(src) { ||
329
+ src.write_ln(visit_node(node.[](:"then")))
330
+ }
331
+ (if node.[](:"else")
332
+ src.write_ln("else")
333
+ indented(src) { ||
334
+ src.write_ln(visit_node(node.[](:"else")))
335
+ }
336
+ end)
337
+ src.write_ln("end)")
338
+ when "Unless"
339
+ src.write_ln("unless #{visit_node(node.[](:"condition"))}")
340
+ indented(src) { ||
341
+ src.write_ln(visit_node(node.[](:"then")))
342
+ }
343
+ (if node.[](:"else")
344
+ src.write_ln("else")
345
+ indented(src) { ||
346
+ src.write_ln(visit_node(node.[](:"else")))
347
+ }
348
+ end)
349
+ src.write_ln("end")
350
+ when "Case"
351
+ src.write("case")
352
+ (if node.[](:"condition")
353
+ src.write(" #{visit_node(node.[](:"condition"))
354
+ .strip}\n")
355
+ end)
356
+ indented(src) { ||
357
+ node.[](:"whens")
358
+ .each() { |w|
359
+ src.write_ln(visit_node(w))
360
+ }
361
+ (if node.[](:"else")
362
+ src.write_ln("else")
363
+ indented(src) { ||
364
+ src.write_ln(visit_node(node.[](:"else")))
365
+ }
366
+ end)
367
+ }
368
+ src.write_ln("end")
369
+ when "When"
370
+ src.write_ln("when #{node.[](:"conditions")
371
+ .map() { |n|
372
+ visit_node(n)
373
+ }
374
+ .join(", ")}")
375
+ indented(src) { ||
376
+ src.write_ln((if node.[](:"body")
377
+ visit_node(node.[](:"body"))
378
+ else
379
+ "# no op"
380
+ end))
381
+ }
382
+ when "MacroFor"
383
+ vars, expr, body = node.[](:"vars"), node.[](:"expr"), node.[](:"body")
384
+ var_names = vars.map() { |v|
385
+ visit_node(v)
386
+ }
387
+ @inside_macro = true
388
+ indent_level = @indent_level
389
+ unless indent_level.zero?
390
+ @indent_level -= 1
376
391
  end
377
- if node[:ensure]
378
- src.write_ln "ensure"
379
- intended(src) { src.write_ln visit_node(node[:ensure]) }
392
+ # @type var expanded: Array[String]
393
+ expanded = eval(visit_node(expr))
394
+ .map() { |a|
395
+ locals = [var_names.join("\", \"")].zip(a)
396
+ .to_h
397
+ (if @inside_macro
398
+ locals.merge!(scope)
399
+ end)
400
+ visit_node(body, locals)
401
+ }
402
+ .flatten
403
+ unless indent_level.zero?
404
+ @indent_level += 1
380
405
  end
381
- src.write_ln "end"
382
- when "Generic"
383
- src.write "#{node[:name]}[#{node[:args].map { |a| visit_node a }.join(", ")}]"
384
- when "Proc"
385
- fn = node[:function]
386
- src.write "->#{render_args(fn)} { #{visit_node fn[:body]} }"
387
- when "Include"
388
- src.write_ln "include #{visit_node node[:name]}"
389
- when "Extend"
390
- src.write_ln "extend #{visit_node node[:name]}"
391
- when "RegexLiteral"
392
- contents = visit_node node[:value]
393
- src.write Regexp.new(contents.undump).inspect
394
- when "EmptyNode"
395
- # pass
396
- else
397
- raise "Not implemented: #{node[:type]}"
406
+ expanded.each() { |e|
407
+ src.write(e)
408
+ }
409
+ @inside_macro = false
410
+ when "MacroLiteral"
411
+ src.write(node.[](:"value"))
412
+ when "MacroExpression"
413
+ (if node.[](:"output")
414
+ expr = visit_node(node.[](:"expr"), scope)
415
+ val = scope.[](expr)
416
+ src.write(val)
417
+ end)
418
+ when "MacroIf"
419
+ (if evaluate_macro_condition(node.[](:"condition"), scope)
420
+ (if node.[](:"then")
421
+ src.write_ln(visit_node(node.[](:"then"), scope))
422
+ end)
423
+ else
424
+ (if node.[](:"else")
425
+ src.write_ln(visit_node(node.[](:"else"), scope))
426
+ end)
427
+ end)
428
+ when "Return"
429
+ val = (if node.[](:"value")
430
+ " #{visit_node(node.[](:"value"))
431
+ .strip}"
432
+ else
433
+ nil
434
+ end)
435
+ src.write("return#{val}")
436
+ when "TypeDeclaration"
437
+ src.write_ln("# @type var #{visit_node(node.[](:"var"))}: #{visit_node(node.[](:"declared_type"))}")
438
+ src.write_ln("#{visit_node(node.[](:"var"))} = #{visit_node(node.[](:"value"))}")
439
+ when "ExceptionHandler"
440
+ src.write_ln("begin")
441
+ indented(src) { ||
442
+ src.write_ln(visit_node(node.[](:"body")))
443
+ }
444
+ (if node.[](:"rescues")
445
+ node.[](:"rescues")
446
+ .each() { |r|
447
+ src.write_ln("rescue #{(if r.[](:"types")
448
+ r.[](:"types")
449
+ .map() { |n|
450
+ visit_node(n)
451
+ }
452
+ .join(", ")
453
+ end)}#{(if r.[](:"name")
454
+ " => #{r.[](:"name")}"
455
+ end)}")
456
+ (if r.[](:"body")
457
+ indented(src) { ||
458
+ src.write_ln(visit_node(r.[](:"body")))
459
+ }
460
+ end)
461
+ }
462
+ end)
463
+ (if node.[](:"else")
464
+ src.write_ln("else")
465
+ indented(src) { ||
466
+ src.write_ln(visit_node(node.[](:"else")))
467
+ }
468
+ end)
469
+ (if node.[](:"ensure")
470
+ src.write_ln("ensure")
471
+ indented(src) { ||
472
+ src.write_ln(visit_node(node.[](:"ensure")))
473
+ }
474
+ end)
475
+ src.write_ln("end")
476
+ when "Generic"
477
+ src.write("#{visit_node(node.[](:"name"))}[#{node.[](:"args")
478
+ .map() { |a|
479
+ visit_node(a)
480
+ }
481
+ .join(", ")}]")
482
+ when "Proc"
483
+ fn = node.[](:"function")
484
+ src.write("->#{render_args(fn)} { #{visit_node(fn.[](:"body"))} }")
485
+ when "Include"
486
+ current_namespace = (if @current_scope
487
+ @current_scope.name
488
+ .to_namespace
489
+ else
490
+ RBS::Namespace.root
491
+ end)
492
+ name = visit_node(node.[](:"name"))
493
+ src.write_ln("include #{name}")
494
+ type = RBS::AST::Members::Include.new(name: method(:"TypeName")
495
+ .call(name), args: Array.new, annotations: Array.new, location: node.[](:"location"), comment: node.[](:"comment"))
496
+ (if @current_scope
497
+ @current_scope.members
498
+ .<<(type)
499
+ else
500
+ @type_checker.type_env
501
+ .<<(type)
502
+ end)
503
+ when "Extend"
504
+ current_namespace = (if @current_scope
505
+ @current_scope.name
506
+ .to_namespace
507
+ else
508
+ RBS::Namespace.root
509
+ end)
510
+ name = visit_node(node.[](:"name"))
511
+ src.write_ln("extend #{name}")
512
+ type = RBS::AST::Members::Extend.new(name: method(:"TypeName")
513
+ .call(name), args: Array.new, annotations: Array.new, location: node.[](:"location"), comment: node.[](:"comment"))
514
+ (if @current_scope
515
+ @current_scope.members
516
+ .<<(type)
517
+ else
518
+ @type_checker.type_env
519
+ .<<(type)
520
+ end)
521
+ when "RegexLiteral"
522
+ contents = visit_node(node.[](:"value"))
523
+ src.write(Regexp.new(contents.undump)
524
+ .inspect)
525
+ when "Union"
526
+ types = node.[](:"types")
527
+ output = (if types.length
528
+ .==(2) && types.[](1)
529
+ .[](:"type")
530
+ .==("Path") && types.[](1)
531
+ .[]("value")
532
+ .==(nil)
533
+ "#{visit_node(types.[](0))}?"
534
+ else
535
+ types.map() { |t|
536
+ visit_node(t)
537
+ }
538
+ .join(" | ")
539
+ end)
540
+ src.write(output)
541
+ when "EmptyNode"
542
+ # no op
543
+ else
544
+ raise("Not implemented: #{node.[](:"type")}")
398
545
  end
399
-
400
- src
546
+ src
401
547
  end
402
-
403
- private
404
-
405
- def evaluate_macro_condition(condition_node, scope)
548
+ private def evaluate_macro_condition(condition_node, scope)
406
549
  @eval_vars = true
407
550
  eval(visit_node(condition_node, scope))
408
551
  @eval_vars = false
409
552
  end
410
-
411
- def indented(src)
553
+ private def indented(src)
412
554
  increment_indent(src)
413
555
  yield
414
556
  decrement_indent(src)
415
557
  end
416
-
417
- def increment_indent(src)
558
+ private def increment_indent(src)
418
559
  @indent_level += 1
419
560
  src.increment_indent
420
561
  end
421
-
422
- def decrement_indent(src)
562
+ private def decrement_indent(src)
423
563
  @indent_level -= 1
424
564
  src.decrement_indent
425
565
  end
426
-
427
- def render_args(node)
428
- rp = node[:rp_args] || EMPTY_ARRAY
429
- op = node[:op_args] || EMPTY_ARRAY
430
- rkw = node[:req_kw_args] || EMPTY_HASH
431
- okw = node[:opt_kw_args] || EMPTY_HASH
432
- rest_p = node[:rest_p_args]
433
- rest_kw = node[:rest_kw_args]
434
- return nil unless [rp, op, rkw, okw, rest_p, rest_kw].any? { |a| !a.nil? || !a.empty? }
435
-
436
- contents = [
437
- rp.map { |a| visit_node(a) },
438
- op.map { |pos| "#{pos.name} = #{value}" },
439
- rkw.map { |name, _| "#{name}:" },
440
- okw.map { |name, _| "#{name}: #{value}" },
441
- rest_p ? "*#{rest_p}" : "",
442
- rest_kw ? "**#{visit_node(rest_kw)}" : ""
443
- ].reject(&:empty?).flatten.join(", ")
444
- "(#{contents})"
566
+ private def render_args(node)
567
+ # @type var rp: Array[Hash[Symbol, Any]]
568
+ rp = node.fetch(:"positional_args") { ||
569
+ EMPTY_ARRAY }
570
+ .filter() { |a|
571
+ !a.[](:"value") }
572
+ # @type var op: Array[Hash[Symbol, Any]]
573
+ op = node.fetch(:"positional_args") { ||
574
+ EMPTY_ARRAY }
575
+ .filter() { |a|
576
+ a.[](:"value")
577
+ }
578
+ # @type var rkw: Hash[Symbol, Any]
579
+ rkw = node.fetch(:"req_kw_args") { ||
580
+ EMPTY_HASH }
581
+ # @type var okw: Hash[Symbol, Any]
582
+ okw = node.fetch(:"opt_kw_args") { ||
583
+ EMPTY_HASH }
584
+ # @type var rest_p: String?
585
+ rest_p = (if node.[](:"rest_p_args")
586
+ visit_node(node.[](:"rest_p_args"))
587
+ else
588
+ nil
589
+ end)
590
+ # @type var rest_kw: Hash[Symbol, Any]?
591
+ rest_kw = node.[](:"rest_kw_args")
592
+ (if [rp, op, rkw, okw, rest_p, rest_kw].all?() { |a|
593
+ a && a.empty? }
594
+ return nil
595
+ end)
596
+ contents = [rp.map() { |a|
597
+ visit_node(a)
598
+ }, op.map() { |a|
599
+ "#{a.[](:"name")} = #{visit_node(a.[](:"value"))
600
+ .strip}" }, rkw.map() { |name, _|
601
+ "#{name}:" }, okw.map() { |name, value|
602
+ "#{name}: #{value}" }, (if rest_p
603
+ "*#{rest_p}"
604
+ else
605
+ ""
606
+ end), (if rest_kw
607
+ "**#{visit_node(rest_kw)}"
608
+ else
609
+ ""
610
+ end)].reject(&:"empty?")
611
+ .flatten
612
+ .join(", ")
613
+ "(#{contents})"
445
614
  end
446
615
  end
447
616
  end