typeprof 0.30.0 → 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/doc/doc.ja.md +1 -1
- data/lib/typeprof/cli/cli.rb +28 -10
- data/lib/typeprof/cli.rb +1 -0
- data/lib/typeprof/code_range.rb +9 -7
- data/lib/typeprof/core/ast/base.rb +27 -10
- data/lib/typeprof/core/ast/call.rb +90 -21
- data/lib/typeprof/core/ast/const.rb +7 -12
- data/lib/typeprof/core/ast/control.rb +349 -74
- data/lib/typeprof/core/ast/meta.rb +5 -5
- data/lib/typeprof/core/ast/method.rb +19 -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 +11 -3
- 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 +43 -12
- data/lib/typeprof/core/graph/box.rb +218 -101
- data/lib/typeprof/core/graph/change_set.rb +44 -37
- data/lib/typeprof/core/graph/vertex.rb +7 -21
- data/lib/typeprof/core/service.rb +61 -40
- data/lib/typeprof/core/type.rb +52 -123
- data/lib/typeprof/core.rb +1 -1
- data/lib/typeprof/diagnostic.rb +5 -6
- data/lib/typeprof/lsp/messages.rb +27 -36
- data/lib/typeprof/lsp/server.rb +144 -25
- data/lib/typeprof/lsp/text.rb +1 -0
- data/lib/typeprof/lsp/util.rb +0 -10
- data/lib/typeprof/version.rb +1 -1
- data/typeprof.conf.jsonc +22 -0
- data/typeprof.gemspec +1 -0
- metadata +19 -5
- data/lib/typeprof/core/graph.rb +0 -3
|
@@ -13,6 +13,42 @@ module TypeProf::Core
|
|
|
13
13
|
return nil
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
# Apply multiple narrowings from the new narrowing system
|
|
17
|
+
def self.with_narrowing(genv, node, lenv, narrowing)
|
|
18
|
+
return yield if narrowing.map.empty?
|
|
19
|
+
|
|
20
|
+
# Store original vertices (only for local variables)
|
|
21
|
+
original_vtxs = {}
|
|
22
|
+
narrowing.map.each do |var, narrowing|
|
|
23
|
+
original_vtxs[var] = var.start_with?("@") ? nil : lenv.get_var(var)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Apply all narrowings
|
|
27
|
+
narrowing.map.each do |var, narrowing|
|
|
28
|
+
if var.start_with?("@")
|
|
29
|
+
lenv.push_ivar_narrowing(var, narrowing)
|
|
30
|
+
else
|
|
31
|
+
original_vtx = original_vtxs[var]
|
|
32
|
+
narrowed_vtx = original_vtx.new_vertex(genv, node)
|
|
33
|
+
narrowed_vtx = narrowing.narrow(genv, node, narrowed_vtx)
|
|
34
|
+
lenv.set_var(var, narrowed_vtx)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
result = yield
|
|
39
|
+
|
|
40
|
+
# Restore original vertices and remove instance variable filters
|
|
41
|
+
original_vtxs.each do |var, original_vtx|
|
|
42
|
+
if var.start_with?("@")
|
|
43
|
+
lenv.pop_ivar_narrowing(var)
|
|
44
|
+
else
|
|
45
|
+
lenv.set_var(var, original_vtx)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
result
|
|
50
|
+
end
|
|
51
|
+
|
|
16
52
|
class BranchNode < Node
|
|
17
53
|
def initialize(raw_node, lenv)
|
|
18
54
|
super(raw_node, lenv)
|
|
@@ -37,11 +73,11 @@ module TypeProf::Core
|
|
|
37
73
|
@cond.install(genv)
|
|
38
74
|
|
|
39
75
|
vars = []
|
|
40
|
-
vars << @cond.var if @cond.is_a?(LocalVariableReadNode)
|
|
41
|
-
var, filter_class = AST.is_a_class(@cond)
|
|
42
|
-
vars << var if var
|
|
43
76
|
@then.modified_vars(@lenv.locals.keys, vars) if @then
|
|
44
77
|
@else.modified_vars(@lenv.locals.keys, vars) if @else
|
|
78
|
+
then_narrowing, else_narrowing = @cond.narrowings
|
|
79
|
+
vars.concat(then_narrowing.map.keys.reject {|var| var.start_with?("@") })
|
|
80
|
+
vars.concat(else_narrowing.map.keys.reject {|var| var.start_with?("@") })
|
|
45
81
|
modified_vtxs = {}
|
|
46
82
|
vars.uniq.each do |var|
|
|
47
83
|
vtx = @lenv.get_var(var)
|
|
@@ -49,48 +85,30 @@ module TypeProf::Core
|
|
|
49
85
|
nvtx_else = vtx.new_vertex(genv, self)
|
|
50
86
|
modified_vtxs[var] = [nvtx_then, nvtx_else]
|
|
51
87
|
end
|
|
52
|
-
if @cond.is_a?(LocalVariableReadNode)
|
|
53
|
-
nvtx_then, nvtx_else = modified_vtxs[@cond.var]
|
|
54
|
-
nvtx_then = NilFilter.new(genv, self, nvtx_then, !self.is_a?(IfNode)).next_vtx
|
|
55
|
-
nvtx_else = NilFilter.new(genv, self, nvtx_else, self.is_a?(IfNode)).next_vtx
|
|
56
|
-
modified_vtxs[@cond.var] = [nvtx_then, nvtx_else]
|
|
57
|
-
end
|
|
58
|
-
if filter_class
|
|
59
|
-
nvtx_then, nvtx_else = modified_vtxs[var]
|
|
60
|
-
nvtx_then = IsAFilter.new(genv, self, nvtx_then, !self.is_a?(IfNode), filter_class).next_vtx
|
|
61
|
-
nvtx_else = IsAFilter.new(genv, self, nvtx_else, self.is_a?(IfNode), filter_class).next_vtx
|
|
62
|
-
modified_vtxs[var] = [nvtx_then, nvtx_else]
|
|
63
|
-
end
|
|
64
88
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
end
|
|
72
|
-
then_val = @then.install(genv)
|
|
73
|
-
if @cond.is_a?(InstanceVariableReadNode)
|
|
74
|
-
@lenv.pop_read_filter(@cond.var)
|
|
75
|
-
end
|
|
89
|
+
narrowing = self.is_a?(IfNode) ? then_narrowing : else_narrowing
|
|
90
|
+
modified_vtxs.each do |var, (nvtx_then, _)|
|
|
91
|
+
@lenv.set_var(var, nvtx_then)
|
|
92
|
+
end
|
|
93
|
+
then_val = AST.with_narrowing(genv, self, @lenv, narrowing) do
|
|
94
|
+
val = @then ? @then.install(genv) : Source.new(genv.nil_type)
|
|
76
95
|
modified_vtxs.each do |var, ary|
|
|
77
96
|
ary[0] = @lenv.get_var(var)
|
|
78
97
|
end
|
|
79
|
-
|
|
80
|
-
then_val = Source.new(genv.nil_type)
|
|
98
|
+
val
|
|
81
99
|
end
|
|
82
100
|
@changes.add_edge(genv, then_val, ret)
|
|
83
101
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
102
|
+
narrowing = self.is_a?(IfNode) ? else_narrowing : then_narrowing
|
|
103
|
+
modified_vtxs.each do |var, (_, nvtx_else)|
|
|
104
|
+
@lenv.set_var(var, nvtx_else)
|
|
105
|
+
end
|
|
106
|
+
else_val = AST.with_narrowing(genv, self, @lenv, narrowing) do
|
|
107
|
+
val = @else ? @else.install(genv) : Source.new(genv.nil_type)
|
|
89
108
|
modified_vtxs.each do |var, ary|
|
|
90
109
|
ary[1] = @lenv.get_var(var)
|
|
91
110
|
end
|
|
92
|
-
|
|
93
|
-
else_val = Source.new(genv.nil_type)
|
|
111
|
+
val
|
|
94
112
|
end
|
|
95
113
|
@changes.add_edge(genv, else_val, ret)
|
|
96
114
|
|
|
@@ -176,7 +194,7 @@ module TypeProf::Core
|
|
|
176
194
|
class BreakNode < Node
|
|
177
195
|
def initialize(raw_node, lenv)
|
|
178
196
|
super(raw_node, lenv)
|
|
179
|
-
@arg =
|
|
197
|
+
@arg = AST.parse_return_arguments(raw_node, lenv, code_range)
|
|
180
198
|
end
|
|
181
199
|
|
|
182
200
|
attr_reader :arg
|
|
@@ -184,8 +202,9 @@ module TypeProf::Core
|
|
|
184
202
|
def subnodes = { arg: }
|
|
185
203
|
|
|
186
204
|
def install0(genv)
|
|
187
|
-
|
|
188
|
-
|
|
205
|
+
arg = @arg.install(genv)
|
|
206
|
+
@changes.add_edge(genv, arg, @lenv.get_break_vtx)
|
|
207
|
+
Source.new()
|
|
189
208
|
end
|
|
190
209
|
end
|
|
191
210
|
|
|
@@ -215,7 +234,7 @@ module TypeProf::Core
|
|
|
215
234
|
def install0(genv)
|
|
216
235
|
@arg.install(genv)
|
|
217
236
|
if @lenv.exist_var?(:"*expected_block_ret")
|
|
218
|
-
@lenv.add_next_box(@changes.add_escape_box(genv, @arg.ret
|
|
237
|
+
@lenv.add_next_box(@changes.add_escape_box(genv, @arg.ret))
|
|
219
238
|
end
|
|
220
239
|
Source.new(Type::Bot.new(genv))
|
|
221
240
|
end
|
|
@@ -232,31 +251,115 @@ module TypeProf::Core
|
|
|
232
251
|
end
|
|
233
252
|
end
|
|
234
253
|
|
|
254
|
+
class WhenNode < Node
|
|
255
|
+
def initialize(raw_when_node, lenv, pivot_var = nil)
|
|
256
|
+
super(raw_when_node, lenv)
|
|
257
|
+
@conditions = raw_when_node.conditions.map {|cond| AST.create_node(cond, lenv) }
|
|
258
|
+
@body = raw_when_node.statements ? AST.create_node(raw_when_node.statements, lenv) : DummyNilNode.new(code_range, lenv)
|
|
259
|
+
@pivot_var = pivot_var
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
attr_reader :conditions, :body, :pivot_var
|
|
263
|
+
|
|
264
|
+
def subnodes = { conditions:, body: }
|
|
265
|
+
|
|
266
|
+
def install0(genv)
|
|
267
|
+
@conditions.each {|condition| condition.install(genv) }
|
|
268
|
+
|
|
269
|
+
# 型絞り込みが必要な場合(pivot_varが設定されている場合)
|
|
270
|
+
if @pivot_var && @lenv.locals.key?(:"*pivot")
|
|
271
|
+
original_vtx = @lenv.locals[:"*pivot"]
|
|
272
|
+
|
|
273
|
+
# 複数条件のOR(union)処理
|
|
274
|
+
filtered_vtxs = []
|
|
275
|
+
|
|
276
|
+
@conditions.each do |condition|
|
|
277
|
+
if condition.is_a?(ConstantReadNode) && condition.static_ret
|
|
278
|
+
# 各条件に対して独立して型絞り込みを適用
|
|
279
|
+
condition_vtx = original_vtx.new_vertex(genv, self)
|
|
280
|
+
condition_vtx = IsAFilter.new(genv, self, condition_vtx, false, condition.static_ret).next_vtx
|
|
281
|
+
filtered_vtxs << condition_vtx
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
# 複数の絞り込み結果をマージして使用
|
|
286
|
+
if !filtered_vtxs.empty?
|
|
287
|
+
merged_vtx = Vertex.new(self)
|
|
288
|
+
filtered_vtxs.each do |vtx|
|
|
289
|
+
@changes.add_edge(genv, vtx, merged_vtx)
|
|
290
|
+
end
|
|
291
|
+
@lenv.set_var(@pivot_var, merged_vtx)
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
@body.install(genv)
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# else節での型除外に使用する条件を取得
|
|
299
|
+
def get_exclusion_conditions
|
|
300
|
+
@conditions.select {|condition| condition.is_a?(ConstantReadNode) && condition.static_ret }
|
|
301
|
+
.map {|condition| condition.static_ret }
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
235
305
|
class CaseNode < Node
|
|
236
306
|
def initialize(raw_node, lenv)
|
|
237
307
|
super(raw_node, lenv)
|
|
238
308
|
@pivot = raw_node.predicate ? AST.create_node(raw_node.predicate, lenv) : nil
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
end
|
|
309
|
+
|
|
310
|
+
# pivot変数名を決定
|
|
311
|
+
pivot_var = @pivot.is_a?(LocalVariableReadNode) ? @pivot.var : nil
|
|
312
|
+
|
|
313
|
+
@when_nodes = raw_node.conditions.map {|raw_cond| WhenNode.new(raw_cond, lenv, pivot_var) }
|
|
245
314
|
@else_clause = raw_node.else_clause && raw_node.else_clause.statements ? AST.create_node(raw_node.else_clause.statements, lenv) : DummyNilNode.new(code_range, lenv) # TODO: code_range for NilNode
|
|
246
315
|
end
|
|
247
316
|
|
|
248
|
-
attr_reader :pivot, :
|
|
317
|
+
attr_reader :pivot, :when_nodes, :else_clause
|
|
249
318
|
|
|
250
|
-
def subnodes = { pivot:,
|
|
319
|
+
def subnodes = { pivot:, when_nodes:, else_clause: }
|
|
251
320
|
|
|
252
321
|
def install0(genv)
|
|
253
322
|
ret = Vertex.new(self)
|
|
254
323
|
@pivot&.install(genv)
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
324
|
+
|
|
325
|
+
# case文での型絞り込みを実装
|
|
326
|
+
if @pivot && @pivot.is_a?(LocalVariableReadNode)
|
|
327
|
+
var = @pivot.var
|
|
328
|
+
original_vtx = @lenv.get_var(var)
|
|
329
|
+
|
|
330
|
+
# ダミー変数に元の型情報を設定
|
|
331
|
+
@lenv.set_var(:"*pivot", original_vtx)
|
|
332
|
+
|
|
333
|
+
# 各when節を実行
|
|
334
|
+
@when_nodes.each do |when_node|
|
|
335
|
+
clause_result = when_node.install(genv)
|
|
336
|
+
@changes.add_edge(genv, clause_result, ret)
|
|
337
|
+
# 元の型に戻す
|
|
338
|
+
@lenv.set_var(var, original_vtx)
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# else節(他のwhen節で除外された後の型)
|
|
342
|
+
filtered_else_vtx = original_vtx.new_vertex(genv, self)
|
|
343
|
+
@when_nodes.each do |when_node|
|
|
344
|
+
when_node.get_exclusion_conditions.each do |static_ret|
|
|
345
|
+
# 各when節の型を除外(negation)
|
|
346
|
+
filtered_else_vtx = IsAFilter.new(genv, self, filtered_else_vtx, true, static_ret).next_vtx
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
@lenv.set_var(var, filtered_else_vtx)
|
|
350
|
+
@changes.add_edge(genv, @else_clause.install(genv), ret)
|
|
351
|
+
@lenv.set_var(var, original_vtx)
|
|
352
|
+
|
|
353
|
+
# ダミー変数をクリア
|
|
354
|
+
@lenv.locals.delete(:"*pivot")
|
|
355
|
+
else
|
|
356
|
+
# pivotが変数でない場合は従来通り
|
|
357
|
+
@when_nodes.each do |when_node|
|
|
358
|
+
@changes.add_edge(genv, when_node.install(genv), ret)
|
|
359
|
+
end
|
|
360
|
+
@changes.add_edge(genv, @else_clause.install(genv), ret)
|
|
258
361
|
end
|
|
259
|
-
|
|
362
|
+
|
|
260
363
|
ret
|
|
261
364
|
end
|
|
262
365
|
end
|
|
@@ -292,8 +395,9 @@ module TypeProf::Core
|
|
|
292
395
|
end
|
|
293
396
|
|
|
294
397
|
class AndNode < Node
|
|
295
|
-
def initialize(raw_node, e1 = nil, raw_e2 =
|
|
398
|
+
def initialize(raw_node, e1 = nil, raw_e2 = raw_node.right, lenv)
|
|
296
399
|
super(raw_node, lenv)
|
|
400
|
+
|
|
297
401
|
@e1 = e1 || AST.create_node(raw_node.left, lenv)
|
|
298
402
|
@e2 = AST.create_node(raw_e2 || raw_node.right, lenv)
|
|
299
403
|
end
|
|
@@ -304,15 +408,39 @@ module TypeProf::Core
|
|
|
304
408
|
|
|
305
409
|
def install0(genv)
|
|
306
410
|
ret = Vertex.new(self)
|
|
307
|
-
|
|
308
|
-
|
|
411
|
+
|
|
412
|
+
v1 = @e1.install(genv)
|
|
413
|
+
|
|
414
|
+
# For AND: if left side is truthy, apply its narrowing to right side
|
|
415
|
+
# Use legacy detect_narrowing for now to maintain compatibility
|
|
416
|
+
then_narrowing, _else_narrowing = @e1.narrowings
|
|
417
|
+
if then_narrowing
|
|
418
|
+
v2 = AST.with_narrowing(genv, self, @lenv, then_narrowing) do
|
|
419
|
+
@e2.install(genv)
|
|
420
|
+
end
|
|
421
|
+
else
|
|
422
|
+
v2 = @e2.install(genv)
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
@changes.add_edge(genv, v1, ret)
|
|
426
|
+
@changes.add_edge(genv, v2, ret)
|
|
427
|
+
|
|
309
428
|
ret
|
|
310
429
|
end
|
|
430
|
+
|
|
431
|
+
def narrowings
|
|
432
|
+
@narrowings ||= begin
|
|
433
|
+
e1_then_narrowing, e1_else_narrowing = @e1.narrowings
|
|
434
|
+
e2_then_narrowing, e2_else_narrowing = @e2.narrowings
|
|
435
|
+
[e1_then_narrowing.and(e2_then_narrowing), e1_else_narrowing.or(e2_else_narrowing)]
|
|
436
|
+
end
|
|
437
|
+
end
|
|
311
438
|
end
|
|
312
439
|
|
|
313
440
|
class OrNode < Node
|
|
314
|
-
def initialize(raw_node, e1 = nil, raw_e2 =
|
|
441
|
+
def initialize(raw_node, e1 = nil, raw_e2 = raw_node.right, lenv)
|
|
315
442
|
super(raw_node, lenv)
|
|
443
|
+
|
|
316
444
|
@e1 = e1 || AST.create_node(raw_node.left, lenv)
|
|
317
445
|
@e2 = AST.create_node(raw_e2 || raw_node.right, lenv)
|
|
318
446
|
end
|
|
@@ -323,12 +451,35 @@ module TypeProf::Core
|
|
|
323
451
|
|
|
324
452
|
def install0(genv)
|
|
325
453
|
ret = Vertex.new(self)
|
|
454
|
+
|
|
326
455
|
v1 = @e1.install(genv)
|
|
327
456
|
v1 = NilFilter.new(genv, self, v1, false).next_vtx
|
|
457
|
+
|
|
458
|
+
# For OR: if left side is falsy, apply negated narrowing to right side
|
|
459
|
+
# Use legacy detect_narrowing for now to maintain compatibility
|
|
460
|
+
_then_narrowing, else_narrowing = @e1.narrowings
|
|
461
|
+
if else_narrowing
|
|
462
|
+
# For OR: negated narrowing (negate: true)
|
|
463
|
+
v2 = AST.with_narrowing(genv, self, @lenv, else_narrowing) do
|
|
464
|
+
@e2.install(genv)
|
|
465
|
+
end
|
|
466
|
+
else
|
|
467
|
+
v2 = @e2.install(genv)
|
|
468
|
+
end
|
|
469
|
+
|
|
328
470
|
@changes.add_edge(genv, v1, ret)
|
|
329
|
-
@changes.add_edge(genv,
|
|
471
|
+
@changes.add_edge(genv, v2, ret)
|
|
472
|
+
|
|
330
473
|
ret
|
|
331
474
|
end
|
|
475
|
+
|
|
476
|
+
def narrowings
|
|
477
|
+
@narrowings ||= begin
|
|
478
|
+
e1_then_narrowing, e1_else_narrowing = @e1.narrowings
|
|
479
|
+
e2_then_narrowing, e2_else_narrowing = @e2.narrowings
|
|
480
|
+
[e1_then_narrowing.or(e2_then_narrowing), e1_else_narrowing.and(e2_else_narrowing)]
|
|
481
|
+
end
|
|
482
|
+
end
|
|
332
483
|
end
|
|
333
484
|
|
|
334
485
|
class ReturnNode < Node
|
|
@@ -344,38 +495,86 @@ module TypeProf::Core
|
|
|
344
495
|
def install0(genv)
|
|
345
496
|
@arg.install(genv)
|
|
346
497
|
e_ret = @lenv.locals[:"*expected_method_ret"]
|
|
347
|
-
@lenv.add_return_box(@changes.add_escape_box(genv, @arg.ret
|
|
498
|
+
@lenv.add_return_box(@changes.add_escape_box(genv, @arg.ret)) if e_ret
|
|
348
499
|
Source.new(Type::Bot.new(genv))
|
|
349
500
|
end
|
|
350
501
|
end
|
|
351
502
|
|
|
503
|
+
class RescueNode < Node
|
|
504
|
+
def initialize(raw_node, lenv)
|
|
505
|
+
super(raw_node, lenv)
|
|
506
|
+
|
|
507
|
+
@exceptions = raw_node.exceptions.map {|raw_cond| AST.create_node(raw_cond, lenv) }
|
|
508
|
+
@statements = AST.create_node(raw_node.statements, lenv) if raw_node.statements
|
|
509
|
+
if raw_node.reference && @statements
|
|
510
|
+
@reference = AST.create_target_node(raw_node.reference, @statements.lenv)
|
|
511
|
+
end
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
attr_reader :exceptions, :reference, :statements
|
|
515
|
+
|
|
516
|
+
def subnodes = { exceptions:, reference:, statements: }
|
|
517
|
+
|
|
518
|
+
def define0(genv)
|
|
519
|
+
@exceptions.each {|exc| exc.define(genv) }
|
|
520
|
+
@reference.define(genv) if @reference
|
|
521
|
+
@statements.define(genv) if @statements
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
def undefine0(genv)
|
|
525
|
+
@exceptions.each {|exc| exc.undefine(genv) }
|
|
526
|
+
@reference.undefine(genv) if @reference
|
|
527
|
+
@statements.undefine(genv) if @statements
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
def install0(genv)
|
|
531
|
+
cond_vtxs = @exceptions.map do |exc|
|
|
532
|
+
case exc
|
|
533
|
+
when AST::SplatNode
|
|
534
|
+
ary_vtx = exc.expr.install(genv)
|
|
535
|
+
@changes.add_splat_box(genv, ary_vtx).ret
|
|
536
|
+
else
|
|
537
|
+
exc.install(genv)
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
if @reference
|
|
542
|
+
@reference.install(genv)
|
|
543
|
+
cond_vtxs.each do |cond_vtx|
|
|
544
|
+
instance_ty_box = @changes.add_instance_type_box(genv, cond_vtx)
|
|
545
|
+
@changes.add_edge(genv, instance_ty_box.ret, @reference.rhs.ret)
|
|
546
|
+
end
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
if @statements
|
|
550
|
+
@statements.install(genv)
|
|
551
|
+
else
|
|
552
|
+
Source.new(genv.nil_type)
|
|
553
|
+
end
|
|
554
|
+
end
|
|
555
|
+
end
|
|
556
|
+
|
|
352
557
|
class BeginNode < Node
|
|
353
558
|
def initialize(raw_node, lenv)
|
|
354
559
|
super(raw_node, lenv)
|
|
355
560
|
@body = raw_node.statements ? AST.create_node(raw_node.statements, lenv) : DummyNilNode.new(code_range, lenv)
|
|
356
|
-
|
|
561
|
+
|
|
357
562
|
@rescue_clauses = []
|
|
358
563
|
raw_res = raw_node.rescue_clause
|
|
359
564
|
while raw_res
|
|
360
|
-
raw_res
|
|
361
|
-
@rescue_conds << AST.create_node(raw_cond, lenv)
|
|
362
|
-
end
|
|
363
|
-
if raw_res.statements
|
|
364
|
-
@rescue_clauses << AST.create_node(raw_res.statements, lenv)
|
|
365
|
-
end
|
|
565
|
+
@rescue_clauses << AST.create_node(raw_res, lenv)
|
|
366
566
|
raw_res = raw_res.subsequent
|
|
367
567
|
end
|
|
368
|
-
@else_clause =
|
|
369
|
-
@ensure_clause =
|
|
568
|
+
@else_clause = AST.create_node(raw_node.else_clause.statements, lenv) if raw_node.else_clause&.statements
|
|
569
|
+
@ensure_clause = AST.create_node(raw_node.ensure_clause.statements, lenv) if raw_node.ensure_clause&.statements
|
|
370
570
|
end
|
|
371
571
|
|
|
372
|
-
attr_reader :body, :
|
|
572
|
+
attr_reader :body, :rescue_clauses, :else_clause, :ensure_clause
|
|
373
573
|
|
|
374
|
-
def subnodes = { body:,
|
|
574
|
+
def subnodes = { body:, rescue_clauses:, else_clause:, ensure_clause: }
|
|
375
575
|
|
|
376
576
|
def define0(genv)
|
|
377
577
|
@body.define(genv)
|
|
378
|
-
@rescue_conds.each {|cond| cond.define(genv) }
|
|
379
578
|
@rescue_clauses.each {|clause| clause.define(genv) }
|
|
380
579
|
@else_clause.define(genv) if @else_clause
|
|
381
580
|
@ensure_clause.define(genv) if @ensure_clause
|
|
@@ -383,7 +582,6 @@ module TypeProf::Core
|
|
|
383
582
|
|
|
384
583
|
def undefine0(genv)
|
|
385
584
|
@body.undefine(genv)
|
|
386
|
-
@rescue_conds.each {|cond| cond.undefine(genv) }
|
|
387
585
|
@rescue_clauses.each {|clause| clause.undefine(genv) }
|
|
388
586
|
@else_clause.undefine(genv) if @else_clause
|
|
389
587
|
@ensure_clause.undefine(genv) if @ensure_clause
|
|
@@ -391,11 +589,88 @@ module TypeProf::Core
|
|
|
391
589
|
|
|
392
590
|
def install0(genv)
|
|
393
591
|
ret = Vertex.new(self)
|
|
592
|
+
|
|
593
|
+
vars = []
|
|
594
|
+
@body.modified_vars(@lenv.locals.keys, vars) if @body
|
|
595
|
+
vars.uniq!
|
|
596
|
+
|
|
597
|
+
old_vtxs = {}
|
|
598
|
+
vars.each do |var|
|
|
599
|
+
vtx = @lenv.get_var(var)
|
|
600
|
+
old_vtxs[var] = vtx
|
|
601
|
+
end
|
|
602
|
+
|
|
394
603
|
@changes.add_edge(genv, @body.install(genv), ret)
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
604
|
+
|
|
605
|
+
body_vtxs = {}
|
|
606
|
+
vars.each do |var|
|
|
607
|
+
body_vtxs[var] = @lenv.get_var(var)
|
|
608
|
+
end
|
|
609
|
+
|
|
610
|
+
clause_vtxs_list = []
|
|
611
|
+
@rescue_clauses.each do |clause|
|
|
612
|
+
vars.each do |var|
|
|
613
|
+
old_vtx = old_vtxs[var]
|
|
614
|
+
nvtx = old_vtx.new_vertex(genv, self)
|
|
615
|
+
|
|
616
|
+
@changes.add_edge(genv, body_vtxs[var], nvtx) unless body_vtxs[var] == old_vtxs[var]
|
|
617
|
+
|
|
618
|
+
@lenv.set_var(var, nvtx)
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
@changes.add_edge(genv, clause.install(genv), ret)
|
|
622
|
+
|
|
623
|
+
clause_vtxs_list << {}
|
|
624
|
+
vars.each do |var|
|
|
625
|
+
clause_vtxs_list.last[var] = @lenv.get_var(var)
|
|
626
|
+
end
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
if @else_clause
|
|
630
|
+
vars.each do |var|
|
|
631
|
+
@lenv.set_var(var, body_vtxs[var])
|
|
632
|
+
end
|
|
633
|
+
@changes.add_edge(genv, @else_clause.install(genv), ret)
|
|
634
|
+
clause_vtxs_list << {}
|
|
635
|
+
vars.each do |var|
|
|
636
|
+
clause_vtxs_list.last[var] = @lenv.get_var(var)
|
|
637
|
+
end
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
if @ensure_clause
|
|
641
|
+
vars.each do |var|
|
|
642
|
+
union_vtx = old_vtxs[var].new_vertex(genv, self)
|
|
643
|
+
@changes.add_edge(genv, body_vtxs[var], union_vtx)
|
|
644
|
+
clause_vtxs_list.each do |clause_vtx|
|
|
645
|
+
@changes.add_edge(genv, clause_vtx[var], union_vtx)
|
|
646
|
+
end
|
|
647
|
+
@lenv.set_var(var, union_vtx)
|
|
648
|
+
end
|
|
649
|
+
|
|
650
|
+
@ensure_clause.install(genv)
|
|
651
|
+
|
|
652
|
+
clause_vtxs_list << {}
|
|
653
|
+
vars.each do |var|
|
|
654
|
+
clause_vtxs_list.last[var] = @lenv.get_var(var)
|
|
655
|
+
end
|
|
656
|
+
end
|
|
657
|
+
|
|
658
|
+
result_vtxs = {}
|
|
659
|
+
vars.each do |var|
|
|
660
|
+
result_vtx = old_vtxs[var].new_vertex(genv, self)
|
|
661
|
+
result_vtxs[var] = result_vtx
|
|
662
|
+
|
|
663
|
+
@changes.add_edge(genv, body_vtxs[var], result_vtx) unless body_vtxs[var] == old_vtxs[var]
|
|
664
|
+
|
|
665
|
+
clause_vtxs_list.each do |clause_vtx|
|
|
666
|
+
@changes.add_edge(genv, clause_vtx[var], result_vtx)
|
|
667
|
+
end
|
|
668
|
+
end
|
|
669
|
+
|
|
670
|
+
vars.each do |var|
|
|
671
|
+
@lenv.set_var(var, result_vtxs[var])
|
|
672
|
+
end
|
|
673
|
+
|
|
399
674
|
ret
|
|
400
675
|
end
|
|
401
676
|
end
|
|
@@ -6,7 +6,9 @@ module TypeProf::Core
|
|
|
6
6
|
# TODO: error for splat
|
|
7
7
|
@args = raw_node.arguments.arguments.map do |raw_arg|
|
|
8
8
|
next if raw_arg.is_a?(Prism::SplatNode)
|
|
9
|
-
|
|
9
|
+
lenv.use_strict_const_scope do
|
|
10
|
+
AST.create_node(raw_arg, lenv)
|
|
11
|
+
end
|
|
10
12
|
end.compact
|
|
11
13
|
# TODO: error for non-LIT
|
|
12
14
|
# TODO: fine-grained hover
|
|
@@ -77,8 +79,7 @@ module TypeProf::Core
|
|
|
77
79
|
@args.each do |arg|
|
|
78
80
|
ivar_name = :"@#{ arg }"
|
|
79
81
|
ivar_box = @changes.add_ivar_read_box(genv, @lenv.cref.cpath, false, ivar_name)
|
|
80
|
-
|
|
81
|
-
ret_box = @changes.add_escape_box(genv, ivar_box.ret, e_ret)
|
|
82
|
+
ret_box = @changes.add_escape_box(genv, ivar_box.ret)
|
|
82
83
|
@changes.add_method_def_box(genv, @lenv.cref.cpath, false, arg, FormalArguments::Empty, [ret_box])
|
|
83
84
|
end
|
|
84
85
|
Source.new
|
|
@@ -134,8 +135,7 @@ module TypeProf::Core
|
|
|
134
135
|
def install0(genv)
|
|
135
136
|
@args.zip(@static_ret) do |arg, ive|
|
|
136
137
|
ivar_box = @changes.add_ivar_read_box(genv, @lenv.cref.cpath, false, :"@#{ arg }")
|
|
137
|
-
|
|
138
|
-
ret_box = @changes.add_escape_box(genv, ivar_box.ret, e_ret)
|
|
138
|
+
ret_box = @changes.add_escape_box(genv, ivar_box.ret)
|
|
139
139
|
@changes.add_method_def_box(genv, @lenv.cref.cpath, false, arg, FormalArguments::Empty, [ret_box])
|
|
140
140
|
|
|
141
141
|
vtx = Vertex.new(self)
|
|
@@ -64,7 +64,7 @@ module TypeProf::Core
|
|
|
64
64
|
|
|
65
65
|
post_positionals = raw_args.posts.map {|n| (n.is_a?(Prism::MultiTargetNode) ? nil : n.name) }
|
|
66
66
|
|
|
67
|
-
rest_positionals = raw_args.rest
|
|
67
|
+
rest_positionals = raw_args.rest ? (raw_args.rest.name || :"*anonymous_rest") : nil
|
|
68
68
|
|
|
69
69
|
req_keywords = []
|
|
70
70
|
opt_keywords = []
|
|
@@ -82,7 +82,11 @@ module TypeProf::Core
|
|
|
82
82
|
|
|
83
83
|
case raw_args.keyword_rest
|
|
84
84
|
when Prism::KeywordRestParameterNode
|
|
85
|
-
rest_keywords = raw_args.keyword_rest.name
|
|
85
|
+
rest_keywords = raw_args.keyword_rest.name || :"**anonymous_keyword"
|
|
86
|
+
when Prism::ForwardingParameterNode
|
|
87
|
+
# TODO: The variable names might be subject to change when supporting the propagation of parameter values to the graph during method calls.
|
|
88
|
+
rest_positionals = :"..."
|
|
89
|
+
rest_keywords = :"..."
|
|
86
90
|
when Prism::NoKeywordsParameterNode
|
|
87
91
|
# what to do?
|
|
88
92
|
when nil
|
|
@@ -91,7 +95,7 @@ module TypeProf::Core
|
|
|
91
95
|
raise "unexpected keyword rest: #{ raw_args.keyword_rest.class }"
|
|
92
96
|
end
|
|
93
97
|
|
|
94
|
-
block = raw_args.block.name if raw_args.block
|
|
98
|
+
block = raw_args.block.name || :"*anonymous_block" if raw_args.block
|
|
95
99
|
|
|
96
100
|
{
|
|
97
101
|
req_positionals:,
|
|
@@ -220,6 +224,16 @@ module TypeProf::Core
|
|
|
220
224
|
rest_keywords = @rest_keywords ? @body.lenv.new_var(@rest_keywords, self) : nil
|
|
221
225
|
block = @block ? @body.lenv.new_var(@block, self) : nil
|
|
222
226
|
|
|
227
|
+
if rest_positionals
|
|
228
|
+
@changes.add_edge(genv, Source.new(genv.gen_ary_type(Vertex.new(self))), rest_positionals)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
if rest_keywords
|
|
232
|
+
if @rest_keywords == :"**anonymous_keyword"
|
|
233
|
+
@changes.add_edge(genv, Source.new(genv.gen_hash_type(Vertex.new(self), Vertex.new(self))), rest_keywords)
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
223
237
|
@opt_positional_defaults.zip(opt_positionals) do |expr, vtx|
|
|
224
238
|
@changes.add_edge(genv, expr.install(genv), vtx)
|
|
225
239
|
end
|
|
@@ -234,9 +248,9 @@ module TypeProf::Core
|
|
|
234
248
|
end
|
|
235
249
|
|
|
236
250
|
if @body
|
|
237
|
-
|
|
251
|
+
@body.lenv.locals[:"*expected_method_ret"] = Vertex.new(self)
|
|
238
252
|
@body.install(genv)
|
|
239
|
-
@body.lenv.add_return_box(@changes.add_escape_box(genv, @body.ret
|
|
253
|
+
@body.lenv.add_return_box(@changes.add_escape_box(genv, @body.ret))
|
|
240
254
|
end
|
|
241
255
|
|
|
242
256
|
f_args = FormalArguments.new(
|