typeprof 0.12.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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
|
|