steep 0.36.0 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,770 @@
1
+ module Steep
2
+ module Interface
3
+ class Function
4
+ class Params
5
+ attr_reader :required
6
+ attr_reader :optional
7
+ attr_reader :rest
8
+ attr_reader :required_keywords
9
+ attr_reader :optional_keywords
10
+ attr_reader :rest_keywords
11
+
12
+ def initialize(required:, optional:, rest:, required_keywords:, optional_keywords:, rest_keywords:)
13
+ @required = required
14
+ @optional = optional
15
+ @rest = rest
16
+ @required_keywords = required_keywords
17
+ @optional_keywords = optional_keywords
18
+ @rest_keywords = rest_keywords
19
+ end
20
+
21
+ def update(required: self.required, optional: self.optional, rest: self.rest, required_keywords: self.required_keywords, optional_keywords: self.optional_keywords, rest_keywords: self.rest_keywords)
22
+ self.class.new(
23
+ required: required,
24
+ optional: optional,
25
+ rest: rest,
26
+ required_keywords: required_keywords,
27
+ optional_keywords: optional_keywords,
28
+ rest_keywords: rest_keywords,
29
+ )
30
+ end
31
+
32
+ RequiredPositional = Struct.new(:type)
33
+ OptionalPositional = Struct.new(:type)
34
+ RestPositional = Struct.new(:type)
35
+
36
+ def first_param
37
+ case
38
+ when !required.empty?
39
+ RequiredPositional.new(required[0])
40
+ when !optional.empty?
41
+ OptionalPositional.new(optional[0])
42
+ when rest
43
+ RestPositional.new(rest)
44
+ else
45
+ nil
46
+ end
47
+ end
48
+
49
+ def with_first_param(param)
50
+ case param
51
+ when RequiredPositional
52
+ update(required: [param.type] + required)
53
+ when OptionalPositional
54
+ update(optional: [param.type] + required)
55
+ when RestPositional
56
+ update(rest: param.type)
57
+ else
58
+ self
59
+ end
60
+ end
61
+
62
+ def has_positional?
63
+ first_param
64
+ end
65
+
66
+ def self.empty
67
+ self.new(
68
+ required: [],
69
+ optional: [],
70
+ rest: nil,
71
+ required_keywords: {},
72
+ optional_keywords: {},
73
+ rest_keywords: nil
74
+ )
75
+ end
76
+
77
+ def ==(other)
78
+ other.is_a?(self.class) &&
79
+ other.required == required &&
80
+ other.optional == optional &&
81
+ other.rest == rest &&
82
+ other.required_keywords == required_keywords &&
83
+ other.optional_keywords == optional_keywords &&
84
+ other.rest_keywords == rest_keywords
85
+ end
86
+
87
+ alias eql? ==
88
+
89
+ def hash
90
+ required.hash ^ optional.hash ^ rest.hash ^ required_keywords.hash ^ optional_keywords.hash ^ rest_keywords.hash
91
+ end
92
+
93
+ def flat_unnamed_params
94
+ required.map {|p| [:required, p] } + optional.map {|p| [:optional, p] }
95
+ end
96
+
97
+ def flat_keywords
98
+ required_keywords.merge optional_keywords
99
+ end
100
+
101
+ def has_keywords?
102
+ !required_keywords.empty? || !optional_keywords.empty? || rest_keywords
103
+ end
104
+
105
+ def without_keywords
106
+ self.class.new(
107
+ required: required,
108
+ optional: optional,
109
+ rest: rest,
110
+ required_keywords: {},
111
+ optional_keywords: {},
112
+ rest_keywords: nil
113
+ )
114
+ end
115
+
116
+ def drop_first
117
+ case
118
+ when required.any? || optional.any? || rest
119
+ self.class.new(
120
+ required: required.any? ? required.drop(1) : [],
121
+ optional: required.empty? && optional.any? ? optional.drop(1) : optional,
122
+ rest: required.empty? && optional.empty? ? nil : rest,
123
+ required_keywords: required_keywords,
124
+ optional_keywords: optional_keywords,
125
+ rest_keywords: rest_keywords
126
+ )
127
+ when has_keywords?
128
+ without_keywords
129
+ else
130
+ raise "Cannot drop from empty params"
131
+ end
132
+ end
133
+
134
+ def each_missing_argument(args)
135
+ required.size.times do |index|
136
+ if index >= args.size
137
+ yield index
138
+ end
139
+ end
140
+ end
141
+
142
+ def each_extra_argument(args)
143
+ return if rest
144
+
145
+ if has_keywords?
146
+ args = args.take(args.count - 1) if args.count > 0
147
+ end
148
+
149
+ args.size.times do |index|
150
+ if index >= required.count + optional.count
151
+ yield index
152
+ end
153
+ end
154
+ end
155
+
156
+ def each_missing_keyword(args)
157
+ return unless has_keywords?
158
+
159
+ keywords, rest = extract_keywords(args)
160
+
161
+ return unless rest.empty?
162
+
163
+ required_keywords.each do |keyword, _|
164
+ yield keyword unless keywords.key?(keyword)
165
+ end
166
+ end
167
+
168
+ def each_extra_keyword(args)
169
+ return unless has_keywords?
170
+ return if rest_keywords
171
+
172
+ keywords, rest = extract_keywords(args)
173
+
174
+ return unless rest.empty?
175
+
176
+ all_keywords = flat_keywords
177
+ keywords.each do |keyword, _|
178
+ yield keyword unless all_keywords.key?(keyword)
179
+ end
180
+ end
181
+
182
+ def extract_keywords(args)
183
+ last_arg = args.last
184
+
185
+ keywords = {}
186
+ rest = []
187
+
188
+ if last_arg&.type == :hash
189
+ last_arg.children.each do |element|
190
+ case element.type
191
+ when :pair
192
+ if element.children[0].type == :sym
193
+ name = element.children[0].children[0]
194
+ keywords[name] = element.children[1]
195
+ end
196
+ when :kwsplat
197
+ rest << element.children[0]
198
+ end
199
+ end
200
+ end
201
+
202
+ [keywords, rest]
203
+ end
204
+
205
+ def each_type()
206
+ if block_given?
207
+ flat_unnamed_params.each do |(_, type)|
208
+ yield type
209
+ end
210
+ flat_keywords.each do |_, type|
211
+ yield type
212
+ end
213
+ rest and yield rest
214
+ rest_keywords and yield rest_keywords
215
+ else
216
+ enum_for :each_type
217
+ end
218
+ end
219
+
220
+ def free_variables()
221
+ @fvs ||= Set.new.tap do |set|
222
+ each_type do |type|
223
+ set.merge(type.free_variables)
224
+ end
225
+ end
226
+ end
227
+
228
+ def closed?
229
+ required.all?(&:closed?) && optional.all?(&:closed?) && (!rest || rest.closed?) && required_keywords.values.all?(&:closed?) && optional_keywords.values.all?(&:closed?) && (!rest_keywords || rest_keywords.closed?)
230
+ end
231
+
232
+ def subst(s)
233
+ return self if s.empty?
234
+ return self if empty?
235
+ return self if free_variables.disjoint?(s.domain)
236
+
237
+ rs = required.map {|t| t.subst(s) }
238
+ os = optional.map {|t| t.subst(s) }
239
+ r = rest&.subst(s)
240
+ rk = required_keywords.transform_values {|t| t.subst(s) }
241
+ ok = optional_keywords.transform_values {|t| t.subst(s) }
242
+ k = rest_keywords&.subst(s)
243
+
244
+ if rs == required && os == optional && r == rest && rk == required_keywords && ok == optional_keywords && k == rest_keywords
245
+ self
246
+ else
247
+ self.class.new(
248
+ required: required.map {|t| t.subst(s) },
249
+ optional: optional.map {|t| t.subst(s) },
250
+ rest: rest&.subst(s),
251
+ required_keywords: required_keywords.transform_values {|t| t.subst(s) },
252
+ optional_keywords: optional_keywords.transform_values {|t| t.subst(s) },
253
+ rest_keywords: rest_keywords&.subst(s)
254
+ )
255
+ end
256
+ end
257
+
258
+ def size
259
+ required.size + optional.size + (rest ? 1 : 0) + required_keywords.size + optional_keywords.size + (rest_keywords ? 1 : 0)
260
+ end
261
+
262
+ def to_s
263
+ required = self.required.map {|ty| ty.to_s }
264
+ optional = self.optional.map {|ty| "?#{ty}" }
265
+ rest = self.rest ? ["*#{self.rest}"] : []
266
+ required_keywords = self.required_keywords.map {|name, type| "#{name}: #{type}" }
267
+ optional_keywords = self.optional_keywords.map {|name, type| "?#{name}: #{type}"}
268
+ rest_keywords = self.rest_keywords ? ["**#{self.rest_keywords}"] : []
269
+ "(#{(required + optional + rest + required_keywords + optional_keywords + rest_keywords).join(", ")})"
270
+ end
271
+
272
+ def map_type(&block)
273
+ self.class.new(
274
+ required: required.map(&block),
275
+ optional: optional.map(&block),
276
+ rest: rest && yield(rest),
277
+ required_keywords: required_keywords.transform_values(&block),
278
+ optional_keywords: optional_keywords.transform_values(&block),
279
+ rest_keywords: rest_keywords && yield(rest_keywords)
280
+ )
281
+ end
282
+
283
+ def empty?
284
+ !has_positional? && !has_keywords?
285
+ end
286
+
287
+ # self + params returns a new params for overloading.
288
+ #
289
+ def +(other)
290
+ a = first_param
291
+ b = other.first_param
292
+
293
+ case
294
+ when a.is_a?(RequiredPositional) && b.is_a?(RequiredPositional)
295
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
296
+ (self.drop_first + other.drop_first).with_first_param(RequiredPositional.new(type))
297
+ end
298
+ when a.is_a?(RequiredPositional) && b.is_a?(OptionalPositional)
299
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
300
+ (self.drop_first + other.drop_first).with_first_param(OptionalPositional.new(type))
301
+ end
302
+ when a.is_a?(RequiredPositional) && b.is_a?(RestPositional)
303
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
304
+ (self.drop_first + other).with_first_param(OptionalPositional.new(type))
305
+ end
306
+ when a.is_a?(RequiredPositional) && b.nil?
307
+ (self.drop_first + other).with_first_param(OptionalPositional.new(a.type))
308
+ when a.is_a?(OptionalPositional) && b.is_a?(RequiredPositional)
309
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
310
+ (self.drop_first + other.drop_first).with_first_param(OptionalPositional.new(type))
311
+ end
312
+ when a.is_a?(OptionalPositional) && b.is_a?(OptionalPositional)
313
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
314
+ (self.drop_first + other.drop_first).with_first_param(OptionalPositional.new(type))
315
+ end
316
+ when a.is_a?(OptionalPositional) && b.is_a?(RestPositional)
317
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
318
+ (self.drop_first + other).with_first_param(OptionalPositional.new(type))
319
+ end
320
+ when a.is_a?(OptionalPositional) && b.nil?
321
+ (self.drop_first + other).with_first_param(OptionalPositional.new(a.type))
322
+ when a.is_a?(RestPositional) && b.is_a?(RequiredPositional)
323
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
324
+ (self + other.drop_first).with_first_param(OptionalPositional.new(type))
325
+ end
326
+ when a.is_a?(RestPositional) && b.is_a?(OptionalPositional)
327
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
328
+ (self + other.drop_first).with_first_param(OptionalPositional.new(type))
329
+ end
330
+ when a.is_a?(RestPositional) && b.is_a?(RestPositional)
331
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
332
+ (self.drop_first + other.drop_first).with_first_param(RestPositional.new(type))
333
+ end
334
+ when a.is_a?(RestPositional) && b.nil?
335
+ (self.drop_first + other).with_first_param(RestPositional.new(a.type))
336
+ when a.nil? && b.is_a?(RequiredPositional)
337
+ (self + other.drop_first).with_first_param(OptionalPositional.new(b.type))
338
+ when a.nil? && b.is_a?(OptionalPositional)
339
+ (self + other.drop_first).with_first_param(OptionalPositional.new(b.type))
340
+ when a.nil? && b.is_a?(RestPositional)
341
+ (self + other.drop_first).with_first_param(RestPositional.new(b.type))
342
+ when a.nil? && b.nil?
343
+ required_keywords = {}
344
+
345
+ (Set.new(self.required_keywords.keys) & Set.new(other.required_keywords.keys)).each do |keyword|
346
+ required_keywords[keyword] = AST::Types::Union.build(
347
+ types: [
348
+ self.required_keywords[keyword],
349
+ other.required_keywords[keyword]
350
+ ]
351
+ )
352
+ end
353
+
354
+ optional_keywords = {}
355
+ self.required_keywords.each do |keyword, t|
356
+ unless required_keywords.key?(keyword)
357
+ case
358
+ when other.optional_keywords.key?(keyword)
359
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, other.optional_keywords[keyword]])
360
+ when other.rest_keywords
361
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, other.rest_keywords])
362
+ else
363
+ optional_keywords[keyword] = t
364
+ end
365
+ end
366
+ end
367
+ other.required_keywords.each do |keyword, t|
368
+ unless required_keywords.key?(keyword)
369
+ case
370
+ when self.optional_keywords.key?(keyword)
371
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, self.optional_keywords[keyword]])
372
+ when self.rest_keywords
373
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, self.rest_keywords])
374
+ else
375
+ optional_keywords[keyword] = t
376
+ end
377
+ end
378
+ end
379
+ self.optional_keywords.each do |keyword, t|
380
+ unless optional_keywords.key?(keyword)
381
+ case
382
+ when other.optional_keywords.key?(keyword)
383
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, other.optional_keywords[keyword]])
384
+ when other.rest_keywords
385
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, other.rest_keywords])
386
+ else
387
+ optional_keywords[keyword] = t
388
+ end
389
+ end
390
+ end
391
+ other.optional_keywords.each do |keyword, t|
392
+ unless optional_keywords.key?(keyword)
393
+ case
394
+ when self.optional_keywords.key?(keyword)
395
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, self.optional_keywords[keyword]])
396
+ when self.rest_keywords
397
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, self.rest_keywords])
398
+ else
399
+ optional_keywords[keyword] = t
400
+ end
401
+ end
402
+ end
403
+
404
+ rest = case
405
+ when self.rest_keywords && other.rest_keywords
406
+ AST::Types::Union.build(types: [self.rest_keywords, other.rest_keywords])
407
+ else
408
+ self.rest_keywords || other.rest_keywords
409
+ end
410
+
411
+ Params.new(
412
+ required: [],
413
+ optional: [],
414
+ rest: nil,
415
+ required_keywords: required_keywords,
416
+ optional_keywords: optional_keywords,
417
+ rest_keywords: rest)
418
+ end
419
+ end
420
+
421
+ # Returns the intersection between self and other.
422
+ # Returns nil if the intersection cannot be computed.
423
+ #
424
+ def &(other)
425
+ a = first_param
426
+ b = other.first_param
427
+
428
+ case
429
+ when a.is_a?(RequiredPositional) && b.is_a?(RequiredPositional)
430
+ AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
431
+ (self.drop_first & other.drop_first)&.with_first_param(RequiredPositional.new(type))
432
+ end
433
+ when a.is_a?(RequiredPositional) && b.is_a?(OptionalPositional)
434
+ AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
435
+ (self.drop_first & other.drop_first)&.with_first_param(RequiredPositional.new(type))
436
+ end
437
+ when a.is_a?(RequiredPositional) && b.is_a?(RestPositional)
438
+ AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
439
+ (self.drop_first & other)&.with_first_param(RequiredPositional.new(type))
440
+ end
441
+ when a.is_a?(RequiredPositional) && b.nil?
442
+ nil
443
+ when a.is_a?(OptionalPositional) && b.is_a?(RequiredPositional)
444
+ AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
445
+ (self.drop_first & other.drop_first)&.with_first_param(RequiredPositional.new(type))
446
+ end
447
+ when a.is_a?(OptionalPositional) && b.is_a?(OptionalPositional)
448
+ AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
449
+ (self.drop_first & other.drop_first)&.with_first_param(OptionalPositional.new(type))
450
+ end
451
+ when a.is_a?(OptionalPositional) && b.is_a?(RestPositional)
452
+ AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
453
+ (self.drop_first & other)&.with_first_param(OptionalPositional.new(type))
454
+ end
455
+ when a.is_a?(OptionalPositional) && b.nil?
456
+ self.drop_first & other
457
+ when a.is_a?(RestPositional) && b.is_a?(RequiredPositional)
458
+ AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
459
+ (self & other.drop_first)&.with_first_param(RequiredPositional.new(type))
460
+ end
461
+ when a.is_a?(RestPositional) && b.is_a?(OptionalPositional)
462
+ AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
463
+ (self & other.drop_first)&.with_first_param(OptionalPositional.new(type))
464
+ end
465
+ when a.is_a?(RestPositional) && b.is_a?(RestPositional)
466
+ AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
467
+ (self.drop_first & other.drop_first)&.with_first_param(RestPositional.new(type))
468
+ end
469
+ when a.is_a?(RestPositional) && b.nil?
470
+ self.drop_first & other
471
+ when a.nil? && b.is_a?(RequiredPositional)
472
+ nil
473
+ when a.nil? && b.is_a?(OptionalPositional)
474
+ self & other.drop_first
475
+ when a.nil? && b.is_a?(RestPositional)
476
+ self & other.drop_first
477
+ when a.nil? && b.nil?
478
+ optional_keywords = {}
479
+
480
+ (Set.new(self.optional_keywords.keys) & Set.new(other.optional_keywords.keys)).each do |keyword|
481
+ optional_keywords[keyword] = AST::Types::Intersection.build(
482
+ types: [
483
+ self.optional_keywords[keyword],
484
+ other.optional_keywords[keyword]
485
+ ]
486
+ )
487
+ end
488
+
489
+ required_keywords = {}
490
+ self.optional_keywords.each do |keyword, t|
491
+ unless optional_keywords.key?(keyword)
492
+ case
493
+ when other.required_keywords.key?(keyword)
494
+ required_keywords[keyword] = AST::Types::Intersection.build(types: [t, other.required_keywords[keyword]])
495
+ when other.rest_keywords
496
+ optional_keywords[keyword] = AST::Types::Intersection.build(types: [t, other.rest_keywords])
497
+ end
498
+ end
499
+ end
500
+ other.optional_keywords.each do |keyword, t|
501
+ unless optional_keywords.key?(keyword)
502
+ case
503
+ when self.required_keywords.key?(keyword)
504
+ required_keywords[keyword] = AST::Types::Intersection.build(types: [t, self.required_keywords[keyword]])
505
+ when self.rest_keywords
506
+ optional_keywords[keyword] = AST::Types::Intersection.build(types: [t, self.rest_keywords])
507
+ end
508
+ end
509
+ end
510
+ self.required_keywords.each do |keyword, t|
511
+ unless required_keywords.key?(keyword)
512
+ case
513
+ when other.required_keywords.key?(keyword)
514
+ required_keywords[keyword] = AST::Types::Intersection.build(types: [t, other.required_keywords[keyword]])
515
+ when other.rest_keywords
516
+ required_keywords[keyword] = AST::Types::Intersection.build(types: [t, other.rest_keywords])
517
+ else
518
+ return
519
+ end
520
+ end
521
+ end
522
+ other.required_keywords.each do |keyword, t|
523
+ unless required_keywords.key?(keyword)
524
+ case
525
+ when self.required_keywords.key?(keyword)
526
+ required_keywords[keyword] = AST::Types::Intersection.build(types: [t, self.required_keywords[keyword]])
527
+ when self.rest_keywords
528
+ required_keywords[keyword] = AST::Types::Intersection.build(types: [t, self.rest_keywords])
529
+ else
530
+ return
531
+ end
532
+ end
533
+ end
534
+
535
+ rest = case
536
+ when self.rest_keywords && other.rest_keywords
537
+ AST::Types::Intersection.build(types: [self.rest_keywords, other.rest_keywords])
538
+ else
539
+ nil
540
+ end
541
+
542
+ Params.new(
543
+ required: [],
544
+ optional: [],
545
+ rest: nil,
546
+ required_keywords: required_keywords,
547
+ optional_keywords: optional_keywords,
548
+ rest_keywords: rest)
549
+ end
550
+ end
551
+
552
+ # Returns the union between self and other.
553
+ #
554
+ def |(other)
555
+ a = first_param
556
+ b = other.first_param
557
+
558
+ case
559
+ when a.is_a?(RequiredPositional) && b.is_a?(RequiredPositional)
560
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
561
+ (self.drop_first | other.drop_first)&.with_first_param(RequiredPositional.new(type))
562
+ end
563
+ when a.is_a?(RequiredPositional) && b.is_a?(OptionalPositional)
564
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
565
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
566
+ end
567
+ when a.is_a?(RequiredPositional) && b.is_a?(RestPositional)
568
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
569
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
570
+ end
571
+ when a.is_a?(RequiredPositional) && b.nil?
572
+ self.drop_first&.with_first_param(OptionalPositional.new(a.type))
573
+ when a.is_a?(OptionalPositional) && b.is_a?(RequiredPositional)
574
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
575
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
576
+ end
577
+ when a.is_a?(OptionalPositional) && b.is_a?(OptionalPositional)
578
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
579
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
580
+ end
581
+ when a.is_a?(OptionalPositional) && b.is_a?(RestPositional)
582
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
583
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
584
+ end
585
+ when a.is_a?(OptionalPositional) && b.nil?
586
+ (self.drop_first | other)&.with_first_param(a)
587
+ when a.is_a?(RestPositional) && b.is_a?(RequiredPositional)
588
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
589
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
590
+ end
591
+ when a.is_a?(RestPositional) && b.is_a?(OptionalPositional)
592
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
593
+ (self | other.drop_first)&.with_first_param(OptionalPositional.new(type))
594
+ end
595
+ when a.is_a?(RestPositional) && b.is_a?(RestPositional)
596
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
597
+ (self.drop_first | other.drop_first)&.with_first_param(RestPositional.new(type))
598
+ end
599
+ when a.is_a?(RestPositional) && b.nil?
600
+ (self.drop_first | other)&.with_first_param(a)
601
+ when a.nil? && b.is_a?(RequiredPositional)
602
+ other.drop_first&.with_first_param(OptionalPositional.new(b.type))
603
+ when a.nil? && b.is_a?(OptionalPositional)
604
+ (self | other.drop_first)&.with_first_param(b)
605
+ when a.nil? && b.is_a?(RestPositional)
606
+ (self | other.drop_first)&.with_first_param(b)
607
+ when a.nil? && b.nil?
608
+ required_keywords = {}
609
+ optional_keywords = {}
610
+
611
+ (Set.new(self.required_keywords.keys) & Set.new(other.required_keywords.keys)).each do |keyword|
612
+ required_keywords[keyword] = AST::Types::Union.build(
613
+ types: [
614
+ self.required_keywords[keyword],
615
+ other.required_keywords[keyword]
616
+ ]
617
+ )
618
+ end
619
+
620
+ self.optional_keywords.each do |keyword, t|
621
+ unless optional_keywords.key?(keyword) || required_keywords.key?(keyword)
622
+ case
623
+ when s = other.required_keywords[keyword]
624
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
625
+ when s = other.optional_keywords[keyword]
626
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
627
+ when r = other.rest_keywords
628
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, r])
629
+ else
630
+ optional_keywords[keyword] = t
631
+ end
632
+ end
633
+ end
634
+ other.optional_keywords.each do |keyword, t|
635
+ unless optional_keywords.key?(keyword) || required_keywords.key?(keyword)
636
+ case
637
+ when s = self.required_keywords[keyword]
638
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
639
+ when s = self.optional_keywords[keyword]
640
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
641
+ when r = self.rest_keywords
642
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, r])
643
+ else
644
+ optional_keywords[keyword] = t
645
+ end
646
+ end
647
+ end
648
+ self.required_keywords.each do |keyword, t|
649
+ unless optional_keywords.key?(keyword) || required_keywords.key?(keyword)
650
+ case
651
+ when s = other.optional_keywords[keyword]
652
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
653
+ when r = other.rest_keywords
654
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, r])
655
+ else
656
+ optional_keywords[keyword] = t
657
+ end
658
+ end
659
+ end
660
+ other.required_keywords.each do |keyword, t|
661
+ unless optional_keywords.key?(keyword) || required_keywords.key?(keyword)
662
+ case
663
+ when s = self.optional_keywords[keyword]
664
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
665
+ when r = self.rest_keywords
666
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, r])
667
+ else
668
+ optional_keywords[keyword] = t
669
+ end
670
+ end
671
+ end
672
+
673
+ rest = case
674
+ when self.rest_keywords && other.rest_keywords
675
+ AST::Types::Union.build(types: [self.rest_keywords, other.rest_keywords])
676
+ when self.rest_keywords
677
+ if required_keywords.empty? && optional_keywords.empty?
678
+ self.rest_keywords
679
+ end
680
+ when other.rest_keywords
681
+ if required_keywords.empty? && optional_keywords.empty?
682
+ other.rest_keywords
683
+ end
684
+ else
685
+ nil
686
+ end
687
+
688
+ Params.new(
689
+ required: [],
690
+ optional: [],
691
+ rest: nil,
692
+ required_keywords: required_keywords,
693
+ optional_keywords: optional_keywords,
694
+ rest_keywords: rest)
695
+ end
696
+ end
697
+ end
698
+
699
+ attr_reader :params
700
+ attr_reader :return_type
701
+ attr_reader :location
702
+
703
+ def initialize(params:, return_type:, location:)
704
+ @params = params
705
+ @return_type = return_type
706
+ @location = location
707
+ end
708
+
709
+ def ==(other)
710
+ other.is_a?(Function) && other.params == params && other.return_type == return_type
711
+ end
712
+
713
+ alias eql? ==
714
+
715
+ def hash
716
+ self.class.hash ^ params.hash ^ return_type.hash
717
+ end
718
+
719
+ def free_variables
720
+ @fvs ||= Set[].tap do |fvs|
721
+ fvs.merge(params.free_variables)
722
+ fvs.merge(return_type.free_variables)
723
+ end
724
+ end
725
+
726
+ def subst(s)
727
+ return self if s.empty?
728
+
729
+ Function.new(
730
+ params: params.subst(s),
731
+ return_type: return_type.subst(s),
732
+ location: location
733
+ )
734
+ end
735
+
736
+ def each_type(&block)
737
+ if block_given?
738
+ params.each_type(&block)
739
+ yield return_type
740
+ else
741
+ enum_for :each_type
742
+ end
743
+ end
744
+
745
+ def map_type(&block)
746
+ Function.new(
747
+ params: params.map_type(&block),
748
+ return_type: yield(return_type),
749
+ location: location
750
+ )
751
+ end
752
+
753
+ def with(params: self.params, return_type: self.return_type)
754
+ Function.new(
755
+ params: params,
756
+ return_type: return_type,
757
+ location: location
758
+ )
759
+ end
760
+
761
+ def to_s
762
+ "#{params} -> #{return_type}"
763
+ end
764
+
765
+ def closed?
766
+ params.closed? && return_type.closed?
767
+ end
768
+ end
769
+ end
770
+ end