typeprof 0.12.0 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +10 -10
- data/lib/typeprof/analyzer.rb +236 -117
- data/lib/typeprof/block.rb +7 -6
- data/lib/typeprof/builtin.rb +63 -17
- data/lib/typeprof/cli.rb +1 -0
- data/lib/typeprof/config.rb +10 -15
- data/lib/typeprof/export.rb +10 -10
- data/lib/typeprof/import.rb +60 -22
- data/lib/typeprof/iseq.rb +100 -41
- data/lib/typeprof/type.rb +96 -46
- data/lib/typeprof/version.rb +1 -1
- data/smoke/alias2.rb +1 -1
- data/smoke/array3.rb +1 -1
- data/smoke/attr-module.rb +1 -4
- data/smoke/attr-vis.rb +1 -1
- data/smoke/attr.rb +1 -1
- data/smoke/break4.rb +17 -0
- data/smoke/class_eval.rb +22 -0
- data/smoke/define_method7.rb +18 -0
- data/smoke/extended.rb +38 -0
- data/smoke/flow11.rb +17 -0
- data/smoke/huge_union.rb +86 -0
- data/smoke/included.rb +38 -0
- data/smoke/inherited.rb +26 -0
- data/smoke/initialize.rb +1 -1
- data/smoke/instance_eval.rb +1 -1
- data/smoke/instance_eval4.rb +12 -0
- data/smoke/ivar2.rb +1 -1
- data/smoke/ivar3.rb +1 -1
- data/smoke/kwrest.rb +2 -2
- data/smoke/kwrest.rbs +1 -1
- data/smoke/method_missing.rb +1 -1
- data/smoke/noname.rb +9 -0
- data/smoke/proc6.rb +13 -0
- data/smoke/proc7.rb +32 -0
- data/smoke/rbs-tyvar4.rb +1 -1
- data/smoke/require1.rb +13 -0
- data/smoke/require2.rb +13 -0
- data/smoke/struct5.rb +1 -1
- data/smoke/struct6.rb +1 -1
- data/smoke/struct7.rb +1 -1
- data/smoke/super3.rb +1 -1
- data/smoke/symbol-proc-attr.rb +1 -1
- data/smoke/symbol-proc-attr2.rb +1 -1
- data/typeprof.gemspec +1 -1
- metadata +19 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dcefd3a4da176820246ad53757286aa1f7f8b2d21a6d1300763c91ba252e95ca
|
4
|
+
data.tar.gz: 1bf7429a4cf7d59e1ab4ca10f5f065a22b85adbbda922c67060d0ede64aab60f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff14f14aa923ca807db9d7f1bc7f537c46e735bd194a0b59758dfdba0e04c04175ca0505fe6c00f739fec7933eeeab5010646891f56e14d5245f5b8613dd7d3b
|
7
|
+
data.tar.gz: 73a05bece353a7b4dbefba9f16e723fb088795e9f029b143721b03543e53ae19a8adb9908b3de41c839fbfb10a8d34c76ed0fa4f1b072801d7334233be63b1c9
|
data/Gemfile.lock
CHANGED
@@ -1,25 +1,25 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
typeprof (0.
|
5
|
-
rbs (>= 1.
|
4
|
+
typeprof (0.15.0)
|
5
|
+
rbs (>= 1.3.1)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
10
|
coverage-helpers (1.0.0)
|
11
|
-
docile (1.
|
12
|
-
power_assert (
|
11
|
+
docile (1.4.0)
|
12
|
+
power_assert (2.0.0)
|
13
13
|
rake (13.0.1)
|
14
|
-
rbs (1.
|
15
|
-
simplecov (0.
|
14
|
+
rbs (1.3.1)
|
15
|
+
simplecov (0.21.2)
|
16
16
|
docile (~> 1.1)
|
17
17
|
simplecov-html (~> 0.11)
|
18
18
|
simplecov_json_formatter (~> 0.1)
|
19
19
|
simplecov-html (0.12.3)
|
20
|
-
simplecov_json_formatter (0.1.
|
21
|
-
stackprof (0.2.
|
22
|
-
test-unit (3.
|
20
|
+
simplecov_json_formatter (0.1.3)
|
21
|
+
stackprof (0.2.17)
|
22
|
+
test-unit (3.4.2)
|
23
23
|
power_assert
|
24
24
|
|
25
25
|
PLATFORMS
|
@@ -36,4 +36,4 @@ DEPENDENCIES
|
|
36
36
|
typeprof!
|
37
37
|
|
38
38
|
BUNDLED WITH
|
39
|
-
2.2.
|
39
|
+
2.2.15
|
data/lib/typeprof/analyzer.rb
CHANGED
@@ -42,6 +42,10 @@ module TypeProf
|
|
42
42
|
"<builtin>"
|
43
43
|
end
|
44
44
|
end
|
45
|
+
|
46
|
+
def replace_cref(cref)
|
47
|
+
Context.new(@iseq, cref, @mid)
|
48
|
+
end
|
45
49
|
end
|
46
50
|
|
47
51
|
class TypedContext
|
@@ -61,6 +65,10 @@ module TypeProf
|
|
61
65
|
"<typed-context:#{ @mid }>"
|
62
66
|
end
|
63
67
|
end
|
68
|
+
|
69
|
+
def replace_cref(cref)
|
70
|
+
# What to do?
|
71
|
+
end
|
64
72
|
end
|
65
73
|
|
66
74
|
class ExecutionPoint
|
@@ -86,6 +94,10 @@ module TypeProf
|
|
86
94
|
ExecutionPoint.new(@ctx, @pc + 1, @outer)
|
87
95
|
end
|
88
96
|
|
97
|
+
def replace_cref(cref)
|
98
|
+
ExecutionPoint.new(@ctx.replace_cref(cref), @pc, @outer)
|
99
|
+
end
|
100
|
+
|
89
101
|
def source_location
|
90
102
|
@ctx.source_location(@pc)
|
91
103
|
end
|
@@ -238,6 +250,8 @@ module TypeProf
|
|
238
250
|
end
|
239
251
|
|
240
252
|
def initialize
|
253
|
+
@entrypoints = []
|
254
|
+
|
241
255
|
@worklist = Utils::WorkList.new
|
242
256
|
|
243
257
|
@ep2env = {}
|
@@ -263,16 +277,22 @@ module TypeProf
|
|
263
277
|
@pending_execution = {}
|
264
278
|
@executed_iseqs = Utils::MutableSet.new
|
265
279
|
|
266
|
-
@
|
280
|
+
@loaded_files = {}
|
267
281
|
|
268
282
|
@rbs_reader = RBSReader.new
|
269
283
|
|
270
284
|
@terminated = false
|
271
285
|
|
272
286
|
@anonymous_struct_gen_id = 0
|
287
|
+
|
288
|
+
@types_being_shown = []
|
289
|
+
end
|
290
|
+
|
291
|
+
def add_entrypoint(iseq)
|
292
|
+
@entrypoints << iseq
|
273
293
|
end
|
274
294
|
|
275
|
-
attr_reader :return_envs, :
|
295
|
+
attr_reader :return_envs, :loaded_files, :rbs_reader
|
276
296
|
|
277
297
|
def get_env(ep)
|
278
298
|
@ep2env[ep]
|
@@ -311,9 +331,10 @@ module TypeProf
|
|
311
331
|
@cvars = VarTable.new
|
312
332
|
@absolute_path = absolute_path
|
313
333
|
@namespace = nil
|
334
|
+
@subclasses = []
|
314
335
|
end
|
315
336
|
|
316
|
-
attr_reader :kind, :modules, :consts, :methods, :ivars, :cvars, :absolute_path
|
337
|
+
attr_reader :kind, :modules, :consts, :methods, :ivars, :cvars, :absolute_path, :subclasses
|
317
338
|
attr_accessor :name, :klass_obj
|
318
339
|
|
319
340
|
def mix_module(kind, mod, type_args, singleton, absolute_path)
|
@@ -427,6 +448,7 @@ module TypeProf
|
|
427
448
|
idx = @class_defs.size
|
428
449
|
if superclass
|
429
450
|
@class_defs[idx] = ClassDef.new(:class, show_name, absolute_path)
|
451
|
+
@class_defs[superclass.idx].subclasses << idx unless superclass == :__root__
|
430
452
|
klass = Type::Class.new(:class, idx, type_params, superclass, show_name)
|
431
453
|
@class_defs[idx].klass_obj = klass
|
432
454
|
cbase ||= klass # for bootstrap
|
@@ -453,6 +475,7 @@ module TypeProf
|
|
453
475
|
superclass = Type::Builtin[:struct]
|
454
476
|
name = "AnonymousStruct_generated_#{ @anonymous_struct_gen_id += 1 }"
|
455
477
|
@class_defs[idx] = ClassDef.new(:class, [name], ep.ctx.iseq.absolute_path)
|
478
|
+
#@class_defs[superclass.idx].subclasses << idx # needed?
|
456
479
|
klass = Type::Class.new(:class, idx, [], superclass, name)
|
457
480
|
add_superclass_type_args!(klass, [Type.any])
|
458
481
|
@class_defs[idx].klass_obj = klass
|
@@ -508,6 +531,13 @@ module TypeProf
|
|
508
531
|
end
|
509
532
|
end
|
510
533
|
|
534
|
+
def traverse_subclasses(klass, &blk)
|
535
|
+
@class_defs[klass.idx].subclasses.each do |subclass|
|
536
|
+
yield @class_defs[subclass]
|
537
|
+
traverse_subclasses(@class_defs[subclass].klass_obj, &blk)
|
538
|
+
end
|
539
|
+
end
|
540
|
+
|
511
541
|
def search_method(klass, singleton, mid, &blk)
|
512
542
|
# XXX: support method alias correctly
|
513
543
|
klass_orig = klass
|
@@ -527,7 +557,18 @@ module TypeProf
|
|
527
557
|
end
|
528
558
|
end
|
529
559
|
|
530
|
-
def get_method(klass, singleton, mid)
|
560
|
+
def get_method(klass, singleton, include_subclasses, mid)
|
561
|
+
if include_subclasses
|
562
|
+
subclasses_mthds = []
|
563
|
+
traverse_subclasses(klass) do |subclass|
|
564
|
+
subclass.search_method(singleton, mid, {}) do |mthds,|
|
565
|
+
subclasses_mthds.concat(mthds.to_a)
|
566
|
+
end
|
567
|
+
end
|
568
|
+
search_method(klass, singleton, mid) {|mthds,| return subclasses_mthds + mthds.to_a }
|
569
|
+
return subclasses_mthds
|
570
|
+
end
|
571
|
+
|
531
572
|
search_method(klass, singleton, mid) {|mthds,| return mthds }
|
532
573
|
end
|
533
574
|
|
@@ -628,9 +669,10 @@ module TypeProf
|
|
628
669
|
if klass == Type.any
|
629
670
|
self
|
630
671
|
else
|
631
|
-
mdefs = get_method(klass, singleton, orig_mid)
|
672
|
+
mdefs = get_method(klass, singleton, false, orig_mid) # XXX: include_subclass == false??
|
632
673
|
if mdefs
|
633
|
-
|
674
|
+
# dup is needed for `alias foo foo` (otherwise, "can't add a new key into hash during iteration" error occurs)
|
675
|
+
mdefs.dup.each do |mdef|
|
634
676
|
@class_defs[klass.idx].add_method(alias_mid, singleton, AliasMethodDef.new(orig_mid, mdef, ep))
|
635
677
|
end
|
636
678
|
end
|
@@ -737,24 +779,32 @@ module TypeProf
|
|
737
779
|
end
|
738
780
|
end
|
739
781
|
|
740
|
-
def
|
782
|
+
def identify_class_for_ivar(recv, var)
|
783
|
+
klass, singleton = recv.method_dispatch_info
|
784
|
+
return nil unless klass
|
785
|
+
search_method(klass, singleton, var) do |mthds, klass0, singleton0|
|
786
|
+
if mthds.any? {|mthd| mthd.is_a?(AttrMethodDef) }
|
787
|
+
return klass0, singleton
|
788
|
+
end
|
789
|
+
end
|
790
|
+
return klass, singleton
|
791
|
+
end
|
792
|
+
|
793
|
+
def get_ivar(recv, var)
|
741
794
|
recv = recv.base_type while recv.respond_to?(:base_type)
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
when Type::Any
|
748
|
-
return
|
795
|
+
|
796
|
+
klass, singleton = identify_class_for_ivar(recv, var.to_s[1..].to_sym) # search attr_reader
|
797
|
+
|
798
|
+
if klass
|
799
|
+
return @class_defs[klass.idx], singleton
|
749
800
|
else
|
750
|
-
|
751
|
-
return
|
801
|
+
return nil
|
752
802
|
end
|
753
803
|
end
|
754
804
|
|
755
805
|
def add_ivar_read!(recv, var, ep, &ctn)
|
756
806
|
recv.each_child do |recv|
|
757
|
-
class_def, singleton = get_ivar(recv)
|
807
|
+
class_def, singleton = get_ivar(recv, var)
|
758
808
|
next unless class_def
|
759
809
|
class_def.ivars.add_read!([singleton, var], ep, &ctn)
|
760
810
|
end
|
@@ -762,7 +812,7 @@ module TypeProf
|
|
762
812
|
|
763
813
|
def add_ivar_write!(recv, var, ty, ep)
|
764
814
|
recv.each_child do |recv|
|
765
|
-
class_def, singleton = get_ivar(recv)
|
815
|
+
class_def, singleton = get_ivar(recv, var)
|
766
816
|
next unless class_def
|
767
817
|
class_def.ivars.add_write!([singleton, var], ty, ep, self)
|
768
818
|
end
|
@@ -878,56 +928,77 @@ module TypeProf
|
|
878
928
|
iter_counter = 0
|
879
929
|
stat_eps = Utils::MutableSet.new
|
880
930
|
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
931
|
+
prologue_ctx = Context.new(nil, nil, nil)
|
932
|
+
prologue_ep = ExecutionPoint.new(prologue_ctx, -1, nil)
|
933
|
+
prologue_env = Env.new(StaticEnv.new(Type.bot, Type.nil, false, true), [], [], Utils::HashWrapper.new({}))
|
934
|
+
|
935
|
+
until @entrypoints.empty?
|
936
|
+
entrypoint = @entrypoints.shift
|
937
|
+
if entrypoint.is_a?(String)
|
938
|
+
file = entrypoint
|
939
|
+
next if @loaded_files[File.expand_path(file)]
|
940
|
+
iseq = ISeq.compile(file)
|
941
|
+
else
|
942
|
+
iseq = entrypoint
|
943
|
+
end
|
944
|
+
|
945
|
+
@loaded_files[iseq.absolute_path] = true
|
946
|
+
ep, env = TypeProf.starting_state(iseq)
|
947
|
+
merge_env(ep, env)
|
948
|
+
add_callsite!(ep.ctx, prologue_ep, prologue_env) {|ty, ep| }
|
949
|
+
|
950
|
+
while true
|
951
|
+
until @worklist.empty?
|
952
|
+
ep = @worklist.deletemin
|
953
|
+
|
954
|
+
iter_counter += 1
|
955
|
+
if Config.options[:show_indicator]
|
956
|
+
tick2 = Time.now
|
957
|
+
if tick2 - tick >= 1
|
958
|
+
tick = tick2
|
959
|
+
$stderr << "\rType Profiling... (%d instructions @ %s)\e[K" % [iter_counter, ep.source_location]
|
960
|
+
$stderr.flush
|
961
|
+
end
|
892
962
|
end
|
893
|
-
end
|
894
963
|
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
964
|
+
if (Config.max_sec && Time.now - start_time >= Config.max_sec) || (Config.max_iter && Config.max_iter <= iter_counter)
|
965
|
+
@terminated = true
|
966
|
+
break
|
967
|
+
end
|
899
968
|
|
900
|
-
|
901
|
-
|
902
|
-
|
969
|
+
stat_eps << ep
|
970
|
+
step(ep)
|
971
|
+
end
|
903
972
|
|
904
|
-
|
973
|
+
break if @terminated
|
905
974
|
|
906
|
-
|
975
|
+
break unless Config.options[:stub_execution]
|
907
976
|
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
977
|
+
begin
|
978
|
+
iseq, (kind, dummy_continuation) = @pending_execution.first
|
979
|
+
break if !iseq
|
980
|
+
@pending_execution.delete(iseq)
|
981
|
+
end while @executed_iseqs.include?(iseq)
|
913
982
|
|
914
|
-
|
983
|
+
puts "DEBUG: trigger stub execution (#{ iseq&.name || "(nil)" }): rest #{ @pending_execution.size }" if Config.verbose >= 2
|
915
984
|
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
merge_env(ep, env)
|
921
|
-
add_iseq_method_call!(meth, ep.ctx)
|
922
|
-
|
923
|
-
when :block
|
924
|
-
blk, epenvs = dummy_continuation
|
925
|
-
epenvs.each do |ep, env|
|
985
|
+
break if !iseq
|
986
|
+
case kind
|
987
|
+
when :method
|
988
|
+
meth, ep, env = dummy_continuation
|
926
989
|
merge_env(ep, env)
|
927
|
-
|
990
|
+
add_iseq_method_call!(meth, ep.ctx)
|
991
|
+
|
992
|
+
when :block
|
993
|
+
blk, epenvs = dummy_continuation
|
994
|
+
epenvs.each do |ep, env|
|
995
|
+
merge_env(ep, env)
|
996
|
+
add_block_to_ctx!(blk.block_body, ep.ctx)
|
997
|
+
end
|
928
998
|
end
|
929
999
|
end
|
930
1000
|
end
|
1001
|
+
|
931
1002
|
$stderr.print "\r\e[K" if Config.options[:show_indicator]
|
932
1003
|
|
933
1004
|
stat_eps
|
@@ -1245,7 +1316,13 @@ module TypeProf
|
|
1245
1316
|
end
|
1246
1317
|
if cbase.is_a?(Type::Class)
|
1247
1318
|
klass = new_class(cbase, id, [], superclass, ep.ctx.iseq.absolute_path)
|
1248
|
-
|
1319
|
+
if superclass
|
1320
|
+
add_superclass_type_args!(klass, superclass.type_params.map { Type.any })
|
1321
|
+
|
1322
|
+
# inherited hook
|
1323
|
+
aargs = ActualArguments.new([klass], nil, {}, Type.nil)
|
1324
|
+
do_send(superclass, :inherited, aargs, ep, env) {|_ret_ty, _ep| }
|
1325
|
+
end
|
1249
1326
|
else
|
1250
1327
|
klass = Type.any
|
1251
1328
|
end
|
@@ -1280,15 +1357,13 @@ module TypeProf
|
|
1280
1357
|
when :send
|
1281
1358
|
env, recvs, mid, aargs = setup_actual_arguments(:method, operands, ep, env)
|
1282
1359
|
recvs = Type.any if recvs == Type.bot
|
1283
|
-
recvs
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
merge_env(ep.next, nenv)
|
1288
|
-
end
|
1360
|
+
do_send(recvs, mid, aargs, ep, env) do |ret_ty, ep, env|
|
1361
|
+
nenv, ret_ty, = localize_type(ret_ty, env, ep)
|
1362
|
+
nenv = nenv.push(ret_ty)
|
1363
|
+
merge_env(ep.next, nenv)
|
1289
1364
|
end
|
1290
1365
|
return
|
1291
|
-
when :
|
1366
|
+
when :recv_getlocal_send_branch
|
1292
1367
|
getlocal_operands, send_operands, branch_operands = operands
|
1293
1368
|
env, recvs, mid, aargs = setup_actual_arguments(:method, send_operands, ep, env)
|
1294
1369
|
recvs = Type.any if recvs == Type.bot
|
@@ -1316,28 +1391,59 @@ module TypeProf
|
|
1316
1391
|
end
|
1317
1392
|
end
|
1318
1393
|
return
|
1394
|
+
when :arg_getlocal_send_branch
|
1395
|
+
getlocal_operands, send_operands, branch_operands = operands
|
1396
|
+
env, recvs, mid, aargs = setup_actual_arguments(:method, send_operands, ep, env)
|
1397
|
+
raise if aargs.lead_tys.size != 1
|
1398
|
+
aarg = aargs.lead_tys[0]
|
1399
|
+
aarg = Type.any if aarg == Type.bot
|
1400
|
+
recvs.each_child do |recv|
|
1401
|
+
aarg.each_child do |aarg|
|
1402
|
+
aargs_tmp = ActualArguments.new([aarg], nil, {}, aargs.blk_ty)
|
1403
|
+
do_send(recv, mid, aargs_tmp, ep, env) do |ret_ty, ep, env|
|
1404
|
+
env, ret_ty, = localize_type(ret_ty, env, ep)
|
1405
|
+
|
1406
|
+
branchtype, target, = branch_operands
|
1407
|
+
# branchtype: :if or :unless or :nil
|
1408
|
+
ep_then = ep.next
|
1409
|
+
ep_else = ep.jump(target)
|
1410
|
+
|
1411
|
+
var_idx, _scope_idx, _escaped = getlocal_operands
|
1412
|
+
flow_env = env.local_update(-var_idx+2, aarg)
|
1413
|
+
|
1414
|
+
case ret_ty
|
1415
|
+
when Type::Instance.new(Type::Builtin[:true])
|
1416
|
+
merge_env(branchtype == :if ? ep_else : ep_then, flow_env)
|
1417
|
+
when Type::Instance.new(Type::Builtin[:false])
|
1418
|
+
merge_env(branchtype == :if ? ep_then : ep_else, flow_env)
|
1419
|
+
else
|
1420
|
+
merge_env(ep_then, env)
|
1421
|
+
merge_env(ep_else, env)
|
1422
|
+
end
|
1423
|
+
end
|
1424
|
+
end
|
1425
|
+
end
|
1426
|
+
return
|
1319
1427
|
when :send_branch
|
1320
1428
|
send_operands, branch_operands = operands
|
1321
1429
|
env, recvs, mid, aargs = setup_actual_arguments(:method, send_operands, ep, env)
|
1322
1430
|
recvs = Type.any if recvs == Type.bot
|
1323
|
-
recvs
|
1324
|
-
|
1325
|
-
env, ret_ty, = localize_type(ret_ty, env, ep)
|
1431
|
+
do_send(recvs, mid, aargs, ep, env) do |ret_ty, ep, env|
|
1432
|
+
env, ret_ty, = localize_type(ret_ty, env, ep)
|
1326
1433
|
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1434
|
+
branchtype, target, = branch_operands
|
1435
|
+
# branchtype: :if or :unless or :nil
|
1436
|
+
ep_then = ep.next
|
1437
|
+
ep_else = ep.jump(target)
|
1331
1438
|
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
end
|
1439
|
+
case ret_ty
|
1440
|
+
when Type::Instance.new(Type::Builtin[:true])
|
1441
|
+
merge_env(branchtype == :if ? ep_else : ep_then, env)
|
1442
|
+
when Type::Instance.new(Type::Builtin[:false])
|
1443
|
+
merge_env(branchtype == :if ? ep_then : ep_else, env)
|
1444
|
+
else
|
1445
|
+
merge_env(ep_then, env)
|
1446
|
+
merge_env(ep_else, env)
|
1341
1447
|
end
|
1342
1448
|
end
|
1343
1449
|
return
|
@@ -1371,12 +1477,10 @@ module TypeProf
|
|
1371
1477
|
# XXX: this decomposition is really needed??
|
1372
1478
|
# It calls `Object.new` with union receiver which causes an error, but
|
1373
1479
|
# it may be a fault of builtin Object.new implementation.
|
1374
|
-
recv
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
merge_env(ep.next, nenv)
|
1379
|
-
end
|
1480
|
+
meth.do_send(recv, mid, aargs, ep, env, self) do |ret_ty, ep, env|
|
1481
|
+
nenv, ret_ty, = localize_type(ret_ty, env, ep)
|
1482
|
+
nenv = nenv.push(ret_ty)
|
1483
|
+
merge_env(ep.next, nenv)
|
1380
1484
|
end
|
1381
1485
|
end
|
1382
1486
|
end
|
@@ -1419,7 +1523,7 @@ module TypeProf
|
|
1419
1523
|
end
|
1420
1524
|
_type, _iseq, cont, stack_depth = tmp_ep.ctx.iseq.catch_table[tmp_ep.pc]&.find {|type,| type == :break }
|
1421
1525
|
if cont
|
1422
|
-
nenv = @return_envs[tmp_ep]
|
1526
|
+
nenv = @return_envs[tmp_ep] || env
|
1423
1527
|
nenv, = nenv.pop(nenv.stack.size - stack_depth)
|
1424
1528
|
nenv = nenv.push(ty)
|
1425
1529
|
tmp_ep = tmp_ep.jump(cont)
|
@@ -1778,8 +1882,10 @@ module TypeProf
|
|
1778
1882
|
when :nop
|
1779
1883
|
when :setn
|
1780
1884
|
idx, = operands
|
1781
|
-
|
1782
|
-
|
1885
|
+
if idx >= 1
|
1886
|
+
env, (ty,) = env.pop(1)
|
1887
|
+
env = env.setn(idx, ty).push(ty)
|
1888
|
+
end
|
1783
1889
|
when :topn
|
1784
1890
|
idx, = operands
|
1785
1891
|
env = env.topn(idx)
|
@@ -2062,39 +2168,41 @@ module TypeProf
|
|
2062
2168
|
return env, recv, mid, aargs
|
2063
2169
|
end
|
2064
2170
|
|
2065
|
-
def do_send(
|
2066
|
-
|
2067
|
-
|
2068
|
-
|
2069
|
-
|
2070
|
-
|
2071
|
-
|
2072
|
-
|
2073
|
-
klass, singleton = recv.method_dispatch_info
|
2074
|
-
meths = get_method(klass, singleton, mid) if klass
|
2075
|
-
if meths
|
2076
|
-
meths.each do |meth|
|
2077
|
-
meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
|
2078
|
-
end
|
2171
|
+
def do_send(recvs, mid, aargs, ep, env, &ctn)
|
2172
|
+
recvs.each_child do |recv|
|
2173
|
+
case recv
|
2174
|
+
when Type::Void
|
2175
|
+
error(ep, "void's method is called: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
|
2176
|
+
ctn[Type.any, ep, env]
|
2177
|
+
when Type::Any
|
2178
|
+
ctn[Type.any, ep, env]
|
2079
2179
|
else
|
2080
|
-
|
2180
|
+
klass, singleton, include_subclasses = recv.method_dispatch_info
|
2181
|
+
meths = get_method(klass, singleton, include_subclasses, mid) if klass
|
2081
2182
|
if meths
|
2082
|
-
aargs = aargs.for_method_missing(Type::Symbol.new(mid, Type::Instance.new(Type::Builtin[:sym])))
|
2083
2183
|
meths.each do |meth|
|
2084
|
-
meth.do_send(recv,
|
2184
|
+
meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
|
2085
2185
|
end
|
2086
2186
|
else
|
2087
|
-
|
2088
|
-
|
2187
|
+
meths = get_method(klass, singleton, include_subclasses, :method_missing) if klass
|
2188
|
+
if meths
|
2189
|
+
aargs = aargs.for_method_missing(Type::Symbol.new(mid, Type::Instance.new(Type::Builtin[:sym])))
|
2190
|
+
meths.each do |meth|
|
2191
|
+
meth.do_send(recv, :method_missing, aargs, ep, env, self, &ctn)
|
2192
|
+
end
|
2193
|
+
else
|
2194
|
+
error(ep, "undefined method: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
|
2195
|
+
ctn[Type.any, ep, env]
|
2196
|
+
end
|
2089
2197
|
end
|
2090
2198
|
end
|
2091
2199
|
end
|
2092
2200
|
end
|
2093
2201
|
|
2094
|
-
def do_invoke_block(blk, aargs, ep, env, replace_recv_ty: nil, &ctn)
|
2202
|
+
def do_invoke_block(blk, aargs, ep, env, replace_recv_ty: nil, replace_cref: nil, &ctn)
|
2095
2203
|
blk.each_child do |blk|
|
2096
2204
|
if blk.is_a?(Type::Proc)
|
2097
|
-
blk.block_body.do_call(aargs, ep, env, self, replace_recv_ty: replace_recv_ty, &ctn)
|
2205
|
+
blk.block_body.do_call(aargs, ep, env, self, replace_recv_ty: replace_recv_ty, replace_cref: replace_cref, &ctn)
|
2098
2206
|
else
|
2099
2207
|
warn(ep, "non-proc is passed as a block")
|
2100
2208
|
ctn[Type.any, ep, env]
|
@@ -2170,7 +2278,11 @@ module TypeProf
|
|
2170
2278
|
next unless @block_to_ctx[blk.block_body] # this occurs when screen_name is called before type-profiling finished (e.g., error message)
|
2171
2279
|
@block_to_ctx[blk.block_body].each do |blk_ctx|
|
2172
2280
|
if farg_tys
|
2173
|
-
|
2281
|
+
if @method_signatures[blk_ctx]
|
2282
|
+
farg_tys = farg_tys.merge_as_block_arguments(@method_signatures[blk_ctx])
|
2283
|
+
else
|
2284
|
+
# this occurs when screen_name is called before type-profiling finished (e.g., error message)
|
2285
|
+
end
|
2174
2286
|
else
|
2175
2287
|
farg_tys = @method_signatures[blk_ctx]
|
2176
2288
|
end
|
@@ -2180,17 +2292,24 @@ module TypeProf
|
|
2180
2292
|
end
|
2181
2293
|
end
|
2182
2294
|
|
2183
|
-
|
2184
|
-
|
2185
|
-
|
2295
|
+
return Type.any.screen_name(self) if @types_being_shown.include?(farg_tys) || @types_being_shown.include?(ret_ty)
|
2296
|
+
|
2297
|
+
begin
|
2298
|
+
@types_being_shown << farg_tys << ret_ty
|
2299
|
+
farg_tys = farg_tys ? farg_tys.screen_name(nil, self) : "(unknown)"
|
2300
|
+
ret_ty = ret_ty.screen_name(self)
|
2301
|
+
ret_ty = (ret_ty.include?("|") ? "(#{ ret_ty })" : ret_ty) # XXX?
|
2186
2302
|
|
2187
|
-
|
2188
|
-
|
2303
|
+
farg_tys = farg_tys + " " if farg_tys != ""
|
2304
|
+
"^#{ farg_tys }-> #{ ret_ty }"
|
2305
|
+
ensure
|
2306
|
+
@types_being_shown.pop(2)
|
2307
|
+
end
|
2189
2308
|
end
|
2190
2309
|
|
2191
2310
|
def show_method_signature(ctx)
|
2192
2311
|
farg_tys = @method_signatures[ctx]
|
2193
|
-
ret_ty = @return_values[ctx] || Type.bot
|
2312
|
+
ret_ty = ctx.mid == :initialize ? Type::Void.new : @return_values[ctx] || Type.bot
|
2194
2313
|
|
2195
2314
|
untyped = farg_tys.include_untyped?(self) || ret_ty.include_untyped?(self)
|
2196
2315
|
|