typeprof 0.21.11 → 0.30.1

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.
Files changed (72) 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 +178 -0
  7. data/lib/typeprof/cli.rb +3 -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 +259 -0
  11. data/lib/typeprof/core/ast/const.rb +126 -0
  12. data/lib/typeprof/core/ast/control.rb +433 -0
  13. data/lib/typeprof/core/ast/meta.rb +150 -0
  14. data/lib/typeprof/core/ast/method.rb +339 -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 +366 -0
  31. data/lib/typeprof/core/graph/box.rb +998 -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 +225 -0
  35. data/lib/typeprof/core/service.rb +514 -0
  36. data/lib/typeprof/core/type.rb +352 -0
  37. data/lib/typeprof/core/util.rb +81 -0
  38. data/lib/typeprof/core.rb +31 -0
  39. data/lib/typeprof/diagnostic.rb +35 -0
  40. data/lib/typeprof/lsp/messages.rb +415 -0
  41. data/lib/typeprof/lsp/server.rb +203 -0
  42. data/lib/typeprof/lsp/text.rb +69 -0
  43. data/lib/typeprof/lsp/util.rb +51 -0
  44. data/lib/typeprof/lsp.rb +4 -907
  45. data/lib/typeprof/version.rb +1 -1
  46. data/lib/typeprof.rb +4 -18
  47. data/typeprof.gemspec +5 -7
  48. metadata +47 -33
  49. data/.github/dependabot.yml +0 -6
  50. data/.github/workflows/main.yml +0 -39
  51. data/.gitignore +0 -9
  52. data/Gemfile +0 -17
  53. data/Gemfile.lock +0 -41
  54. data/Rakefile +0 -10
  55. data/exe/typeprof +0 -10
  56. data/lib/typeprof/analyzer.rb +0 -2598
  57. data/lib/typeprof/arguments.rb +0 -414
  58. data/lib/typeprof/block.rb +0 -176
  59. data/lib/typeprof/builtin.rb +0 -893
  60. data/lib/typeprof/code-range.rb +0 -177
  61. data/lib/typeprof/config.rb +0 -158
  62. data/lib/typeprof/container-type.rb +0 -912
  63. data/lib/typeprof/export.rb +0 -589
  64. data/lib/typeprof/import.rb +0 -852
  65. data/lib/typeprof/insns-def.rb +0 -65
  66. data/lib/typeprof/iseq.rb +0 -864
  67. data/lib/typeprof/method.rb +0 -355
  68. data/lib/typeprof/type.rb +0 -1140
  69. data/lib/typeprof/utils.rb +0 -212
  70. data/tools/coverage.rb +0 -14
  71. data/tools/setup-insns-def.rb +0 -30
  72. data/typeprof-lsp +0 -3
