typeprof 0.21.11 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +15 -31
- data/bin/typeprof +5 -0
- data/doc/doc.ja.md +134 -0
- data/doc/doc.md +136 -0
- data/lib/typeprof/cli/cli.rb +180 -0
- data/lib/typeprof/cli.rb +2 -133
- data/lib/typeprof/code_range.rb +112 -0
- data/lib/typeprof/core/ast/base.rb +263 -0
- data/lib/typeprof/core/ast/call.rb +251 -0
- data/lib/typeprof/core/ast/const.rb +126 -0
- data/lib/typeprof/core/ast/control.rb +432 -0
- data/lib/typeprof/core/ast/meta.rb +150 -0
- data/lib/typeprof/core/ast/method.rb +335 -0
- data/lib/typeprof/core/ast/misc.rb +263 -0
- data/lib/typeprof/core/ast/module.rb +123 -0
- data/lib/typeprof/core/ast/pattern.rb +140 -0
- data/lib/typeprof/core/ast/sig_decl.rb +471 -0
- data/lib/typeprof/core/ast/sig_type.rb +663 -0
- data/lib/typeprof/core/ast/value.rb +319 -0
- data/lib/typeprof/core/ast/variable.rb +315 -0
- data/lib/typeprof/core/ast.rb +472 -0
- data/lib/typeprof/core/builtin.rb +146 -0
- data/lib/typeprof/core/env/method.rb +137 -0
- data/lib/typeprof/core/env/method_entity.rb +55 -0
- data/lib/typeprof/core/env/module_entity.rb +408 -0
- data/lib/typeprof/core/env/static_read.rb +155 -0
- data/lib/typeprof/core/env/type_alias_entity.rb +27 -0
- data/lib/typeprof/core/env/value_entity.rb +32 -0
- data/lib/typeprof/core/env.rb +360 -0
- data/lib/typeprof/core/graph/box.rb +991 -0
- data/lib/typeprof/core/graph/change_set.rb +224 -0
- data/lib/typeprof/core/graph/filter.rb +155 -0
- data/lib/typeprof/core/graph/vertex.rb +222 -0
- data/lib/typeprof/core/graph.rb +3 -0
- data/lib/typeprof/core/service.rb +522 -0
- data/lib/typeprof/core/type.rb +348 -0
- data/lib/typeprof/core/util.rb +81 -0
- data/lib/typeprof/core.rb +32 -0
- data/lib/typeprof/diagnostic.rb +35 -0
- data/lib/typeprof/lsp/messages.rb +430 -0
- data/lib/typeprof/lsp/server.rb +177 -0
- data/lib/typeprof/lsp/text.rb +69 -0
- data/lib/typeprof/lsp/util.rb +61 -0
- data/lib/typeprof/lsp.rb +4 -907
- data/lib/typeprof/version.rb +1 -1
- data/lib/typeprof.rb +4 -18
- data/typeprof.gemspec +5 -7
- metadata +48 -35
- data/.github/dependabot.yml +0 -6
- data/.github/workflows/main.yml +0 -39
- data/.gitignore +0 -9
- data/Gemfile +0 -17
- data/Gemfile.lock +0 -41
- data/Rakefile +0 -10
- data/exe/typeprof +0 -10
- data/lib/typeprof/analyzer.rb +0 -2598
- data/lib/typeprof/arguments.rb +0 -414
- data/lib/typeprof/block.rb +0 -176
- data/lib/typeprof/builtin.rb +0 -893
- data/lib/typeprof/code-range.rb +0 -177
- data/lib/typeprof/config.rb +0 -158
- data/lib/typeprof/container-type.rb +0 -912
- data/lib/typeprof/export.rb +0 -589
- data/lib/typeprof/import.rb +0 -852
- data/lib/typeprof/insns-def.rb +0 -65
- data/lib/typeprof/iseq.rb +0 -864
- data/lib/typeprof/method.rb +0 -355
- data/lib/typeprof/type.rb +0 -1140
- data/lib/typeprof/utils.rb +0 -212
- data/tools/coverage.rb +0 -14
- data/tools/setup-insns-def.rb +0 -30
- data/typeprof-lsp +0 -3
@@ -0,0 +1,112 @@
|
|
1
|
+
module TypeProf
|
2
|
+
class CodePosition
|
3
|
+
def initialize(lineno, column)
|
4
|
+
@lineno = lineno
|
5
|
+
@column = column
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.from_lsp(pos)
|
9
|
+
new(pos[:line] + 1, pos[:character])
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_lsp
|
13
|
+
{ line: @lineno - 1, character: @column }
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :lineno, :column
|
17
|
+
|
18
|
+
def <=>(other)
|
19
|
+
cmp = @lineno <=> other.lineno
|
20
|
+
cmp == 0 ? @column <=> other.column : cmp
|
21
|
+
end
|
22
|
+
|
23
|
+
include Comparable
|
24
|
+
|
25
|
+
def ==(other)
|
26
|
+
@lineno == other.lineno && @column == other.column
|
27
|
+
end
|
28
|
+
|
29
|
+
alias eql? ==
|
30
|
+
|
31
|
+
def hash
|
32
|
+
[@lineno, @column].hash
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
"(%d,%d)" % [@lineno, @column]
|
37
|
+
end
|
38
|
+
|
39
|
+
alias inspect to_s
|
40
|
+
|
41
|
+
def left
|
42
|
+
raise if @column == 0
|
43
|
+
CodePosition.new(@lineno, @column - 1)
|
44
|
+
end
|
45
|
+
|
46
|
+
def right
|
47
|
+
CodePosition.new(@lineno, @column + 1)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class CodeRange
|
52
|
+
def initialize(first, last)
|
53
|
+
@first = first
|
54
|
+
@last = last
|
55
|
+
raise unless first
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.from_node(node, encoding = Encoding::UTF_16LE)
|
59
|
+
node = node.location if node.is_a?(Prism::Node)
|
60
|
+
if node.is_a?(Prism::Location)
|
61
|
+
pos1 = CodePosition.new(node.start_line, node.start_code_units_column(encoding))
|
62
|
+
pos2 = CodePosition.new(node.end_line, node.end_code_units_column(encoding))
|
63
|
+
elsif node.respond_to?(:location)
|
64
|
+
loc = node.location
|
65
|
+
row, col = loc.start_loc
|
66
|
+
pos1 = CodePosition.new(row, col) # TODO: use SPLAT
|
67
|
+
row, col = loc.end_loc
|
68
|
+
pos2 = CodePosition.new(row, col)
|
69
|
+
else
|
70
|
+
p node.class.ancestors
|
71
|
+
raise "unknown type: #{ node.class }"
|
72
|
+
end
|
73
|
+
new(pos1, pos2)
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.[](a, b, c, d)
|
77
|
+
pos1 = CodePosition.new(a, b)
|
78
|
+
pos2 = CodePosition.new(c, d)
|
79
|
+
new(pos1, pos2)
|
80
|
+
end
|
81
|
+
|
82
|
+
def to_lsp
|
83
|
+
{ start: @first.to_lsp, end: @last.to_lsp }
|
84
|
+
end
|
85
|
+
|
86
|
+
attr_reader :first, :last
|
87
|
+
|
88
|
+
def include?(pos)
|
89
|
+
@first <= pos && pos < @last
|
90
|
+
end
|
91
|
+
|
92
|
+
def ==(other)
|
93
|
+
@first == other.first && @last == other.last
|
94
|
+
end
|
95
|
+
|
96
|
+
alias eql? ==
|
97
|
+
|
98
|
+
def hash
|
99
|
+
[@first, @last].hash
|
100
|
+
end
|
101
|
+
|
102
|
+
def to_s
|
103
|
+
"%p-%p" % [@first, @last]
|
104
|
+
end
|
105
|
+
|
106
|
+
alias inspect to_s
|
107
|
+
|
108
|
+
def ==(other)
|
109
|
+
@first == other.first && @last == other.last
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,263 @@
|
|
1
|
+
module TypeProf::Core
|
2
|
+
class AST
|
3
|
+
class Node
|
4
|
+
def initialize(raw_node, lenv)
|
5
|
+
@raw_node = raw_node
|
6
|
+
@lenv = lenv
|
7
|
+
@prev_node = nil
|
8
|
+
@static_ret = nil
|
9
|
+
@ret = nil
|
10
|
+
|
11
|
+
@changes = ChangeSet.new(self, nil)
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :lenv
|
15
|
+
attr_reader :prev_node
|
16
|
+
attr_reader :static_ret
|
17
|
+
attr_reader :ret
|
18
|
+
attr_reader :changes
|
19
|
+
|
20
|
+
def subnodes = {}
|
21
|
+
def attrs = {}
|
22
|
+
|
23
|
+
#: { (TypeProf::Core::AST::Node) -> void } -> nil
|
24
|
+
def each_subnode
|
25
|
+
queue = subnodes.values
|
26
|
+
|
27
|
+
until queue.empty?
|
28
|
+
subnode = queue.shift
|
29
|
+
next unless subnode
|
30
|
+
|
31
|
+
case subnode
|
32
|
+
when AST::Node
|
33
|
+
yield subnode
|
34
|
+
when Array
|
35
|
+
queue.unshift(*subnode)
|
36
|
+
when Hash
|
37
|
+
queue.unshift(*subnode.values)
|
38
|
+
else
|
39
|
+
raise subnode.class.to_s
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def traverse(&blk)
|
45
|
+
yield :enter, self
|
46
|
+
each_subnode do |subnode|
|
47
|
+
subnode.traverse(&blk)
|
48
|
+
end
|
49
|
+
yield :leave, self
|
50
|
+
end
|
51
|
+
|
52
|
+
def code_range
|
53
|
+
if @raw_node
|
54
|
+
TypeProf::CodeRange.from_node(@raw_node)
|
55
|
+
else
|
56
|
+
pp self
|
57
|
+
raise
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def define(genv)
|
62
|
+
@static_ret = define0(genv)
|
63
|
+
end
|
64
|
+
|
65
|
+
def define_copy(genv)
|
66
|
+
@lenv = @prev_node.lenv
|
67
|
+
each_subnode do |subnode|
|
68
|
+
subnode.define_copy(genv)
|
69
|
+
end
|
70
|
+
@prev_node.instance_variable_set(:@reused, true)
|
71
|
+
@static_ret = @prev_node.static_ret
|
72
|
+
end
|
73
|
+
|
74
|
+
def define0(genv)
|
75
|
+
each_subnode do |subnode|
|
76
|
+
subnode.define(genv)
|
77
|
+
end
|
78
|
+
return nil
|
79
|
+
end
|
80
|
+
|
81
|
+
def undefine(genv)
|
82
|
+
unless @reused
|
83
|
+
undefine0(genv)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def undefine0(genv)
|
88
|
+
each_subnode do |subnode|
|
89
|
+
subnode.undefine(genv)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def install(genv)
|
94
|
+
@ret = install0(genv)
|
95
|
+
@changes.reinstall(genv)
|
96
|
+
@ret
|
97
|
+
end
|
98
|
+
|
99
|
+
def install_copy(genv)
|
100
|
+
@changes.copy_from(@prev_node.changes)
|
101
|
+
@changes.reuse(self)
|
102
|
+
each_subnode do |subnode|
|
103
|
+
subnode.install_copy(genv)
|
104
|
+
end
|
105
|
+
@ret = @prev_node.ret
|
106
|
+
end
|
107
|
+
|
108
|
+
def install0(_)
|
109
|
+
raise "should override"
|
110
|
+
end
|
111
|
+
|
112
|
+
def uninstall(genv)
|
113
|
+
@changes.reinstall(genv)
|
114
|
+
each_subnode do |subnode|
|
115
|
+
subnode.uninstall(genv)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def diff(prev_node)
|
120
|
+
if prev_node.is_a?(self.class) && attrs.all? {|key, attr| attr == prev_node.send(key) }
|
121
|
+
raise unless prev_node # annotation
|
122
|
+
s1 = subnodes
|
123
|
+
s2 = prev_node.subnodes
|
124
|
+
return if s1.keys != s2.keys
|
125
|
+
s1.each do |key, subnode|
|
126
|
+
prev_subnode = s2[key]
|
127
|
+
if subnode && prev_subnode
|
128
|
+
subnode = [subnode] if subnode.is_a?(AST::Node)
|
129
|
+
prev_subnode = [prev_subnode] if prev_subnode.is_a?(AST::Node)
|
130
|
+
subnode.zip(prev_subnode) do |subnode0, prev_subnode0|
|
131
|
+
next if subnode0 == nil && prev_subnode0 == nil
|
132
|
+
subnode0.diff(prev_subnode0)
|
133
|
+
return unless subnode0.prev_node
|
134
|
+
end
|
135
|
+
else
|
136
|
+
return if subnode != prev_subnode
|
137
|
+
end
|
138
|
+
end
|
139
|
+
@prev_node = prev_node
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def retrieve_at(pos, &blk)
|
144
|
+
if code_range.include?(pos)
|
145
|
+
each_subnode do |subnode|
|
146
|
+
subnode.retrieve_at(pos, &blk)
|
147
|
+
end
|
148
|
+
yield self
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def boxes(key)
|
153
|
+
@changes.boxes.each do |(k, *), box|
|
154
|
+
# TODO: make it recursive
|
155
|
+
box.changes.boxes.each do |(k, *), box|
|
156
|
+
yield box if k == key
|
157
|
+
end
|
158
|
+
yield box if k == key
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def diagnostics(genv, &blk)
|
163
|
+
@changes.diagnostics.each(&blk)
|
164
|
+
@changes.boxes.each_value do |box|
|
165
|
+
box.diagnostics(genv, &blk)
|
166
|
+
end
|
167
|
+
each_subnode do |subnode|
|
168
|
+
subnode.diagnostics(genv, &blk)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def get_vertexes(vtxs)
|
173
|
+
return if @reused
|
174
|
+
@changes.boxes.each_value do |box|
|
175
|
+
vtxs << box.ret
|
176
|
+
end
|
177
|
+
vtxs << @ret
|
178
|
+
each_subnode do |subnode|
|
179
|
+
subnode.get_vertexes(vtxs)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def modified_vars(tbl, vars)
|
184
|
+
each_subnode do |subnode|
|
185
|
+
subnode.modified_vars(tbl, vars)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def pretty_print_instance_variables
|
190
|
+
super() - [:@raw_node, :@lenv, :@prev_node, :@static_ret, :@changes]
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
class ProgramNode < Node
|
195
|
+
def initialize(raw_node, lenv)
|
196
|
+
super(raw_node, lenv)
|
197
|
+
|
198
|
+
@tbl = raw_node.locals
|
199
|
+
raw_body = raw_node.statements
|
200
|
+
|
201
|
+
@body = AST.create_node(raw_body, lenv, false)
|
202
|
+
end
|
203
|
+
|
204
|
+
attr_reader :tbl, :body
|
205
|
+
|
206
|
+
def subnodes = { body: }
|
207
|
+
def attrs = { tbl: }
|
208
|
+
|
209
|
+
def install0(genv)
|
210
|
+
@tbl.each {|var| @lenv.locals[var] = Source.new(genv.nil_type) }
|
211
|
+
@lenv.locals[:"*self"] = lenv.cref.get_self(genv)
|
212
|
+
|
213
|
+
# for toplevel return
|
214
|
+
@body.lenv.locals[:"*expected_method_ret"] = Vertex.new(self)
|
215
|
+
@body.install(genv)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
class DummyNilNode < Node
|
220
|
+
def initialize(code_range, lenv)
|
221
|
+
@code_range = code_range
|
222
|
+
super(nil, lenv)
|
223
|
+
end
|
224
|
+
|
225
|
+
def code_range
|
226
|
+
@code_range
|
227
|
+
end
|
228
|
+
|
229
|
+
def install0(genv)
|
230
|
+
Source.new(genv.nil_type)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
class DummyRHSNode < Node
|
235
|
+
def initialize(code_range, lenv)
|
236
|
+
@code_range = code_range
|
237
|
+
super(nil, lenv)
|
238
|
+
end
|
239
|
+
|
240
|
+
def code_range
|
241
|
+
@code_range
|
242
|
+
end
|
243
|
+
|
244
|
+
def install0(_)
|
245
|
+
Vertex.new(self)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
class DummySymbolNode
|
250
|
+
def initialize(sym, code_range, ret)
|
251
|
+
@sym = sym
|
252
|
+
@code_range = code_range
|
253
|
+
@ret = ret
|
254
|
+
end
|
255
|
+
|
256
|
+
attr_reader :lenv, :prev_node, :ret
|
257
|
+
|
258
|
+
def boxes(_)
|
259
|
+
[]
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
@@ -0,0 +1,251 @@
|
|
1
|
+
module TypeProf::Core
|
2
|
+
class AST
|
3
|
+
class CallBaseNode < Node
|
4
|
+
def initialize(raw_node, recv, mid, mid_code_range, raw_args, last_arg, raw_block, lenv)
|
5
|
+
super(raw_node, lenv)
|
6
|
+
|
7
|
+
@recv = recv
|
8
|
+
@mid = mid
|
9
|
+
@mid_code_range = mid_code_range
|
10
|
+
|
11
|
+
# args
|
12
|
+
@positional_args = []
|
13
|
+
@splat_flags = []
|
14
|
+
@keyword_args = nil
|
15
|
+
|
16
|
+
@block_pass = nil
|
17
|
+
@block_tbl = nil
|
18
|
+
@block_f_args = nil
|
19
|
+
@block_body = nil
|
20
|
+
|
21
|
+
if raw_args
|
22
|
+
args = []
|
23
|
+
@splat_flags = []
|
24
|
+
raw_args.arguments.each do |raw_arg|
|
25
|
+
if raw_arg.is_a?(Prism::SplatNode)
|
26
|
+
args << raw_arg.expression
|
27
|
+
@splat_flags << true
|
28
|
+
else
|
29
|
+
args << raw_arg
|
30
|
+
@splat_flags << false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
@positional_args = args.map {|arg| AST.create_node(arg, lenv) }
|
34
|
+
|
35
|
+
if @positional_args.last.is_a?(TypeProf::Core::AST::HashNode) && @positional_args.last.keywords
|
36
|
+
@keyword_args = @positional_args.pop
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
@positional_args << last_arg if last_arg
|
41
|
+
|
42
|
+
if raw_block
|
43
|
+
if raw_block.type == :block_argument_node
|
44
|
+
@block_pass = AST.create_node(raw_block.expression, lenv)
|
45
|
+
else
|
46
|
+
@block_pass = nil
|
47
|
+
@block_tbl = raw_block.locals
|
48
|
+
# TODO: optional args, etc.
|
49
|
+
@block_f_args = case raw_block.parameters
|
50
|
+
when Prism::BlockParametersNode
|
51
|
+
raw_block.parameters.parameters.requireds.map {|n| n.is_a?(Prism::MultiTargetNode) ? nil : n.name }
|
52
|
+
when Prism::NumberedParametersNode
|
53
|
+
1.upto(raw_block.parameters.maximum).map { |n| :"_#{n}" }
|
54
|
+
when nil
|
55
|
+
[]
|
56
|
+
else
|
57
|
+
raise "not supported yet: #{ raw_block.parameters.class }"
|
58
|
+
end
|
59
|
+
ncref = CRef.new(lenv.cref.cpath, :instance, @mid, lenv.cref)
|
60
|
+
nlenv = LocalEnv.new(@lenv.path, ncref, {}, @lenv.return_boxes)
|
61
|
+
@block_body = raw_block.body ? AST.create_node(raw_block.body, nlenv) : DummyNilNode.new(code_range, lenv)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
@yield = raw_node.type == :yield_node
|
66
|
+
end
|
67
|
+
|
68
|
+
attr_reader :recv, :mid, :mid_code_range, :yield
|
69
|
+
attr_reader :positional_args, :splat_flags, :keyword_args
|
70
|
+
attr_reader :block_tbl, :block_f_args, :block_body, :block_pass
|
71
|
+
|
72
|
+
def subnodes = { recv:, positional_args:, keyword_args:, block_body:, block_pass: }
|
73
|
+
def attrs = { mid:, splat_flags:, block_tbl:, block_f_args:, yield: }
|
74
|
+
|
75
|
+
def install0(genv)
|
76
|
+
recv = @recv ? @recv.install(genv) : @yield ? @lenv.get_var(:"*given_block") : @lenv.get_var(:"*self")
|
77
|
+
|
78
|
+
positional_args = @positional_args.map do |arg|
|
79
|
+
arg.install(genv)
|
80
|
+
end
|
81
|
+
|
82
|
+
keyword_args = @keyword_args ? @keyword_args.install(genv) : nil
|
83
|
+
|
84
|
+
if @block_body
|
85
|
+
@lenv.locals.each {|var, vtx| @block_body.lenv.locals[var] = vtx }
|
86
|
+
@block_tbl.each {|var| @block_body.lenv.locals[var] = Source.new(genv.nil_type) }
|
87
|
+
@block_body.lenv.locals[:"*self"] = @block_body.lenv.cref.get_self(genv)
|
88
|
+
|
89
|
+
blk_f_args = []
|
90
|
+
if @block_f_args
|
91
|
+
@block_f_args.each do |arg|
|
92
|
+
blk_f_args << @block_body.lenv.new_var(arg, self)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
@lenv.locals.each do |var, vtx|
|
97
|
+
@block_body.lenv.set_var(var, vtx)
|
98
|
+
end
|
99
|
+
vars = []
|
100
|
+
@block_body.modified_vars(@lenv.locals.keys - @block_tbl, vars)
|
101
|
+
vars.uniq!
|
102
|
+
vars.each do |var|
|
103
|
+
vtx = @lenv.get_var(var)
|
104
|
+
nvtx = vtx.new_vertex(genv, self)
|
105
|
+
@lenv.set_var(var, nvtx)
|
106
|
+
@block_body.lenv.set_var(var, nvtx)
|
107
|
+
end
|
108
|
+
|
109
|
+
e_ret = @block_body.lenv.locals[:"*expected_block_ret"] = Vertex.new(self)
|
110
|
+
@block_body.install(genv)
|
111
|
+
@block_body.lenv.add_next_box(@changes.add_escape_box(genv, @block_body.ret, e_ret))
|
112
|
+
|
113
|
+
vars.each do |var|
|
114
|
+
@changes.add_edge(genv, @block_body.lenv.get_var(var), @lenv.get_var(var))
|
115
|
+
end
|
116
|
+
|
117
|
+
blk_f_ary_arg = Vertex.new(self)
|
118
|
+
@changes.add_masgn_box(genv, blk_f_ary_arg, blk_f_args, nil, nil) # TODO: support splat "do |a, *b, c|"
|
119
|
+
block = Block.new(self, blk_f_ary_arg, blk_f_args, @block_body.lenv.next_boxes)
|
120
|
+
blk_ty = Source.new(Type::Proc.new(genv, block))
|
121
|
+
elsif @block_pass
|
122
|
+
blk_ty = @block_pass.install(genv)
|
123
|
+
end
|
124
|
+
|
125
|
+
a_args = ActualArguments.new(positional_args, @splat_flags, keyword_args, blk_ty)
|
126
|
+
box = @changes.add_method_call_box(genv, recv, @mid, a_args, !@recv)
|
127
|
+
box.ret
|
128
|
+
end
|
129
|
+
|
130
|
+
def block_last_stmt_code_range
|
131
|
+
if @block_body
|
132
|
+
if @block_body.is_a?(AST::StatementsNode)
|
133
|
+
@block_body.stmts.last.code_range
|
134
|
+
else
|
135
|
+
@block_body.code_range
|
136
|
+
end
|
137
|
+
else
|
138
|
+
nil
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def retrieve_at(pos, &blk)
|
143
|
+
yield self if @mid_code_range && @mid_code_range.include?(pos)
|
144
|
+
each_subnode do |subnode|
|
145
|
+
next unless subnode
|
146
|
+
subnode.retrieve_at(pos, &blk)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def modified_vars(tbl, vars)
|
151
|
+
subnodes.each do |key, subnode|
|
152
|
+
next unless subnode
|
153
|
+
if key == :block_body
|
154
|
+
subnode.modified_vars(tbl - self.block_tbl, vars)
|
155
|
+
elsif subnode.is_a?(AST::Node)
|
156
|
+
subnode.modified_vars(tbl, vars)
|
157
|
+
else
|
158
|
+
subnode.each {|n| n.modified_vars(tbl, vars) }
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
class CallNode < CallBaseNode
|
165
|
+
def initialize(raw_node, lenv)
|
166
|
+
recv = raw_node.receiver ? AST.create_node(raw_node.receiver, lenv) : nil
|
167
|
+
mid = raw_node.name
|
168
|
+
mid_code_range = TypeProf::CodeRange.from_node(raw_node.message_loc) if raw_node.message_loc
|
169
|
+
raw_args = raw_node.arguments
|
170
|
+
raw_block = raw_node.block
|
171
|
+
super(raw_node, recv, mid, mid_code_range, raw_args, nil, raw_block, lenv)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
class SuperNode < CallBaseNode
|
176
|
+
def initialize(raw_node, lenv)
|
177
|
+
raw_args = raw_node.arguments
|
178
|
+
raw_block = raw_node.block
|
179
|
+
super(raw_node, nil, :"*super", nil, raw_args, nil, raw_block, lenv)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
class ForwardingSuperNode < CallBaseNode
|
184
|
+
def initialize(raw_node, lenv)
|
185
|
+
raw_args = nil # TODO: forward args properly
|
186
|
+
raw_block = raw_node.block
|
187
|
+
super(raw_node, nil, :"*super", nil, raw_args, nil, raw_block, lenv)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
class YieldNode < CallBaseNode
|
192
|
+
def initialize(raw_node, lenv)
|
193
|
+
raw_args = raw_node.arguments
|
194
|
+
super(raw_node, nil, :call, nil, raw_args, nil, nil, lenv)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
class OperatorNode < CallBaseNode
|
199
|
+
def initialize(raw_node, recv, lenv)
|
200
|
+
mid = raw_node.binary_operator
|
201
|
+
mid_code_range = TypeProf::CodeRange.from_node(raw_node.binary_operator_loc)
|
202
|
+
last_arg = AST.create_node(raw_node.value, lenv)
|
203
|
+
super(raw_node, recv, mid, mid_code_range, nil, last_arg, nil, lenv)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
class IndexReadNode < CallBaseNode
|
208
|
+
def initialize(raw_node, lenv)
|
209
|
+
recv = AST.create_node(raw_node.receiver, lenv)
|
210
|
+
mid = :[]
|
211
|
+
mid_code_range = nil
|
212
|
+
raw_args = raw_node.arguments
|
213
|
+
super(raw_node, recv, mid, mid_code_range, raw_args, nil, nil, lenv)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
class IndexWriteNode < CallBaseNode
|
218
|
+
def initialize(raw_node, rhs, lenv)
|
219
|
+
recv = AST.create_node(raw_node.receiver, lenv)
|
220
|
+
mid = :[]=
|
221
|
+
mid_code_range = nil
|
222
|
+
raw_args = raw_node.arguments
|
223
|
+
@rhs = rhs
|
224
|
+
super(raw_node, recv, mid, mid_code_range, raw_args, rhs, nil, lenv)
|
225
|
+
end
|
226
|
+
|
227
|
+
attr_reader :rhs
|
228
|
+
end
|
229
|
+
|
230
|
+
class CallReadNode < CallBaseNode
|
231
|
+
def initialize(raw_node, lenv)
|
232
|
+
recv = AST.create_node(raw_node.receiver, lenv)
|
233
|
+
mid = raw_node.read_name
|
234
|
+
mid_code_range = TypeProf::CodeRange.from_node(raw_node.message_loc)
|
235
|
+
super(raw_node, recv, mid, mid_code_range, nil, nil, nil, lenv)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
class CallWriteNode < CallBaseNode
|
240
|
+
def initialize(raw_node, rhs, lenv)
|
241
|
+
recv = AST.create_node(raw_node.receiver, lenv)
|
242
|
+
mid = raw_node.is_a?(Prism::CallTargetNode) ? raw_node.name : raw_node.write_name
|
243
|
+
mid_code_range = TypeProf::CodeRange.from_node(raw_node.message_loc)
|
244
|
+
@rhs = rhs
|
245
|
+
super(raw_node, recv, mid, mid_code_range, nil, rhs, nil, lenv)
|
246
|
+
end
|
247
|
+
|
248
|
+
attr_reader :rhs
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|