gloss 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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