@@ -0,0 +1,126 @@
1
+ module TypeProf::Core
2
+ class AST
3
+ class ConstantReadNode < Node
4
+ def initialize(raw_node, lenv)
5
+ super(raw_node, lenv)
6
+ case raw_node.type
7
+ when :constant_read_node, :constant_operator_write_node, :constant_or_write_node, :constant_and_write_node
8
+ @cbase = nil
9
+ @toplevel = false
10
+ @cname = raw_node.name
11
+ @cname_code_range = TypeProf::CodeRange.from_node(raw_node.location)
12
+ when :constant_path_node, :constant_path_target_node
13
+ if raw_node.parent
14
+ @cbase = AST.create_node(raw_node.parent, lenv)
15
+ @toplevel = false
16
+ else
17
+ @cbase = nil
18
+ @toplevel = true
19
+ end
20
+ # temporarily support old Prism https://bugs.ruby-lang.org/issues/20467
21
+ if raw_node.respond_to?(:name)
22
+ @cname = raw_node.name
23
+ @cname_code_range = TypeProf::CodeRange.from_node(raw_node.name_loc)
24
+ else
25
+ @cname = raw_node.child.name
26
+ @cname_code_range = TypeProf::CodeRange.from_node(raw_node.child.location)
27
+ end
28
+ else
29
+ raise raw_node.type.to_s
30
+ end
31
+ end
32
+
33
+ attr_reader :cname, :cbase, :toplevel, :cname_code_range
34
+
35
+ def attrs = { cname:, toplevel: }
36
+ def subnodes = { cbase: }
37
+
38
+ def define0(genv)
39
+ if @cbase
40
+ ScopedConstRead.new(@cname, @cbase.define(genv))
41
+ else
42
+ BaseConstRead.new(genv, @cname, @toplevel ? CRef::Toplevel : @lenv.cref)
43
+ end
44
+ end
45
+
46
+ def undefine0(genv)
47
+ @static_ret.destroy(genv)
48
+ end
49
+
50
+ def install0(genv)
51
+ @cbase.install(genv) if @cbase
52
+ box = @changes.add_const_read_box(genv, @static_ret)
53
+ box.ret
54
+ end
55
+ end
56
+
57
+ class ConstantWriteNode < Node
58
+ def initialize(raw_node, rhs, lenv)
59
+ super(raw_node, lenv)
60
+ case raw_node.type
61
+ when :constant_write_node, :constant_target_node, :constant_operator_write_node, :constant_or_write_node, :constant_and_write_node
62
+ # C = expr
63
+ @cpath = nil
64
+ @static_cpath = lenv.cref.cpath + [raw_node.name]
65
+ @cname_code_range = TypeProf::CodeRange.from_node(raw_node.respond_to?(:name_loc) ? raw_node.name_loc : raw_node)
66
+ when :constant_path_write_node, :constant_path_operator_write_node, :constant_path_or_write_node, :constant_path_and_write_node
67
+ # expr::C = expr
68
+ @cpath = AST.create_node(raw_node.target, lenv)
69
+ @static_cpath = AST.parse_cpath(raw_node.target, lenv.cref)
70
+ @cname_code_range = TypeProf::CodeRange.from_node(raw_node.target)
71
+ when :constant_path_target_node
72
+ # expr::C, * = ary
73
+ @cpath = ConstantReadNode.new(raw_node, lenv)
74
+ @static_cpath = AST.parse_cpath(raw_node, lenv.cref)
75
+ @cname_code_range = TypeProf::CodeRange.from_node(raw_node)
76
+ else
77
+ raise
78
+ end
79
+ @rhs = rhs
80
+ end
81
+
82
+ attr_reader :cpath, :rhs, :static_cpath, :cname_code_range
83
+
84
+ def subnodes = { cpath:, rhs: }
85
+ def attrs = { static_cpath: }
86
+
87
+ def define0(genv)
88
+ @cpath.define(genv) if @cpath
89
+ @rhs.define(genv) if @rhs
90
+ if @static_cpath
91
+ mod = genv.resolve_const(@static_cpath)
92
+ mod.add_def(self)
93
+ mod
94
+ else
95
+ nil
96
+ end
97
+ end
98
+
99
+ def define_copy(genv)
100
+ if @static_cpath
101
+ mod = genv.resolve_const(@static_cpath)
102
+ mod.add_def(self)
103
+ mod.remove_def(@prev_node)
104
+ end
105
+ super(genv)
106
+ end
107
+
108
+ def undefine0(genv)
109
+ if @static_cpath
110
+ genv.resolve_const(@static_cpath).remove_def(self)
111
+ end
112
+ @rhs.undefine(genv) if @rhs
113
+ @cpath.undefine(genv) if @cpath
114
+ end
115
+
116
+ def install0(genv)
117
+ @cpath.install(genv) if @cpath
118
+ val = @rhs.install(genv)
119
+ if @static_cpath
120
+ @changes.add_edge(genv, val, @static_ret.vtx)
121
+ end
122
+ val
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,433 @@
1
+ module TypeProf::Core
2
+ class AST
3
+ def self.is_a_class(node)
4
+ if node.is_a?(CallNode)
5
+ recv = node.recv
6
+ if recv.is_a?(LocalVariableReadNode)
7
+ if node.positional_args && node.positional_args.size == 1 && node.positional_args[0].static_ret
8
+ # TODO: need static resolusion of a constant
9
+ return [recv.var, node.positional_args[0].static_ret]
10
+ end
11
+ end
12
+ end
13
+ return nil
14
+ end
15
+
16
+ class BranchNode < Node
17
+ def initialize(raw_node, lenv)
18
+ super(raw_node, lenv)
19
+ @cond = AST.create_node(raw_node.predicate, lenv)
20
+ @then = raw_node.statements ? AST.create_node(raw_node.statements, lenv) : nil
21
+ else_clause = raw_node.is_a?(Prism::IfNode) ? raw_node.subsequent : raw_node.else_clause
22
+ if else_clause
23
+ else_clause = else_clause.statements if else_clause.type == :else_node
24
+ @else = else_clause ? AST.create_node(else_clause, lenv) : nil
25
+ else
26
+ @else = nil
27
+ end
28
+ end
29
+
30
+ attr_reader :cond, :then, :else
31
+
32
+ def subnodes = { cond:, then:, else: }
33
+
34
+ def install0(genv)
35
+ ret = Vertex.new(self)
36
+
37
+ @cond.install(genv)
38
+
39
+ 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
+ @then.modified_vars(@lenv.locals.keys, vars) if @then
44
+ @else.modified_vars(@lenv.locals.keys, vars) if @else
45
+ modified_vtxs = {}
46
+ vars.uniq.each do |var|
47
+ vtx = @lenv.get_var(var)
48
+ nvtx_then = vtx.new_vertex(genv, self)
49
+ nvtx_else = vtx.new_vertex(genv, self)
50
+ modified_vtxs[var] = [nvtx_then, nvtx_else]
51
+ 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
+
65
+ if @then
66
+ modified_vtxs.each do |var, (nvtx_then, _)|
67
+ @lenv.set_var(var, nvtx_then)
68
+ end
69
+ if @cond.is_a?(InstanceVariableReadNode)
70
+ @lenv.push_read_filter(@cond.var, :non_nil)
71
+ end
72
+ then_val = @then.install(genv)
73
+ if @cond.is_a?(InstanceVariableReadNode)
74
+ @lenv.pop_read_filter(@cond.var)
75
+ end
76
+ modified_vtxs.each do |var, ary|
77
+ ary[0] = @lenv.get_var(var)
78
+ end
79
+ else
80
+ then_val = Source.new(genv.nil_type)
81
+ end
82
+ @changes.add_edge(genv, then_val, ret)
83
+
84
+ if @else
85
+ modified_vtxs.each do |var, (_, nvtx_else)|
86
+ @lenv.set_var(var, nvtx_else)
87
+ end
88
+ else_val = @else.install(genv)
89
+ modified_vtxs.each do |var, ary|
90
+ ary[1] = @lenv.get_var(var)
91
+ end
92
+ else
93
+ else_val = Source.new(genv.nil_type)
94
+ end
95
+ @changes.add_edge(genv, else_val, ret)
96
+
97
+ modified_vtxs.each do |var, (nvtx_then, nvtx_else)|
98
+ nvtx_then = BotFilter.new(genv, self, nvtx_then, then_val).next_vtx
99
+ nvtx_else = BotFilter.new(genv, self, nvtx_else, else_val).next_vtx
100
+ nvtx_join = nvtx_then.new_vertex(genv, self)
101
+ @changes.add_edge(genv, nvtx_else, nvtx_join)
102
+ @lenv.set_var(var, nvtx_join)
103
+ end
104
+
105
+ ret
106
+ end
107
+ end
108
+
109
+ class IfNode < BranchNode
110
+ end
111
+
112
+ class UnlessNode < BranchNode
113
+ end
114
+
115
+ class LoopNode < Node
116
+ def initialize(raw_node, lenv)
117
+ super(raw_node, lenv)
118
+ @cond = AST.create_node(raw_node.predicate, lenv)
119
+ @body = raw_node.statements ? AST.create_node(raw_node.statements, lenv) : DummyNilNode.new(code_range, lenv)
120
+ end
121
+
122
+ attr_reader :cond, :body
123
+
124
+ def subnodes = { cond:, body: }
125
+
126
+ def install0(genv)
127
+ vars = []
128
+ vars << @cond.var if @cond.is_a?(LocalVariableReadNode)
129
+ @cond.modified_vars(@lenv.locals.keys, vars)
130
+ @body.modified_vars(@lenv.locals.keys, vars)
131
+ vars.uniq!
132
+ old_vtxs = {}
133
+ vars.each do |var|
134
+ vtx = @lenv.get_var(var)
135
+ nvtx = vtx.new_vertex(genv, self)
136
+ old_vtxs[var] = nvtx
137
+ @lenv.set_var(var, nvtx)
138
+ end
139
+
140
+ @cond.install(genv)
141
+ if @cond.is_a?(LocalVariableReadNode)
142
+ nvtx_then = NilFilter.new(genv, self, old_vtxs[@cond.var], self.is_a?(UntilNode)).next_vtx
143
+ @lenv.set_var(@cond.var, nvtx_then)
144
+ end
145
+
146
+ if @lenv.exist_var?(:"*expected_block_ret")
147
+ expected_block_ret = @lenv.locals[:"*expected_block_ret"]
148
+ @lenv.set_var(:"*expected_block_ret", nil)
149
+ end
150
+
151
+ @body.install(genv)
152
+
153
+ if expected_block_ret
154
+ @lenv.set_var(:"*expected_block_ret", expected_block_ret)
155
+ end
156
+
157
+ vars.each do |var|
158
+ @changes.add_edge(genv, @lenv.get_var(var), old_vtxs[var])
159
+ @lenv.set_var(var, old_vtxs[var])
160
+ end
161
+ if @cond.is_a?(LocalVariableReadNode)
162
+ nvtx_then = NilFilter.new(genv, self, old_vtxs[@cond.var], !self.is_a?(UntilNode)).next_vtx
163
+ @lenv.set_var(@cond.var, nvtx_then)
164
+ end
165
+
166
+ Source.new(genv.nil_type)
167
+ end
168
+ end
169
+
170
+ class WhileNode < LoopNode
171
+ end
172
+
173
+ class UntilNode < LoopNode
174
+ end
175
+
176
+ class BreakNode < Node
177
+ def initialize(raw_node, lenv)
178
+ super(raw_node, lenv)
179
+ @arg = AST.parse_return_arguments(raw_node, lenv, code_range)
180
+ end
181
+
182
+ attr_reader :arg
183
+
184
+ def subnodes = { arg: }
185
+
186
+ def install0(genv)
187
+ arg = @arg.install(genv)
188
+ @changes.add_edge(genv, arg, @lenv.get_break_vtx)
189
+ Source.new()
190
+ end
191
+ end
192
+
193
+ def self.parse_return_arguments(raw_node, lenv, code_range)
194
+ if raw_node.arguments
195
+ elems = raw_node.arguments.arguments
196
+ if elems.one?
197
+ AST.create_node(elems.first, lenv)
198
+ else
199
+ ArrayNode.new(raw_node.arguments, lenv, elems)
200
+ end
201
+ else
202
+ DummyNilNode.new(code_range, lenv)
203
+ end
204
+ end
205
+
206
+ class NextNode < Node
207
+ def initialize(raw_node, lenv)
208
+ super(raw_node, lenv)
209
+ @arg = AST.parse_return_arguments(raw_node, lenv, code_range)
210
+ end
211
+
212
+ attr_reader :arg
213
+
214
+ def subnodes = { arg: }
215
+
216
+ def install0(genv)
217
+ @arg.install(genv)
218
+ if @lenv.exist_var?(:"*expected_block_ret")
219
+ @lenv.add_next_box(@changes.add_escape_box(genv, @arg.ret, @lenv.get_var(:"*expected_block_ret")))
220
+ end
221
+ Source.new(Type::Bot.new(genv))
222
+ end
223
+ end
224
+
225
+ class RedoNode < Node
226
+ def initialize(raw_node, lenv)
227
+ super(raw_node, lenv)
228
+ end
229
+
230
+ def install0(genv)
231
+ # TODO: This should return a bot type
232
+ Source.new()
233
+ end
234
+ end
235
+
236
+ class CaseNode < Node
237
+ def initialize(raw_node, lenv)
238
+ super(raw_node, lenv)
239
+ @pivot = raw_node.predicate ? AST.create_node(raw_node.predicate, lenv) : nil
240
+ @whens = []
241
+ @clauses = []
242
+ raw_node.conditions.each do |raw_cond|
243
+ @whens << AST.create_node(raw_cond.conditions.first, lenv) # XXX: multiple conditions
244
+ @clauses << (raw_cond.statements ? AST.create_node(raw_cond.statements, lenv) : DummyNilNode.new(code_range, lenv)) # TODO: code_range for NilNode
245
+ end
246
+ @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
247
+ end
248
+
249
+ attr_reader :pivot, :whens, :clauses, :else_clause
250
+
251
+ def subnodes = { pivot:, whens:, clauses:, else_clause: }
252
+
253
+ def install0(genv)
254
+ ret = Vertex.new(self)
255
+ @pivot&.install(genv)
256
+ @whens.zip(@clauses) do |vals, clause|
257
+ vals.install(genv)
258
+ @changes.add_edge(genv, clause.install(genv), ret)
259
+ end
260
+ @changes.add_edge(genv, @else_clause.install(genv), ret)
261
+ ret
262
+ end
263
+ end
264
+
265
+ class CaseMatchNode < Node
266
+ def initialize(raw_node, lenv)
267
+ super(raw_node, lenv)
268
+ @pivot = AST.create_node(raw_node.predicate, lenv)
269
+ @patterns = []
270
+ @clauses = []
271
+ raw_node.conditions.each do |raw_cond|
272
+ raise if raw_cond.type != :in_node
273
+ @patterns << AST.create_pattern_node(raw_cond.pattern, lenv)
274
+ @clauses << (raw_cond.statements ? AST.create_node(raw_cond.statements, lenv) : DummyNilNode.new(code_range, lenv)) # TODO: code_range for NilNode
275
+ end
276
+ @else_clause = raw_node.else_clause && raw_node.else_clause.statements ? AST.create_node(raw_node.else_clause.statements, lenv) : nil
277
+ end
278
+
279
+ attr_reader :pivot, :patterns, :clauses, :else_clause
280
+
281
+ def subnodes = { pivot:, patterns:, clauses:, else_clause: }
282
+
283
+ def install0(genv)
284
+ ret = Vertex.new(self)
285
+ @pivot&.install(genv)
286
+ @patterns.zip(@clauses) do |pattern, clause|
287
+ pattern.install(genv)
288
+ @changes.add_edge(genv, clause.install(genv), ret)
289
+ end
290
+ @changes.add_edge(genv, @else_clause.install(genv), ret) if @else_clause
291
+ ret
292
+ end
293
+ end
294
+
295
+ class AndNode < Node
296
+ def initialize(raw_node, e1 = nil, raw_e2 = nil, lenv)
297
+ super(raw_node, lenv)
298
+ @e1 = e1 || AST.create_node(raw_node.left, lenv)
299
+ @e2 = AST.create_node(raw_e2 || raw_node.right, lenv)
300
+ end
301
+
302
+ attr_reader :e1, :e2
303
+
304
+ def subnodes = { e1:, e2: }
305
+
306
+ def install0(genv)
307
+ ret = Vertex.new(self)
308
+ @changes.add_edge(genv, @e1.install(genv), ret)
309
+ @changes.add_edge(genv, @e2.install(genv), ret)
310
+ ret
311
+ end
312
+ end
313
+
314
+ class OrNode < Node
315
+ def initialize(raw_node, e1 = nil, raw_e2 = nil, lenv)
316
+ super(raw_node, lenv)
317
+ @e1 = e1 || AST.create_node(raw_node.left, lenv)
318
+ @e2 = AST.create_node(raw_e2 || raw_node.right, lenv)
319
+ end
320
+
321
+ attr_reader :e1, :e2
322
+
323
+ def subnodes = { e1:, e2: }
324
+
325
+ def install0(genv)
326
+ ret = Vertex.new(self)
327
+ v1 = @e1.install(genv)
328
+ v1 = NilFilter.new(genv, self, v1, false).next_vtx
329
+ @changes.add_edge(genv, v1, ret)
330
+ @changes.add_edge(genv, @e2.install(genv), ret)
331
+ ret
332
+ end
333
+ end
334
+
335
+ class ReturnNode < Node
336
+ def initialize(raw_node, lenv)
337
+ super(raw_node, lenv)
338
+ @arg = AST.parse_return_arguments(raw_node, lenv, code_range)
339
+ end
340
+
341
+ attr_reader :arg
342
+
343
+ def subnodes = { arg: }
344
+
345
+ def install0(genv)
346
+ @arg.install(genv)
347
+ e_ret = @lenv.locals[:"*expected_method_ret"]
348
+ @lenv.add_return_box(@changes.add_escape_box(genv, @arg.ret, e_ret)) if e_ret
349
+ Source.new(Type::Bot.new(genv))
350
+ end
351
+ end
352
+
353
+ class BeginNode < Node
354
+ def initialize(raw_node, lenv)
355
+ super(raw_node, lenv)
356
+ @body = raw_node.statements ? AST.create_node(raw_node.statements, lenv) : DummyNilNode.new(code_range, lenv)
357
+ @rescue_conds = []
358
+ @rescue_clauses = []
359
+ raw_res = raw_node.rescue_clause
360
+ while raw_res
361
+ raw_res.exceptions.each do |raw_cond|
362
+ @rescue_conds << AST.create_node(raw_cond, lenv)
363
+ end
364
+ if raw_res.statements
365
+ @rescue_clauses << AST.create_node(raw_res.statements, lenv)
366
+ end
367
+ raw_res = raw_res.subsequent
368
+ end
369
+ @else_clause = raw_node.else_clause&.statements ? AST.create_node(raw_node.else_clause.statements, lenv) : DummyNilNode.new(code_range, lenv)
370
+ @ensure_clause = raw_node.ensure_clause&.statements ? AST.create_node(raw_node.ensure_clause.statements, lenv) : DummyNilNode.new(code_range, lenv)
371
+ end
372
+
373
+ attr_reader :body, :rescue_conds, :rescue_clauses, :else_clause, :ensure_clause
374
+
375
+ def subnodes = { body:, rescue_conds:, rescue_clauses:, else_clause:, ensure_clause: }
376
+
377
+ def define0(genv)
378
+ @body.define(genv)
379
+ @rescue_conds.each {|cond| cond.define(genv) }
380
+ @rescue_clauses.each {|clause| clause.define(genv) }
381
+ @else_clause.define(genv) if @else_clause
382
+ @ensure_clause.define(genv) if @ensure_clause
383
+ end
384
+
385
+ def undefine0(genv)
386
+ @body.undefine(genv)
387
+ @rescue_conds.each {|cond| cond.undefine(genv) }
388
+ @rescue_clauses.each {|clause| clause.undefine(genv) }
389
+ @else_clause.undefine(genv) if @else_clause
390
+ @ensure_clause.undefine(genv) if @ensure_clause
391
+ end
392
+
393
+ def install0(genv)
394
+ ret = Vertex.new(self)
395
+ @changes.add_edge(genv, @body.install(genv), ret)
396
+ @rescue_conds.each {|cond| cond.install(genv) }
397
+ @rescue_clauses.each {|clause| @changes.add_edge(genv, clause.install(genv), ret) }
398
+ @changes.add_edge(genv, @else_clause.install(genv), ret) if @else_clause
399
+ @ensure_clause.install(genv) if @ensure_clause
400
+ ret
401
+ end
402
+ end
403
+
404
+ class RetryNode < Node
405
+ def initialize(raw_node, lenv)
406
+ super(raw_node, lenv)
407
+ end
408
+
409
+ def install0(genv)
410
+ Source.new(Type::Bot.new(genv))
411
+ end
412
+ end
413
+
414
+ class RescueModifierNode < Node
415
+ def initialize(raw_node, lenv)
416
+ super(raw_node, lenv)
417
+ @expression = AST.create_node(raw_node.expression, lenv)
418
+ @rescue_expression = AST.create_node(raw_node.rescue_expression, lenv)
419
+ end
420
+
421
+ attr_reader :expression, :rescue_expression
422
+
423
+ def subnodes = { expression:, rescue_expression: }
424
+
425
+ def install0(genv)
426
+ ret = Vertex.new(self)
427
+ @changes.add_edge(genv, @expression.install(genv), ret)
428
+ @changes.add_edge(genv, @rescue_expression.install(genv), ret)
429
+ ret
430
+ end
431
+ end
432
+ end
433
+ end
@@ -0,0 +1,150 @@
1
+ module TypeProf::Core
2
+ class AST
3
+ class IncludeMetaNode < Node
4
+ def initialize(raw_node, lenv)
5
+ super(raw_node, lenv)
6
+ # TODO: error for splat
7
+ @args = raw_node.arguments.arguments.map do |raw_arg|
8
+ next if raw_arg.is_a?(Prism::SplatNode)
9
+ AST.create_node(raw_arg, lenv)
10
+ end.compact
11
+ # TODO: error for non-LIT
12
+ # TODO: fine-grained hover
13
+ end
14
+
15
+ attr_reader :args
16
+
17
+ def subnodes = { args: }
18
+
19
+ def define0(genv)
20
+ mod = genv.resolve_cpath(@lenv.cref.cpath)
21
+ @args.each do |arg|
22
+ arg.define(genv)
23
+ if arg.static_ret
24
+ arg.static_ret.followers << mod
25
+ mod.add_include_def(genv, arg)
26
+ end
27
+ end
28
+ end
29
+
30
+ def undefine0(genv)
31
+ mod = genv.resolve_cpath(@lenv.cref.cpath)
32
+ @args.each do |arg|
33
+ if arg.static_ret
34
+ mod.remove_include_def(genv, arg)
35
+ end
36
+ arg.undefine(genv)
37
+ end
38
+ super(genv)
39
+ end
40
+
41
+ def install0(genv)
42
+ @args.each {|arg| arg.install(genv) }
43
+ Source.new
44
+ end
45
+ end
46
+
47
+ class AttrReaderMetaNode < Node
48
+ def initialize(raw_node, lenv)
49
+ super(raw_node, lenv)
50
+ @args = []
51
+ raw_node.arguments.arguments.each do |raw_arg|
52
+ @args << raw_arg.value.to_sym if raw_arg.type == :symbol_node
53
+ end
54
+ # TODO: error for non-LIT
55
+ # TODO: fine-grained hover
56
+ end
57
+
58
+ attr_reader :args
59
+
60
+ def attrs = { args: }
61
+
62
+ def req_positionals = []
63
+ def opt_positionals = []
64
+ def post_positionals = []
65
+ def rest_positionals = nil
66
+ def req_keywords = []
67
+ def opt_keywords = []
68
+ def rest_keywords = nil
69
+
70
+ def mname_code_range(name)
71
+ idx = @args.index(name.to_sym) # TODO: support string args
72
+ node = @raw_node.arguments.arguments[idx].location
73
+ TypeProf::CodeRange.from_node(node)
74
+ end
75
+
76
+ def install0(genv)
77
+ @args.each do |arg|
78
+ ivar_name = :"@#{ arg }"
79
+ ivar_box = @changes.add_ivar_read_box(genv, @lenv.cref.cpath, false, ivar_name)
80
+ e_ret = Vertex.new(self)
81
+ ret_box = @changes.add_escape_box(genv, ivar_box.ret, e_ret)
82
+ @changes.add_method_def_box(genv, @lenv.cref.cpath, false, arg, FormalArguments::Empty, [ret_box])
83
+ end
84
+ Source.new
85
+ end
86
+ end
87
+
88
+ class AttrAccessorMetaNode < Node
89
+ def initialize(raw_node, lenv)
90
+ super(raw_node, lenv)
91
+ @args = []
92
+ raw_node.arguments.arguments.each do |raw_arg|
93
+ @args << raw_arg.value.to_sym if raw_arg.type == :symbol_node
94
+ end
95
+ # TODO: error for non-LIT
96
+ # TODO: fine-grained hover
97
+ end
98
+
99
+ attr_reader :args
100
+
101
+ def attrs = { args: }
102
+
103
+ def mname_code_range(name)
104
+ idx = @args.index(name.to_sym) # TODO: support string args
105
+ node = @raw_node.arguments.arguments[idx].location
106
+ TypeProf::CodeRange.from_node(node)
107
+ end
108
+
109
+ def define0(genv)
110
+ @args.map do |arg|
111
+ mod = genv.resolve_ivar(lenv.cref.cpath, false, :"@#{ arg }")
112
+ mod.add_def(self)
113
+ mod
114
+ end
115
+ end
116
+
117
+ def define_copy(genv)
118
+ @args.map do |arg|
119
+ mod = genv.resolve_ivar(lenv.cref.cpath, false, :"@#{ arg }")
120
+ mod.add_def(self)
121
+ mod.remove_def(@prev_node)
122
+ mod
123
+ end
124
+ super(genv)
125
+ end
126
+
127
+ def undefine0(genv)
128
+ @args.each do |arg|
129
+ mod = genv.resolve_ivar(lenv.cref.cpath, false, :"@#{ arg }")
130
+ mod.remove_def(self)
131
+ end
132
+ end
133
+
134
+ def install0(genv)
135
+ @args.zip(@static_ret) do |arg, ive|
136
+ ivar_box = @changes.add_ivar_read_box(genv, @lenv.cref.cpath, false, :"@#{ arg }")
137
+ e_ret = Vertex.new(self)
138
+ ret_box = @changes.add_escape_box(genv, ivar_box.ret, e_ret)
139
+ @changes.add_method_def_box(genv, @lenv.cref.cpath, false, arg, FormalArguments::Empty, [ret_box])
140
+
141
+ vtx = Vertex.new(self)
142
+ @changes.add_edge(genv, vtx, ive.vtx)
143
+ f_args = FormalArguments.new([vtx], [], nil, [], [], [], nil, nil)
144
+ @changes.add_method_def_box(genv, @lenv.cref.cpath, false, :"#{ arg }=", f_args, [ret_box])
145
+ end
146
+ Source.new
147
+ end
148
+ end
149
+ end
150
+ end