typeprof 0.21.11 → 0.30.1

Sign up to get free protection for your applications and to get access to all the features.
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