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
@@ -1,414 +0,0 @@
1
- module TypeProf
2
- # Arguments from caller side
3
- class ActualArguments
4
- def initialize(lead_tys, rest_ty, kw_tys, blk_ty)
5
- @lead_tys = lead_tys
6
- raise unless lead_tys
7
- @rest_ty = rest_ty
8
- @kw_tys = kw_tys # kw_tys should be {:key1 => Type, :key2 => Type, ...} or {nil => Type}
9
- raise if !kw_tys.is_a?(::Hash)
10
- @blk_ty = blk_ty
11
- raise unless blk_ty
12
- end
13
-
14
- def for_method_missing(mid)
15
- ActualArguments.new([mid] + @lead_tys, @rest_ty, @kw_tys, @blk_ty)
16
- end
17
-
18
- attr_reader :lead_tys, :rest_ty, :kw_tys, :blk_ty
19
- attr_accessor :node_id
20
-
21
- def globalize(caller_env, visited, depth)
22
- lead_tys = @lead_tys.map {|ty| ty.globalize(caller_env, visited, depth) }
23
- rest_ty = @rest_ty.globalize(caller_env, visited, depth) if @rest_ty
24
- kw_tys = @kw_tys.to_h do |key, ty|
25
- [key, ty.globalize(caller_env, visited, depth)]
26
- end
27
- ActualArguments.new(lead_tys, rest_ty, kw_tys, @blk_ty)
28
- end
29
-
30
- def limit_size(limit)
31
- self
32
- end
33
-
34
- def consistent_with_method_signature?(msig)
35
- aargs = @lead_tys.dup
36
-
37
- # aargs: lead_tys, rest_ty
38
- # msig: lead_tys, opt_tys, rest_ty, post_tys
39
- if @rest_ty
40
- lower_bound = [0, msig.lead_tys.size + msig.post_tys.size - aargs.size].max
41
- upper_bound = [0, lower_bound + msig.opt_tys.size].max
42
- (lower_bound..upper_bound).each do |n|
43
- # BUG: @rest_ty is an Array, so need to squash
44
- tmp_aargs = ActualArguments.new(@lead_tys + [@rest_ty] * n, nil, @kw_tys, @blk_ty)
45
- subst = tmp_aargs.consistent_with_method_signature?(msig) # XXX: wrong subst handling in the loop!
46
- return subst if subst
47
- end
48
- return nil
49
- end
50
-
51
- subst = {}
52
- if msig.rest_ty
53
- return nil if aargs.size < msig.lead_tys.size + msig.post_tys.size
54
- aargs.shift(msig.lead_tys.size).zip(msig.lead_tys) do |aarg, farg|
55
- return nil unless subst2 = Type.match?(aarg, farg)
56
- subst = Type.merge_substitution(subst, subst2)
57
- end
58
- aargs.pop(msig.post_tys.size).zip(msig.post_tys) do |aarg, farg|
59
- return nil unless subst2 = Type.match?(aarg, farg)
60
- subst = Type.merge_substitution(subst, subst2)
61
- end
62
- msig.opt_tys.each do |farg|
63
- break if aargs.empty?
64
- aarg = aargs.shift
65
- return nil unless subst2 = Type.match?(aarg, farg)
66
- subst = Type.merge_substitution(subst, subst2)
67
- end
68
- aargs.each do |aarg|
69
- return nil unless subst2 = Type.match?(aarg, msig.rest_ty)
70
- subst = Type.merge_substitution(subst, subst2)
71
- end
72
- else
73
- return nil if aargs.size < msig.lead_tys.size + msig.post_tys.size
74
- return nil if aargs.size > msig.lead_tys.size + msig.post_tys.size + msig.opt_tys.size
75
- aargs.shift(msig.lead_tys.size).zip(msig.lead_tys) do |aarg, farg|
76
- return nil unless subst2 = Type.match?(aarg, farg)
77
- subst = Type.merge_substitution(subst, subst2)
78
- end
79
- aargs.pop(msig.post_tys.size).zip(msig.post_tys) do |aarg, farg|
80
- return nil unless subst2 = Type.match?(aarg, farg)
81
- subst = Type.merge_substitution(subst, subst2)
82
- end
83
- aargs.zip(msig.opt_tys) do |aarg, farg|
84
- return nil unless subst2 = Type.match?(aarg, farg)
85
- subst = Type.merge_substitution(subst, subst2)
86
- end
87
- end
88
- # XXX: msig.keyword_tys
89
-
90
- case msig.blk_ty
91
- when Type::Proc
92
- return nil if @blk_ty == Type.nil
93
- when Type.nil
94
- return nil if @blk_ty != Type.nil
95
- when Type::Any
96
- else
97
- raise "unknown type of formal block signature"
98
- end
99
-
100
- subst
101
- end
102
-
103
- def argument_error(given, exp_lower, exp_upper)
104
- case
105
- when !exp_upper then exp = "#{ exp_lower }+"
106
- when exp_lower == exp_upper then exp = "#{ exp_lower }"
107
- else exp = "#{ exp_lower }..#{ exp_upper }"
108
- end
109
- "wrong number of arguments (given #{ given }, expected #{ exp })"
110
- end
111
-
112
- def to_block_signature
113
- if @rest_ty
114
- rest_ty = Type.bot
115
- @rest_ty.each_child_global do |ty|
116
- if ty.is_a?(Type::Array)
117
- rest_ty = rest_ty.union(ty.elems.squash)
118
- else
119
- # XXX: to_ary?
120
- rest_ty = rest_ty.union(ty)
121
- end
122
- end
123
- end
124
- BlockSignature.new(@lead_tys, [], rest_ty, @blk_ty)
125
- end
126
-
127
- def setup_formal_arguments(kind, locals, fargs_format)
128
- lead_num = fargs_format[:lead_num] || 0
129
- post_num = fargs_format[:post_num] || 0
130
- post_index = fargs_format[:post_start]
131
- rest_index = fargs_format[:rest_start]
132
- keyword = fargs_format[:keyword]
133
- kw_index = fargs_format[:kwbits] - keyword.size if keyword
134
- kwrest_index = fargs_format[:kwrest]
135
- block_index = fargs_format[:block_start]
136
- opt = fargs_format[:opt] || [0]
137
- ambiguous_param0 = fargs_format[:ambiguous_param0]
138
-
139
- lead_tys = @lead_tys
140
- rest_ty = @rest_ty
141
-
142
- if kind == :block
143
- # The rule of passing arguments to block:
144
- #
145
- # Let A is actual arguments and F is formal arguments.
146
- # If F is NOT ambiguous_param0, and if length(A) == 1, and if A[0] is an Array,
147
- # then replace A with A[0]. And then, F[i] = A[i] for all 0 <= i < length(F).
148
-
149
- # Handling the special case
150
- if !ambiguous_param0
151
- if lead_tys.size == 1 && !rest_ty && @kw_tys.empty? # length(A) == 1
152
- ty = lead_tys[0]
153
- case ty
154
- when Type::Array
155
- lead_tys = ty.elems.lead_tys
156
- rest_ty = ty.elems.rest_ty
157
- when Type::Union
158
- if ty.elems
159
- other_elems = {}
160
- ty.elems.each do |(container_kind, base_type), elems|
161
- if container_kind == Type::Array
162
- rest_ty = rest_ty ? rest_ty.union(elems.squash) : elems.squash
163
- else
164
- other_elems[[container_kind, base_type]] = elems
165
- end
166
- end
167
- end
168
- lead_tys = [Type::Union.new(ty.types, other_elems)]
169
- end
170
- end
171
- end
172
- end
173
-
174
- # Normal case: copy actual args to formal args
175
- if rest_ty
176
- ty = Type.bot
177
- additional_lead_size = nil
178
- rest_ty.each_child_global do |ty0|
179
- if ty0.is_a?(Type::Array)
180
- additional_lead_size = [additional_lead_size, ty0.elems.lead_tys.size].compact.min
181
- else
182
- additional_lead_size = 0
183
- end
184
- end
185
- additional_lead_tys = [Type.bot] * (additional_lead_size || 0)
186
- rest_ty.each_child_global do |ty0|
187
- if ty0.is_a?(Type::Array)
188
- tys, new_rest_ty = ty0.elems.take_first(additional_lead_size)
189
- tys.each_with_index do |ty00, i|
190
- additional_lead_tys[i] = additional_lead_tys[i].union(ty00)
191
- end
192
- ty = ty.union(new_rest_ty.elems.squash)
193
- else
194
- # XXX: to_ary?
195
- ty = ty.union(ty0)
196
- end
197
- end
198
- lead_tys += additional_lead_tys
199
- rest_ty = ty
200
-
201
- # XXX: Strictly speaking, this is needed, but it brings false positives. Which is better?
202
- #rest_ty = rest_ty.union(Type.nil)
203
-
204
- if rest_index
205
- # foo(a0, a1, a2, ...(rest_ty)) -->
206
- # def foo(l0, l1, o0=, o1=, *rest, p0, p1)
207
- # lead_ty argc == 0: - - - - - - -
208
- # lead_ty argc == 1: a0 - - - - - -
209
- # lead_ty argc == 2: a0 a1 - - - - -
210
- # lead_ty argc == 3: a0 a1 - - - a2 -
211
- # lead_ty argc == 4: a0 a1 - - - a2 a3
212
- # lead_ty argc == 5: a0 a1 a2 - - a3 a4
213
- # lead_ty argc == 6: a0 a1 a2 a3 - a4 a5
214
- # lead_ty argc == 7: a0 a1 a2 a3 a4 a5 a6
215
- # lead_ty argc == 8: a0 a1 a2 a3 a4|a5 a6 a7
216
- #
217
- # l0 = a0
218
- # l1 = a1
219
- # o0 = a2
220
- # o1 = a3
221
- # rest = a4|a5|...|rest_ty (= cum_lead_tys[4])
222
- # p0 = a2|a3|...|rest_ty (= cum_lead_tys[2])
223
- # p1 = a3|a4|...|rest_ty (= cum_lead_tys[3])
224
-
225
- cum_lead_tys = []
226
- ty = rest_ty
227
- lead_tys.reverse_each do |ty0|
228
- cum_lead_tys.unshift(ty = ty.union(ty0))
229
- end
230
-
231
- # l1, l2, o1, o2
232
- (lead_num + opt.size - 1).times {|i| locals[i] = lead_tys[i] || rest_ty }
233
- opt_count = opt.size - 1
234
-
235
- # rest
236
- ty = cum_lead_tys[lead_num + opt.size - 1] || rest_ty
237
- locals[rest_index] = Type::Array.new(Type::Array::Elements.new([], ty), Type::Instance.new(Type::Builtin[:ary]))
238
-
239
- # p0, p1
240
- off = [lead_num, lead_tys.size - post_num].max
241
- post_num.times {|i| locals[post_index + i] = cum_lead_tys[off + i] || rest_ty }
242
- else
243
- # foo(a0, a1, a2, ...(rest_ty)) -->
244
- # def foo(l0, l1, o0=, o1=, p0, p1)
245
- # lead_ty argc == 0: - - - - - -
246
- # lead_ty argc == 1: a0 - - - - -
247
- # lead_ty argc == 2: a0 a1 - - - -
248
- # lead_ty argc == 3: a0 a1 - - a2 -
249
- # lead_ty argc == 4: a0 a1 - - a2 a3
250
- # lead_ty argc == 5: a0 a1 a2 - a3 a4
251
- # lead_ty argc == 6: a0 a1 a2 a3 a4 a5
252
- # lead_ty argc == 7: a0 a1 a2 a3 a4 a5 (if there is a6, report error if kind is method, or ignore if kind is block)
253
- #
254
- # l0 = a0
255
- # l1 = a1
256
- # o0 = a2
257
- # o1 = a3
258
- # p0 = a2|a3|a4
259
- # p1 = a3|a4|a5
260
-
261
- if kind == :method && lead_num + opt.size - 1 + post_num < lead_tys.size
262
- return argument_error(lead_tys.size, lead_num + post_num, lead_num + post_num + opt.size - 1)
263
- end
264
-
265
- # l1, l2, o1, o2
266
- (lead_num + opt.size - 1).times {|i| locals[i] = lead_tys[i] || rest_ty }
267
- opt_count = opt.size - 1
268
-
269
- # p0, p1
270
- post_num.times do |i|
271
- candidates = lead_tys[lead_num, opt.size] || []
272
- candidates << rest_ty if candidates.size < opt.size
273
- locals[post_index + i] = candidates.inject(&:union)
274
- end
275
- end
276
- else
277
- if rest_index
278
- # foo(a0, a1, a2) -->
279
- # def foo(l0, l1, o0=, o1=, *rest, p0, p1)
280
- # lead_ty argc == 0: - - - - - - - (error if kind is method)
281
- # lead_ty argc == 1: a0 - - - - - - (error if kind is method)
282
- # lead_ty argc == 2: a0 a1 - - - - - (error if kind is method)
283
- # lead_ty argc == 3: a0 a1 - - - a2 - (error if kind is method)
284
- # lead_ty argc == 4: a0 a1 - - - a2 a3
285
- # lead_ty argc == 5: a0 a1 a2 - - a3 a4
286
- # lead_ty argc == 6: a0 a1 a2 a3 - a4 a5
287
- # lead_ty argc == 7: a0 a1 a2 a3 a4 a5 a6
288
- # lead_ty argc == 8: a0 a1 a2 a3 a4|a5 a6 a7
289
- #
290
- # len(a) < 4 -> error
291
- #
292
- # l0 = a0
293
- # l1 = a1
294
- # o0 = a2
295
- # o1 = a3
296
- # rest = a4|a5|...|a[[4,len(a)-3].max]
297
- # p0 = a[[2,len(a)-2].max]
298
- # p1 = a[[3,len(a)-1].max]
299
-
300
- if kind == :method && lead_tys.size < lead_num + post_num
301
- return argument_error(lead_tys.size, lead_num + post_num, nil)
302
- end
303
-
304
- # l0, l1
305
- lead_num.times {|i| locals[i] = lead_tys[i] || Type.nil }
306
-
307
- # o0, o1
308
- opt_count = (lead_tys.size - lead_num - post_num).clamp(0, opt.size - 1)
309
- (opt.size - 1).times {|i| locals[lead_num + i] = i < opt_count ? lead_tys[lead_num + i] : Type.nil }
310
-
311
- # rest
312
- rest_b = lead_num + opt_count
313
- rest_e = [0, lead_tys.size - post_num].max
314
- locals[rest_index] = Type::Array.new(Type::Array::Elements.new(lead_tys[rest_b...rest_e] || [], Type.bot), Type::Instance.new(Type::Builtin[:ary]))
315
-
316
- # p0, p1
317
- off = [lead_num, lead_tys.size - post_num].max
318
- post_num.times {|i| locals[post_index + i] = lead_tys[off + i] || Type.nil }
319
- else
320
- # yield a0, a1, a2 -->
321
- # do |l0, l1, o0=, o1=, p0, p1|
322
- # lead_ty argc == 0: - - - - - - (error if kind is method)
323
- # lead_ty argc == 1: a0 - - - - - (error if kind is method)
324
- # lead_ty argc == 2: a0 a1 - - - - (error if kind is method)
325
- # lead_ty argc == 3: a0 a1 - - a2 - (error if kind is method)
326
- # lead_ty argc == 4: a0 a1 - - a2 a3
327
- # lead_ty argc == 5: a0 a1 a2 - a3 a4
328
- # lead_ty argc == 6: a0 a1 a2 a3 a4 a5
329
- # lead_ty argc == 7: a0 a1 a2 a3 a4 a5 (if there is a6, report error if kind is method, or ignore if kind is block)
330
- #
331
- # l0 = a0
332
- # l1 = a1
333
- # o0 = a2
334
- # o1 = a3
335
- # p0 = a2|a3|a4
336
- # p1 = a3|a4|a5
337
-
338
- if kind == :method && (lead_tys.size < lead_num + post_num || lead_num + opt.size - 1 + post_num < lead_tys.size)
339
- return argument_error(lead_tys.size, lead_num + post_num, lead_num + post_num + opt.size - 1)
340
- end
341
-
342
- # l0, l1
343
- lead_num.times {|i| locals[i] = lead_tys[i] || Type.nil }
344
-
345
- # o0, o1
346
- opt_count = (lead_tys.size - lead_num - post_num).clamp(0, opt.size - 1)
347
- (opt.size - 1).times {|i| locals[lead_num + i] = i < opt_count ? lead_tys[lead_num + i] : Type.nil }
348
-
349
- # p0, p1
350
- off = lead_num + opt_count
351
- post_num.times {|i| locals[post_index + i] = lead_tys[off + i] || Type.nil }
352
- end
353
- end
354
-
355
- kw_tys = @kw_tys.dup
356
- if keyword
357
- keyword.each_with_index do |kw, i|
358
- case
359
- when kw.is_a?(Symbol) # required keyword
360
- key = kw
361
- req = true
362
- when kw.size == 2 # optional keyword (default value is a literal)
363
- key, default_ty = *kw
364
- default_ty = Type.guess_literal_type(default_ty)
365
- default_ty = default_ty.base_type if default_ty.is_a?(Type::Literal)
366
- req = false
367
- else # optional keyword (default value is an expression)
368
- key, = kw
369
- req = false
370
- end
371
-
372
- if kw_tys.key?(key)
373
- ty = kw_tys.delete(key)
374
- else
375
- ty = kw_tys[nil] || Type.bot
376
- end
377
-
378
- if ty == Type.bot && req
379
- return "no argument for required keywords"
380
- end
381
-
382
- ty = ty.union(default_ty) if default_ty
383
- locals[kw_index + i] = ty
384
- end
385
- end
386
-
387
- if kwrest_index
388
- if kw_tys.key?(nil)
389
- kw_rest_ty = Type.gen_hash {|h| h[Type.any] = kw_tys[nil] }
390
- else
391
- kw_rest_ty = Type.gen_hash do |h|
392
- kw_tys.each do |key, ty|
393
- sym = Type::Symbol.new(key, Type::Instance.new(Type::Builtin[:sym]))
394
- h[sym] = ty
395
- end
396
- end
397
- end
398
- locals[kwrest_index] = kw_rest_ty
399
- else
400
- if !kw_tys.empty?
401
- return "unknown keyword: #{ kw_tys.keys.join(", ") }"
402
- end
403
- end
404
-
405
- if block_index
406
- locals[block_index] = @blk_ty
407
- end
408
-
409
- start_pcs = opt[0..opt_count]
410
-
411
- return @blk_ty, start_pcs
412
- end
413
- end
414
- end
@@ -1,176 +0,0 @@
1
- module TypeProf
2
- class Block
3
- include Utils::StructuralEquality
4
- end
5
-
6
- class ISeqBlock < Block
7
- def initialize(iseq, ep)
8
- @iseq = iseq
9
- @outer_ep = ep
10
- end
11
-
12
- attr_reader :iseq, :outer_ep
13
-
14
- def inspect
15
- "#<ISeqBlock: #{ @outer_ep.source_location }>"
16
- end
17
-
18
- def consistent?(other)
19
- if other.is_a?(ISeqBlock)
20
- self == other
21
- else
22
- true # XXX
23
- end
24
- end
25
-
26
- def substitute(_subst, _depth)
27
- self
28
- end
29
-
30
- def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, replace_cref:, &ctn)
31
- blk_env = scratch.return_envs[@outer_ep]
32
- if replace_recv_ty
33
- replace_recv_ty = scratch.globalize_type(replace_recv_ty, caller_env, caller_ep)
34
- blk_env = blk_env.replace_recv_ty(replace_recv_ty)
35
- end
36
- aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
37
-
38
- scratch.add_block_signature!(self, aargs.to_block_signature)
39
-
40
- locals = [Type.nil] * @iseq.locals.size
41
-
42
- blk_ty, start_pcs = aargs.setup_formal_arguments(:block, locals, @iseq.fargs_format)
43
- if blk_ty.is_a?(String)
44
- scratch.error(caller_ep, blk_ty)
45
- ctn[Type.any, caller_ep, caller_env]
46
- return
47
- end
48
-
49
- cref = replace_cref || @outer_ep.ctx.cref
50
- nctx = Context.new(@iseq, cref, nil)
51
- callee_ep = ExecutionPoint.new(nctx, 0, @outer_ep)
52
- nenv = Env.new(blk_env.static_env, locals, [], nil)
53
- alloc_site = AllocationSite.new(callee_ep)
54
- locals.each_with_index do |ty, i|
55
- alloc_site2 = alloc_site.add_id(i)
56
- nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
57
- nenv = nenv.local_update(i, ty)
58
- end
59
-
60
- start_pcs.each do |start_pc|
61
- scratch.merge_env(ExecutionPoint.new(nctx, start_pc, @outer_ep), nenv)
62
- end
63
-
64
- scratch.add_block_to_ctx!(self, callee_ep.ctx)
65
- scratch.add_callsite!(callee_ep.ctx, caller_ep, caller_env, &ctn)
66
- end
67
- end
68
-
69
- class TypedBlock < Block
70
- def initialize(msig, ret_ty)
71
- @msig = msig
72
- @ret_ty = ret_ty
73
- end
74
-
75
- attr_reader :msig, :ret_ty
76
-
77
- def consistent?(other)
78
- if other.is_a?(ISeqBlock)
79
- raise "assert false"
80
- else
81
- self == other
82
- end
83
- end
84
-
85
- def substitute(subst, depth)
86
- msig = @msig.substitute(subst, depth)
87
- ret_ty = @ret_ty.substitute(subst, depth)
88
- TypedBlock.new(msig, ret_ty)
89
- end
90
-
91
- def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, replace_cref:, &ctn)
92
- aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
93
- subst = aargs.consistent_with_method_signature?(@msig)
94
- unless subst
95
- scratch.warn(caller_ep, "The arguments is not compatible to RBS block")
96
- end
97
- # check?
98
- #subst = { Type::Var.new(:self) => caller_env.static_env.recv_ty }
99
- # XXX: Update type vars
100
- ret_ty = @ret_ty.remove_type_vars
101
- ctn[ret_ty, caller_ep, caller_env]
102
- end
103
- end
104
-
105
- class SymbolBlock < Block
106
- def initialize(sym)
107
- @sym = sym
108
- end
109
-
110
- attr_reader :iseq, :outer_ep
111
-
112
- def inspect
113
- "#<SymbolBlock: #{ @sym }>"
114
- end
115
-
116
- def consistent?(other)
117
- true # XXX
118
- end
119
-
120
- def substitute(_subst, _depth)
121
- self
122
- end
123
-
124
- def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, replace_cref:, &ctn)
125
- if aargs.lead_tys.size >= 1
126
- recv = aargs.lead_tys[0]
127
- recv = Type.any if recv == Type.bot
128
- aargs = ActualArguments.new(aargs.lead_tys[1..], aargs.rest_ty, aargs.kw_tys, aargs.blk_ty)
129
- elsif aargs.rest_ty
130
- recv = aargs.rest_ty.elems.squash_or_any # XXX: need to shift
131
- else
132
- recv = Type.any
133
- end
134
-
135
- scratch.add_block_signature!(self, aargs.to_block_signature)
136
-
137
- recv.each_child do |recv|
138
- scratch.do_send(recv, @sym, aargs, caller_ep, caller_env, &ctn)
139
- end
140
- end
141
- end
142
-
143
- class CustomBlock < Block
144
- def initialize(caller_ep, mid, &blk)
145
- @caller_ep = caller_ep
146
- @mid = mid
147
- @blk = blk
148
- end
149
-
150
- def inspect
151
- "#<CustomBlock>"
152
- end
153
-
154
- def consistent?(other)
155
- true # XXX
156
- end
157
-
158
- def substitute(_subst, _depth)
159
- self
160
- end
161
-
162
- def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, replace_cref:, &ctn)
163
- aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
164
-
165
- dummy_ctx = TypedContext.new(@caller_ep, @mid)
166
-
167
- scratch.add_block_signature!(self, aargs.to_block_signature)
168
- scratch.add_block_to_ctx!(self, dummy_ctx)
169
-
170
- @blk.call(aargs, caller_ep, caller_env, scratch, replace_recv_ty: replace_recv_ty, replace_cref: replace_cref) do |ret_ty, ep, env|
171
- scratch.add_return_value!(dummy_ctx, ret_ty)
172
- ctn[ret_ty, ep, env]
173
- end
174
- end
175
- end
176
- end