typeprof 0.32.0 → 0.33.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/lib/typeprof/core/ast/base.rb +13 -0
- data/lib/typeprof/core/ast/call.rb +47 -30
- data/lib/typeprof/core/ast/const.rb +15 -7
- data/lib/typeprof/core/ast/control.rb +2 -2
- data/lib/typeprof/core/ast/meta.rb +96 -23
- data/lib/typeprof/core/ast/method.rb +18 -14
- data/lib/typeprof/core/ast/misc.rb +16 -7
- data/lib/typeprof/core/ast/module.rb +6 -2
- data/lib/typeprof/core/ast/pattern.rb +51 -23
- data/lib/typeprof/core/ast/sig_decl.rb +57 -4
- data/lib/typeprof/core/ast/sig_type.rb +36 -1
- data/lib/typeprof/core/ast/variable.rb +6 -0
- data/lib/typeprof/core/ast.rb +3 -0
- data/lib/typeprof/core/env/method.rb +192 -20
- data/lib/typeprof/core/env/module_entity.rb +61 -1
- data/lib/typeprof/core/env.rb +34 -6
- data/lib/typeprof/core/graph/box.rb +135 -17
- data/lib/typeprof/core/graph/change_set.rb +11 -6
- data/lib/typeprof/core/service.rb +24 -2
- data/lib/typeprof/version.rb +1 -1
- metadata +2 -2
|
@@ -256,9 +256,20 @@ module TypeProf::Core
|
|
|
256
256
|
vtx = @expr.install(genv)
|
|
257
257
|
|
|
258
258
|
a_args = ActualArguments.new([], [], nil, nil)
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
259
|
+
# Receiver types with no `to_a` are collected here, so that each union
|
|
260
|
+
# member can independently fall back to wrapping itself as `[x]`.
|
|
261
|
+
unresolved_recv = Vertex.new(self)
|
|
262
|
+
to_a_box = @changes.add_method_call_box(
|
|
263
|
+
genv,
|
|
264
|
+
vtx,
|
|
265
|
+
:to_a,
|
|
266
|
+
a_args,
|
|
267
|
+
false,
|
|
268
|
+
suppress_errors: true,
|
|
269
|
+
unresolved_recv: unresolved_recv,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
@changes.add_splat_box(genv, to_a_box.ret, nil, unresolved_recv).ret
|
|
262
273
|
end
|
|
263
274
|
end
|
|
264
275
|
|
|
@@ -332,8 +343,7 @@ module TypeProf::Core
|
|
|
332
343
|
def subnodes = { value:, pat: }
|
|
333
344
|
|
|
334
345
|
def install0(genv)
|
|
335
|
-
@value.install(genv)
|
|
336
|
-
@pat.install(genv)
|
|
346
|
+
@pat.install_pattern(genv, @value.install(genv))
|
|
337
347
|
Source.new(genv.nil_type)
|
|
338
348
|
end
|
|
339
349
|
end
|
|
@@ -350,8 +360,7 @@ module TypeProf::Core
|
|
|
350
360
|
def subnodes = { value:, pat: }
|
|
351
361
|
|
|
352
362
|
def install0(genv)
|
|
353
|
-
@value.install(genv)
|
|
354
|
-
@pat.install(genv)
|
|
363
|
+
@pat.install_pattern(genv, @value.install(genv))
|
|
355
364
|
Source.new(genv.true_type, genv.false_type)
|
|
356
365
|
end
|
|
357
366
|
end
|
|
@@ -18,11 +18,15 @@ module TypeProf::Core
|
|
|
18
18
|
@body = nil
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
@
|
|
21
|
+
@cname_code_range_loc = meta ? nil : raw_node.constant_path
|
|
22
22
|
@mod_cdef = nil
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
attr_reader :tbl, :cpath, :static_cpath, :
|
|
25
|
+
attr_reader :tbl, :cpath, :static_cpath, :body
|
|
26
|
+
|
|
27
|
+
def cname_code_range
|
|
28
|
+
@cname_code_range ||= @lenv.code_range_from_node(@cname_code_range_loc) if @cname_code_range_loc
|
|
29
|
+
end
|
|
26
30
|
|
|
27
31
|
def subnodes = { cpath:, body: }
|
|
28
32
|
def attrs = { static_cpath:, tbl: }
|
|
@@ -22,14 +22,19 @@ module TypeProf::Core
|
|
|
22
22
|
def attrs = { rest: }
|
|
23
23
|
def subnodes = { requireds:, rest_pattern:, posts: }
|
|
24
24
|
|
|
25
|
-
def
|
|
26
|
-
@requireds.
|
|
27
|
-
pat.
|
|
25
|
+
def install_pattern0(genv, subject)
|
|
26
|
+
@requireds.each_with_index do |pat, i|
|
|
27
|
+
pat.install_pattern(genv, @changes.add_splat_box(genv, subject, i).ret)
|
|
28
|
+
end
|
|
29
|
+
if @rest_pattern
|
|
30
|
+
elem = @changes.add_splat_box(genv, subject).ret
|
|
31
|
+
@rest_pattern.install_pattern(genv, Source.new(genv.gen_ary_type(elem)))
|
|
28
32
|
end
|
|
29
|
-
@rest_pattern.install(genv) if @rest_pattern
|
|
30
33
|
@posts.each do |pat|
|
|
31
|
-
|
|
34
|
+
# TODO: precise indices for post elements (those after `*rest`)
|
|
35
|
+
pat.install_pattern(genv, @changes.add_splat_box(genv, subject).ret)
|
|
32
36
|
end
|
|
37
|
+
subject
|
|
33
38
|
end
|
|
34
39
|
end
|
|
35
40
|
|
|
@@ -39,7 +44,14 @@ module TypeProf::Core
|
|
|
39
44
|
@keys = raw_node.elements.map {|raw_assoc| raw_assoc.key.value.to_sym }
|
|
40
45
|
@values = raw_node.elements.map {|raw_assoc| AST.create_pattern_node(raw_assoc.value, lenv) }
|
|
41
46
|
@rest = !!raw_node.rest
|
|
42
|
-
@rest_pattern =
|
|
47
|
+
@rest_pattern = case raw_node.rest
|
|
48
|
+
when Prism::AssocSplatNode
|
|
49
|
+
AST.create_pattern_node(raw_node.rest.value, lenv) if raw_node.rest.value
|
|
50
|
+
when Prism::NoKeywordsParameterNode, nil
|
|
51
|
+
nil
|
|
52
|
+
else
|
|
53
|
+
raise
|
|
54
|
+
end
|
|
43
55
|
end
|
|
44
56
|
|
|
45
57
|
attr_reader :keys, :values, :rest, :rest_pattern
|
|
@@ -47,32 +59,37 @@ module TypeProf::Core
|
|
|
47
59
|
def attrs = { keys:, rest: }
|
|
48
60
|
def subnodes = { values:, rest_pattern: }
|
|
49
61
|
|
|
50
|
-
def
|
|
62
|
+
def install_pattern0(genv, subject)
|
|
63
|
+
# TODO: extract each key's value type from `subject` (captures stay untyped for now)
|
|
51
64
|
@values.each do |pat|
|
|
52
|
-
pat.
|
|
65
|
+
pat.install_pattern(genv, Vertex.new(self))
|
|
53
66
|
end
|
|
54
|
-
@rest_pattern.
|
|
67
|
+
@rest_pattern.install_pattern(genv, Vertex.new(self)) if @rest_pattern
|
|
68
|
+
subject
|
|
55
69
|
end
|
|
56
70
|
end
|
|
57
71
|
|
|
58
72
|
class FindPatternNode < Node
|
|
59
73
|
def initialize(raw_node, lenv)
|
|
60
74
|
super(raw_node, lenv)
|
|
61
|
-
@left = raw_node.left ? AST.create_pattern_node(raw_node.left.expression, lenv) : nil
|
|
75
|
+
@left = raw_node.left.expression ? AST.create_pattern_node(raw_node.left.expression, lenv) : nil
|
|
62
76
|
@requireds = raw_node.requireds.map {|raw_elem| AST.create_pattern_node(raw_elem, lenv) }
|
|
63
|
-
@right = raw_node.right ? AST.create_pattern_node(raw_node.right.expression, lenv) : nil
|
|
77
|
+
@right = raw_node.right.expression ? AST.create_pattern_node(raw_node.right.expression, lenv) : nil
|
|
64
78
|
end
|
|
65
79
|
|
|
66
80
|
attr_reader :left, :requireds, :right
|
|
67
81
|
|
|
68
82
|
def subnodes = { left:, requireds:, right: }
|
|
69
83
|
|
|
70
|
-
def
|
|
71
|
-
@
|
|
84
|
+
def install_pattern0(genv, subject)
|
|
85
|
+
elem = @changes.add_splat_box(genv, subject).ret
|
|
86
|
+
rest_ary = Source.new(genv.gen_ary_type(elem))
|
|
87
|
+
@left.install_pattern(genv, rest_ary) if @left
|
|
72
88
|
@requireds.each do |pat|
|
|
73
|
-
pat.
|
|
89
|
+
pat.install_pattern(genv, elem)
|
|
74
90
|
end
|
|
75
|
-
@right.
|
|
91
|
+
@right.install_pattern(genv, rest_ary) if @right
|
|
92
|
+
subject
|
|
76
93
|
end
|
|
77
94
|
end
|
|
78
95
|
|
|
@@ -87,9 +104,10 @@ module TypeProf::Core
|
|
|
87
104
|
|
|
88
105
|
def subnodes = { left:, right: }
|
|
89
106
|
|
|
90
|
-
def
|
|
91
|
-
@left.
|
|
92
|
-
@right.
|
|
107
|
+
def install_pattern0(genv, subject)
|
|
108
|
+
@left.install_pattern(genv, subject)
|
|
109
|
+
@right.install_pattern(genv, subject)
|
|
110
|
+
subject
|
|
93
111
|
end
|
|
94
112
|
end
|
|
95
113
|
|
|
@@ -104,9 +122,18 @@ module TypeProf::Core
|
|
|
104
122
|
|
|
105
123
|
def subnodes = { value:, target: }
|
|
106
124
|
|
|
107
|
-
def
|
|
108
|
-
@value.
|
|
109
|
-
|
|
125
|
+
def install_pattern0(genv, subject)
|
|
126
|
+
@value.install_pattern(genv, subject)
|
|
127
|
+
# For `Const => var`, narrow the capture by the class, as `when Const` does
|
|
128
|
+
narrowed =
|
|
129
|
+
if @value.is_a?(ConstantReadNode) && @value.static_ret
|
|
130
|
+
filtered = subject.new_vertex(genv, self)
|
|
131
|
+
IsAFilter.new(genv, self, filtered, false, @value.static_ret).next_vtx
|
|
132
|
+
else
|
|
133
|
+
subject
|
|
134
|
+
end
|
|
135
|
+
@target.install_pattern(genv, narrowed)
|
|
136
|
+
subject
|
|
110
137
|
end
|
|
111
138
|
end
|
|
112
139
|
|
|
@@ -124,9 +151,10 @@ module TypeProf::Core
|
|
|
124
151
|
|
|
125
152
|
def subnodes = { cond:, body: }
|
|
126
153
|
|
|
127
|
-
def
|
|
154
|
+
def install_pattern0(genv, subject)
|
|
128
155
|
@cond.install(genv)
|
|
129
|
-
@body.
|
|
156
|
+
@body.install_pattern(genv, subject)
|
|
157
|
+
subject
|
|
130
158
|
end
|
|
131
159
|
end
|
|
132
160
|
|
|
@@ -190,7 +190,7 @@ module TypeProf::Core
|
|
|
190
190
|
def initialize(raw_decl, lenv)
|
|
191
191
|
super(raw_decl, lenv)
|
|
192
192
|
@mid = raw_decl.name
|
|
193
|
-
@
|
|
193
|
+
@mid_code_range_loc = raw_decl.location[:name]
|
|
194
194
|
@singleton = raw_decl.singleton?
|
|
195
195
|
@instance = raw_decl.instance?
|
|
196
196
|
@method_types = OverloadSet.new(raw_decl.overloads.map do |overload|
|
|
@@ -200,12 +200,16 @@ module TypeProf::Core
|
|
|
200
200
|
@overloading = raw_decl.overloading
|
|
201
201
|
end
|
|
202
202
|
|
|
203
|
-
attr_reader :mid, :singleton, :instance, :method_types, :overloading
|
|
203
|
+
attr_reader :mid, :singleton, :instance, :method_types, :overloading
|
|
204
|
+
|
|
205
|
+
def mid_code_range
|
|
206
|
+
@mid_code_range ||= @lenv.code_range_from_node(@mid_code_range_loc) if @mid_code_range_loc
|
|
207
|
+
end
|
|
204
208
|
|
|
205
209
|
def subnodes = { method_types: @method_types.to_a }
|
|
206
|
-
def attrs = { mid:,
|
|
210
|
+
def attrs = { mid:, singleton:, instance:, overloading: }
|
|
207
211
|
|
|
208
|
-
def mname_code_range(_name) =
|
|
212
|
+
def mname_code_range(_name) = mid_code_range
|
|
209
213
|
|
|
210
214
|
def install0(genv)
|
|
211
215
|
[[@singleton, true], [@instance, false]].each do |enabled, singleton|
|
|
@@ -314,6 +318,55 @@ module TypeProf::Core
|
|
|
314
318
|
end
|
|
315
319
|
end
|
|
316
320
|
|
|
321
|
+
class SigExtendNode < Node
|
|
322
|
+
def initialize(raw_decl, lenv)
|
|
323
|
+
super(raw_decl, lenv)
|
|
324
|
+
name = raw_decl.name
|
|
325
|
+
@cpath = name.namespace.path + [name.name]
|
|
326
|
+
@toplevel = name.namespace.absolute?
|
|
327
|
+
@args = raw_decl.args.map {|arg| AST.create_rbs_type(arg, lenv) }
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
attr_reader :cpath, :toplevel, :args
|
|
331
|
+
def subnodes = { args: }
|
|
332
|
+
def attrs = { cpath:, toplevel: }
|
|
333
|
+
|
|
334
|
+
def define0(genv)
|
|
335
|
+
@args.each {|arg| arg.define(genv) }
|
|
336
|
+
const_reads = []
|
|
337
|
+
const_read = BaseConstRead.new(genv, @cpath.first, @toplevel ? CRef::Toplevel : @lenv.cref, true)
|
|
338
|
+
const_reads << const_read
|
|
339
|
+
@cpath[1..].each do |cname|
|
|
340
|
+
const_read = ScopedConstRead.new(cname, const_read, true)
|
|
341
|
+
const_reads << const_read
|
|
342
|
+
end
|
|
343
|
+
mod = genv.resolve_cpath(@lenv.cref.cpath)
|
|
344
|
+
const_read.followers << mod
|
|
345
|
+
mod.add_extend_decl(genv, self)
|
|
346
|
+
const_reads
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def define_copy(genv)
|
|
350
|
+
mod = genv.resolve_cpath(@lenv.cref.cpath)
|
|
351
|
+
mod.add_extend_decl(genv, self)
|
|
352
|
+
mod.remove_extend_decl(genv, @prev_node)
|
|
353
|
+
super(genv)
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def undefine0(genv)
|
|
357
|
+
mod = genv.resolve_cpath(@lenv.cref.cpath)
|
|
358
|
+
mod.remove_extend_decl(genv, self)
|
|
359
|
+
@static_ret.each do |const_read|
|
|
360
|
+
const_read.destroy(genv)
|
|
361
|
+
end
|
|
362
|
+
@args.each {|arg| arg.undefine(genv) }
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
def install0(genv)
|
|
366
|
+
Source.new
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
|
|
317
370
|
class SigAliasNode < Node
|
|
318
371
|
def initialize(raw_decl, lenv)
|
|
319
372
|
super(raw_decl, lenv)
|
|
@@ -23,6 +23,9 @@ module TypeProf::Core
|
|
|
23
23
|
if f_mod.module?
|
|
24
24
|
return true if typecheck_for_prepended_modules(genv, changes, ty, f_mod, f_args, subst)
|
|
25
25
|
return true if typecheck_for_included_modules(genv, changes, ty, f_mod, f_args, subst)
|
|
26
|
+
if ty.is_a?(Type::Singleton)
|
|
27
|
+
return true if typecheck_for_extended_modules(genv, changes, ty, f_mod, f_args, subst)
|
|
28
|
+
end
|
|
26
29
|
end
|
|
27
30
|
|
|
28
31
|
ty = genv.get_superclass_type(ty, changes, {})
|
|
@@ -81,6 +84,32 @@ module TypeProf::Core
|
|
|
81
84
|
return false
|
|
82
85
|
end
|
|
83
86
|
|
|
87
|
+
def self.typecheck_for_extended_modules(genv, changes, a_ty, f_mod, f_args, subst)
|
|
88
|
+
a_ty.mod.extended_modules.each do |ext_decl, ext_mod|
|
|
89
|
+
if ext_decl.is_a?(AST::SigExtendNode) && ext_mod.type_params
|
|
90
|
+
ext_ty = genv.get_instance_type(ext_mod, ext_decl.args, changes, {}, a_ty)
|
|
91
|
+
else
|
|
92
|
+
type_params = ext_mod.type_params.map {|(_name, _default_ty)| Source.new() } # TODO: better support
|
|
93
|
+
ext_ty = Type::Instance.new(genv, ext_mod, type_params)
|
|
94
|
+
end
|
|
95
|
+
if ext_ty.mod == f_mod
|
|
96
|
+
args_all_match = true
|
|
97
|
+
f_args.zip(ext_ty.args) do |f_arg_node, a_arg_vtx|
|
|
98
|
+
unless f_arg_node.typecheck(genv, changes, a_arg_vtx, subst)
|
|
99
|
+
args_all_match = false
|
|
100
|
+
break
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
return true if args_all_match
|
|
104
|
+
end
|
|
105
|
+
changes.add_depended_superclass(ext_ty.mod)
|
|
106
|
+
|
|
107
|
+
# The extended module may itself include other modules
|
|
108
|
+
return true if typecheck_for_included_modules(genv, changes, ext_ty, f_mod, f_args, subst)
|
|
109
|
+
end
|
|
110
|
+
return false
|
|
111
|
+
end
|
|
112
|
+
|
|
84
113
|
class SigFuncType < Node
|
|
85
114
|
def initialize(raw_decl, raw_type_params, raw_block, lenv)
|
|
86
115
|
super(raw_decl, lenv)
|
|
@@ -465,7 +494,13 @@ module TypeProf::Core
|
|
|
465
494
|
decl = tae.decls.each {|decl| break decl }
|
|
466
495
|
subst0 = subst.dup
|
|
467
496
|
decl.params.zip(@args) do |param, arg|
|
|
468
|
-
|
|
497
|
+
if arg.is_a?(SigTyVarNode) && subst[arg.var]
|
|
498
|
+
# Share the vertex so that the types inferred in the alias body flow
|
|
499
|
+
# back into the variable, which makes `U` of `(array[U])` inferrable
|
|
500
|
+
subst0[param] = subst[arg.var]
|
|
501
|
+
else
|
|
502
|
+
subst0[param] = arg.covariant_vertex(genv, changes, subst0)
|
|
503
|
+
end
|
|
469
504
|
end
|
|
470
505
|
tae.type.typecheck(genv, changes, vtx, subst0)
|
|
471
506
|
end
|
|
@@ -63,6 +63,12 @@ module TypeProf::Core
|
|
|
63
63
|
val
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
+
def install_pattern0(genv, subject)
|
|
67
|
+
install0(genv)
|
|
68
|
+
@changes.add_edge(genv, subject, @rhs.ret)
|
|
69
|
+
subject
|
|
70
|
+
end
|
|
71
|
+
|
|
66
72
|
def retrieve_at(pos, &blk)
|
|
67
73
|
yield self if @var_code_range && @var_code_range.include?(pos)
|
|
68
74
|
super(pos, &blk)
|
data/lib/typeprof/core/ast.rb
CHANGED
|
@@ -283,6 +283,8 @@ module TypeProf::Core
|
|
|
283
283
|
case raw_node.name
|
|
284
284
|
when :include
|
|
285
285
|
return IncludeMetaNode.new(raw_node, lenv)
|
|
286
|
+
when :extend
|
|
287
|
+
return ExtendMetaNode.new(raw_node, lenv)
|
|
286
288
|
when :attr_reader
|
|
287
289
|
return AttrReaderMetaNode.new(raw_node, lenv)
|
|
288
290
|
when :attr_writer
|
|
@@ -460,6 +462,7 @@ module TypeProf::Core
|
|
|
460
462
|
when RBS::AST::Members::Prepend
|
|
461
463
|
SigPrependNode.new(raw_decl, lenv)
|
|
462
464
|
when RBS::AST::Members::Extend
|
|
465
|
+
SigExtendNode.new(raw_decl, lenv)
|
|
463
466
|
when RBS::AST::Members::Public
|
|
464
467
|
when RBS::AST::Members::Private
|
|
465
468
|
when RBS::AST::Members::Alias
|
|
@@ -48,10 +48,33 @@ module TypeProf::Core
|
|
|
48
48
|
@positionals + [@keywords],
|
|
49
49
|
@splat_flags + [false],
|
|
50
50
|
nil,
|
|
51
|
-
@block
|
|
51
|
+
@block,
|
|
52
52
|
)
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
+
def prepend_positionals(positionals, splat_flags)
|
|
56
|
+
return self if positionals.empty?
|
|
57
|
+
|
|
58
|
+
ActualArguments.new(positionals + @positionals, splat_flags + @splat_flags, @keywords, @block)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def with_keywords(keywords)
|
|
62
|
+
ActualArguments.new(@positionals, @splat_flags, keywords, @block)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def with_block(block, omittable: false)
|
|
66
|
+
ActualArguments.new(@positionals, @splat_flags, @keywords, block)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def add_box_edges(genv, box)
|
|
70
|
+
@keywords.add_edge(genv, box) if @keywords
|
|
71
|
+
@block.add_edge(genv, box) if @block
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def normalize_for_method_call(_genv)
|
|
75
|
+
self
|
|
76
|
+
end
|
|
77
|
+
|
|
55
78
|
def get_rest_args(genv, changes, start_rest, end_rest)
|
|
56
79
|
vtxs = []
|
|
57
80
|
|
|
@@ -95,45 +118,175 @@ module TypeProf::Core
|
|
|
95
118
|
end
|
|
96
119
|
end
|
|
97
120
|
|
|
121
|
+
class ForwardingActualArguments < ActualArguments
|
|
122
|
+
def initialize(positionals, splat_flags, keywords, block, positionals_omittable, keywords_omittable, block_omittable, activation, activation_required)
|
|
123
|
+
super(positionals, splat_flags, keywords, block)
|
|
124
|
+
@positionals_omittable = positionals_omittable
|
|
125
|
+
@keywords_omittable = keywords_omittable
|
|
126
|
+
@block_omittable = block_omittable
|
|
127
|
+
@activation = activation
|
|
128
|
+
@activation_required = activation_required
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
attr_reader :positionals_omittable, :keywords_omittable, :block_omittable
|
|
132
|
+
|
|
133
|
+
def new_vertexes(genv, node)
|
|
134
|
+
positionals = @positionals.map {|arg| arg.new_vertex(genv, node) }
|
|
135
|
+
splat_flags = @splat_flags
|
|
136
|
+
keywords = @keywords ? @keywords.new_vertex(genv, node) : nil
|
|
137
|
+
block = @block ? @block.new_vertex(genv, node) : nil
|
|
138
|
+
activation = @activation.new_vertex(genv, node)
|
|
139
|
+
ForwardingActualArguments.new(positionals, splat_flags, keywords, block, @positionals_omittable, @keywords_omittable, @block_omittable, activation, @activation_required)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def with_keywords_as_last_positional_hash
|
|
143
|
+
return self unless @keywords
|
|
144
|
+
|
|
145
|
+
ForwardingActualArguments.new(
|
|
146
|
+
@positionals + [@keywords],
|
|
147
|
+
@splat_flags + [false],
|
|
148
|
+
nil,
|
|
149
|
+
@block,
|
|
150
|
+
@positionals_omittable + [false],
|
|
151
|
+
false,
|
|
152
|
+
@block_omittable,
|
|
153
|
+
@activation,
|
|
154
|
+
@activation_required,
|
|
155
|
+
)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def prepend_positionals(positionals, splat_flags)
|
|
159
|
+
return self if positionals.empty?
|
|
160
|
+
|
|
161
|
+
ForwardingActualArguments.new(
|
|
162
|
+
positionals + @positionals,
|
|
163
|
+
splat_flags + @splat_flags,
|
|
164
|
+
@keywords,
|
|
165
|
+
@block,
|
|
166
|
+
::Array.new(positionals.size, false) + @positionals_omittable,
|
|
167
|
+
@keywords_omittable,
|
|
168
|
+
@block_omittable,
|
|
169
|
+
@activation,
|
|
170
|
+
@activation_required,
|
|
171
|
+
)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def with_keywords(keywords, keywords_omittable: false)
|
|
175
|
+
ForwardingActualArguments.new(
|
|
176
|
+
@positionals,
|
|
177
|
+
@splat_flags,
|
|
178
|
+
keywords,
|
|
179
|
+
@block,
|
|
180
|
+
@positionals_omittable,
|
|
181
|
+
keywords_omittable,
|
|
182
|
+
@block_omittable,
|
|
183
|
+
@activation,
|
|
184
|
+
@activation_required,
|
|
185
|
+
)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def with_block(block, omittable: false)
|
|
189
|
+
ForwardingActualArguments.new(
|
|
190
|
+
@positionals,
|
|
191
|
+
@splat_flags,
|
|
192
|
+
@keywords,
|
|
193
|
+
block,
|
|
194
|
+
@positionals_omittable,
|
|
195
|
+
@keywords_omittable,
|
|
196
|
+
omittable,
|
|
197
|
+
@activation,
|
|
198
|
+
@activation_required,
|
|
199
|
+
)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def add_box_edges(genv, box)
|
|
203
|
+
@activation.add_edge(genv, box)
|
|
204
|
+
super
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def normalize_for_method_call(genv)
|
|
208
|
+
if @activation.types.empty?
|
|
209
|
+
return nil if @activation_required
|
|
210
|
+
return self
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
positionals = []
|
|
214
|
+
splat_flags = []
|
|
215
|
+
|
|
216
|
+
@positionals.each_with_index do |arg, i|
|
|
217
|
+
unless @positionals_omittable[i] && @splat_flags[i] && empty_omittable_splat_argument?(genv, arg)
|
|
218
|
+
positionals << arg
|
|
219
|
+
splat_flags << @splat_flags[i]
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
keywords = @keywords
|
|
224
|
+
keywords = nil if @keywords_omittable && keywords && keywords.types.empty?
|
|
225
|
+
|
|
226
|
+
block = @block
|
|
227
|
+
block = nil if @block_omittable && block && block.types.empty?
|
|
228
|
+
|
|
229
|
+
ActualArguments.new(positionals, splat_flags, keywords, block)
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
private
|
|
233
|
+
|
|
234
|
+
def empty_omittable_splat_argument?(genv, arg)
|
|
235
|
+
empty = true
|
|
236
|
+
arg.each_type do |ty|
|
|
237
|
+
ty = ty.base_type(genv)
|
|
238
|
+
unless ty.is_a?(Type::Instance) && ty.mod == genv.mod_ary && ty.args[0] && ty.args[0].types.empty?
|
|
239
|
+
empty = false
|
|
240
|
+
break
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
empty
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
98
247
|
class ForwardingArguments
|
|
99
|
-
def initialize(req_positionals, opt_positionals,
|
|
248
|
+
def initialize(req_positionals, opt_positionals, rest_positionals, post_positionals, req_keyword_pairs, opt_keyword_pairs, rest_keywords, block, activation)
|
|
100
249
|
@req_positionals = req_positionals
|
|
101
250
|
@opt_positionals = opt_positionals
|
|
102
|
-
@opt_positional_elems = opt_positional_elems
|
|
103
251
|
@rest_positionals = rest_positionals
|
|
104
252
|
@post_positionals = post_positionals
|
|
105
253
|
@req_keyword_pairs = req_keyword_pairs
|
|
106
254
|
@opt_keyword_pairs = opt_keyword_pairs
|
|
107
255
|
@rest_keywords = rest_keywords
|
|
108
256
|
@block = block
|
|
257
|
+
@activation = activation
|
|
109
258
|
end
|
|
110
259
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
def to_actual_arguments(genv, changes, node)
|
|
114
|
-
positionals = @req_positionals.dup
|
|
260
|
+
def to_actual_arguments(genv, changes, node, include_leading_positionals: true, activation_required: false)
|
|
261
|
+
positionals = include_leading_positionals ? @req_positionals.dup : []
|
|
115
262
|
splat_flags = ::Array.new(positionals.size, false)
|
|
263
|
+
positionals_omittable = ::Array.new(positionals.size, false)
|
|
116
264
|
|
|
117
|
-
@opt_positionals.each do |
|
|
118
|
-
positionals <<
|
|
265
|
+
@opt_positionals.each do |elem_vtx|
|
|
266
|
+
positionals << Source.new(genv.gen_ary_type(elem_vtx))
|
|
119
267
|
splat_flags << true
|
|
268
|
+
positionals_omittable << true
|
|
120
269
|
end
|
|
121
270
|
|
|
122
271
|
if @rest_positionals
|
|
123
|
-
positionals << @rest_positionals
|
|
272
|
+
positionals << Source.new(genv.gen_ary_type(@rest_positionals))
|
|
124
273
|
splat_flags << true
|
|
274
|
+
positionals_omittable << true
|
|
125
275
|
end
|
|
126
276
|
|
|
127
277
|
@post_positionals.each do |arg|
|
|
128
278
|
positionals << arg
|
|
129
279
|
splat_flags << false
|
|
280
|
+
positionals_omittable << false
|
|
130
281
|
end
|
|
131
282
|
|
|
132
|
-
keywords = build_keyword_args(genv, changes, node)
|
|
133
|
-
|
|
283
|
+
keywords, keywords_omittable = build_keyword_args(genv, changes, node)
|
|
284
|
+
ForwardingActualArguments.new(positionals, splat_flags, keywords, @block, positionals_omittable, keywords_omittable, true, @activation, activation_required)
|
|
134
285
|
end
|
|
135
286
|
|
|
136
287
|
def accept_actual_arguments(genv, changes, a_args)
|
|
288
|
+
changes.add_edge(genv, Source.new(genv.true_type), @activation)
|
|
289
|
+
|
|
137
290
|
if a_args.splat_flags.any?
|
|
138
291
|
start_rest = [a_args.splat_flags.index(true), @req_positionals.size + @opt_positionals.size].min
|
|
139
292
|
end_rest = [a_args.splat_flags.rindex(true) + 1, a_args.positionals.size - @post_positionals.size].max
|
|
@@ -149,7 +302,7 @@ module TypeProf::Core
|
|
|
149
302
|
end
|
|
150
303
|
end
|
|
151
304
|
|
|
152
|
-
@
|
|
305
|
+
@opt_positionals.each_with_index do |elem_vtx, i|
|
|
153
306
|
i += @req_positionals.size
|
|
154
307
|
if i < start_rest
|
|
155
308
|
changes.add_edge(genv, a_args.positionals[i], elem_vtx)
|
|
@@ -171,6 +324,12 @@ module TypeProf::Core
|
|
|
171
324
|
end
|
|
172
325
|
end
|
|
173
326
|
|
|
327
|
+
if @rest_positionals
|
|
328
|
+
rest_vtxs.each do |vtx|
|
|
329
|
+
changes.add_edge(genv, vtx, @rest_positionals)
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
|
|
174
333
|
else
|
|
175
334
|
@req_positionals.each_with_index do |f_vtx, i|
|
|
176
335
|
changes.add_edge(genv, a_args.positionals[i], f_vtx)
|
|
@@ -184,11 +343,17 @@ module TypeProf::Core
|
|
|
184
343
|
start_rest = @req_positionals.size
|
|
185
344
|
end_rest = a_args.positionals.size - @post_positionals.size
|
|
186
345
|
i = 0
|
|
187
|
-
while i < @
|
|
188
|
-
changes.add_edge(genv, a_args.positionals[start_rest], @
|
|
346
|
+
while i < @opt_positionals.size && start_rest < end_rest
|
|
347
|
+
changes.add_edge(genv, a_args.positionals[start_rest], @opt_positionals[i])
|
|
189
348
|
i += 1
|
|
190
349
|
start_rest += 1
|
|
191
350
|
end
|
|
351
|
+
|
|
352
|
+
if @rest_positionals
|
|
353
|
+
start_rest.upto(end_rest - 1) do |i|
|
|
354
|
+
changes.add_edge(genv, a_args.positionals[i], @rest_positionals)
|
|
355
|
+
end
|
|
356
|
+
end
|
|
192
357
|
end
|
|
193
358
|
|
|
194
359
|
changes.add_edge(genv, a_args.block, @block) if @block && a_args.block
|
|
@@ -222,8 +387,11 @@ module TypeProf::Core
|
|
|
222
387
|
private
|
|
223
388
|
|
|
224
389
|
def build_keyword_args(genv, changes, node)
|
|
225
|
-
|
|
226
|
-
|
|
390
|
+
opt_keyword_pairs = @opt_keyword_pairs
|
|
391
|
+
|
|
392
|
+
if @req_keyword_pairs.empty? && opt_keyword_pairs.empty?
|
|
393
|
+
return @rest_keywords, !!@rest_keywords
|
|
394
|
+
end
|
|
227
395
|
|
|
228
396
|
unified_key = Vertex.new(node)
|
|
229
397
|
unified_val = Vertex.new(node)
|
|
@@ -235,18 +403,22 @@ module TypeProf::Core
|
|
|
235
403
|
literal_pairs[name] = vtx
|
|
236
404
|
end
|
|
237
405
|
|
|
238
|
-
|
|
406
|
+
opt_keyword_pairs.each do |name, vtx|
|
|
239
407
|
changes.add_edge(genv, Source.new(Type::Symbol.new(genv, name)), unified_key)
|
|
240
408
|
changes.add_edge(genv, vtx, unified_val)
|
|
409
|
+
literal_pairs[name] = vtx
|
|
241
410
|
end
|
|
242
411
|
|
|
243
412
|
base_hash_type = genv.gen_hash_type(unified_key, unified_val)
|
|
244
413
|
changes.add_hash_splat_box(genv, @rest_keywords, unified_key, unified_val) if @rest_keywords
|
|
245
414
|
|
|
246
415
|
if literal_pairs.empty?
|
|
247
|
-
Source.new(base_hash_type)
|
|
416
|
+
[Source.new(base_hash_type), false]
|
|
417
|
+
elsif @rest_keywords
|
|
418
|
+
fallback = Source.new(Type::Record.new(genv, literal_pairs, base_hash_type))
|
|
419
|
+
[changes.add_keyword_merge_box(genv, @rest_keywords, literal_pairs, fallback).ret, false]
|
|
248
420
|
else
|
|
249
|
-
Source.new(Type::Record.new(genv, literal_pairs, base_hash_type))
|
|
421
|
+
[Source.new(Type::Record.new(genv, literal_pairs, base_hash_type)), false]
|
|
250
422
|
end
|
|
251
423
|
end
|
|
252
424
|
end
|