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,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