typeprof 0.21.11 → 0.30.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -31
  3. data/bin/typeprof +5 -0
  4. data/doc/doc.ja.md +134 -0
  5. data/doc/doc.md +136 -0
  6. data/lib/typeprof/cli/cli.rb +180 -0
  7. data/lib/typeprof/cli.rb +2 -133
  8. data/lib/typeprof/code_range.rb +112 -0
  9. data/lib/typeprof/core/ast/base.rb +263 -0
  10. data/lib/typeprof/core/ast/call.rb +251 -0
  11. data/lib/typeprof/core/ast/const.rb +126 -0
  12. data/lib/typeprof/core/ast/control.rb +432 -0
  13. data/lib/typeprof/core/ast/meta.rb +150 -0
  14. data/lib/typeprof/core/ast/method.rb +335 -0
  15. data/lib/typeprof/core/ast/misc.rb +263 -0
  16. data/lib/typeprof/core/ast/module.rb +123 -0
  17. data/lib/typeprof/core/ast/pattern.rb +140 -0
  18. data/lib/typeprof/core/ast/sig_decl.rb +471 -0
  19. data/lib/typeprof/core/ast/sig_type.rb +663 -0
  20. data/lib/typeprof/core/ast/value.rb +319 -0
  21. data/lib/typeprof/core/ast/variable.rb +315 -0
  22. data/lib/typeprof/core/ast.rb +472 -0
  23. data/lib/typeprof/core/builtin.rb +146 -0
  24. data/lib/typeprof/core/env/method.rb +137 -0
  25. data/lib/typeprof/core/env/method_entity.rb +55 -0
  26. data/lib/typeprof/core/env/module_entity.rb +408 -0
  27. data/lib/typeprof/core/env/static_read.rb +155 -0
  28. data/lib/typeprof/core/env/type_alias_entity.rb +27 -0
  29. data/lib/typeprof/core/env/value_entity.rb +32 -0
  30. data/lib/typeprof/core/env.rb +360 -0
  31. data/lib/typeprof/core/graph/box.rb +991 -0
  32. data/lib/typeprof/core/graph/change_set.rb +224 -0
  33. data/lib/typeprof/core/graph/filter.rb +155 -0
  34. data/lib/typeprof/core/graph/vertex.rb +222 -0
  35. data/lib/typeprof/core/graph.rb +3 -0
  36. data/lib/typeprof/core/service.rb +522 -0
  37. data/lib/typeprof/core/type.rb +348 -0
  38. data/lib/typeprof/core/util.rb +81 -0
  39. data/lib/typeprof/core.rb +32 -0
  40. data/lib/typeprof/diagnostic.rb +35 -0
  41. data/lib/typeprof/lsp/messages.rb +430 -0
  42. data/lib/typeprof/lsp/server.rb +177 -0
  43. data/lib/typeprof/lsp/text.rb +69 -0
  44. data/lib/typeprof/lsp/util.rb +61 -0
  45. data/lib/typeprof/lsp.rb +4 -907
  46. data/lib/typeprof/version.rb +1 -1
  47. data/lib/typeprof.rb +4 -18
  48. data/typeprof.gemspec +5 -7
  49. metadata +48 -35
  50. data/.github/dependabot.yml +0 -6
  51. data/.github/workflows/main.yml +0 -39
  52. data/.gitignore +0 -9
  53. data/Gemfile +0 -17
  54. data/Gemfile.lock +0 -41
  55. data/Rakefile +0 -10
  56. data/exe/typeprof +0 -10
  57. data/lib/typeprof/analyzer.rb +0 -2598
  58. data/lib/typeprof/arguments.rb +0 -414
  59. data/lib/typeprof/block.rb +0 -176
  60. data/lib/typeprof/builtin.rb +0 -893
  61. data/lib/typeprof/code-range.rb +0 -177
  62. data/lib/typeprof/config.rb +0 -158
  63. data/lib/typeprof/container-type.rb +0 -912
  64. data/lib/typeprof/export.rb +0 -589
  65. data/lib/typeprof/import.rb +0 -852
  66. data/lib/typeprof/insns-def.rb +0 -65
  67. data/lib/typeprof/iseq.rb +0 -864
  68. data/lib/typeprof/method.rb +0 -355
  69. data/lib/typeprof/type.rb +0 -1140
  70. data/lib/typeprof/utils.rb +0 -212
  71. data/tools/coverage.rb +0 -14
  72. data/tools/setup-insns-def.rb +0 -30
  73. data/typeprof-lsp +0 -3
