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,319 @@
1
+ module TypeProf::Core
2
+ class AST
3
+ def self.create_part_node(raw_part, lenv)
4
+ case raw_part.type
5
+ when :string_node
6
+ AST.create_node(raw_part, lenv)
7
+ when :embedded_statements_node
8
+ AST.create_node(raw_part.statements, lenv)
9
+ when :embedded_variable_node
10
+ AST.create_node(raw_part.variable, lenv)
11
+ else
12
+ raise "unknown symbol part: #{ raw_part.type }"
13
+ end
14
+ end
15
+
16
+ class SelfNode < Node
17
+ def install0(genv)
18
+ @lenv.get_var(:"*self")
19
+ end
20
+ end
21
+
22
+ class LiteralNode < Node
23
+ def initialize(raw_node, lenv, lit)
24
+ super(raw_node, lenv)
25
+ @lit = lit
26
+ end
27
+
28
+ attr_reader :lit
29
+
30
+ def attrs = { lit: }
31
+
32
+ def install0(genv)
33
+ raise "not supported yet: #{ @lit.inspect }"
34
+ end
35
+ end
36
+
37
+ class NilNode < LiteralNode
38
+ def initialize(raw_node, lenv)
39
+ super(raw_node, lenv, nil)
40
+ end
41
+
42
+ def install0(genv) = Source.new(genv.nil_type)
43
+ end
44
+
45
+ class TrueNode < LiteralNode
46
+ def initialize(raw_node, lenv)
47
+ super(raw_node, lenv, true)
48
+ end
49
+
50
+ def install0(genv) = Source.new(genv.true_type)
51
+ end
52
+
53
+ class FalseNode < LiteralNode
54
+ def initialize(raw_node, lenv)
55
+ super(raw_node, lenv, false)
56
+ end
57
+
58
+ def install0(genv) = Source.new(genv.false_type)
59
+ end
60
+
61
+ class IntegerNode < LiteralNode
62
+ def initialize(raw_node, lenv, lit = raw_node.slice)
63
+ super(raw_node, lenv, Integer(lit))
64
+ end
65
+
66
+ def install0(genv) = Source.new(genv.int_type)
67
+ end
68
+
69
+ class FloatNode < LiteralNode
70
+ def initialize(raw_node, lenv)
71
+ super(raw_node, lenv, Float(raw_node.slice))
72
+ end
73
+
74
+ def install0(genv) = Source.new(genv.float_type)
75
+ end
76
+
77
+ class RationalNode < LiteralNode
78
+ def initialize(raw_node, lenv)
79
+ super(raw_node, lenv, raw_node.slice.to_r)
80
+ end
81
+
82
+ def install0(genv) = Source.new(genv.rational_type)
83
+ end
84
+
85
+ class ComplexNode < LiteralNode
86
+ def initialize(raw_node, lenv)
87
+ super(raw_node, lenv, raw_node.slice.to_c)
88
+ end
89
+
90
+ def install0(genv) = Source.new(genv.complex_type)
91
+ end
92
+
93
+ class SymbolNode < LiteralNode
94
+ def initialize(raw_node, lenv)
95
+ super(raw_node, lenv, raw_node.value.to_sym)
96
+ end
97
+
98
+ def install0(genv) = Source.new(Type::Symbol.new(genv, @lit))
99
+ end
100
+
101
+ class InterpolatedSymbolNode < Node
102
+ def initialize(raw_node, lenv)
103
+ super(raw_node, lenv)
104
+ @parts = raw_node.parts.map do |raw_part|
105
+ AST.create_part_node(raw_part, lenv)
106
+ end
107
+ end
108
+
109
+ attr_reader :parts
110
+
111
+ def subnodes = { parts: }
112
+
113
+ def install0(genv)
114
+ @parts.each do |subnode|
115
+ subnode.install(genv)
116
+ end
117
+ Source.new(genv.symbol_type)
118
+ end
119
+ end
120
+
121
+ class StringNode < LiteralNode
122
+ def initialize(raw_node, lenv, content)
123
+ super(raw_node, lenv, content)
124
+ end
125
+
126
+ def install0(genv) = Source.new(genv.str_type)
127
+ end
128
+
129
+ class InterpolatedStringNode < Node
130
+ def initialize(raw_node, lenv)
131
+ super(raw_node, lenv)
132
+ @parts = []
133
+
134
+ queue = raw_node.parts.dup
135
+
136
+ until queue.empty?
137
+ raw_part = queue.shift
138
+
139
+ if raw_part.type == :interpolated_string_node
140
+ queue.unshift(*raw_part.parts)
141
+ else
142
+ @parts << AST.create_part_node(raw_part, lenv)
143
+ end
144
+ end
145
+ end
146
+
147
+ attr_reader :parts
148
+
149
+ def subnodes = { parts: }
150
+
151
+ def install0(genv)
152
+ @parts.each do |subnode|
153
+ subnode.install(genv)
154
+ end
155
+ Source.new(genv.str_type)
156
+ end
157
+ end
158
+
159
+ class RegexpNode < Node
160
+ def initialize(raw_node, lenv)
161
+ super(raw_node, lenv)
162
+ end
163
+
164
+ def install0(genv) = Source.new(genv.regexp_type)
165
+ end
166
+
167
+ class InterpolatedRegexpNode < Node
168
+ def initialize(raw_node, lenv)
169
+ super(raw_node, lenv)
170
+ @parts = raw_node.parts.map do |raw_part|
171
+ AST.create_part_node(raw_part, lenv)
172
+ end
173
+ end
174
+
175
+ attr_reader :parts
176
+
177
+ def subnodes = { parts: }
178
+
179
+ def install0(genv)
180
+ @parts.each do |subnode|
181
+ subnode.install(genv)
182
+ end
183
+ Source.new(genv.regexp_type)
184
+ end
185
+ end
186
+
187
+ class MatchLastLineNode < Node
188
+ def initialize(raw_node, lenv)
189
+ super(raw_node, lenv)
190
+ end
191
+
192
+ def install0(genv) = Source.new(genv.true_type, genv.false_type)
193
+ end
194
+
195
+ class InterpolatedMatchLastLineNode < Node
196
+ def initialize(raw_node, lenv)
197
+ super(raw_node, lenv)
198
+ @parts = raw_node.parts.map do |raw_part|
199
+ AST.create_part_node(raw_part, lenv)
200
+ end
201
+ end
202
+
203
+ attr_reader :parts
204
+
205
+ def subnodes = { parts: }
206
+
207
+ def install0(genv)
208
+ @parts.each do |subnode|
209
+ subnode.install(genv)
210
+ end
211
+ Source.new(genv.true_type, genv.false_type)
212
+ end
213
+ end
214
+
215
+ class RangeNode < Node
216
+ def initialize(raw_node, lenv)
217
+ super(raw_node, lenv)
218
+ @begin = raw_node.left ? AST.create_node(raw_node.left, lenv) : DummyNilNode.new(raw_node, lenv)
219
+ @end = raw_node.right ? AST.create_node(raw_node.right, lenv) : DummyNilNode.new(raw_node, lenv)
220
+ end
221
+
222
+ attr_reader :begin, :end
223
+
224
+ def subnodes = { begin:, end: }
225
+
226
+ def install0(genv)
227
+ elem = Vertex.new(self)
228
+ @changes.add_edge(genv, @begin.install(genv), elem)
229
+ @changes.add_edge(genv, @end.install(genv), elem)
230
+ Source.new(genv.gen_range_type(elem))
231
+ end
232
+ end
233
+
234
+ class ArrayNode < Node
235
+ def initialize(raw_node, lenv, elems = raw_node.elements)
236
+ super(raw_node, lenv)
237
+ @elems = elems.map {|n| AST.create_node(n, lenv) }
238
+ @splat = @elems.any? {|e| e.is_a?(SplatNode) }
239
+ end
240
+
241
+ attr_reader :elems, :splat
242
+
243
+ def subnodes = { elems: }
244
+ def attrs = { splat: }
245
+
246
+ def install0(genv)
247
+ elems = @elems.map {|e| e.install(genv).new_vertex(genv, self) }
248
+ unified_elem = Vertex.new(self)
249
+ elems.each {|vtx| @changes.add_edge(genv, vtx, unified_elem) }
250
+ base_ty = genv.gen_ary_type(unified_elem)
251
+ if @splat
252
+ Source.new(base_ty)
253
+ else
254
+ Source.new(Type::Array.new(genv, elems, base_ty))
255
+ end
256
+ end
257
+ end
258
+
259
+ class HashNode < Node
260
+ def initialize(raw_node, lenv, keywords)
261
+ super(raw_node, lenv)
262
+ @keys = []
263
+ @vals = []
264
+ @keywords = keywords
265
+ @splat = false
266
+
267
+ raw_node.elements.each do |raw_elem|
268
+ # TODO: Support :assoc_splat_node
269
+ case raw_elem.type
270
+ when :assoc_node
271
+ @keys << AST.create_node(raw_elem.key, lenv)
272
+ @vals << AST.create_node(raw_elem.value, lenv)
273
+ when :assoc_splat_node
274
+ @keys << nil
275
+ @vals << AST.create_node(raw_elem.value, lenv)
276
+ @splat = true
277
+ else
278
+ raise "unknown hash elem: #{ raw_elem.type }"
279
+ end
280
+ end
281
+ end
282
+
283
+ attr_reader :keys, :vals, :splat, :keywords
284
+
285
+ def subnodes = { keys:, vals: }
286
+ def attrs = { splat:, keywords: }
287
+
288
+ def install0(genv)
289
+ unified_key = Vertex.new(self)
290
+ unified_val = Vertex.new(self)
291
+ literal_pairs = {}
292
+ @keys.zip(@vals) do |key, val|
293
+ if key
294
+ k = key.install(genv).new_vertex(genv, self)
295
+ v = val.install(genv).new_vertex(genv, self)
296
+ @changes.add_edge(genv, k, unified_key)
297
+ @changes.add_edge(genv, v, unified_val)
298
+ literal_pairs[key.lit] = v if key.is_a?(SymbolNode)
299
+ else
300
+ h = val.install(genv)
301
+ # TODO: do we want to call to_hash on h?
302
+ @changes.add_hash_splat_box(genv, h, unified_key, unified_val)
303
+ end
304
+ end
305
+ if @splat
306
+ Source.new(genv.gen_hash_type(unified_key, unified_val))
307
+ else
308
+ Source.new(Type::Hash.new(genv, literal_pairs, genv.gen_hash_type(unified_key, unified_val)))
309
+ end
310
+ end
311
+ end
312
+
313
+ class LambdaNode < Node
314
+ def install0(genv)
315
+ Source.new(genv.proc_type)
316
+ end
317
+ end
318
+ end
319
+ end
@@ -0,0 +1,315 @@
1
+ module TypeProf::Core
2
+ class AST
3
+ class LocalVariableReadNode < Node
4
+ def initialize(raw_node, lenv)
5
+ super(raw_node, lenv)
6
+ @var = raw_node.name
7
+ end
8
+
9
+ attr_reader :var
10
+
11
+ def attrs = { var: }
12
+
13
+ def install0(genv)
14
+ @lenv.get_var(@var)
15
+ end
16
+
17
+ def retrieve_at(pos)
18
+ yield self if code_range.include?(pos)
19
+ end
20
+ end
21
+
22
+ class LocalVariableWriteNode < Node
23
+ def initialize(raw_node, rhs, lenv)
24
+ super(raw_node, lenv)
25
+ @var = raw_node.name
26
+ @var_code_range = TypeProf::CodeRange.from_node(raw_node.respond_to?(:name_loc) ? raw_node.name_loc : raw_node)
27
+ @rhs = rhs
28
+ end
29
+
30
+ attr_reader :var, :var_code_range, :rhs
31
+
32
+ def subnodes = { rhs: }
33
+ def attrs = { var: }
34
+
35
+ def install0(genv)
36
+ val = @rhs.install(genv)
37
+
38
+ vtx = @lenv.new_var(@var, self)
39
+ @changes.add_edge(genv, val, vtx)
40
+ val
41
+ end
42
+
43
+ def retrieve_at(pos, &blk)
44
+ yield self if @var_code_range && @var_code_range.include?(pos)
45
+ super(pos, &blk)
46
+ end
47
+
48
+ def modified_vars(tbl, vars)
49
+ vars << self.var if tbl.include?(self.var)
50
+ end
51
+ end
52
+
53
+ class InstanceVariableReadNode < Node
54
+ def initialize(raw_node, lenv)
55
+ super(raw_node, lenv)
56
+ @var = raw_node.name
57
+ end
58
+
59
+ attr_reader :var
60
+
61
+ def attrs = { var: }
62
+
63
+ def install0(genv)
64
+ case @lenv.cref.scope_level
65
+ when :class, :instance
66
+ box = @changes.add_ivar_read_box(genv, lenv.cref.cpath, lenv.cref.scope_level == :class, @var)
67
+ @lenv.apply_read_filter(genv, self, @var, box.ret)
68
+ else
69
+ Source.new()
70
+ end
71
+ end
72
+
73
+ def retrieve_at(pos)
74
+ yield self if code_range.include?(pos)
75
+ end
76
+ end
77
+
78
+ class InstanceVariableWriteNode < Node
79
+ def initialize(raw_node, rhs, lenv)
80
+ super(raw_node, lenv)
81
+ @var = raw_node.name
82
+ @var_code_range = TypeProf::CodeRange.from_node(raw_node.respond_to?(:name_loc) ? raw_node.name_loc : raw_node)
83
+ @rhs = rhs
84
+ end
85
+
86
+ attr_reader :var, :var_code_range, :rhs
87
+
88
+ def subnodes = { rhs: }
89
+ def attrs = { var: }
90
+
91
+ def define0(genv)
92
+ @rhs.define(genv) if @rhs
93
+ case @lenv.cref.scope_level
94
+ when :class, :instance
95
+ val = genv.resolve_ivar(@lenv.cref.cpath, @lenv.cref.scope_level == :class, @var)
96
+ val.add_def(self)
97
+ val
98
+ else
99
+ # TODO: warn
100
+ nil
101
+ end
102
+ end
103
+
104
+ def define_copy(genv)
105
+ case @lenv.cref.scope_level
106
+ when :class, :instance
107
+ val = genv.resolve_ivar(@lenv.cref.cpath, @lenv.cref.scope_level == :class, @var)
108
+ val.add_def(self)
109
+ val.remove_def(@prev_node)
110
+ end
111
+ super(genv)
112
+ end
113
+
114
+ def undefine0(genv)
115
+ case @lenv.cref.scope_level
116
+ when :class, :instance
117
+ val = genv.resolve_ivar(@lenv.cref.cpath, @lenv.cref.scope_level == :class, @var)
118
+ val.remove_def(self)
119
+ end
120
+ @rhs.undefine(genv) if @rhs
121
+ end
122
+
123
+ def install0(genv)
124
+ val = @rhs.install(genv)
125
+ case @lenv.cref.scope_level
126
+ when :class, :instance
127
+ @changes.add_ivar_read_box(genv, @lenv.cref.cpath, @lenv.cref.scope_level == :class, @var)
128
+ val = val.new_vertex(genv, self) # avoid multi-edge from val to static_ret.vtx
129
+ @changes.add_edge(genv, val, @static_ret.vtx)
130
+ end
131
+ val
132
+ end
133
+
134
+ def retrieve_at(pos, &blk)
135
+ yield self if @var_code_range && @var_code_range.include?(pos)
136
+ super(pos, &blk)
137
+ end
138
+ end
139
+
140
+ class GlobalVariableReadNode < Node
141
+ def initialize(raw_node, lenv)
142
+ super(raw_node, lenv)
143
+ @var = raw_node.name
144
+ end
145
+
146
+ attr_reader :var
147
+
148
+ def attrs = { var: }
149
+
150
+ def install0(genv)
151
+ box = @changes.add_gvar_read_box(genv, @var)
152
+ box.ret
153
+ end
154
+
155
+ def retrieve_at(pos)
156
+ yield self if code_range.include?(pos)
157
+ end
158
+ end
159
+
160
+ class GlobalVariableWriteNode < Node
161
+ def initialize(raw_node, rhs, lenv)
162
+ super(raw_node, lenv)
163
+ @var = raw_node.name
164
+ @var_code_range = TypeProf::CodeRange.from_node(raw_node.respond_to?(:name_loc) ? raw_node.name_loc : raw_node)
165
+ @rhs = rhs
166
+ end
167
+
168
+ attr_reader :var, :var_code_range, :rhs
169
+
170
+ def subnodes = { rhs: }
171
+ def attrs = { var: }
172
+
173
+ def define0(genv)
174
+ @rhs.define(genv) if @rhs
175
+ val = genv.resolve_gvar(@var)
176
+ val.add_def(self)
177
+ val
178
+ end
179
+
180
+ def define_copy(genv)
181
+ val = genv.resolve_gvar(@var)
182
+ val.add_def(self)
183
+ val.remove_def(@prev_node)
184
+ super(genv)
185
+ end
186
+
187
+ def undefine0(genv)
188
+ val = genv.resolve_gvar(@var)
189
+ val.remove_def(self)
190
+ @rhs.undefine(genv) if @rhs
191
+ end
192
+
193
+ def install0(genv)
194
+ val = @rhs.install(genv)
195
+ val = val.new_vertex(genv, self) # avoid multi-edge from val to static_ret.vtx
196
+ @changes.add_edge(genv, val, @static_ret.vtx)
197
+ val
198
+ end
199
+
200
+ def retrieve_at(pos, &blk)
201
+ yield self if @var_code_range && @var_code_range.include?(pos)
202
+ super(pos, &blk)
203
+ end
204
+ end
205
+
206
+ class AliasGlobalVariableNode < Node
207
+ def initialize(raw_node, lenv)
208
+ super(raw_node, lenv)
209
+ # XXX: Who use this? I want to hard-code English.rb
210
+ end
211
+
212
+ def install0(genv)
213
+ Source.new(genv.nil_type)
214
+ end
215
+ end
216
+
217
+ class PostExecutionNode < Node
218
+ def initialize(raw_node, lenv)
219
+ super(raw_node, lenv)
220
+ @body = raw_node.statements ? AST.create_node(raw_node.statements, lenv) : DummyNilNode.new(TypeProf::CodeRange.new(code_range.last, code_range.last), lenv)
221
+ end
222
+
223
+ attr_reader :body
224
+
225
+ def subnodes = { body: }
226
+
227
+ def install0(genv)
228
+ @body.install(genv)
229
+ Source.new(genv.nil_type)
230
+ end
231
+ end
232
+
233
+ class ClassVariableWriteNode < Node
234
+ def initialize(raw_node, rhs, lenv)
235
+ super(raw_node, lenv)
236
+ @var = raw_node.name
237
+ @var_code_range = TypeProf::CodeRange.from_node(raw_node.respond_to?(:name_loc) ? raw_node.name_loc : raw_node)
238
+ @rhs = rhs
239
+ end
240
+
241
+ attr_reader :var, :var_code_range, :rhs
242
+
243
+ def subnodes = { rhs: }
244
+ def attrs = { var: }
245
+
246
+ def define0(genv)
247
+ @rhs.define(genv) if @rhs
248
+ mod = genv.resolve_cvar(@lenv.cref.cpath, @var)
249
+ mod.add_def(self)
250
+ mod
251
+ end
252
+
253
+ def define_copy(genv)
254
+ mod = genv.resolve_cvar(@lenv.cref.cpath, @var)
255
+ mod.add_def(self)
256
+ mod.remove_def(@prev_node)
257
+ super(genv)
258
+ end
259
+
260
+ def undefine0(genv)
261
+ mod = genv.resolve_cvar(@lenv.cref.cpath, @var)
262
+ mod.remove_def(self)
263
+ @rhs.undefine(genv) if @rhs
264
+ end
265
+
266
+ def install0(genv)
267
+ @changes.add_cvar_read_box(genv, @lenv.cref.cpath, @var)
268
+ val = @rhs.install(genv)
269
+ val = val.new_vertex(genv, self) # avoid multi-edge from val to static_ret.vtx
270
+ @changes.add_edge(genv, val, @static_ret.vtx)
271
+ val
272
+ end
273
+
274
+ def retrieve_at(pos, &blk)
275
+ yield self if @var_code_range && @var_code_range.include?(pos)
276
+ super(pos, &blk)
277
+ end
278
+ end
279
+
280
+ class ClassVariableReadNode < Node
281
+ def initialize(raw_node, lenv)
282
+ super(raw_node, lenv)
283
+ @var = raw_node.name
284
+ end
285
+
286
+ attr_reader :var
287
+
288
+ def attrs = { var: }
289
+
290
+ def install0(genv)
291
+ box = @changes.add_cvar_read_box(genv, lenv.cref.cpath, @var)
292
+ @lenv.apply_read_filter(genv, self, @var, box.ret)
293
+ end
294
+
295
+ def retrieve_at(pos)
296
+ yield self if code_range.include?(pos)
297
+ end
298
+ end
299
+
300
+ class RegexpReferenceReadNode < Node
301
+ def initialize(raw_node, lenv)
302
+ super(raw_node, lenv)
303
+ @var = raw_node.type == :back_reference_read_node ? :"$&" : :"$#{raw_node.number}"
304
+ end
305
+
306
+ attr_reader :var
307
+
308
+ def attrs = { var: }
309
+
310
+ def install0(genv)
311
+ Source.new(genv.str_type)
312
+ end
313
+ end
314
+ end
315
+ end