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.
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,893 +0,0 @@
1
- module TypeProf
2
- module Builtin
3
- module_function
4
-
5
- def get_sym(target, ty, ep, scratch)
6
- unless ty.is_a?(Type::Symbol)
7
- scratch.warn(ep, "symbol expected")
8
- return
9
- end
10
- sym = ty.sym
11
- unless sym
12
- scratch.warn(ep, "dynamic symbol is given to #{ target }; ignored")
13
- return
14
- end
15
- sym
16
- end
17
-
18
- def vmcore_set_method_alias(recv, mid, aargs, ep, env, scratch, &ctn)
19
- klass, new_mid, old_mid = aargs.lead_tys
20
- new_sym = get_sym("alias", new_mid, ep, scratch) or return
21
- old_sym = get_sym("alias", old_mid, ep, scratch) or return
22
- scratch.alias_method(klass, ep.ctx.cref.singleton, new_sym, old_sym, ep)
23
- ctn[Type.nil, ep, env]
24
- end
25
-
26
- def vmcore_undef_method(recv, mid, aargs, ep, env, scratch, &ctn)
27
- # no-op
28
- ctn[Type.nil, ep, env]
29
- end
30
-
31
- def vmcore_hash_merge_kwd(recv, mid, aargs, ep, env, scratch, &ctn)
32
- h1 = aargs.lead_tys[0]
33
- h2 = aargs.lead_tys[1]
34
- elems = nil
35
- h1.each_child do |h1|
36
- if h1.is_a?(Type::Local) && h1.kind == Type::Hash
37
- h1_elems = scratch.get_container_elem_types(env, ep, h1.id)
38
- h2.each_child do |h2|
39
- if h2.is_a?(Type::Local) && h2.kind == Type::Hash
40
- h2_elems = scratch.get_container_elem_types(env, ep, h2.id)
41
- elems0 = h1_elems.union(h2_elems)
42
- if elems
43
- elems = elems.union(elems0)
44
- else
45
- elems = elems0
46
- end
47
- end
48
- end
49
- end
50
- end
51
- elems ||= Type::Hash::Elements.new({Type.any => Type.any})
52
- base_ty = Type::Instance.new(Type::Builtin[:hash])
53
- ret_ty = Type::Hash.new(elems, base_ty)
54
- ctn[ret_ty, ep, env]
55
- end
56
-
57
- def vmcore_raise(recv, mid, aargs, ep, env, scratch, &ctn)
58
- # no-op
59
- end
60
-
61
- def lambda(recv, mid, aargs, ep, env, scratch, &ctn)
62
- ctn[aargs.blk_ty, ep, env]
63
- end
64
-
65
- def proc_call(recv, mid, aargs, ep, env, scratch, &ctn)
66
- scratch.do_invoke_block(recv, aargs, ep, env, &ctn)
67
- end
68
-
69
- def object_s_new(recv, mid, aargs, ep, env, scratch, &ctn)
70
- if recv.type_params.size >= 1
71
- ty = Type::ContainerType.create_empty_instance(recv)
72
- env, ty = scratch.localize_type(ty, env, ep, AllocationSite.new(ep).add_id(:object_s_new))
73
- else
74
- ty = Type::Instance.new(recv)
75
- end
76
- meths = scratch.get_method(recv, false, false, :initialize)
77
- meths.flat_map do |meth|
78
- meth.do_send(ty, :initialize, aargs, ep, env, scratch) do |_ret_ty, ep, env|
79
- ctn[ty, ep, env]
80
- end
81
- end
82
- end
83
-
84
- def object_is_a?(recv, mid, aargs, ep, env, scratch, &ctn)
85
- if aargs.lead_tys.size == 1
86
- if recv.is_a?(Type::Instance)
87
- if recv.klass == aargs.lead_tys[0] # XXX: inheritance
88
- true_val = Type::Instance.new(Type::Builtin[:true])
89
- ctn[true_val, ep, env]
90
- else
91
- false_val = Type::Instance.new(Type::Builtin[:false])
92
- ctn[false_val, ep, env]
93
- end
94
- else
95
- ctn[Type.bool, ep, env]
96
- end
97
- else
98
- ctn[Type.bool, ep, env]
99
- end
100
- end
101
-
102
- def object_respond_to?(recv, mid, aargs, ep, env, scratch, &ctn)
103
- if aargs.lead_tys.size == 1
104
- sym = get_sym("respond_to?", aargs.lead_tys[0], ep, scratch)
105
- if sym
106
- klass, singleton = recv.method_dispatch_info
107
- if scratch.get_method(klass, singleton, false, sym)
108
- true_val = Type::Instance.new(Type::Builtin[:true])
109
- ctn[true_val, ep, env]
110
- else
111
- false_val = Type::Instance.new(Type::Builtin[:false])
112
- ctn[false_val, ep, env]
113
- end
114
- else
115
- ctn[Type.bool, ep, env]
116
- end
117
- else
118
- ctn[Type.bool, ep, env]
119
- end
120
- end
121
-
122
- def object_class(recv, mid, aargs, ep, env, scratch, &ctn)
123
- if recv.is_a?(Type::Instance)
124
- ctn[recv.klass, ep, env]
125
- else
126
- ctn[Type.any, ep, env]
127
- end
128
- end
129
-
130
- def object_send(recv, mid, aargs, ep, env, scratch, &ctn)
131
- if aargs.lead_tys.size >= 1
132
- mid_ty, = aargs.lead_tys
133
- elsif aargs.rest_ty
134
- mid_ty = aargs.rest_ty
135
- else
136
- return ctn[Type.any, ep, env]
137
- end
138
- aargs = ActualArguments.new(aargs.lead_tys[1..] || [], aargs.rest_ty, aargs.kw_tys, aargs.blk_ty)
139
- found = false
140
- mid_ty.each_child do |mid|
141
- if mid.is_a?(Type::Symbol)
142
- found = true
143
- mid = mid.sym
144
- scratch.do_send(recv, mid, aargs, ep, env, &ctn)
145
- end
146
- end
147
- unless found
148
- ctn[Type.any, ep, env]
149
- end
150
- end
151
-
152
- def object_instance_eval(recv, mid, aargs, ep, env, scratch, &ctn)
153
- if aargs.lead_tys.size >= 1
154
- scratch.warn(ep, "instance_eval with arguments is ignored")
155
- ctn[Type.any, ep, env]
156
- return
157
- end
158
- naargs = ActualArguments.new([recv], nil, {}, Type.nil)
159
- nrecv = recv
160
- nrecv = nrecv.base_type if nrecv.is_a?(Type::ContainerType)
161
- scratch.do_invoke_block(aargs.blk_ty, naargs, ep, env, replace_recv_ty: nrecv) do |ret_ty, ep|
162
- ctn[ret_ty, ep, env]
163
- end
164
- end
165
-
166
- def module_eqq(recv, mid, aargs, ep, env, scratch, &ctn)
167
- if aargs.lead_tys.size == 1
168
- aargs.lead_tys[0].each_child do |aarg|
169
- aarg = aarg.base_type if aarg.is_a?(Type::Symbol) # XXX
170
- if aarg.is_a?(Type::Instance)
171
- if aarg.klass == recv # XXX: inheritance
172
- true_val = Type::Instance.new(Type::Builtin[:true])
173
- ctn[true_val, ep, env]
174
- else
175
- false_val = Type::Instance.new(Type::Builtin[:false])
176
- ctn[false_val, ep, env]
177
- end
178
- else
179
- ctn[Type.bool, ep, env]
180
- end
181
- end
182
- else
183
- ctn[Type.bool, ep, env]
184
- end
185
- end
186
-
187
- def object_module_eval(recv, mid, aargs, ep, env, scratch, &ctn)
188
- if aargs.lead_tys.size >= 1
189
- scratch.warn(ep, "class_eval with arguments is ignored")
190
- ctn[Type.any, ep, env]
191
- return
192
- end
193
- naargs = ActualArguments.new([recv], nil, {}, Type.nil)
194
- nrecv = recv
195
- nrecv = nrecv.base_type if nrecv.is_a?(Type::ContainerType)
196
- ncref = ep.ctx.cref.extend(nrecv, true)
197
- scratch.do_invoke_block(aargs.blk_ty, naargs, ep, env, replace_recv_ty: nrecv, replace_cref: ncref) do |_ret_ty, ep|
198
- ctn[recv, ep, env]
199
- end
200
- end
201
-
202
- def object_enum_for(recv, mid, aargs, ep, env, scratch, &ctn)
203
- if aargs.lead_tys.size >= 1
204
- mid_ty, = aargs.lead_tys
205
- naargs = ActualArguments.new(aargs.lead_tys[1..], aargs.rest_ty, aargs.kw_tys, aargs.blk_ty)
206
- elsif aargs.rest_ty
207
- mid_ty = aargs.rest_ty
208
- naargs = aargs
209
- else
210
- mid_ty = Type::Symbol.new(:each, Type::Instance.new(Type::Builtin[:sym]))
211
- naargs = aargs
212
- end
213
-
214
- elem_ty = Type.bot
215
- enum_for_blk = CustomBlock.new(ep, mid) do |aargs, caller_ep, caller_env, scratch, replace_recv_ty:, replace_cref:, &blk_ctn|
216
- if aargs.lead_tys.size >= 1
217
- elem_ty = elem_ty.union(aargs.lead_tys[0])
218
- else
219
- elem_ty = elem_ty.union(Type.any)
220
- end
221
- ctn[Type::Cell.new(Type::Cell::Elements.new([elem_ty, Type.any]), Type::Instance.new(Type::Builtin[:enumerator])), ep, env]
222
- blk_ctn[Type.any, caller_ep, caller_env]
223
- end
224
- enum_for_blk_ty = Type::Proc.new(enum_for_blk, Type::Instance.new(Type::Builtin[:proc]))
225
-
226
- naargs = ActualArguments.new(naargs.lead_tys, naargs.rest_ty, naargs.kw_tys, enum_for_blk_ty)
227
- mid_ty.each_child do |mid|
228
- if mid.is_a?(Type::Symbol)
229
- mid = mid.sym
230
- scratch.do_send(recv, mid, naargs, ep, env) do |_ret_ty, _ep|
231
- ctn[Type::Cell.new(Type::Cell::Elements.new([elem_ty, Type.any]), Type::Instance.new(Type::Builtin[:enumerator])), ep, env]
232
- end
233
- end
234
- end
235
- end
236
-
237
- def object_privitive_method(recv, mid, aargs, ep, env, scratch, &ctn)
238
- ctn[Type::Symbol.new(ep.ctx.mid, Type::Instance.new(Type::Builtin[:sym])), ep, env]
239
- end
240
-
241
- def object_block_given?(recv, mid, aargs, ep, env, scratch, &ctn)
242
- procs = Type.bot
243
- no_proc = false
244
- env.static_env.blk_ty.each_child do |blk_ty|
245
- case blk_ty
246
- when Type::Proc
247
- procs = procs.union(blk_ty)
248
- when Type.nil
249
- no_proc = true
250
- else
251
- ctn[Type.bool, ep, env]
252
- end
253
- end
254
- if procs != Type.bot
255
- ctn[Type::Instance.new(Type::Builtin[:true]), ep, env.replace_blk_ty(procs)]
256
- end
257
- if no_proc
258
- ctn[Type::Instance.new(Type::Builtin[:false]), ep, env.replace_blk_ty(Type.nil)]
259
- end
260
- end
261
-
262
- def module_include(recv, mid, aargs, ep, env, scratch, &ctn)
263
- if aargs.lead_tys.size != 1
264
- scratch.warn(ep, "Module#include without an argument is ignored")
265
- ctn[Type.any, ep, env]
266
- return
267
- end
268
-
269
- unless recv.is_a?(Type::Class)
270
- # XXX: warn?
271
- return ctn[Type.any, ep, env]
272
- end
273
-
274
- # support multiple arguments: include M1, M2
275
- arg = aargs.lead_tys[0]
276
- arg.each_child do |arg|
277
- if arg.is_a?(Type::Class)
278
- aargs = ActualArguments.new([recv], nil, {}, Type.nil)
279
- scratch.do_send(arg, :included, aargs, ep, env) {|_ret_ty, _ep| }
280
- scratch.mix_module(:after, recv, arg, nil, ep.ctx.cref.singleton, ep)
281
- end
282
- end
283
- ctn[recv, ep, env]
284
- end
285
-
286
- def module_extend(recv, mid, aargs, ep, env, scratch, &ctn)
287
- if aargs.lead_tys.size != 1
288
- scratch.warn(ep, "Module#extend without an argument is ignored")
289
- ctn[Type.any, ep, env]
290
- return
291
- end
292
-
293
- unless recv.is_a?(Type::Class)
294
- # XXX: warn?
295
- return ctn[Type.any, ep, env]
296
- end
297
-
298
- arg = aargs.lead_tys[0]
299
- arg.each_child do |arg|
300
- if arg.is_a?(Type::Class)
301
- aargs = ActualArguments.new([recv], nil, {}, Type.nil)
302
- scratch.do_send(arg, :extended, aargs, ep, env) {|_ret_ty, _ep| }
303
- # if ep.ctx.cref.singleton is true, the meta-meta level is ignored. Should we warn?
304
- scratch.mix_module(:after, recv, arg, nil, true, ep)
305
- end
306
- end
307
- ctn[recv, ep, env]
308
- end
309
-
310
- def module_prepend(recv, mid, aargs, ep, env, scratch, &ctn)
311
- if aargs.lead_tys.size != 1
312
- scratch.warn(ep, "Module#prepend without an argument is ignored")
313
- ctn[Type.any, ep, env]
314
- return
315
- end
316
-
317
- unless recv.is_a?(Type::Class)
318
- # XXX: warn?
319
- return ctn[Type.any, ep, env]
320
- end
321
-
322
- arg = aargs.lead_tys[0]
323
- arg.each_child do |arg|
324
- if arg.is_a?(Type::Class)
325
- scratch.mix_module(:before, recv, arg, nil, ep.ctx.cref.singleton, ep)
326
- end
327
- end
328
- ctn[recv, ep, env]
329
- end
330
-
331
- def module_module_function(recv, mid, aargs, ep, env, scratch, &ctn)
332
- if aargs.lead_tys.empty?
333
- ctn[recv, ep, env.enable_module_function]
334
- else
335
- aargs.lead_tys.each do |aarg|
336
- sym = get_sym("module_function", aarg, ep, scratch) or next
337
- meths = scratch.get_method(recv, false, false, sym)
338
- meths.each do |mdef|
339
- scratch.add_method(recv, sym, true, mdef)
340
- end
341
- end
342
- ctn[recv, ep, env]
343
- end
344
- end
345
-
346
- def module_public(recv, mid, aargs, ep, env, scratch, &ctn)
347
- if aargs.lead_tys.empty?
348
- ctn[recv, ep, env.method_public_set(true)]
349
- else
350
- if recv.is_a?(Type::Class)
351
- aargs.lead_tys.each do |aarg|
352
- sym = get_sym("public", aarg, ep, scratch) or next
353
- meths = scratch.get_method(recv, false, false, sym)
354
- next unless meths
355
- meths.each do |mdef|
356
- mdef.pub_meth = true if mdef.respond_to?(:pub_meth=)
357
- end
358
- end
359
- else
360
- # XXX: warn?
361
- end
362
- ctn[recv, ep, env]
363
- end
364
- end
365
-
366
- def module_private(recv, mid, aargs, ep, env, scratch, &ctn)
367
- if aargs.lead_tys.empty?
368
- ctn[recv, ep, env.method_public_set(false)]
369
- else
370
- if recv.is_a?(Type::Class)
371
- aargs.lead_tys.each do |aarg|
372
- sym = get_sym("private", aarg, ep, scratch) or next
373
- meths = scratch.get_method(recv, false, false, sym)
374
- next unless meths
375
- meths.each do |mdef|
376
- mdef.pub_meth = false if mdef.respond_to?(:pub_meth=)
377
- end
378
- end
379
- else
380
- # XXX: warn?
381
- end
382
- ctn[recv, ep, env]
383
- end
384
- end
385
-
386
- def module_define_method(recv, mid, aargs, ep, env, scratch, &ctn)
387
- if aargs.lead_tys.size != 1
388
- scratch.warn(ep, "Module#define with #{ aargs.lead_tys.size } argument is ignored")
389
- ctn[Type.any, ep, env]
390
- return
391
- end
392
-
393
- mid, = aargs.lead_tys
394
- mid.each_child do |mid|
395
- if mid.is_a?(Type::Symbol)
396
- mid = mid.sym
397
- aargs.blk_ty.each_child do |blk_ty|
398
- if blk_ty.is_a?(Type::Proc)
399
- blk = blk_ty.block_body
400
- case blk
401
- when ISeqBlock
402
- scratch.do_define_iseq_method(ep, env, mid, blk.iseq, blk.outer_ep)
403
- else
404
- # XXX: what to do?
405
- end
406
- else
407
- # XXX: what to do?
408
- end
409
- end
410
- else
411
- # XXX: what to do?
412
- end
413
- end
414
- ctn[Type.any, ep, env]
415
- end
416
-
417
- def module_attr_accessor(recv, mid, aargs, ep, env, scratch, &ctn)
418
- aargs.lead_tys.each do |aarg|
419
- sym = get_sym("attr_accessor", aarg, ep, scratch) or next
420
- cref = ep.ctx.cref
421
- scratch.add_attr_method(cref.klass, sym, :"@#{ sym }", :accessor, env.static_env.pub_meth, ep)
422
- end
423
- ctn[Type.nil, ep, env]
424
- end
425
-
426
- def module_attr_reader(recv, mid, aargs, ep, env, scratch, &ctn)
427
- aargs.lead_tys.each do |aarg|
428
- sym = get_sym("attr_reader", aarg, ep, scratch) or next
429
- cref = ep.ctx.cref
430
- scratch.add_attr_method(cref.klass, sym, :"@#{ sym }", :reader, env.static_env.pub_meth, ep)
431
- end
432
- ctn[Type.nil, ep, env]
433
- end
434
-
435
- def module_attr_writer(recv, mid, aargs, ep, env, scratch, &ctn)
436
- aargs.lead_tys.each do |aarg|
437
- sym = get_sym("attr_writer", aarg, ep, scratch) or next
438
- cref = ep.ctx.cref
439
- scratch.add_attr_method(cref.klass, sym, :"@#{ sym }", :writer, env.static_env.pub_meth, ep)
440
- end
441
- ctn[Type.nil, ep, env]
442
- end
443
-
444
- def kernel_p(recv, mid, aargs, ep, env, scratch, &ctn)
445
- aargs.lead_tys.each do |aarg|
446
- scratch.reveal_type(ep, scratch.globalize_type(aarg, env, ep))
447
- end
448
- ctn[aargs.lead_tys.size == 1 ? aargs.lead_tys.first : Type.any, ep, env]
449
- end
450
-
451
- def array_aref(recv, mid, aargs, ep, env, scratch, &ctn)
452
- return ctn[Type.any, ep, env] unless recv.is_a?(Type::Local) && recv.kind == Type::Array
453
-
454
- case aargs.lead_tys.size
455
- when 1
456
- idx = aargs.lead_tys.first
457
- if idx.is_a?(Type::Literal)
458
- idx = idx.lit
459
- idx = nil if !idx.is_a?(Integer) && !idx.is_a?(Range)
460
- elsif idx == Type::Instance.new(Type::Builtin[:range])
461
- idx = (nil..nil)
462
- else
463
- idx = nil
464
- end
465
- ty = scratch.get_array_elem_type(env, ep, recv.id, idx)
466
- ctn[ty, ep, env]
467
- when 2
468
- ty = scratch.get_array_elem_type(env, ep, recv.id)
469
- base_ty = Type::Instance.new(Type::Builtin[:ary])
470
- ret_ty = Type::Array.new(Type::Array::Elements.new([], ty), base_ty)
471
- ctn[ret_ty, ep, env]
472
- else
473
- ctn[Type.any, ep, env]
474
- end
475
- end
476
-
477
- def array_aset(recv, mid, aargs, ep, env, scratch, &ctn)
478
- return ctn[Type.any, ep, env] unless recv.is_a?(Type::Local) && recv.kind == Type::Array
479
-
480
- if aargs.lead_tys.size != 2
481
- # XXX: Support `ary[idx, len] = val`
482
- #raise NotImplementedError # XXX
483
- return ctn[Type.any, ep, env]
484
- end
485
-
486
- idx = aargs.lead_tys.first
487
- if idx.is_a?(Type::Literal)
488
- idx = idx.lit
489
- if !idx.is_a?(Integer)
490
- # XXX: Support `ary[idx..end] = val`
491
- #raise NotImplementedError # XXX
492
- return ctn[Type.any, ep, env]
493
- end
494
- else
495
- idx = nil
496
- end
497
-
498
- ty = aargs.lead_tys.last
499
-
500
- env = scratch.update_container_elem_types(env, ep, recv.id, recv.base_type) do |elems|
501
- elems.update(idx, ty)
502
- end
503
-
504
- ctn[ty, ep, env]
505
- end
506
-
507
- def array_pop(recv, mid, aargs, ep, env, scratch, &ctn)
508
- return ctn[Type.any, ep, env] unless recv.is_a?(Type::Local) && recv.kind == Type::Array
509
-
510
- if aargs.lead_tys.size != 0
511
- ctn[Type.any, ep, env]
512
- return
513
- end
514
-
515
- ty = scratch.get_array_elem_type(env, ep, recv.id)
516
- ctn[ty, ep, env]
517
- end
518
-
519
- def hash_aref(recv, mid, aargs, ep, env, scratch, &ctn)
520
- return ctn[Type.any, ep, env] unless recv.is_a?(Type::Local) && recv.kind == Type::Hash
521
-
522
- if aargs.lead_tys.size != 1
523
- ctn[Type.any, ep, env]
524
- return
525
- end
526
- idx = aargs.lead_tys.first
527
- recv.each_child do |recv|
528
- if recv.is_a?(Type::Local) && recv.kind == Type::Hash
529
- ty = scratch.get_hash_elem_type(env, ep, recv.id, idx)
530
- ty = Type.nil if ty == Type.bot
531
- else
532
- ty = Type.any
533
- end
534
- ctn[ty, ep, env]
535
- end
536
- end
537
-
538
- def hash_aset(recv, mid, aargs, ep, env, scratch, &ctn)
539
- return ctn[Type.any, ep, env] unless recv.is_a?(Type::Local) && recv.kind == Type::Hash
540
-
541
- if aargs.lead_tys.size != 2
542
- # XXX: error?
543
- ctn[Type.any, ep, env]
544
- return
545
- end
546
-
547
- idx = aargs.lead_tys.first
548
- idx = scratch.globalize_type(idx, env, ep)
549
- ty = aargs.lead_tys.last
550
-
551
- unless recv.is_a?(Type::Local) && recv.kind == Type::Hash
552
- # to ignore: class OptionMap < Hash
553
- return ctn[ty, ep, env]
554
- end
555
-
556
- env = scratch.update_container_elem_types(env, ep, recv.id, recv.base_type) do |elems|
557
- elems.update(idx, ty)
558
- end
559
-
560
- ctn[ty, ep, env]
561
- end
562
-
563
- def struct_initialize(recv, mid, aargs, ep, env, scratch, &ctn)
564
- struct_klass = recv.klass
565
- while struct_klass.superclass != Type::Builtin[:struct]
566
- struct_klass = struct_klass.superclass
567
- end
568
- if struct_klass.superclass != Type::Builtin[:struct]
569
- ctn[Type.any, ep, env]
570
- return
571
- end
572
- scratch.add_ivar_read!(Type::Instance.new(struct_klass), :_keyword_init, ep) do |keyword_init, ep|
573
- scratch.add_ivar_read!(Type::Instance.new(struct_klass), :_members, ep) do |member_ary_ty, ep|
574
- next if member_ary_ty == Type.nil
575
- if keyword_init == Type::Instance.new(Type::Builtin[:true])
576
- # TODO: support kw_rest_ty
577
- aargs.kw_tys.each do |key, val_ty|
578
- found = false
579
- member_ary_ty.elems.lead_tys.each do |sym|
580
- if sym.sym == key
581
- found = true
582
- scratch.set_instance_variable(recv, sym.sym, val_ty, ep, env)
583
- end
584
- end
585
- unless found
586
- # TODO: what to do when not found?
587
- end
588
- end
589
- else
590
- member_ary_ty.elems.lead_tys.zip(aargs.lead_tys) do |sym, ty|
591
- ty ||= Type.nil
592
- scratch.set_instance_variable(recv, sym.sym, ty, ep, env)
593
- end
594
- end
595
- end
596
- end
597
- ctn[recv, ep, env]
598
- end
599
-
600
- def struct_s_new(recv, mid, aargs, ep, env, scratch, &ctn)
601
- keyword_init = false
602
- if aargs.kw_tys && aargs.kw_tys[:keyword_init] # XXX: more canonical way to extract keyword...
603
- if aargs.kw_tys[:keyword_init] == Type::Instance.new(Type::Builtin[:true])
604
- keyword_init = true
605
- end
606
- end
607
-
608
- fields = aargs.lead_tys.map {|ty| get_sym("Struct.new", ty, ep, scratch) }.compact
609
- struct_klass = scratch.new_struct(ep)
610
-
611
- scratch.set_singleton_custom_method(struct_klass, :new, Builtin.method(:object_s_new))
612
- scratch.set_singleton_custom_method(struct_klass, :[], Builtin.method(:object_s_new))
613
- fields.each do |field|
614
- scratch.add_attr_method(struct_klass, field, field, :accessor, true, ep)
615
- end
616
- fields = fields.map {|field| Type::Symbol.new(field, Type::Instance.new(Type::Builtin[:sym])) }
617
- base_ty = Type::Instance.new(Type::Builtin[:ary])
618
- fields = Type::Array.new(Type::Array::Elements.new(fields), base_ty)
619
- scratch.add_ivar_write!(Type::Instance.new(struct_klass), :_members, fields, ep)
620
- scratch.add_ivar_write!(Type::Instance.new(struct_klass), :_keyword_init, Type::Instance.new(Type::Builtin[:true]), ep) if keyword_init
621
- #set_singleton_custom_method(struct_klass, :members, Builtin.method(:...))
622
-
623
- ctn[struct_klass, ep, env]
624
- end
625
-
626
- def self.file_load(path, ep, env, scratch, &ctn)
627
- iseq, = ISeq.compile(path)
628
- callee_ep, callee_env = TypeProf.starting_state(iseq)
629
- scratch.merge_env(callee_ep, callee_env)
630
-
631
- scratch.add_callsite!(callee_ep.ctx, ep, env) do |_ret_ty, ep|
632
- ret_ty = Type::Instance.new(Type::Builtin[:true])
633
- ctn[ret_ty, ep, env]
634
- end
635
- end
636
-
637
- def self.file_require(feature, scratch)
638
- # XXX: dynamic RBS load is really needed?? Another idea:
639
- #
640
- # * RBS should be loaded in advance of analysis
641
- # * require "some_gem/foo" should be ignored
642
- # * require "app/foo" should always load .rb file (in this case, app/foo.rb)
643
- return :done, :true if Import.import_library(scratch, feature)
644
-
645
- # Try to analyze the source code of the gem
646
- begin
647
- gem feature
648
- rescue Gem::MissingSpecError, Gem::LoadError
649
- end
650
-
651
- begin
652
- filetype, path = $LOAD_PATH.resolve_feature_path(feature)
653
-
654
- if filetype == :rb
655
- return :done, :false if scratch.loaded_files[path]
656
- scratch.loaded_files[path] = true
657
-
658
- return :do, path if File.readable?(path)
659
-
660
- return :error, "failed to load: #{ path }"
661
- else
662
- return :error, "cannot load a .so file: #{ path }"
663
- end
664
- rescue LoadError
665
- return :error, "failed to require: #{ feature }"
666
- end
667
- end
668
-
669
- def kernel_require(recv, mid, aargs, ep, env, scratch, &ctn)
670
- if aargs.lead_tys.size != 1
671
- # XXX: handle correctly
672
- ctn[Type.any, ep, env]
673
- return
674
- end
675
-
676
- feature = aargs.lead_tys.first
677
- if feature.is_a?(Type::Literal)
678
- feature = feature.lit
679
-
680
- unless feature.is_a?(String)
681
- return ctn[Type.any, ep, env]
682
- end
683
-
684
- action, arg = Builtin.file_require(feature, scratch)
685
- case action
686
- when :do
687
- Builtin.file_load(arg, ep, env, scratch, &ctn)
688
- when :done
689
- result = Type::Instance.new(Type::Builtin[arg])
690
- ctn[result, ep, env]
691
- when :error
692
- scratch.warn(ep, arg)
693
- result = Type.bool
694
- ctn[result, ep, env]
695
- end
696
- else
697
- scratch.warn(ep, "require target cannot be identified statically")
698
- result = Type.bool
699
- ctn[result, ep, env]
700
- end
701
- end
702
-
703
- def kernel_require_relative(recv, mid, aargs, ep, env, scratch, &ctn)
704
- if aargs.lead_tys.size != 1
705
- # XXX: handle correctly
706
- ctn[Type.any, ep, env]
707
- return
708
- end
709
-
710
- feature = aargs.lead_tys.first
711
- if feature.is_a?(Type::Literal)
712
- feature = feature.lit
713
-
714
- unless feature.is_a?(String)
715
- return ctn[Type.any, ep, env]
716
- end
717
-
718
- path = File.join(File.dirname(ep.ctx.iseq.absolute_path), feature) + ".rb" # XXX
719
-
720
- if scratch.loaded_files[path]
721
- result = Type::Instance.new(Type::Builtin[:false])
722
- return ctn[result, ep, env]
723
- end
724
- scratch.loaded_files[path] = true
725
-
726
- return Builtin.file_load(path, ep, env, scratch, &ctn) if File.readable?(path)
727
-
728
- scratch.warn(ep, "failed to load: #{ path }")
729
- else
730
- scratch.warn(ep, "require target cannot be identified statically")
731
- feature = nil
732
- end
733
-
734
- result = Type::Instance.new(Type::Builtin[:true])
735
- ctn[result, ep, env]
736
- end
737
-
738
- def kernel_autoload(recv, mid, aargs, ep, env, scratch, &ctn)
739
- if aargs.lead_tys.size != 2
740
- # XXX: handle correctly
741
- ctn[Type.any, ep, env]
742
- return
743
- end
744
-
745
- feature = aargs.lead_tys[1]
746
- if feature.is_a?(Type::Literal)
747
- feature = feature.lit
748
-
749
- action, arg = Builtin.file_require(feature, scratch)
750
- case action
751
- when :do
752
- Builtin.file_load(arg, ep, env, scratch, &ctn)
753
- when :done
754
- when :error
755
- scratch.warn(ep, arg)
756
- end
757
- ctn[Type.nil, ep, env]
758
- else
759
- scratch.warn(ep, "autoload target cannot be identified statically")
760
- ctn[Type.nil, ep, env]
761
- end
762
- end
763
-
764
- def module_autoload(recv, mid, aargs, ep, env, scratch, &ctn)
765
- kernel_autoload(recv, mid, aargs, ep, env, scratch, &ctn)
766
- end
767
-
768
- def kernel_Array(recv, mid, aargs, ep, env, scratch, &ctn)
769
- raise NotImplementedError if aargs.lead_tys.size != 1
770
- ty = aargs.lead_tys.first
771
- ty = scratch.globalize_type(ty, env, ep)
772
- all_ty = Type.bot
773
- ty.each_child_global do |ty|
774
- if ty.is_a?(Type::Array)
775
- all_ty = all_ty.union(ty)
776
- else
777
- base_ty = Type::Instance.new(Type::Builtin[:ary])
778
- ret_ty = Type::Array.new(Type::Array::Elements.new([ty]), base_ty)
779
- all_ty = all_ty.union(ret_ty)
780
- end
781
- end
782
- ctn[all_ty, ep, env]
783
- end
784
-
785
- def self.setup_initial_global_env(scratch)
786
- klass_basic_obj = scratch.new_class(nil, :BasicObject, [], :__root__, nil) # cbase, name, superclass
787
- klass_obj = scratch.new_class(nil, :Object, [], klass_basic_obj, nil)
788
- scratch.add_constant(klass_obj, :Object, klass_obj, nil)
789
- scratch.add_constant(klass_obj, :BasicObject, klass_basic_obj, nil)
790
-
791
- Type::Builtin[:basic_obj] = klass_basic_obj
792
- Type::Builtin[:obj] = klass_obj
793
-
794
- Import.import_builtin(scratch)
795
-
796
- Type::Builtin[:vmcore] , = scratch.new_class(klass_obj, :VMCore, [], klass_obj, nil)
797
- Type::Builtin[:int] , = scratch.get_constant(klass_obj, :Integer)
798
- Type::Builtin[:float] , = scratch.get_constant(klass_obj, :Float)
799
- Type::Builtin[:rational] , = scratch.get_constant(klass_obj, :Rational)
800
- Type::Builtin[:complex] , = scratch.get_constant(klass_obj, :Complex)
801
- Type::Builtin[:sym] , = scratch.get_constant(klass_obj, :Symbol)
802
- Type::Builtin[:str] , = scratch.get_constant(klass_obj, :String)
803
- Type::Builtin[:struct] , = scratch.get_constant(klass_obj, :Struct)
804
- Type::Builtin[:ary] , = scratch.get_constant(klass_obj, :Array)
805
- Type::Builtin[:hash] , = scratch.get_constant(klass_obj, :Hash)
806
- Type::Builtin[:io] , = scratch.get_constant(klass_obj, :IO)
807
- Type::Builtin[:proc] , = scratch.get_constant(klass_obj, :Proc)
808
- Type::Builtin[:range] , = scratch.get_constant(klass_obj, :Range)
809
- Type::Builtin[:regexp] , = scratch.get_constant(klass_obj, :Regexp)
810
- Type::Builtin[:matchdata] , = scratch.get_constant(klass_obj, :MatchData)
811
- Type::Builtin[:class] , = scratch.get_constant(klass_obj, :Class)
812
- Type::Builtin[:module] , = scratch.get_constant(klass_obj, :Module)
813
- Type::Builtin[:exc] , = scratch.get_constant(klass_obj, :Exception)
814
- Type::Builtin[:encoding] , = scratch.get_constant(klass_obj, :Encoding)
815
- Type::Builtin[:enumerator] , = scratch.get_constant(klass_obj, :Enumerator)
816
- Type::Builtin[:kernel] , = scratch.get_constant(klass_obj, :Kernel)
817
-
818
- klass_vmcore = Type::Builtin[:vmcore]
819
- klass_ary = Type::Builtin[:ary]
820
- klass_hash = Type::Builtin[:hash]
821
- klass_struct = Type::Builtin[:struct]
822
- klass_proc = Type::Builtin[:proc]
823
- klass_module = Type::Builtin[:module]
824
-
825
- scratch.set_custom_method(klass_vmcore, :"core#set_method_alias", Builtin.method(:vmcore_set_method_alias))
826
- scratch.set_custom_method(klass_vmcore, :"core#undef_method", Builtin.method(:vmcore_undef_method))
827
- scratch.set_custom_method(klass_vmcore, :"core#hash_merge_kwd", Builtin.method(:vmcore_hash_merge_kwd))
828
- scratch.set_custom_method(klass_vmcore, :"core#raise", Builtin.method(:vmcore_raise))
829
-
830
- scratch.set_custom_method(klass_vmcore, :lambda, Builtin.method(:lambda))
831
- scratch.set_singleton_custom_method(klass_obj, :"new", Builtin.method(:object_s_new))
832
- scratch.set_custom_method(klass_obj, :p, Builtin.method(:kernel_p), false)
833
- scratch.set_custom_method(klass_obj, :is_a?, Builtin.method(:object_is_a?))
834
- scratch.set_custom_method(klass_obj, :respond_to?, Builtin.method(:object_respond_to?))
835
- scratch.set_custom_method(klass_obj, :class, Builtin.method(:object_class))
836
- scratch.set_custom_method(klass_obj, :send, Builtin.method(:object_send))
837
- scratch.set_custom_method(klass_obj, :instance_eval, Builtin.method(:object_instance_eval))
838
- scratch.set_custom_method(klass_obj, :proc, Builtin.method(:lambda), false)
839
- scratch.set_custom_method(klass_obj, :__method__, Builtin.method(:object_privitive_method), false)
840
- scratch.set_custom_method(klass_obj, :block_given?, Builtin.method(:object_block_given?), false)
841
-
842
- scratch.set_custom_method(klass_obj, :enum_for, Builtin.method(:object_enum_for))
843
- scratch.set_custom_method(klass_obj, :to_enum, Builtin.method(:object_enum_for))
844
-
845
- scratch.set_custom_method(klass_module, :include, Builtin.method(:module_include))
846
- scratch.set_custom_method(klass_module, :extend, Builtin.method(:module_extend))
847
- scratch.set_custom_method(klass_module, :prepend, Builtin.method(:module_prepend))
848
- scratch.set_custom_method(klass_module, :module_function, Builtin.method(:module_module_function), false)
849
- scratch.set_custom_method(klass_module, :public, Builtin.method(:module_public), false)
850
- scratch.set_custom_method(klass_module, :private, Builtin.method(:module_private), false)
851
- scratch.set_custom_method(klass_module, :define_method, Builtin.method(:module_define_method))
852
- scratch.set_custom_method(klass_module, :attr_accessor, Builtin.method(:module_attr_accessor))
853
- scratch.set_custom_method(klass_module, :attr_reader, Builtin.method(:module_attr_reader))
854
- scratch.set_custom_method(klass_module, :attr_writer, Builtin.method(:module_attr_writer))
855
- scratch.set_custom_method(klass_module, :class_eval, Builtin.method(:object_module_eval))
856
- scratch.set_custom_method(klass_module, :module_eval, Builtin.method(:object_module_eval))
857
- scratch.set_custom_method(klass_module, :===, Builtin.method(:module_eqq))
858
-
859
- scratch.set_custom_method(klass_proc, :[], Builtin.method(:proc_call))
860
- scratch.set_custom_method(klass_proc, :call, Builtin.method(:proc_call))
861
-
862
- scratch.set_custom_method(klass_ary, :[], Builtin.method(:array_aref))
863
- scratch.set_custom_method(klass_ary, :[]=, Builtin.method(:array_aset))
864
- scratch.set_custom_method(klass_ary, :pop, Builtin.method(:array_pop))
865
-
866
- scratch.set_custom_method(klass_hash, :[], Builtin.method(:hash_aref))
867
- scratch.set_custom_method(klass_hash, :[]=, Builtin.method(:hash_aset))
868
-
869
- scratch.set_custom_method(klass_struct, :initialize, Builtin.method(:struct_initialize))
870
- scratch.set_singleton_custom_method(klass_struct, :new, Builtin.method(:struct_s_new))
871
-
872
- scratch.set_custom_method(klass_obj, :require, Builtin.method(:kernel_require), false)
873
- scratch.set_custom_method(klass_obj, :require_relative, Builtin.method(:kernel_require_relative), false)
874
- scratch.set_custom_method(klass_obj, :Array, Builtin.method(:kernel_Array), false)
875
- scratch.set_custom_method(klass_obj, :autoload, Builtin.method(:kernel_autoload), false)
876
- scratch.set_custom_method(klass_module, :autoload, Builtin.method(:module_autoload))
877
-
878
- # remove BasicObject#method_missing
879
- scratch.set_method(klass_basic_obj, :method_missing, false, nil)
880
-
881
- # ENV: Hash[String, String]
882
- str_ty = Type::Instance.new(Type::Builtin[:str])
883
- env_ty = Type.gen_hash {|h| h[str_ty] = Type.optional(str_ty) }
884
- scratch.add_constant(klass_obj, :ENV, env_ty, nil)
885
-
886
- scratch.search_method(Type::Builtin[:kernel], false, :sprintf) do |mdefs,|
887
- mdefs.each do |mdef|
888
- scratch.add_method(klass_vmcore, :"core#sprintf", false, mdef)
889
- end
890
- end
891
- end
892
- end
893
- end