data/lib/typeprof/type.rb DELETED
@@ -1,1140 +0,0 @@
1
- module TypeProf
2
- class Type # or AbstractValue
3
- include Utils::StructuralEquality
4
-
5
- def initialize
6
- raise "cannot instantiate abstract type"
7
- end
8
-
9
- Builtin = {}
10
-
11
- def globalize(_env, _visited, _depth)
12
- self
13
- end
14
-
15
- def localize(env, _alloc_site, _depth)
16
- return env, self
17
- end
18
-
19
- def limit_size(limit)
20
- self
21
- end
22
-
23
- def self.match?(ty1, ty2)
24
- # both ty1 and ty2 should be global
25
- # ty1 is always concrete; it should not have type variables
26
- # ty2 might be abstract; it may have type variables
27
- case ty2
28
- when Type::Var
29
- { ty2 => ty1 }
30
- when Type::Any
31
- {}
32
- when Type::Union
33
- subst = nil
34
- ty2.each_child_global do |ty2|
35
- # this is very conservative to create subst:
36
- # Type.match?( int | str, int | X) creates { X => int | str } but should be { X => str }???
37
- subst2 = Type.match?(ty1, ty2)
38
- next unless subst2
39
- subst = Type.merge_substitution(subst, subst2)
40
- end
41
- subst
42
- else
43
- case ty1
44
- when Type::Var then raise "should not occur"
45
- when Type::Any
46
- subst = {}
47
- ty2.each_free_type_variable do |tyvar|
48
- subst[tyvar] = Type.any
49
- end
50
- subst
51
- when Type::Union
52
- subst = nil
53
- ty1.each_child_global do |ty1|
54
- subst2 = Type.match?(ty1, ty2)
55
- next unless subst2
56
- subst = Type.merge_substitution(subst, subst2)
57
- end
58
- subst
59
- else
60
- if ty2.is_a?(Type::ContainerType)
61
- # ty2 may have type variables
62
- if ty1.class == ty2.class
63
- ty1.match?(ty2)
64
- else
65
- Type.match?(ty1, ty2.base_type)
66
- end
67
- elsif ty1.is_a?(Type::ContainerType)
68
- Type.match?(ty1.base_type, ty2)
69
- else
70
- ty1.consistent?(ty2) ? {} : nil
71
- end
72
- end
73
- end
74
- end
75
-
76
- def self.merge_substitution(subst1, subst2)
77
- if subst1
78
- subst1 = subst1.dup
79
- subst2.each do |tyvar, ty|
80
- if subst1[tyvar]
81
- subst1[tyvar] = subst1[tyvar].union(ty)
82
- else
83
- subst1[tyvar] = ty
84
- end
85
- end
86
- subst1
87
- else
88
- subst2
89
- end
90
- end
91
-
92
- def each_child
93
- yield self
94
- end
95
-
96
- def each_child_global
97
- yield self
98
- end
99
-
100
- def each_free_type_variable
101
- end
102
-
103
- def union(other)
104
- return self if self == other # fastpath
105
-
106
- ty1, ty2 = self, other
107
-
108
- case
109
- when ty1.is_a?(Union)
110
- ty1_types = ty1.types
111
- ty1_elems = ty1.elems
112
- when ty1.is_a?(Array) || ty1.is_a?(Hash)
113
- ty1_types = Utils::Set[]
114
- ty1_elems = {[ty1.class, ty1.base_type] => ty1.elems}
115
- else
116
- ty1_types = ty1_elems = nil
117
- end
118
-
119
- case
120
- when ty2.is_a?(Union)
121
- ty2_types = ty2.types
122
- ty2_elems = ty2.elems
123
- when ty2.is_a?(Array) || ty2.is_a?(Hash)
124
- ty2_types = Utils::Set[]
125
- ty2_elems = {[ty2.class, ty2.base_type] => ty2.elems}
126
- else
127
- ty2_types = ty2_elems = nil
128
- end
129
-
130
- if ty1_types && ty2_types
131
- ty = ty1_types.sum(ty2_types)
132
- all_elems = ty1_elems.dup || {}
133
- ty2_elems&.each do |key, elems|
134
- all_elems[key] = union_elems(all_elems[key], elems)
135
- end
136
- all_elems = nil if all_elems.empty?
137
-
138
- Type::Union.create(ty, all_elems)
139
- elsif ty1_types
140
- Type::Union.create(ty1_types.add(ty2), ty1_elems)
141
- elsif ty2_types
142
- Type::Union.create(ty2_types.add(ty1), ty2_elems)
143
- else
144
- Type::Union.create(Utils::Set[ty1, ty2], nil)
145
- end
146
- end
147
-
148
- private def union_elems(e1, e2)
149
- if e1
150
- if e2
151
- e1.union(e2)
152
- else
153
- e1
154
- end
155
- else
156
- e2
157
- end
158
- end
159
-
160
- def substitute(_subst, _depth)
161
- raise "cannot substitute abstract type: #{ self.class }"
162
- end
163
-
164
- def generate_substitution
165
- {}
166
- end
167
-
168
- DummySubstitution = Object.new
169
- def DummySubstitution.[](_)
170
- Type.any
171
- end
172
-
173
- def remove_type_vars
174
- substitute(DummySubstitution, Config.current.options[:type_depth_limit])
175
- end
176
-
177
- def include_untyped?(_scratch)
178
- false
179
- end
180
-
181
- class Any < Type
182
- def initialize
183
- end
184
-
185
- def inspect
186
- "Type::Any"
187
- end
188
-
189
- def screen_name(scratch)
190
- "untyped"
191
- end
192
-
193
- def method_dispatch_info
194
- nil
195
- end
196
-
197
- def consistent?(_other)
198
- raise "should not be called"
199
- end
200
-
201
- def substitute(_subst, _depth)
202
- self
203
- end
204
-
205
- def include_untyped?(_scratch)
206
- true
207
- end
208
- end
209
-
210
- class Void < Any
211
- def inspect
212
- "Type::Void"
213
- end
214
-
215
- def screen_name(scratch)
216
- "void"
217
- end
218
- end
219
-
220
-
221
- class Union < Type
222
- def self.create(tys, elems)
223
- if tys.size == 1 && !elems
224
- tys.each {|ty| return ty }
225
- elsif tys.size == 0
226
- if elems && elems.size == 1
227
- (container_kind, base_type), nelems = elems.first
228
- # container_kind = Type::Array or Type::Hash
229
- container_kind.new(nelems, base_type)
230
- else
231
- new(tys, elems)
232
- end
233
- else
234
- class_instances = []
235
- non_class_instances = []
236
- degenerated = false
237
- tys.each do |ty|
238
- if ty != Type::Instance.new(Type::Builtin[:nil]) && ty.is_a?(Type::Instance) && ty.klass.kind == :class
239
- class_instances << ty
240
- degenerated = true if ty.include_subclasses
241
- else
242
- non_class_instances << ty
243
- end
244
- end
245
- if (Config.current.options[:union_width_limit] >= 2 && class_instances.size >= Config.current.options[:union_width_limit]) || (degenerated && class_instances.size >= 2)
246
- create(Utils::Set[Instance.new_degenerate(class_instances), *non_class_instances], elems)
247
- else
248
- new(tys, elems)
249
- end
250
- end
251
- end
252
-
253
- def initialize(tys, elems)
254
- raise unless tys.is_a?(Utils::Set)
255
- @types = tys # Set
256
-
257
- # invariant check
258
- local = nil
259
- tys.each do |ty|
260
- raise ty.inspect unless ty.is_a?(Type)
261
- local = true if ty.is_a?(Local)
262
- end
263
- raise if local && elems
264
-
265
- @elems = elems
266
- raise elems.inspect if elems && !elems.is_a?(::Hash)
267
- end
268
-
269
- def each_free_type_variable(&blk)
270
- each_child_global do |ty|
271
- ty.each_free_type_variable(&blk)
272
- end
273
- end
274
-
275
- def limit_size(limit)
276
- return Type.any if limit <= 0
277
- tys = Utils::Set[]
278
- @types.each do |ty|
279
- tys = tys.add(ty.limit_size(limit - 1))
280
- end
281
- elems = @elems&.to_h do |key, elems|
282
- [key, elems.limit_size(limit - 1)]
283
- end
284
- Union.new(tys, elems)
285
- end
286
-
287
- attr_reader :types, :elems
288
-
289
- def each_child(&blk) # local
290
- @types.each(&blk)
291
- raise if @elems
292
- end
293
-
294
- def each_child_global(&blk)
295
- @types.each(&blk)
296
- @elems&.each do |(container_kind, base_type), elems|
297
- yield container_kind.new(elems, base_type)
298
- end
299
- end
300
-
301
- def inspect
302
- a = []
303
- a << "Type::Union{#{ @types.to_a.map {|ty| ty.inspect }.join(", ") }"
304
- @elems&.each do |(container_kind, base_type), elems|
305
- a << ", #{ container_kind.new(elems, base_type).inspect }"
306
- end
307
- a << "}"
308
- a.join
309
- end
310
-
311
- def screen_name(scratch)
312
- types = @types.to_a
313
- @elems&.each do |(container_kind, base_type), elems|
314
- types << container_kind.new(elems, base_type)
315
- end
316
- if types.size == 0
317
- "bot"
318
- else
319
- types = types.to_a
320
- optional = !!types.delete(Type::Instance.new(Type::Builtin[:nil]))
321
- bool = false
322
- if types.include?(Type::Instance.new(Type::Builtin[:false])) &&
323
- types.include?(Type::Instance.new(Type::Builtin[:true]))
324
- types.delete(Type::Instance.new(Type::Builtin[:false]))
325
- types.delete(Type::Instance.new(Type::Builtin[:true]))
326
- bool = true
327
- end
328
- types.delete(Type.any) unless Config.current.options[:show_untyped]
329
- proc_tys, types = types.partition {|ty| ty.is_a?(Proc) }
330
- types = types.map {|ty| ty.screen_name(scratch) }
331
- types << scratch.show_proc_signature(proc_tys) unless proc_tys.empty?
332
- types << "bool" if bool
333
- types = types.sort
334
- if optional
335
- case types.size
336
- when 0 then "nil"
337
- when 1 then types.first + "?"
338
- else
339
- "(#{ types.join (" | ") })?"
340
- end
341
- else
342
- types.join (" | ")
343
- end
344
- end
345
- end
346
-
347
- def globalize(env, visited, depth)
348
- return Type.any if depth <= 0
349
- tys = Utils::Set[]
350
- if @elems
351
- # XXX: If @elems is non nil, the Union type should global, so calling globalize against such a type should not occur.
352
- # However, currently, ActualArguments may contain global types for flag_args_kw_splat case.
353
- # This should be fixed in future in ActualArguments side. See Scratch#setup_actual_arguments.
354
- #raise
355
- end
356
-
357
- elems = @elems ? @elems.dup : {}
358
- @types.each do |ty|
359
- ty = ty.globalize(env, visited, depth - 1)
360
- case ty
361
- when Type::Array, Type::Hash
362
- key = [ty.class, ty.base_type]
363
- elems[key] = union_elems(elems[key], ty.elems)
364
- else
365
- tys = tys.add(ty)
366
- end
367
- end
368
- elems = nil if elems.empty?
369
-
370
- Type::Union.create(tys, elems)
371
- end
372
-
373
- def localize(env, alloc_site, depth)
374
- return env, Type.any if depth <= 0
375
- tys = @types.map do |ty|
376
- env, ty2 = ty.localize(env, alloc_site, depth - 1)
377
- ty2
378
- end
379
- @elems&.each do |(container_kind, base_type), elems|
380
- ty = container_kind.new(elems, base_type)
381
- env, ty = ty.localize(env, alloc_site, depth - 1)
382
- tys = tys.add(ty)
383
- end
384
- ty = Union.create(tys, nil)
385
- return env, ty
386
- end
387
-
388
- def consistent?(_other)
389
- raise "should not be called"
390
- end
391
-
392
- def substitute(subst, depth)
393
- return Type.any if depth <= 0
394
- unions = []
395
- tys = Utils::Set[]
396
- @types.each do |ty|
397
- ty = ty.substitute(subst, depth - 1)
398
- case ty
399
- when Union
400
- unions << ty
401
- else
402
- tys = tys.add(ty)
403
- end
404
- end
405
- elems = @elems&.to_h do |(container_kind, base_type), elems|
406
- [[container_kind, base_type], elems.substitute(subst, depth - 1)]
407
- end
408
- ty = Union.create(tys, elems)
409
- unions.each do |ty0|
410
- ty = ty.union(ty0)
411
- end
412
- ty
413
- end
414
-
415
- def include_untyped?(scratch)
416
- @types.each do |ty|
417
- return true if ty.include_untyped?(scratch)
418
- end
419
- @elems&.each do |(container_kind, base_type), elems|
420
- return true if base_type.include_untyped?(scratch)
421
- return true if elems.include_untyped?(scratch)
422
- end
423
- false
424
- end
425
- end
426
-
427
- def self.any
428
- Thread.current[:any] ||= Any.new
429
- end
430
-
431
- def self.bot
432
- Thread.current[:bot] ||= Union.new(Utils::Set[], nil)
433
- end
434
-
435
- def self.bool
436
- Thread.current[:bool] ||= Union.new(Utils::Set[
437
- Instance.new(Type::Builtin[:true]),
438
- Instance.new(Type::Builtin[:false])
439
- ], nil)
440
- end
441
-
442
- def self.nil
443
- Thread.current[:nil] ||= Instance.new(Type::Builtin[:nil])
444
- end
445
-
446
- def self.optional(ty)
447
- ty.union(Type.nil)
448
- end
449
-
450
- class Var < Type
451
- def initialize(name)
452
- @name = name
453
- end
454
-
455
- def screen_name(scratch)
456
- "Var[#{ @name }]"
457
- end
458
-
459
- def each_free_type_variable
460
- yield self
461
- end
462
-
463
- def substitute(subst, depth)
464
- if subst[self]
465
- subst[self].limit_size(depth)
466
- else
467
- self
468
- end
469
- end
470
-
471
- def consistent?(_other)
472
- raise "should not be called: #{ self }"
473
- end
474
-
475
- def add_subst!(ty, subst)
476
- if subst[self]
477
- subst[self] = subst[self].union(ty)
478
- else
479
- subst[self] = ty
480
- end
481
- true
482
- end
483
- end
484
-
485
- class Class < Type # or Module
486
- def initialize(kind, idx, type_params, superclass, name)
487
- @kind = kind # :class | :module
488
- @idx = idx
489
- @type_params = type_params
490
- @superclass = superclass
491
- raise if @kind == :class && !@superclass
492
- @_name = name
493
- end
494
-
495
- attr_reader :kind, :idx, :type_params, :superclass
496
- attr_accessor :superclass_type_args
497
-
498
- def inspect
499
- if @_name
500
- "#{ @_name }@#{ @idx }"
501
- else
502
- "Class[#{ @idx }]"
503
- end
504
- end
505
-
506
- def screen_name(scratch)
507
- "singleton(#{ scratch.get_class_name(self) })"
508
- end
509
-
510
- def method_dispatch_info
511
- [self, true, false]
512
- end
513
-
514
- def consistent?(other)
515
- case other
516
- when Type::Class
517
- ty = self
518
- loop do
519
- # ad-hoc
520
- return false if !ty || !other # module
521
-
522
- return true if ty.idx == other.idx
523
- return false if ty.idx == 0 # Object
524
- ty = ty.superclass
525
- end
526
- when Type::Instance
527
- return true if other.klass == Type::Builtin[:obj] || other.klass == Type::Builtin[:class] || other.klass == Type::Builtin[:module]
528
- return false
529
- else
530
- false
531
- end
532
- end
533
-
534
- def substitute(_subst, _depth)
535
- self
536
- end
537
- end
538
-
539
- class Instance < Type
540
- def initialize(klass, include_subclasses=false)
541
- raise unless klass
542
- raise if klass == Type.any
543
- raise if klass.is_a?(Type::Instance)
544
- raise if klass.is_a?(Type::Union)
545
- @klass = klass
546
- @include_subclasses = include_subclasses
547
- end
548
-
549
- def self.new_degenerate(instances)
550
- klass = instances.first.klass
551
- ancestors = []
552
- ancestor_idxs = {}
553
- while klass != :__root__
554
- ancestor_idxs[klass] = ancestors.size
555
- ancestors << klass
556
- klass = klass.superclass
557
- end
558
- common_superclass = nil
559
- instances[1..].each do |instance|
560
- klass = instance.klass
561
- while !ancestor_idxs[klass]
562
- klass = klass.superclass
563
- end
564
- common_superclass = klass
565
- ancestor_idxs[klass].times do |i|
566
- ancestor_idxs.delete(ancestors[i])
567
- ancestors[i] = nil
568
- end
569
- end
570
- new(common_superclass, true)
571
- end
572
-
573
- attr_reader :klass, :include_subclasses
574
-
575
- def inspect
576
- "I[#{ @klass.inspect }]"
577
- end
578
-
579
- def screen_name(scratch)
580
- case @klass
581
- when Type::Builtin[:nil] then "nil"
582
- when Type::Builtin[:true] then "true"
583
- when Type::Builtin[:false] then "false"
584
- else
585
- scratch.get_class_name(@klass) + (@include_subclasses ? "" : "")
586
- end
587
- end
588
-
589
- def method_dispatch_info
590
- [@klass, false, @include_subclasses]
591
- end
592
-
593
- def consistent?(other)
594
- case other
595
- when Type::Instance
596
- @klass.consistent?(other.klass)
597
- when Type::Class
598
- return true if @klass == Type::Builtin[:obj] || @klass == Type::Builtin[:class] || @klass == Type::Builtin[:module]
599
- return false
600
- else
601
- false
602
- end
603
- end
604
-
605
- def substitute(subst, depth)
606
- Instance.new(@klass.substitute(subst, depth))
607
- end
608
- end
609
-
610
- # This is an internal object in MRI, so a user program cannot create this object explicitly
611
- class ISeq < Type
612
- def initialize(iseq)
613
- @iseq = iseq
614
- end
615
-
616
- attr_reader :iseq
617
-
618
- def inspect
619
- "Type::ISeq[#{ @iseq }]"
620
- end
621
-
622
- def screen_name(_scratch)
623
- raise NotImplementedError
624
- end
625
- end
626
-
627
- class Proc < Type
628
- def initialize(block_body, base_type)
629
- @block_body, @base_type = block_body, base_type
630
- end
631
-
632
- attr_reader :block_body, :base_type
633
-
634
- def consistent?(other)
635
- case other
636
- when Type::Proc
637
- @block_body.consistent?(other.block_body)
638
- else
639
- self == other
640
- end
641
- end
642
-
643
- def method_dispatch_info
644
- @base_type.method_dispatch_info
645
- end
646
-
647
- def substitute(subst, depth)
648
- Proc.new(@block_body.substitute(subst, depth), @base_type)
649
- end
650
-
651
- def screen_name(scratch)
652
- scratch.show_proc_signature([self])
653
- end
654
-
655
- def include_untyped?(scratch)
656
- false # XXX: need to check the block signatures recursively
657
- end
658
- end
659
-
660
- class Symbol < Type
661
- def initialize(sym, base_type)
662
- @sym = sym
663
- @base_type = base_type
664
- end
665
-
666
- attr_reader :sym, :base_type
667
-
668
- def inspect
669
- "Type::Symbol[#{ @sym ? @sym.inspect : "(dynamic symbol)" }, #{ @base_type.inspect }]"
670
- end
671
-
672
- def consistent?(other)
673
- case other
674
- when Symbol
675
- @sym == other.sym
676
- else
677
- @base_type.consistent?(other)
678
- end
679
- end
680
-
681
- def screen_name(scratch)
682
- if @sym
683
- @sym.inspect
684
- else
685
- @base_type.screen_name(scratch)
686
- end
687
- end
688
-
689
- def method_dispatch_info
690
- @base_type.method_dispatch_info
691
- end
692
-
693
- def substitute(_subst, _depth)
694
- self # dummy
695
- end
696
- end
697
-
698
- # A local type
699
- class Literal < Type
700
- def initialize(lit, base_type)
701
- @lit = lit
702
- @base_type = base_type
703
- end
704
-
705
- attr_reader :lit, :base_type
706
-
707
- def inspect
708
- "Type::Literal[#{ @lit.inspect }, #{ @base_type.inspect }]"
709
- end
710
-
711
- def screen_name(scratch)
712
- @base_type.screen_name(scratch) + "<#{ @lit.inspect }>"
713
- end
714
-
715
- def globalize(_env, _visited, _depth)
716
- @base_type
717
- end
718
-
719
- def method_dispatch_info
720
- @base_type.method_dispatch_info
721
- end
722
-
723
- def consistent?(_other)
724
- raise "should not called"
725
- end
726
- end
727
-
728
- class HashGenerator
729
- def initialize
730
- @map_tys = {}
731
- end
732
-
733
- attr_reader :map_tys
734
-
735
- def []=(k_ty, v_ty)
736
- k_ty.each_child_global do |k_ty|
737
- if k_ty.is_a?(Type::Union)
738
- # Flatten recursive union
739
- self[k_ty] = v_ty
740
- else
741
- # This is a temporal hack to mitigate type explosion
742
- k_ty = Type.any if k_ty.is_a?(Type::Array)
743
- k_ty = Type.any if k_ty.is_a?(Type::Hash)
744
-
745
- if @map_tys[k_ty]
746
- @map_tys[k_ty] = @map_tys[k_ty].union(v_ty)
747
- else
748
- @map_tys[k_ty] = v_ty
749
- end
750
- end
751
- end
752
- end
753
- end
754
-
755
- def self.gen_hash(base_ty = Type::Instance.new(Type::Builtin[:hash]))
756
- hg = HashGenerator.new
757
- yield hg
758
- Type::Hash.new(Type::Hash::Elements.new(hg.map_tys), base_ty)
759
- end
760
-
761
- def self.guess_literal_type(obj)
762
- case obj
763
- when ::Symbol
764
- Type::Symbol.new(obj, Type::Instance.new(Type::Builtin[:sym]))
765
- when ::Integer
766
- Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:int]))
767
- when ::Rational
768
- Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:rational]))
769
- when ::Complex
770
- Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:complex]))
771
- when ::Float
772
- Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:float]))
773
- when ::Class
774
- return Type.any if obj < Exception
775
- case obj
776
- when ::Object
777
- Type::Builtin[:obj]
778
- when ::Array
779
- Type::Builtin[:ary]
780
- else
781
- raise "unknown class: #{ obj.inspect }"
782
- end
783
- when ::TrueClass
784
- Type::Instance.new(Type::Builtin[:true])
785
- when ::FalseClass
786
- Type::Instance.new(Type::Builtin[:false])
787
- when ::Array
788
- base_ty = Type::Instance.new(Type::Builtin[:ary])
789
- lead_tys = obj.map {|arg| guess_literal_type(arg) }
790
- Type::Array.new(Type::Array::Elements.new(lead_tys), base_ty)
791
- when ::Hash
792
- Type.gen_hash do |h|
793
- obj.each do |k, v|
794
- k_ty = guess_literal_type(k).globalize(nil, {}, Config.current.options[:type_depth_limit])
795
- v_ty = guess_literal_type(v)
796
- h[k_ty] = v_ty
797
- end
798
- end
799
- when ::String
800
- Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:str]))
801
- when ::Regexp
802
- Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:regexp]))
803
- when ::NilClass
804
- Type.nil
805
- when ::Range
806
- Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:range]))
807
- when ::Encoding
808
- Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:encoding]))
809
- else
810
- raise "unknown object: #{ obj.inspect }"
811
- end
812
- end
813
-
814
- def self.builtin_global_variable_type(var)
815
- case var
816
- when :$_, :$/, :$\, :$,, :$;
817
- Type.optional(Type::Instance.new(Type::Builtin[:str]))
818
- when :$0, :$PROGRAM_NAME
819
- Type::Instance.new(Type::Builtin[:str])
820
- when :$~
821
- # optional type is tentatively disabled; it is too conservative
822
- #Type.optional(Type::Instance.new(Type::Builtin[:matchdata]))
823
- Type::Instance.new(Type::Builtin[:matchdata])
824
- when :$., :$$
825
- Type::Instance.new(Type::Builtin[:int])
826
- when :$?
827
- Type.optional(Type::Instance.new(Type::Builtin[:int]))
828
- when :$!
829
- Type.optional(Type::Instance.new(Type::Builtin[:exc]))
830
- when :$@
831
- str = Type::Instance.new(Type::Builtin[:str])
832
- base_ty = Type::Instance.new(Type::Builtin[:ary])
833
- Type.optional(Type::Array.new(Type::Array::Elements.new([], str), base_ty))
834
- when :$*, :$:, :$LOAD_PATH, :$", :$LOADED_FEATURES
835
- str = Type::Instance.new(Type::Builtin[:str])
836
- base_ty = Type::Instance.new(Type::Builtin[:ary])
837
- Type::Array.new(Type::Array::Elements.new([], str), base_ty)
838
- when :$<
839
- :ARGF
840
- when :$>
841
- :STDOUT
842
- when :$DEBUG
843
- Type.bool
844
- when :$FILENAME
845
- Type::Instance.new(Type::Builtin[:str])
846
- when :$stdin
847
- :STDIN
848
- when :$stdout
849
- :STDOUT
850
- when :$stderr
851
- :STDERR
852
- when :$VERBOSE
853
- Type.bool.union(Type.nil)
854
- else
855
- nil
856
- end
857
- end
858
- end
859
-
860
- class Signature
861
- include Utils::StructuralEquality
862
-
863
- def screen_name(iseq, scratch)
864
- fargs_str = "("
865
- sig_help = {}
866
- add_farg = -> farg, name, help: false, key: sig_help.size do
867
- name = "`#{ name }`" if RBS::Parser::KEYWORDS.key?(name.to_s)
868
- name = "noname" if name.is_a?(Integer) || name == :"*"
869
- fargs_str << ", " if fargs_str != "("
870
- i = fargs_str.size
871
- fargs_str << (Config.current.options[:show_parameter_names] && name ? "#{ farg } #{ name }" : farg)
872
- sig_help[key] = (i...fargs_str.size)
873
- end
874
-
875
- @lead_tys.zip(iseq ? iseq.locals : []) do |ty, name|
876
- add_farg.call(ty.screen_name(scratch), name, help: true)
877
- end
878
-
879
- @opt_tys&.zip(iseq ? iseq.locals[@lead_tys.size, @opt_tys.size] : []) do |ty, name|
880
- add_farg.call("?" + ty.screen_name(scratch), name, help: true)
881
- end
882
-
883
- if @rest_ty
884
- if iseq
885
- rest_index = iseq.fargs_format[:rest_start]
886
- name = rest_index ? iseq.locals[rest_index] : nil
887
- end
888
- add_farg.call("*" + @rest_ty.screen_name(scratch), name)
889
- end
890
-
891
- if iseq
892
- post_start = iseq.fargs_format[:post_start]
893
- names = post_start ? iseq.locals[post_start, @post_tys.size] : []
894
- end
895
- @post_tys&.zip(names || []) do |ty, name|
896
- add_farg.call(ty.screen_name(scratch), name)
897
- end
898
-
899
- @kw_tys&.each do |req, sym, ty|
900
- opt = req ? "" : "?"
901
- add_farg.call("#{ opt }#{ sym }: #{ ty.screen_name(scratch) }", nil, help: true, key: sym)
902
- end
903
-
904
- if @kw_rest_ty
905
- all_val_ty = Type.bot
906
- @kw_rest_ty.each_child_global do |ty|
907
- if ty == Type.any
908
- val_ty = ty
909
- else
910
- # ty is a Type::Hash
911
- _key_ty, val_ty = ty.elems.squash
912
- end
913
- all_val_ty = all_val_ty.union(val_ty)
914
- end
915
- add_farg.call("**" + all_val_ty.screen_name(scratch), nil)
916
- end
917
-
918
- fargs_str << ")"
919
-
920
- fargs_str = "" if fargs_str == "()"
921
-
922
- # Dirty Hack: Stop the iteration at most once!
923
- # I'll remove this hack if RBS removes the limitation of nesting blocks
924
- return fargs_str, sig_help if caller_locations.any? {|frame| frame.label =~ /\bshow_block_signature\z/ }
925
-
926
- optional = false
927
- blks = []
928
- @blk_ty.each_child_global do |ty|
929
- if ty.is_a?(Type::Proc)
930
- blks << ty
931
- else
932
- # XXX: how should we handle types other than Type.nil
933
- optional = true
934
- end
935
- end
936
- if blks != []
937
- fargs_str << " " if fargs_str != ""
938
- fargs_str << "?" if optional
939
- fargs_str << scratch.show_block_signature(blks)
940
- end
941
-
942
- return fargs_str, sig_help
943
- end
944
- end
945
-
946
- class MethodSignature < Signature
947
- def initialize(lead_tys, opt_tys, rest_ty, post_tys, kw_tys, kw_rest_ty, blk_ty)
948
- @lead_tys = lead_tys
949
- @opt_tys = opt_tys
950
- raise unless opt_tys.is_a?(Array)
951
- @rest_ty = rest_ty
952
- @post_tys = post_tys
953
- raise unless post_tys
954
- @kw_tys = kw_tys
955
- kw_tys.each {|a| raise if a.size != 3 } if kw_tys
956
- @kw_rest_ty = kw_rest_ty
957
- kw_rest_ty&.each_child_global do |ty|
958
- raise ty.inspect if ty != Type.any && !ty.is_a?(Type::Hash)
959
- end
960
- @blk_ty = blk_ty
961
- end
962
-
963
- def include_untyped?(scratch)
964
- return true if @lead_tys.any? {|ty| ty.include_untyped?(scratch) }
965
- return true if @opt_tys.any? {|ty| ty.include_untyped?(scratch) }
966
- return true if @rest_ty&.include_untyped?(scratch)
967
- return true if @post_tys.any? {|ty| ty.include_untyped?(scratch) }
968
- return true if @kw_tys&.any? {|_, _, ty| ty.include_untyped?(scratch) }
969
- return true if @kw_rest_ty&.include_untyped?(scratch)
970
- return true if @blk_ty&.include_untyped?(scratch)
971
- false
972
- end
973
-
974
- attr_reader :lead_tys, :opt_tys, :rest_ty, :post_tys, :kw_tys, :kw_rest_ty, :blk_ty
975
-
976
- def substitute(subst, depth)
977
- lead_tys = @lead_tys.map {|ty| ty.substitute(subst, depth - 1) }
978
- opt_tys = @opt_tys.map {|ty| ty.substitute(subst, depth - 1) }
979
- rest_ty = @rest_ty&.substitute(subst, depth - 1)
980
- post_tys = @post_tys.map {|ty| ty.substitute(subst, depth - 1) }
981
- kw_tys = @kw_tys.map {|req, key, ty| [req, key, ty.substitute(subst, depth - 1)] }
982
- kw_rest_ty = @kw_rest_ty&.substitute(subst, depth - 1)
983
- blk_ty = @blk_ty.substitute(subst, depth - 1)
984
- MethodSignature.new(lead_tys, opt_tys, rest_ty, post_tys, kw_tys, kw_rest_ty, blk_ty)
985
- end
986
-
987
- def merge_as_block_arguments(other)
988
- lead_tys1, opt_tys1, rest_ty1, post_tys1 = @lead_tys, @opt_tys, @rest_ty, @post_tys
989
- lead_tys2, opt_tys2, rest_ty2, post_tys2 = other.lead_tys, other.opt_tys, other.rest_ty, other.post_tys
990
-
991
- case
992
- when lead_tys1.size > lead_tys2.size
993
- n = lead_tys2.size
994
- lead_tys1, opt_tys1 = lead_tys1[0, n], lead_tys1[n..] + opt_tys1
995
- when lead_tys1.size < lead_tys2.size
996
- n = lead_tys1.size
997
- lead_tys2, opt_tys2 = lead_tys2[0, n], lead_tys2[n..] + opt_tys2
998
- end
999
- case
1000
- when post_tys1.size > post_tys2.size
1001
- i = post_tys1.size - post_tys2.size
1002
- if rest_ty1
1003
- rest_ty1 = post_tys[0, i].inject(rest_ty1) {|ty1, ty2| ty1.union(ty2) }
1004
- post_tys1 = post_tys1[i..]
1005
- else
1006
- opt_tys1, post_tys1 = opt_tys1 + post_tys1[0, i], post_tys1[i..]
1007
- end
1008
- when post_tys1.size < post_tys2.size
1009
- i = post_tys2.size - post_tys1.size
1010
- if rest_ty2
1011
- rest_ty2 = post_tys[0, i].inject(rest_ty2) {|ty1, ty2| ty1.union(ty2) }
1012
- post_tys2 = post_tys2[i..]
1013
- else
1014
- opt_tys2, post_tys2 = opt_tys2 + post_tys2[0, i], post_tys2[i..]
1015
- end
1016
- end
1017
-
1018
- # XXX: tweak keywords too
1019
-
1020
- msig1 = MethodSignature.new(lead_tys1, opt_tys1, rest_ty1, post_tys1, @kw_tys, @kw_rest_ty, @blk_ty)
1021
- msig2 = MethodSignature.new(lead_tys2, opt_tys2, rest_ty2, post_tys2, other.kw_tys, other.kw_rest_ty, other.blk_ty)
1022
- msig1.merge(msig2)
1023
- end
1024
-
1025
- def merge(other)
1026
- raise if @lead_tys.size != other.lead_tys.size
1027
- raise if @post_tys.size != other.post_tys.size
1028
- if @kw_tys && other.kw_tys
1029
- kws1 = {}
1030
- @kw_tys.each {|req, kw, _| kws1[kw] = req }
1031
- kws2 = {}
1032
- other.kw_tys.each {|req, kw, _| kws2[kw] = req }
1033
- (kws1.keys & kws2.keys).each do |kw|
1034
- raise if !!kws1[kw] != !!kws2[kw]
1035
- end
1036
- elsif @kw_tys || other.kw_tys
1037
- (@kw_tys || other.kw_tys).each do |req,|
1038
- raise if req
1039
- end
1040
- end
1041
- lead_tys = @lead_tys.zip(other.lead_tys).map {|ty1, ty2| ty1.union(ty2) }
1042
- if @opt_tys || other.opt_tys
1043
- opt_tys = []
1044
- [@opt_tys.size, other.opt_tys.size].max.times do |i|
1045
- ty1 = @opt_tys[i]
1046
- ty2 = other.opt_tys[i]
1047
- ty = ty1 ? ty2 ? ty1.union(ty2) : ty1 : ty2
1048
- opt_tys << ty
1049
- end
1050
- end
1051
- if @rest_ty || other.rest_ty
1052
- if @rest_ty && other.rest_ty
1053
- rest_ty = @rest_ty.union(other.rest_ty)
1054
- else
1055
- rest_ty = @rest_ty || other.rest_ty
1056
- end
1057
- end
1058
- post_tys = @post_tys.zip(other.post_tys).map {|ty1, ty2| ty1.union(ty2) }
1059
- if @kw_tys && other.kw_tys
1060
- kws1 = {}
1061
- @kw_tys.each {|req, kw, ty| kws1[kw] = [req, ty] }
1062
- kws2 = {}
1063
- other.kw_tys.each {|req, kw, ty| kws2[kw] = [req, ty] }
1064
- kw_tys = (kws1.keys | kws2.keys).map do |kw|
1065
- req1, ty1 = kws1[kw]
1066
- _req2, ty2 = kws2[kw]
1067
- ty1 ||= Type.bot
1068
- ty2 ||= Type.bot
1069
- [!!req1, kw, ty1.union(ty2)]
1070
- end
1071
- elsif @kw_tys || other.kw_tys
1072
- kw_tys = @kw_tys || other.kw_tys
1073
- else
1074
- kw_tys = nil
1075
- end
1076
- if @kw_rest_ty || other.kw_rest_ty
1077
- if @kw_rest_ty && other.kw_rest_ty
1078
- kw_rest_ty = @kw_rest_ty.union(other.kw_rest_ty)
1079
- else
1080
- kw_rest_ty = @kw_rest_ty || other.kw_rest_ty
1081
- end
1082
- end
1083
- blk_ty = @blk_ty.union(other.blk_ty) if @blk_ty
1084
- MethodSignature.new(lead_tys, opt_tys, rest_ty, post_tys, kw_tys, kw_rest_ty, blk_ty)
1085
- end
1086
- end
1087
-
1088
- class BlockSignature < Signature
1089
- def initialize(lead_tys, opt_tys, rest_ty, blk_ty)
1090
- @lead_tys = lead_tys
1091
- @opt_tys = opt_tys
1092
- @rest_ty = rest_ty
1093
- @blk_ty = blk_ty
1094
- # TODO: kw_tys
1095
- end
1096
-
1097
- attr_reader :lead_tys, :opt_tys, :rest_ty, :blk_ty
1098
-
1099
- def merge(bsig)
1100
- if @rest_ty && bsig.rest_ty
1101
- rest_ty = @rest_ty.union(bsig.rest_ty)
1102
- BlockSignature.new(@lead_tys, [], rest_ty, @blk_ty.union(bsig.blk_ty))
1103
- elsif @rest_ty || bsig.rest_ty
1104
- rest_ty = @rest_ty || bsig.rest_ty
1105
- rest_ty = @opt_tys.inject(rest_ty, &:union)
1106
- rest_ty = bsig.opt_tys.inject(rest_ty, &:union)
1107
-
1108
- lead_tys = []
1109
- [@lead_tys.size, bsig.lead_tys.size].max.times do |i|
1110
- ty1 = @lead_tys[i]
1111
- ty2 = bsig.lead_tys[i]
1112
- if ty1 && ty2
1113
- lead_tys << ty1.union(ty2)
1114
- else
1115
- rest_ty = rest_ty.union(ty1 || ty2)
1116
- end
1117
- end
1118
-
1119
- BlockSignature.new(lead_tys, [], rest_ty, @blk_ty.union(bsig.blk_ty))
1120
- else
1121
- lead_tys = []
1122
- n = [@lead_tys.size, bsig.lead_tys.size].min
1123
- n.times do |i|
1124
- lead_tys << @lead_tys[i].union(bsig.lead_tys[i])
1125
- end
1126
- opt_tys1 = @lead_tys[n..] + @opt_tys
1127
- opt_tys2 = bsig.lead_tys[n..] + bsig.opt_tys
1128
- opt_tys = []
1129
- [opt_tys1.size, opt_tys2.size].max.times do |i|
1130
- if opt_tys1[i] && opt_tys2[i]
1131
- opt_tys << opt_tys1[i].union(opt_tys2[i])
1132
- else
1133
- opt_tys << (opt_tys1[i] || opt_tys2[i])
1134
- end
1135
- end
1136
- BlockSignature.new(lead_tys, opt_tys, nil, @blk_ty.union(bsig.blk_ty))
1137
- end
1138
- end
1139
- end
1140
- end