typeprof 0.30.1 → 0.31.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.
- checksums.yaml +4 -4
- data/README.md +23 -4
- data/lib/typeprof/cli/cli.rb +27 -7
- data/lib/typeprof/code_range.rb +9 -7
- data/lib/typeprof/core/ast/base.rb +27 -10
- data/lib/typeprof/core/ast/call.rb +85 -24
- data/lib/typeprof/core/ast/const.rb +7 -12
- data/lib/typeprof/core/ast/control.rb +345 -71
- data/lib/typeprof/core/ast/meta.rb +5 -5
- data/lib/typeprof/core/ast/method.rb +15 -5
- data/lib/typeprof/core/ast/misc.rb +21 -2
- data/lib/typeprof/core/ast/module.rb +10 -7
- data/lib/typeprof/core/ast/pattern.rb +9 -1
- data/lib/typeprof/core/ast/sig_decl.rb +163 -42
- data/lib/typeprof/core/ast/sig_type.rb +394 -24
- data/lib/typeprof/core/ast/value.rb +10 -2
- data/lib/typeprof/core/ast/variable.rb +32 -2
- data/lib/typeprof/core/ast.rb +15 -4
- data/lib/typeprof/core/builtin.rb +15 -9
- data/lib/typeprof/core/env/method.rb +21 -16
- data/lib/typeprof/core/env/method_entity.rb +11 -2
- data/lib/typeprof/core/env/module_entity.rb +57 -0
- data/lib/typeprof/core/env/narrowing.rb +131 -0
- data/lib/typeprof/core/env/static_read.rb +9 -8
- data/lib/typeprof/core/env.rb +37 -12
- data/lib/typeprof/core/graph/box.rb +207 -97
- data/lib/typeprof/core/graph/change_set.rb +44 -37
- data/lib/typeprof/core/graph/vertex.rb +4 -21
- data/lib/typeprof/core/service.rb +30 -1
- data/lib/typeprof/core/type.rb +48 -123
- data/lib/typeprof/core.rb +1 -0
- data/lib/typeprof/diagnostic.rb +5 -6
- data/lib/typeprof/lsp/messages.rb +21 -15
- data/lib/typeprof/lsp/server.rb +132 -39
- data/lib/typeprof/lsp/text.rb +1 -0
- data/lib/typeprof/version.rb +1 -1
- data/typeprof.conf.jsonc +22 -0
- data/typeprof.gemspec +1 -0
- metadata +19 -6
|
@@ -1,5 +1,83 @@
|
|
|
1
1
|
module TypeProf::Core
|
|
2
2
|
class AST
|
|
3
|
+
def self.typecheck_for_module(genv, changes, f_mod, f_args, a_vtx, subst)
|
|
4
|
+
changes.add_edge(genv, a_vtx, changes.target)
|
|
5
|
+
a_vtx.each_type do |ty|
|
|
6
|
+
ty = ty.base_type(genv)
|
|
7
|
+
while ty
|
|
8
|
+
if ty.mod == f_mod && ty.is_a?(Type::Instance)
|
|
9
|
+
args_all_match = true
|
|
10
|
+
f_args.zip(ty.args) do |f_arg_node, a_arg_ty|
|
|
11
|
+
unless f_arg_node.typecheck(genv, changes, a_arg_ty, subst)
|
|
12
|
+
args_all_match = false
|
|
13
|
+
break
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
return true if args_all_match
|
|
17
|
+
end
|
|
18
|
+
changes.add_depended_superclass(ty.mod)
|
|
19
|
+
|
|
20
|
+
if f_mod.module?
|
|
21
|
+
return true if typecheck_for_prepended_modules(genv, changes, ty, f_mod, f_args, subst)
|
|
22
|
+
return true if typecheck_for_included_modules(genv, changes, ty, f_mod, f_args, subst)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
ty = genv.get_superclass_type(ty, changes, {})
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
return false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.typecheck_for_prepended_modules(genv, changes, a_ty, f_mod, f_args, subst)
|
|
32
|
+
a_ty.mod.prepended_modules.each do |prep_decl, prep_mod|
|
|
33
|
+
if prep_decl.is_a?(AST::SigPrependNode) && prep_mod.type_params
|
|
34
|
+
prep_ty = genv.get_instance_type(prep_mod, prep_decl.args, changes, {}, a_ty)
|
|
35
|
+
else
|
|
36
|
+
type_params = prep_mod.type_params.map {|ty_param| Source.new() } # TODO: better support
|
|
37
|
+
prep_ty = Type::Instance.new(genv, prep_mod, type_params)
|
|
38
|
+
end
|
|
39
|
+
if prep_ty.mod == f_mod
|
|
40
|
+
args_all_match = true
|
|
41
|
+
f_args.zip(prep_ty.args) do |f_arg_node, a_arg_ty|
|
|
42
|
+
unless f_arg_node.typecheck(genv, changes, a_arg_ty, subst)
|
|
43
|
+
args_all_match = false
|
|
44
|
+
break
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
return true if args_all_match
|
|
48
|
+
end
|
|
49
|
+
changes.add_depended_superclass(prep_ty.mod)
|
|
50
|
+
|
|
51
|
+
return true if typecheck_for_prepended_modules(genv, changes, prep_ty, f_mod, f_args, subst)
|
|
52
|
+
end
|
|
53
|
+
return false
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.typecheck_for_included_modules(genv, changes, a_ty, f_mod, f_args, subst)
|
|
57
|
+
a_ty.mod.included_modules.each do |inc_decl, inc_mod|
|
|
58
|
+
if inc_decl.is_a?(AST::SigIncludeNode) && inc_mod.type_params
|
|
59
|
+
inc_ty = genv.get_instance_type(inc_mod, inc_decl.args, changes, {}, a_ty)
|
|
60
|
+
else
|
|
61
|
+
type_params = inc_mod.type_params.map {|ty_param| Source.new() } # TODO: better support
|
|
62
|
+
inc_ty = Type::Instance.new(genv, inc_mod, type_params)
|
|
63
|
+
end
|
|
64
|
+
if inc_ty.mod == f_mod
|
|
65
|
+
args_all_match = true
|
|
66
|
+
f_args.zip(inc_ty.args) do |f_arg_node, a_arg_vtx|
|
|
67
|
+
unless f_arg_node.typecheck(genv, changes, a_arg_vtx, subst)
|
|
68
|
+
args_all_match = false
|
|
69
|
+
break
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
return true if args_all_match
|
|
73
|
+
end
|
|
74
|
+
changes.add_depended_superclass(inc_ty.mod)
|
|
75
|
+
|
|
76
|
+
return true if typecheck_for_included_modules(genv, changes, inc_ty, f_mod, f_args, subst)
|
|
77
|
+
end
|
|
78
|
+
return false
|
|
79
|
+
end
|
|
80
|
+
|
|
3
81
|
class SigFuncType < Node
|
|
4
82
|
def initialize(raw_decl, raw_type_params, raw_block, lenv)
|
|
5
83
|
super(raw_decl, lenv)
|
|
@@ -101,6 +179,14 @@ module TypeProf::Core
|
|
|
101
179
|
changes.add_edge(genv, Source.new(genv.true_type, genv.false_type), vtx)
|
|
102
180
|
end
|
|
103
181
|
|
|
182
|
+
def typecheck(genv, changes, vtx, subst)
|
|
183
|
+
changes.add_edge(genv, vtx, changes.target)
|
|
184
|
+
vtx.each_type do |ty|
|
|
185
|
+
return false unless ty == genv.true_type || ty == genv.false_type
|
|
186
|
+
end
|
|
187
|
+
true
|
|
188
|
+
end
|
|
189
|
+
|
|
104
190
|
def show
|
|
105
191
|
"bool"
|
|
106
192
|
end
|
|
@@ -115,6 +201,14 @@ module TypeProf::Core
|
|
|
115
201
|
changes.add_edge(genv, Source.new(genv.nil_type), vtx)
|
|
116
202
|
end
|
|
117
203
|
|
|
204
|
+
def typecheck(genv, changes, vtx, subst)
|
|
205
|
+
changes.add_edge(genv, vtx, changes.target)
|
|
206
|
+
vtx.each_type do |ty|
|
|
207
|
+
return false unless ty == genv.nil_type
|
|
208
|
+
end
|
|
209
|
+
true
|
|
210
|
+
end
|
|
211
|
+
|
|
118
212
|
def show
|
|
119
213
|
"nil"
|
|
120
214
|
end
|
|
@@ -129,6 +223,10 @@ module TypeProf::Core
|
|
|
129
223
|
changes.add_edge(genv, subst[:"*self"], vtx)
|
|
130
224
|
end
|
|
131
225
|
|
|
226
|
+
def typecheck(genv, changes, vtx, subst)
|
|
227
|
+
true # TODO: check self type
|
|
228
|
+
end
|
|
229
|
+
|
|
132
230
|
def show
|
|
133
231
|
"self"
|
|
134
232
|
end
|
|
@@ -143,6 +241,10 @@ module TypeProf::Core
|
|
|
143
241
|
changes.add_edge(genv, Source.new(genv.obj_type), vtx)
|
|
144
242
|
end
|
|
145
243
|
|
|
244
|
+
def typecheck(genv, changes, vtx, subst)
|
|
245
|
+
true
|
|
246
|
+
end
|
|
247
|
+
|
|
146
248
|
def show
|
|
147
249
|
"void"
|
|
148
250
|
end
|
|
@@ -156,6 +258,10 @@ module TypeProf::Core
|
|
|
156
258
|
#Source.new(genv.obj_type).add_edge(genv, vtx) # TODO
|
|
157
259
|
end
|
|
158
260
|
|
|
261
|
+
def typecheck(genv, changes, vtx, subst)
|
|
262
|
+
true
|
|
263
|
+
end
|
|
264
|
+
|
|
159
265
|
def show
|
|
160
266
|
"untyped"
|
|
161
267
|
end
|
|
@@ -170,6 +276,10 @@ module TypeProf::Core
|
|
|
170
276
|
# TODO
|
|
171
277
|
end
|
|
172
278
|
|
|
279
|
+
def typecheck(genv, changes, vtx, subst)
|
|
280
|
+
true
|
|
281
|
+
end
|
|
282
|
+
|
|
173
283
|
def show
|
|
174
284
|
"top"
|
|
175
285
|
end
|
|
@@ -184,6 +294,11 @@ module TypeProf::Core
|
|
|
184
294
|
changes.add_edge(genv, Source.new(Type::Bot.new(genv)), vtx)
|
|
185
295
|
end
|
|
186
296
|
|
|
297
|
+
def typecheck(genv, changes, vtx, subst)
|
|
298
|
+
changes.add_edge(genv, vtx, changes.target)
|
|
299
|
+
vtx.types.empty?
|
|
300
|
+
end
|
|
301
|
+
|
|
187
302
|
def show
|
|
188
303
|
"bot"
|
|
189
304
|
end
|
|
@@ -198,6 +313,10 @@ module TypeProf::Core
|
|
|
198
313
|
changes.add_edge(genv, subst[:"*instance"], vtx)
|
|
199
314
|
end
|
|
200
315
|
|
|
316
|
+
def typecheck(genv, changes, vtx, subst)
|
|
317
|
+
true # TODO: implement
|
|
318
|
+
end
|
|
319
|
+
|
|
201
320
|
def show
|
|
202
321
|
"instance"
|
|
203
322
|
end
|
|
@@ -212,6 +331,10 @@ module TypeProf::Core
|
|
|
212
331
|
changes.add_edge(genv, subst[:"*class"], vtx)
|
|
213
332
|
end
|
|
214
333
|
|
|
334
|
+
def typecheck(genv, changes, vtx, subst)
|
|
335
|
+
true # TODO: implement
|
|
336
|
+
end
|
|
337
|
+
|
|
215
338
|
def show
|
|
216
339
|
"class"
|
|
217
340
|
end
|
|
@@ -236,13 +359,13 @@ module TypeProf::Core
|
|
|
236
359
|
|
|
237
360
|
static_reads = []
|
|
238
361
|
if @cpath.empty?
|
|
239
|
-
static_reads << BaseTypeAliasRead.new(genv, @name, @toplevel ? CRef::Toplevel : @lenv.cref)
|
|
362
|
+
static_reads << BaseTypeAliasRead.new(genv, @name, @toplevel ? CRef::Toplevel : @lenv.cref, false)
|
|
240
363
|
else
|
|
241
|
-
static_reads << BaseConstRead.new(genv, @cpath.first, @toplevel ? CRef::Toplevel : @lenv.cref)
|
|
364
|
+
static_reads << BaseConstRead.new(genv, @cpath.first, @toplevel ? CRef::Toplevel : @lenv.cref, false)
|
|
242
365
|
@cpath[1..].each do |cname|
|
|
243
|
-
static_reads << ScopedConstRead.new(cname, static_reads.last)
|
|
366
|
+
static_reads << ScopedConstRead.new(cname, static_reads.last, false)
|
|
244
367
|
end
|
|
245
|
-
static_reads << ScopedTypeAliasRead.new(@name, static_reads.last)
|
|
368
|
+
static_reads << ScopedTypeAliasRead.new(@name, static_reads.last, false)
|
|
246
369
|
end
|
|
247
370
|
static_reads
|
|
248
371
|
end
|
|
@@ -258,9 +381,24 @@ module TypeProf::Core
|
|
|
258
381
|
changes.add_depended_static_read(@static_ret.last)
|
|
259
382
|
tae = @static_ret.last.type_alias_entity
|
|
260
383
|
if tae && tae.exist?
|
|
384
|
+
# Check for recursive expansion
|
|
385
|
+
expansion_key = [@cpath, @name]
|
|
386
|
+
subst[:__expansion_stack__] ||= []
|
|
387
|
+
|
|
388
|
+
if subst[:__expansion_stack__].include?(expansion_key)
|
|
389
|
+
# Recursive expansion detected: this type alias references itself
|
|
390
|
+
# Stop expansion here to prevent SystemStackError. The type system
|
|
391
|
+
# will handle the incomplete expansion gracefully, typically by
|
|
392
|
+
# treating unresolved recursive references as 'untyped', which
|
|
393
|
+
# maintains type safety while allowing the program to continue.
|
|
394
|
+
return
|
|
395
|
+
end
|
|
396
|
+
|
|
261
397
|
# need to check tae decls are all consistent?
|
|
262
398
|
decl = tae.decls.each {|decl| break decl }
|
|
263
399
|
subst0 = subst.dup
|
|
400
|
+
subst0[:__expansion_stack__] = subst[:__expansion_stack__].dup + [expansion_key]
|
|
401
|
+
|
|
264
402
|
# raise if decl.params.size != @args.size # ?
|
|
265
403
|
decl.params.zip(@args) do |param, arg|
|
|
266
404
|
subst0[param] = arg.covariant_vertex(genv, changes, subst0) # passing subst0 is ok?
|
|
@@ -273,9 +411,24 @@ module TypeProf::Core
|
|
|
273
411
|
changes.add_depended_static_read(@static_ret.last)
|
|
274
412
|
tae = @static_ret.last.type_alias_entity
|
|
275
413
|
if tae && tae.exist?
|
|
414
|
+
# Check for recursive expansion
|
|
415
|
+
expansion_key = [@cpath, @name]
|
|
416
|
+
subst[:__expansion_stack__] ||= []
|
|
417
|
+
|
|
418
|
+
if subst[:__expansion_stack__].include?(expansion_key)
|
|
419
|
+
# Recursive expansion detected: this type alias references itself
|
|
420
|
+
# Stop expansion here to prevent SystemStackError. The type system
|
|
421
|
+
# will handle the incomplete expansion gracefully, typically by
|
|
422
|
+
# treating unresolved recursive references as 'untyped', which
|
|
423
|
+
# maintains type safety while allowing the program to continue.
|
|
424
|
+
return
|
|
425
|
+
end
|
|
426
|
+
|
|
276
427
|
# need to check tae decls are all consistent?
|
|
277
428
|
decl = tae.decls.each {|decl| break decl }
|
|
278
429
|
subst0 = subst.dup
|
|
430
|
+
subst0[:__expansion_stack__] = subst[:__expansion_stack__].dup + [expansion_key]
|
|
431
|
+
|
|
279
432
|
# raise if decl.params.size != @args.size # ?
|
|
280
433
|
decl.params.zip(@args) do |param, arg|
|
|
281
434
|
subst0[param] = arg.contravariant_vertex(genv, changes, subst0)
|
|
@@ -284,6 +437,20 @@ module TypeProf::Core
|
|
|
284
437
|
end
|
|
285
438
|
end
|
|
286
439
|
|
|
440
|
+
def typecheck(genv, changes, vtx, subst)
|
|
441
|
+
changes.add_depended_static_read(@static_ret.last)
|
|
442
|
+
tae = @static_ret.last.type_alias_entity
|
|
443
|
+
if tae && tae.exist?
|
|
444
|
+
# TODO: check for recursive expansion
|
|
445
|
+
decl = tae.decls.each {|decl| break decl }
|
|
446
|
+
subst0 = subst.dup
|
|
447
|
+
decl.params.zip(@args) do |param, arg|
|
|
448
|
+
subst0[param] = arg.covariant_vertex(genv, changes, subst0)
|
|
449
|
+
end
|
|
450
|
+
tae.type.typecheck(genv, changes, vtx, subst0)
|
|
451
|
+
end
|
|
452
|
+
end
|
|
453
|
+
|
|
287
454
|
def show
|
|
288
455
|
"(...alias...)"
|
|
289
456
|
end
|
|
@@ -311,22 +478,49 @@ module TypeProf::Core
|
|
|
311
478
|
end
|
|
312
479
|
end
|
|
313
480
|
|
|
481
|
+
def typecheck(genv, changes, vtx, subst)
|
|
482
|
+
@types.each do |type|
|
|
483
|
+
return true if type.typecheck(genv, changes, vtx, subst)
|
|
484
|
+
end
|
|
485
|
+
false
|
|
486
|
+
end
|
|
487
|
+
|
|
314
488
|
def show
|
|
315
489
|
@types.map {|ty| ty.show }.join(" | ")
|
|
316
490
|
end
|
|
317
491
|
end
|
|
318
492
|
|
|
319
493
|
class SigTyIntersectionNode < SigTyNode
|
|
494
|
+
def initialize(raw_decl, lenv)
|
|
495
|
+
super(raw_decl, lenv)
|
|
496
|
+
@types = (raw_decl.types || []).map {|type| AST.create_rbs_type(type, lenv) }
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
attr_reader :types
|
|
500
|
+
|
|
501
|
+
def subnodes = { types: }
|
|
502
|
+
|
|
320
503
|
def covariant_vertex0(genv, changes, vtx, subst)
|
|
321
|
-
|
|
504
|
+
@types.each do |type|
|
|
505
|
+
type.covariant_vertex0(genv, changes, vtx, subst)
|
|
506
|
+
end
|
|
322
507
|
end
|
|
323
508
|
|
|
324
509
|
def contravariant_vertex0(genv, changes, vtx, subst)
|
|
325
|
-
|
|
510
|
+
@types.each do |type|
|
|
511
|
+
type.contravariant_vertex0(genv, changes, vtx, subst)
|
|
512
|
+
end
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
def typecheck(genv, changes, vtx, subst)
|
|
516
|
+
@types.each do |type|
|
|
517
|
+
return false unless type.typecheck(genv, changes, vtx, subst)
|
|
518
|
+
end
|
|
519
|
+
true
|
|
326
520
|
end
|
|
327
521
|
|
|
328
522
|
def show
|
|
329
|
-
"
|
|
523
|
+
@types.map {|ty| ty.show }.join(" & ")
|
|
330
524
|
end
|
|
331
525
|
end
|
|
332
526
|
|
|
@@ -343,11 +537,11 @@ module TypeProf::Core
|
|
|
343
537
|
|
|
344
538
|
def define0(genv)
|
|
345
539
|
const_reads = []
|
|
346
|
-
const_read = BaseConstRead.new(genv, @cpath.first, @toplevel ? CRef::Toplevel : @lenv.cref)
|
|
540
|
+
const_read = BaseConstRead.new(genv, @cpath.first, @toplevel ? CRef::Toplevel : @lenv.cref, false)
|
|
347
541
|
const_reads << const_read
|
|
348
542
|
unless @cpath.empty?
|
|
349
543
|
@cpath[1..].each do |cname|
|
|
350
|
-
const_read = ScopedConstRead.new(cname, const_read)
|
|
544
|
+
const_read = ScopedConstRead.new(cname, const_read, false)
|
|
351
545
|
const_reads << const_read
|
|
352
546
|
end
|
|
353
547
|
end
|
|
@@ -378,6 +572,30 @@ module TypeProf::Core
|
|
|
378
572
|
changes.add_edge(genv, Source.new(Type::Singleton.new(genv, mod)), vtx)
|
|
379
573
|
end
|
|
380
574
|
|
|
575
|
+
def typecheck(genv, changes, vtx, subst)
|
|
576
|
+
changes.add_depended_static_read(@static_ret.last)
|
|
577
|
+
cpath = @static_ret.last.cpath
|
|
578
|
+
return unless cpath
|
|
579
|
+
f_mod = genv.resolve_cpath(cpath)
|
|
580
|
+
changes.add_edge(genv, vtx, changes.target)
|
|
581
|
+
vtx.each_type do |ty|
|
|
582
|
+
case ty
|
|
583
|
+
when Type::Singleton
|
|
584
|
+
if f_mod.module?
|
|
585
|
+
# TODO: implement
|
|
586
|
+
else
|
|
587
|
+
a_mod = ty.mod
|
|
588
|
+
while a_mod
|
|
589
|
+
return true if a_mod == f_mod
|
|
590
|
+
changes.add_depended_superclass(a_mod)
|
|
591
|
+
a_mod = a_mod.superclass
|
|
592
|
+
end
|
|
593
|
+
end
|
|
594
|
+
end
|
|
595
|
+
end
|
|
596
|
+
false
|
|
597
|
+
end
|
|
598
|
+
|
|
381
599
|
def show
|
|
382
600
|
s = "::#{ @cpath.join("::") }"
|
|
383
601
|
if !@args.empty?
|
|
@@ -403,11 +621,11 @@ module TypeProf::Core
|
|
|
403
621
|
def define0(genv)
|
|
404
622
|
@args.each {|arg| arg.define(genv) }
|
|
405
623
|
const_reads = []
|
|
406
|
-
const_read = BaseConstRead.new(genv, @cpath.first, @toplevel ? CRef::Toplevel : @lenv.cref)
|
|
624
|
+
const_read = BaseConstRead.new(genv, @cpath.first, @toplevel ? CRef::Toplevel : @lenv.cref, false)
|
|
407
625
|
const_reads << const_read
|
|
408
626
|
unless @cpath.empty?
|
|
409
627
|
@cpath[1..].each do |cname|
|
|
410
|
-
const_read = ScopedConstRead.new(cname, const_read)
|
|
628
|
+
const_read = ScopedConstRead.new(cname, const_read, false)
|
|
411
629
|
const_reads << const_read
|
|
412
630
|
end
|
|
413
631
|
end
|
|
@@ -435,16 +653,33 @@ module TypeProf::Core
|
|
|
435
653
|
cpath = @static_ret.last.cpath
|
|
436
654
|
return unless cpath
|
|
437
655
|
mod = genv.resolve_cpath(cpath)
|
|
438
|
-
|
|
656
|
+
# TODO: report error for wrong type arguments
|
|
657
|
+
# TODO: support default type args
|
|
658
|
+
args = mod.type_params.zip(@args).map do |_, arg|
|
|
659
|
+
arg ? arg.contravariant_vertex(genv, changes, subst) : Source.new
|
|
660
|
+
end
|
|
439
661
|
changes.add_edge(genv, Source.new(Type::Instance.new(genv, mod, args)), vtx)
|
|
440
662
|
end
|
|
441
663
|
|
|
664
|
+
def typecheck(genv, changes, vtx, subst)
|
|
665
|
+
changes.add_depended_static_read(@static_ret.last)
|
|
666
|
+
cpath = @static_ret.last.cpath
|
|
667
|
+
return unless cpath
|
|
668
|
+
f_mod = genv.resolve_cpath(cpath)
|
|
669
|
+
AST.typecheck_for_module(genv, changes, f_mod, @args, vtx, subst)
|
|
670
|
+
end
|
|
671
|
+
|
|
442
672
|
def show
|
|
443
|
-
|
|
444
|
-
if
|
|
445
|
-
s
|
|
673
|
+
cpath = @static_ret.last.cpath
|
|
674
|
+
if cpath
|
|
675
|
+
s = "#{ cpath.join("::") }"
|
|
676
|
+
if !@args.empty?
|
|
677
|
+
s << "[...]"
|
|
678
|
+
end
|
|
679
|
+
s
|
|
680
|
+
else
|
|
681
|
+
"(unknown instance)"
|
|
446
682
|
end
|
|
447
|
-
s
|
|
448
683
|
end
|
|
449
684
|
end
|
|
450
685
|
|
|
@@ -477,22 +712,96 @@ module TypeProf::Core
|
|
|
477
712
|
changes.add_edge(genv, Source.new(Type::Array.new(genv, elems, genv.gen_ary_type(unified_elem))), vtx)
|
|
478
713
|
end
|
|
479
714
|
|
|
715
|
+
def typecheck(genv, changes, vtx, subst)
|
|
716
|
+
changes.add_edge(genv, vtx, changes.target)
|
|
717
|
+
vtx.each_type do |ty|
|
|
718
|
+
case ty
|
|
719
|
+
when Type::Array
|
|
720
|
+
next if ty.elems.size != @types.size
|
|
721
|
+
@types.zip(ty.elems) do |f_ty, a_ty|
|
|
722
|
+
return false unless f_ty.typecheck(genv, changes, a_ty, subst)
|
|
723
|
+
end
|
|
724
|
+
return true
|
|
725
|
+
when Type::Instance
|
|
726
|
+
@types.each do |f_ty|
|
|
727
|
+
return false unless f_ty.typecheck(genv, changes, vtx, subst)
|
|
728
|
+
end
|
|
729
|
+
return true
|
|
730
|
+
end
|
|
731
|
+
end
|
|
732
|
+
false
|
|
733
|
+
end
|
|
734
|
+
|
|
480
735
|
def show
|
|
481
736
|
"[#{ @types.map {|ty| ty.show }.join(", ") }]"
|
|
482
737
|
end
|
|
483
738
|
end
|
|
484
739
|
|
|
485
740
|
class SigTyRecordNode < SigTyNode
|
|
741
|
+
def initialize(raw_decl, lenv)
|
|
742
|
+
super(raw_decl, lenv)
|
|
743
|
+
@fields = raw_decl.fields.transform_values { |val| AST.create_rbs_type(val, lenv) }
|
|
744
|
+
end
|
|
745
|
+
|
|
746
|
+
attr_reader :fields
|
|
747
|
+
def subnodes = { fields: }
|
|
748
|
+
|
|
486
749
|
def covariant_vertex0(genv, changes, vtx, subst)
|
|
487
|
-
|
|
750
|
+
field_vertices = {}
|
|
751
|
+
@fields.each do |key, field_node|
|
|
752
|
+
field_vertices[key] = field_node.covariant_vertex(genv, changes, subst)
|
|
753
|
+
end
|
|
754
|
+
|
|
755
|
+
# Create base Hash type for Record
|
|
756
|
+
key_vtx = Source.new(genv.symbol_type)
|
|
757
|
+
# Create union of all field values for the Hash value type
|
|
758
|
+
val_vtx = changes.new_covariant_vertex(genv, [self, :union])
|
|
759
|
+
field_vertices.each_value do |field_vtx|
|
|
760
|
+
changes.add_edge(genv, field_vtx, val_vtx)
|
|
761
|
+
end
|
|
762
|
+
base_hash_type = genv.gen_hash_type(key_vtx, val_vtx)
|
|
763
|
+
|
|
764
|
+
changes.add_edge(genv, Source.new(Type::Record.new(genv, field_vertices, base_hash_type)), vtx)
|
|
488
765
|
end
|
|
489
766
|
|
|
490
767
|
def contravariant_vertex0(genv, changes, vtx, subst)
|
|
491
|
-
|
|
768
|
+
field_vertices = {}
|
|
769
|
+
@fields.each do |key, field_node|
|
|
770
|
+
field_vertices[key] = field_node.contravariant_vertex(genv, changes, subst)
|
|
771
|
+
end
|
|
772
|
+
|
|
773
|
+
# Create base Hash type for Record
|
|
774
|
+
key_vtx = Source.new(genv.symbol_type)
|
|
775
|
+
# Create union of all field values for the Hash value type
|
|
776
|
+
val_vtx = changes.new_contravariant_vertex(genv, [self, :union])
|
|
777
|
+
field_vertices.each_value do |field_vtx|
|
|
778
|
+
changes.add_edge(genv, field_vtx, val_vtx)
|
|
779
|
+
end
|
|
780
|
+
base_hash_type = genv.gen_hash_type(key_vtx, val_vtx)
|
|
781
|
+
|
|
782
|
+
changes.add_edge(genv, Source.new(Type::Record.new(genv, field_vertices, base_hash_type)), vtx)
|
|
783
|
+
end
|
|
784
|
+
|
|
785
|
+
def typecheck(genv, changes, vtx, subst)
|
|
786
|
+
changes.add_edge(genv, vtx, changes.target)
|
|
787
|
+
vtx.each_type do |ty|
|
|
788
|
+
case ty
|
|
789
|
+
when Type::Hash
|
|
790
|
+
@fields.each do |key, field_node|
|
|
791
|
+
val_vtx = ty.get_value(key)
|
|
792
|
+
return false unless field_node.typecheck(genv, changes, val_vtx, subst)
|
|
793
|
+
end
|
|
794
|
+
return true
|
|
795
|
+
end
|
|
796
|
+
end
|
|
797
|
+
false
|
|
492
798
|
end
|
|
493
799
|
|
|
494
800
|
def show
|
|
495
|
-
|
|
801
|
+
field_strs = @fields.map do |key, field_node|
|
|
802
|
+
"#{ key }: #{ field_node.show }"
|
|
803
|
+
end
|
|
804
|
+
"{ #{ field_strs.join(", ") } }"
|
|
496
805
|
end
|
|
497
806
|
end
|
|
498
807
|
|
|
@@ -516,6 +825,11 @@ module TypeProf::Core
|
|
|
516
825
|
changes.add_edge(genv, Source.new(Type::Var.new(genv, @var, subst[@var])), vtx)
|
|
517
826
|
end
|
|
518
827
|
|
|
828
|
+
def typecheck(genv, changes, vtx, subst)
|
|
829
|
+
changes.add_edge(genv, vtx, subst[@var]) unless vtx == subst[@var]
|
|
830
|
+
true
|
|
831
|
+
end
|
|
832
|
+
|
|
519
833
|
def show
|
|
520
834
|
"#{ @var }"
|
|
521
835
|
end
|
|
@@ -540,6 +854,10 @@ module TypeProf::Core
|
|
|
540
854
|
changes.add_edge(genv, Source.new(genv.nil_type), vtx)
|
|
541
855
|
end
|
|
542
856
|
|
|
857
|
+
def typecheck(genv, changes, vtx, subst)
|
|
858
|
+
@type.typecheck(genv, changes, vtx, subst)
|
|
859
|
+
end
|
|
860
|
+
|
|
543
861
|
def show
|
|
544
862
|
s = @type.show
|
|
545
863
|
if @type.is_a?(SigTyIntersectionNode) || @type.is_a?(SigTyUnionNode)
|
|
@@ -579,22 +897,65 @@ module TypeProf::Core
|
|
|
579
897
|
changes.add_edge(genv, Source.new(get_type(genv)), vtx)
|
|
580
898
|
end
|
|
581
899
|
|
|
900
|
+
def typecheck(genv, changes, vtx, subst)
|
|
901
|
+
if @lit.is_a?(::Symbol)
|
|
902
|
+
changes.add_edge(genv, vtx, changes.target)
|
|
903
|
+
vtx.each_type do |ty|
|
|
904
|
+
case ty
|
|
905
|
+
when Type::Symbol
|
|
906
|
+
return true if ty.sym == @lit
|
|
907
|
+
end
|
|
908
|
+
end
|
|
909
|
+
return false
|
|
910
|
+
end
|
|
911
|
+
f_mod = get_type(genv).mod
|
|
912
|
+
AST.typecheck_for_module(genv, changes, f_mod, [], vtx, subst)
|
|
913
|
+
end
|
|
914
|
+
|
|
582
915
|
def show
|
|
583
916
|
@lit.inspect
|
|
584
917
|
end
|
|
585
918
|
end
|
|
586
919
|
|
|
587
920
|
class SigTyProcNode < SigTyNode
|
|
921
|
+
def initialize(raw_decl, lenv)
|
|
922
|
+
super(raw_decl, lenv)
|
|
923
|
+
# raw_decl.type is an RBS::Types::Function, we need to wrap it in a MethodType
|
|
924
|
+
if raw_decl.type
|
|
925
|
+
method_type = RBS::MethodType.new(
|
|
926
|
+
type: raw_decl.type,
|
|
927
|
+
type_params: [],
|
|
928
|
+
block: raw_decl.block,
|
|
929
|
+
location: raw_decl.location
|
|
930
|
+
)
|
|
931
|
+
@type = AST.create_rbs_func_type(method_type, nil, raw_decl.block, lenv)
|
|
932
|
+
else
|
|
933
|
+
@type = nil
|
|
934
|
+
end
|
|
935
|
+
end
|
|
936
|
+
|
|
937
|
+
attr_reader :type
|
|
938
|
+
def subnodes = { type: }
|
|
939
|
+
|
|
588
940
|
def covariant_vertex0(genv, changes, vtx, subst)
|
|
589
|
-
|
|
941
|
+
# For now, just return the base Proc type without the function signature details
|
|
942
|
+
# TODO: Create a proper Type::Proc with the function signature
|
|
943
|
+
changes.add_edge(genv, Source.new(genv.proc_type), vtx)
|
|
590
944
|
end
|
|
591
945
|
|
|
592
946
|
def contravariant_vertex0(genv, changes, vtx, subst)
|
|
593
|
-
|
|
947
|
+
# For now, just return the base Proc type without the function signature details
|
|
948
|
+
# TODO: Create a proper Type::Proc with the function signature
|
|
949
|
+
changes.add_edge(genv, Source.new(genv.proc_type), vtx)
|
|
950
|
+
end
|
|
951
|
+
|
|
952
|
+
def typecheck(genv, changes, vtx, subst)
|
|
953
|
+
# TODO: proper check
|
|
954
|
+
AST.typecheck_for_module(genv, changes, genv.proc_type.mod, [], vtx, subst)
|
|
594
955
|
end
|
|
595
956
|
|
|
596
957
|
def show
|
|
597
|
-
"(...
|
|
958
|
+
"^(...)"
|
|
598
959
|
end
|
|
599
960
|
end
|
|
600
961
|
|
|
@@ -615,11 +976,11 @@ module TypeProf::Core
|
|
|
615
976
|
def define0(genv)
|
|
616
977
|
@args.each {|arg| arg.define(genv) }
|
|
617
978
|
const_reads = []
|
|
618
|
-
const_read = BaseConstRead.new(genv, @cpath.first, @toplevel ? CRef::Toplevel : @lenv.cref)
|
|
979
|
+
const_read = BaseConstRead.new(genv, @cpath.first, @toplevel ? CRef::Toplevel : @lenv.cref, false)
|
|
619
980
|
const_reads << const_read
|
|
620
981
|
unless @cpath.empty?
|
|
621
982
|
@cpath[1..].each do |cname|
|
|
622
|
-
const_read = ScopedConstRead.new(cname, const_read)
|
|
983
|
+
const_read = ScopedConstRead.new(cname, const_read, false)
|
|
623
984
|
const_reads << const_read
|
|
624
985
|
end
|
|
625
986
|
end
|
|
@@ -651,6 +1012,15 @@ module TypeProf::Core
|
|
|
651
1012
|
changes.add_edge(genv, Source.new(Type::Instance.new(genv, mod, args)), vtx)
|
|
652
1013
|
end
|
|
653
1014
|
|
|
1015
|
+
def typecheck(genv, changes, vtx, subst)
|
|
1016
|
+
changes.add_depended_static_read(@static_ret.last)
|
|
1017
|
+
cpath = @static_ret.last.cpath
|
|
1018
|
+
return unless cpath
|
|
1019
|
+
f_mod = genv.resolve_cpath(cpath)
|
|
1020
|
+
# self/f_mod: formal, vtx: actual
|
|
1021
|
+
AST.typecheck_for_module(genv, changes, f_mod, @args, vtx, subst)
|
|
1022
|
+
end
|
|
1023
|
+
|
|
654
1024
|
def show
|
|
655
1025
|
s = "::#{ @cpath.join("::") }"
|
|
656
1026
|
if !@args.empty?
|
|
@@ -272,7 +272,11 @@ module TypeProf::Core
|
|
|
272
272
|
@vals << AST.create_node(raw_elem.value, lenv)
|
|
273
273
|
when :assoc_splat_node
|
|
274
274
|
@keys << nil
|
|
275
|
-
|
|
275
|
+
if raw_elem.value
|
|
276
|
+
@vals << AST.create_node(raw_elem.value, lenv)
|
|
277
|
+
else
|
|
278
|
+
@vals << DummyNilNode.new(code_range, lenv)
|
|
279
|
+
end
|
|
276
280
|
@splat = true
|
|
277
281
|
else
|
|
278
282
|
raise "unknown hash elem: #{ raw_elem.type }"
|
|
@@ -297,7 +301,11 @@ module TypeProf::Core
|
|
|
297
301
|
@changes.add_edge(genv, v, unified_val)
|
|
298
302
|
literal_pairs[key.lit] = v if key.is_a?(SymbolNode)
|
|
299
303
|
else
|
|
300
|
-
|
|
304
|
+
if val.is_a?(DummyNilNode)
|
|
305
|
+
h = @lenv.get_var(:"**anonymous_keyword")
|
|
306
|
+
else
|
|
307
|
+
h = val.install(genv)
|
|
308
|
+
end
|
|
301
309
|
# TODO: do we want to call to_hash on h?
|
|
302
310
|
@changes.add_hash_splat_box(genv, h, unified_key, unified_val)
|
|
303
311
|
end
|