typeprof 0.21.11 → 0.30.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) 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 +180 -0
  7. data/lib/typeprof/cli.rb +2 -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 +251 -0
  11. data/lib/typeprof/core/ast/const.rb +126 -0
  12. data/lib/typeprof/core/ast/control.rb +432 -0
  13. data/lib/typeprof/core/ast/meta.rb +150 -0
  14. data/lib/typeprof/core/ast/method.rb +335 -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 +360 -0
  31. data/lib/typeprof/core/graph/box.rb +991 -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 +222 -0
  35. data/lib/typeprof/core/graph.rb +3 -0
  36. data/lib/typeprof/core/service.rb +522 -0
  37. data/lib/typeprof/core/type.rb +348 -0
  38. data/lib/typeprof/core/util.rb +81 -0
  39. data/lib/typeprof/core.rb +32 -0
  40. data/lib/typeprof/diagnostic.rb +35 -0
  41. data/lib/typeprof/lsp/messages.rb +430 -0
  42. data/lib/typeprof/lsp/server.rb +177 -0
  43. data/lib/typeprof/lsp/text.rb +69 -0
  44. data/lib/typeprof/lsp/util.rb +61 -0
  45. data/lib/typeprof/lsp.rb +4 -907
  46. data/lib/typeprof/version.rb +1 -1
  47. data/lib/typeprof.rb +4 -18
  48. data/typeprof.gemspec +5 -7
  49. metadata +48 -35
  50. data/.github/dependabot.yml +0 -6
  51. data/.github/workflows/main.yml +0 -39
  52. data/.gitignore +0 -9
  53. data/Gemfile +0 -17
  54. data/Gemfile.lock +0 -41
  55. data/Rakefile +0 -10
  56. data/exe/typeprof +0 -10
  57. data/lib/typeprof/analyzer.rb +0 -2598
  58. data/lib/typeprof/arguments.rb +0 -414
  59. data/lib/typeprof/block.rb +0 -176
  60. data/lib/typeprof/builtin.rb +0 -893
  61. data/lib/typeprof/code-range.rb +0 -177
  62. data/lib/typeprof/config.rb +0 -158
  63. data/lib/typeprof/container-type.rb +0 -912
  64. data/lib/typeprof/export.rb +0 -589
  65. data/lib/typeprof/import.rb +0 -852
  66. data/lib/typeprof/insns-def.rb +0 -65
  67. data/lib/typeprof/iseq.rb +0 -864
  68. data/lib/typeprof/method.rb +0 -355
  69. data/lib/typeprof/type.rb +0 -1140
  70. data/lib/typeprof/utils.rb +0 -212
  71. data/tools/coverage.rb +0 -14
  72. data/tools/setup-insns-def.rb +0 -30
  73. 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,432 @@
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 = raw_node.arguments ? AST.create_node(raw_node.arguments.arguments.first, lenv) : nil
180
+ end
181
+
182
+ attr_reader :arg
183
+
184
+ def subnodes = { arg: }
185
+
186
+ def install0(genv)
187
+ _arg = @arg ? @arg.install(genv) : Source.new(genv.nil_type)
188
+ # TODO: implement!
189
+ end
190
+ end
191
+
192
+ def self.parse_return_arguments(raw_node, lenv, code_range)
193
+ if raw_node.arguments
194
+ elems = raw_node.arguments.arguments
195
+ if elems.one?
196
+ AST.create_node(elems.first, lenv)
197
+ else
198
+ ArrayNode.new(raw_node.arguments, lenv, elems)
199
+ end
200
+ else
201
+ DummyNilNode.new(code_range, lenv)
202
+ end
203
+ end
204
+
205
+ class NextNode < Node
206
+ def initialize(raw_node, lenv)
207
+ super(raw_node, lenv)
208
+ @arg = AST.parse_return_arguments(raw_node, lenv, code_range)
209
+ end
210
+
211
+ attr_reader :arg
212
+
213
+ def subnodes = { arg: }
214
+
215
+ def install0(genv)
216
+ @arg.install(genv)
217
+ if @lenv.exist_var?(:"*expected_block_ret")
218
+ @lenv.add_next_box(@changes.add_escape_box(genv, @arg.ret, @lenv.get_var(:"*expected_block_ret")))
219
+ end
220
+ Source.new(Type::Bot.new(genv))
221
+ end
222
+ end
223
+
224
+ class RedoNode < Node
225
+ def initialize(raw_node, lenv)
226
+ super(raw_node, lenv)
227
+ end
228
+
229
+ def install0(genv)
230
+ # TODO: This should return a bot type
231
+ Source.new()
232
+ end
233
+ end
234
+
235
+ class CaseNode < Node
236
+ def initialize(raw_node, lenv)
237
+ super(raw_node, lenv)
238
+ @pivot = raw_node.predicate ? AST.create_node(raw_node.predicate, lenv) : nil
239
+ @whens = []
240
+ @clauses = []
241
+ raw_node.conditions.each do |raw_cond|
242
+ @whens << AST.create_node(raw_cond.conditions.first, lenv) # XXX: multiple conditions
243
+ @clauses << (raw_cond.statements ? AST.create_node(raw_cond.statements, lenv) : DummyNilNode.new(code_range, lenv)) # TODO: code_range for NilNode
244
+ end
245
+ @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
+ end
247
+
248
+ attr_reader :pivot, :whens, :clauses, :else_clause
249
+
250
+ def subnodes = { pivot:, whens:, clauses:, else_clause: }
251
+
252
+ def install0(genv)
253
+ ret = Vertex.new(self)
254
+ @pivot&.install(genv)
255
+ @whens.zip(@clauses) do |vals, clause|
256
+ vals.install(genv)
257
+ @changes.add_edge(genv, clause.install(genv), ret)
258
+ end
259
+ @changes.add_edge(genv, @else_clause.install(genv), ret)
260
+ ret
261
+ end
262
+ end
263
+
264
+ class CaseMatchNode < Node
265
+ def initialize(raw_node, lenv)
266
+ super(raw_node, lenv)
267
+ @pivot = AST.create_node(raw_node.predicate, lenv)
268
+ @patterns = []
269
+ @clauses = []
270
+ raw_node.conditions.each do |raw_cond|
271
+ raise if raw_cond.type != :in_node
272
+ @patterns << AST.create_pattern_node(raw_cond.pattern, lenv)
273
+ @clauses << (raw_cond.statements ? AST.create_node(raw_cond.statements, lenv) : DummyNilNode.new(code_range, lenv)) # TODO: code_range for NilNode
274
+ end
275
+ @else_clause = raw_node.else_clause && raw_node.else_clause.statements ? AST.create_node(raw_node.else_clause.statements, lenv) : nil
276
+ end
277
+
278
+ attr_reader :pivot, :patterns, :clauses, :else_clause
279
+
280
+ def subnodes = { pivot:, patterns:, clauses:, else_clause: }
281
+
282
+ def install0(genv)
283
+ ret = Vertex.new(self)
284
+ @pivot&.install(genv)
285
+ @patterns.zip(@clauses) do |pattern, clause|
286
+ pattern.install(genv)
287
+ @changes.add_edge(genv, clause.install(genv), ret)
288
+ end
289
+ @changes.add_edge(genv, @else_clause.install(genv), ret) if @else_clause
290
+ ret
291
+ end
292
+ end
293
+
294
+ class AndNode < Node
295
+ def initialize(raw_node, e1 = nil, raw_e2 = nil, lenv)
296
+ super(raw_node, lenv)
297
+ @e1 = e1 || AST.create_node(raw_node.left, lenv)
298
+ @e2 = AST.create_node(raw_e2 || raw_node.right, lenv)
299
+ end
300
+
301
+ attr_reader :e1, :e2
302
+
303
+ def subnodes = { e1:, e2: }
304
+
305
+ def install0(genv)
306
+ ret = Vertex.new(self)
307
+ @changes.add_edge(genv, @e1.install(genv), ret)
308
+ @changes.add_edge(genv, @e2.install(genv), ret)
309
+ ret
310
+ end
311
+ end
312
+
313
+ class OrNode < Node
314
+ def initialize(raw_node, e1 = nil, raw_e2 = nil, lenv)
315
+ super(raw_node, lenv)
316
+ @e1 = e1 || AST.create_node(raw_node.left, lenv)
317
+ @e2 = AST.create_node(raw_e2 || raw_node.right, lenv)
318
+ end
319
+
320
+ attr_reader :e1, :e2
321
+
322
+ def subnodes = { e1:, e2: }
323
+
324
+ def install0(genv)
325
+ ret = Vertex.new(self)
326
+ v1 = @e1.install(genv)
327
+ v1 = NilFilter.new(genv, self, v1, false).next_vtx
328
+ @changes.add_edge(genv, v1, ret)
329
+ @changes.add_edge(genv, @e2.install(genv), ret)
330
+ ret
331
+ end
332
+ end
333
+
334
+ class ReturnNode < Node
335
+ def initialize(raw_node, lenv)
336
+ super(raw_node, lenv)
337
+ @arg = AST.parse_return_arguments(raw_node, lenv, code_range)
338
+ end
339
+
340
+ attr_reader :arg
341
+
342
+ def subnodes = { arg: }
343
+
344
+ def install0(genv)
345
+ @arg.install(genv)
346
+ e_ret = @lenv.locals[:"*expected_method_ret"]
347
+ @lenv.add_return_box(@changes.add_escape_box(genv, @arg.ret, e_ret)) if e_ret
348
+ Source.new(Type::Bot.new(genv))
349
+ end
350
+ end
351
+
352
+ class BeginNode < Node
353
+ def initialize(raw_node, lenv)
354
+ super(raw_node, lenv)
355
+ @body = raw_node.statements ? AST.create_node(raw_node.statements, lenv) : DummyNilNode.new(code_range, lenv)
356
+ @rescue_conds = []
357
+ @rescue_clauses = []
358
+ raw_res = raw_node.rescue_clause
359
+ while raw_res
360
+ raw_res.exceptions.each do |raw_cond|
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
366
+ raw_res = raw_res.subsequent
367
+ end
368
+ @else_clause = raw_node.else_clause ? AST.create_node(raw_node.else_clause.statements, lenv) : DummyNilNode.new(code_range, lenv)
369
+ @ensure_clause = raw_node.ensure_clause ? AST.create_node(raw_node.ensure_clause.statements, lenv) : DummyNilNode.new(code_range, lenv)
370
+ end
371
+
372
+ attr_reader :body, :rescue_conds, :rescue_clauses, :else_clause, :ensure_clause
373
+
374
+ def subnodes = { body:, rescue_conds:, rescue_clauses:, else_clause:, ensure_clause: }
375
+
376
+ def define0(genv)
377
+ @body.define(genv)
378
+ @rescue_conds.each {|cond| cond.define(genv) }
379
+ @rescue_clauses.each {|clause| clause.define(genv) }
380
+ @else_clause.define(genv) if @else_clause
381
+ @ensure_clause.define(genv) if @ensure_clause
382
+ end
383
+
384
+ def undefine0(genv)
385
+ @body.undefine(genv)
386
+ @rescue_conds.each {|cond| cond.undefine(genv) }
387
+ @rescue_clauses.each {|clause| clause.undefine(genv) }
388
+ @else_clause.undefine(genv) if @else_clause
389
+ @ensure_clause.undefine(genv) if @ensure_clause
390
+ end
391
+
392
+ def install0(genv)
393
+ ret = Vertex.new(self)
394
+ @changes.add_edge(genv, @body.install(genv), ret)
395
+ @rescue_conds.each {|cond| cond.install(genv) }
396
+ @rescue_clauses.each {|clause| @changes.add_edge(genv, clause.install(genv), ret) }
397
+ @changes.add_edge(genv, @else_clause.install(genv), ret) if @else_clause
398
+ @ensure_clause.install(genv) if @ensure_clause
399
+ ret
400
+ end
401
+ end
402
+
403
+ class RetryNode < Node
404
+ def initialize(raw_node, lenv)
405
+ super(raw_node, lenv)
406
+ end
407
+
408
+ def install0(genv)
409
+ Source.new(Type::Bot.new(genv))
410
+ end
411
+ end
412
+
413
+ class RescueModifierNode < Node
414
+ def initialize(raw_node, lenv)
415
+ super(raw_node, lenv)
416
+ @expression = AST.create_node(raw_node.expression, lenv)
417
+ @rescue_expression = AST.create_node(raw_node.rescue_expression, lenv)
418
+ end
419
+
420
+ attr_reader :expression, :rescue_expression
421
+
422
+ def subnodes = { expression:, rescue_expression: }
423
+
424
+ def install0(genv)
425
+ ret = Vertex.new(self)
426
+ @changes.add_edge(genv, @expression.install(genv), ret)
427
+ @changes.add_edge(genv, @rescue_expression.install(genv), ret)
428
+ ret
429
+ end
430
+ end
431
+ end
432
+ 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