typeprof 0.7.0 → 0.10.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 +8 -5
- data/lib/typeprof/analyzer.rb +211 -98
- data/lib/typeprof/arguments.rb +2 -0
- data/lib/typeprof/block.rb +40 -2
- data/lib/typeprof/builtin.rb +301 -99
- data/lib/typeprof/cli.rb +2 -0
- data/lib/typeprof/config.rb +14 -2
- data/lib/typeprof/container-type.rb +5 -4
- data/lib/typeprof/export.rb +116 -65
- data/lib/typeprof/import.rb +68 -41
- data/lib/typeprof/iseq.rb +46 -11
- data/lib/typeprof/method.rb +47 -23
- data/lib/typeprof/type.rb +96 -18
- data/lib/typeprof/version.rb +1 -1
- data/smoke/alias.rb +5 -4
- data/smoke/alias2.rb +6 -4
- data/smoke/any1.rb +2 -1
- data/smoke/any2.rb +3 -2
- data/smoke/arguments.rb +3 -2
- data/smoke/arguments2.rb +11 -10
- data/smoke/array-each.rb +2 -1
- data/smoke/array-each2.rb +2 -1
- data/smoke/array-each3.rb +2 -1
- data/smoke/array-ltlt.rb +2 -1
- data/smoke/array-ltlt2.rb +2 -1
- data/smoke/array-map.rb +2 -1
- data/smoke/array-map2.rb +2 -1
- data/smoke/array-map3.rb +4 -3
- data/smoke/array-mul.rb +3 -2
- data/smoke/array-plus1.rb +2 -1
- data/smoke/array-plus2.rb +3 -2
- data/smoke/array-pop.rb +2 -1
- data/smoke/array-range-aref.rb +12 -11
- data/smoke/array-replace.rb +2 -1
- data/smoke/array-s-aref.rb +2 -1
- data/smoke/array1.rb +6 -5
- data/smoke/array10.rb +2 -1
- data/smoke/array11.rb +2 -1
- data/smoke/array12.rb +4 -3
- data/smoke/array13.rb +5 -4
- data/smoke/array14.rb +2 -1
- data/smoke/array15.rb +16 -0
- data/smoke/array2.rb +4 -3
- data/smoke/array3.rb +5 -4
- data/smoke/array4.rb +2 -1
- data/smoke/array5.rb +2 -1
- data/smoke/array6.rb +4 -2
- data/smoke/array7.rb +2 -1
- data/smoke/array8.rb +1 -1
- data/smoke/array9.rb +2 -1
- data/smoke/attr-module.rb +27 -0
- data/smoke/attr-vis.rb +43 -0
- data/smoke/attr-vis.rbs +4 -0
- data/smoke/attr.rb +5 -5
- data/smoke/autoload.rb +2 -1
- data/smoke/backtrace.rb +4 -3
- data/smoke/block-ambiguous.rb +9 -8
- data/smoke/block-args1-rest.rb +13 -11
- data/smoke/block-args1.rb +11 -10
- data/smoke/block-args2-rest.rb +13 -11
- data/smoke/block-args2.rb +11 -10
- data/smoke/block-args3-rest.rb +15 -13
- data/smoke/block-args3.rb +13 -12
- data/smoke/block-blockarg.rb +5 -4
- data/smoke/block-kwarg.rb +11 -10
- data/smoke/block1.rb +2 -1
- data/smoke/block10.rb +2 -1
- data/smoke/block11.rb +6 -5
- data/smoke/block12.rb +3 -2
- data/smoke/block14.rb +3 -2
- data/smoke/block2.rb +2 -1
- data/smoke/block3.rb +3 -3
- data/smoke/block4.rb +3 -2
- data/smoke/block5.rb +4 -2
- data/smoke/block6.rb +3 -2
- data/smoke/block7.rb +2 -1
- data/smoke/block8.rb +4 -3
- data/smoke/block9.rb +2 -1
- data/smoke/block_given.rb +37 -0
- data/smoke/blown.rb +2 -1
- data/smoke/break1.rb +3 -2
- data/smoke/break2.rb +2 -1
- data/smoke/break3.rb +13 -0
- data/smoke/case.rb +2 -1
- data/smoke/case2.rb +2 -1
- data/smoke/case3.rb +17 -0
- data/smoke/class-hierarchy.rb +5 -5
- data/smoke/class-hierarchy2.rb +3 -3
- data/smoke/class-new.rb +15 -0
- data/smoke/class_instance_var.rb +1 -1
- data/smoke/class_method.rb +2 -2
- data/smoke/class_method2.rb +2 -2
- data/smoke/class_method3.rb +4 -2
- data/smoke/constant1.rb +6 -6
- data/smoke/constant2.rb +6 -4
- data/smoke/constant3.rb +2 -1
- data/smoke/constant4.rb +2 -1
- data/smoke/context-sensitive1.rb +2 -1
- data/smoke/cvar.rb +7 -5
- data/smoke/cvar2.rb +2 -2
- data/smoke/define_method.rb +2 -2
- data/smoke/define_method2.rb +2 -2
- data/smoke/define_method3.rb +14 -0
- data/smoke/define_method3.rbs +3 -0
- data/smoke/define_method4.rb +15 -0
- data/smoke/define_method4.rbs +3 -0
- data/smoke/define_method5.rb +12 -0
- data/smoke/define_method6.rb +19 -0
- data/smoke/demo.rb +7 -6
- data/smoke/demo1.rb +2 -1
- data/smoke/demo10.rb +3 -2
- data/smoke/demo11.rb +2 -1
- data/smoke/demo2.rb +2 -1
- data/smoke/demo3.rb +2 -1
- data/smoke/demo4.rb +3 -3
- data/smoke/demo5.rb +1 -1
- data/smoke/demo6.rb +4 -3
- data/smoke/demo7.rb +2 -1
- data/smoke/demo8.rb +3 -2
- data/smoke/demo9.rb +4 -2
- data/smoke/dummy-execution1.rb +3 -2
- data/smoke/dummy-execution2.rb +2 -2
- data/smoke/dummy_element.rb +14 -0
- data/smoke/ensure1.rb +3 -2
- data/smoke/enum_for.rb +15 -0
- data/smoke/enum_for2.rb +17 -0
- data/smoke/enumerator.rb +3 -2
- data/smoke/expandarray1.rb +2 -1
- data/smoke/expandarray2.rb +2 -1
- data/smoke/fib.rb +2 -2
- data/smoke/flip-flop.rb +28 -0
- data/smoke/flow1.rb +2 -1
- data/smoke/flow10.rb +17 -0
- data/smoke/flow2.rb +2 -1
- data/smoke/flow3.rb +2 -1
- data/smoke/flow5.rb +2 -1
- data/smoke/flow6.rb +2 -1
- data/smoke/flow7.rb +2 -1
- data/smoke/flow8.rb +2 -1
- data/smoke/flow9.rb +12 -0
- data/smoke/freeze.rb +2 -1
- data/smoke/function.rb +3 -2
- data/smoke/gvar.rb +3 -2
- data/smoke/gvar2.rb +4 -3
- data/smoke/hash-bot.rb +12 -0
- data/smoke/hash-fetch.rb +4 -3
- data/smoke/hash-merge-bang.rb +2 -1
- data/smoke/hash1.rb +3 -2
- data/smoke/hash2.rb +2 -1
- data/smoke/hash3.rb +2 -1
- data/smoke/hash4.rb +2 -1
- data/smoke/hash5.rb +1 -1
- data/smoke/inheritance.rb +4 -4
- data/smoke/inheritance2.rb +2 -2
- data/smoke/initialize.rb +7 -5
- data/smoke/instance_eval.rb +2 -2
- data/smoke/instance_eval2.rb +10 -0
- data/smoke/instance_eval3.rb +25 -0
- data/smoke/int_times.rb +2 -1
- data/smoke/integer.rb +2 -1
- data/smoke/ivar.rb +6 -4
- data/smoke/ivar2.rb +4 -4
- data/smoke/ivar3.rb +4 -3
- data/smoke/ivar4.rb +21 -0
- data/smoke/kernel-class.rb +2 -1
- data/smoke/keyword1.rb +2 -1
- data/smoke/keyword2.rb +2 -1
- data/smoke/keyword3.rb +2 -1
- data/smoke/keyword4.rb +2 -1
- data/smoke/keyword5.rb +2 -1
- data/smoke/kwrest.rb +3 -2
- data/smoke/kwsplat1.rb +5 -4
- data/smoke/kwsplat2.rb +2 -1
- data/smoke/lit-complex.rb +10 -0
- data/smoke/lit-encoding.rb +10 -0
- data/smoke/manual-rbs.rb +6 -4
- data/smoke/manual-rbs2.rb +2 -1
- data/smoke/manual-rbs3.rb +3 -2
- data/smoke/masgn1.rb +2 -1
- data/smoke/masgn2.rb +3 -2
- data/smoke/masgn3.rb +2 -1
- data/smoke/method_in_branch.rb +4 -3
- data/smoke/method_missing.rb +5 -4
- data/smoke/module1.rb +2 -2
- data/smoke/module2.rb +1 -1
- data/smoke/module3.rb +3 -3
- data/smoke/module4.rb +3 -2
- data/smoke/module5.rb +17 -0
- data/smoke/module6.rb +40 -0
- data/smoke/module_function1.rb +4 -3
- data/smoke/module_function2.rb +4 -3
- data/smoke/multiple-include.rb +2 -1
- data/smoke/multiple-superclass.rb +1 -1
- data/smoke/next1.rb +3 -2
- data/smoke/next2.rb +2 -1
- data/smoke/object-send1.rb +4 -3
- data/smoke/object-send2.rb +10 -0
- data/smoke/object-send3.rb +18 -0
- data/smoke/once.rb +2 -1
- data/smoke/optional1.rb +2 -1
- data/smoke/optional2.rb +2 -1
- data/smoke/optional3.rb +2 -1
- data/smoke/parameterizedd-self.rb +4 -2
- data/smoke/parameterizedd-self2.rb +1 -1
- data/smoke/pathname1.rb +2 -1
- data/smoke/pathname2.rb +2 -1
- data/smoke/pattern-match1.rb +2 -1
- data/smoke/pattern-match2.rb +2 -1
- data/smoke/prepend1.rb +33 -0
- data/smoke/prepend2.rb +10 -0
- data/smoke/prepend2.rbs +9 -0
- data/smoke/primitive_method.rb +19 -0
- data/smoke/printf.rb +2 -2
- data/smoke/proc.rb +3 -2
- data/smoke/proc2.rb +2 -1
- data/smoke/proc3.rb +2 -1
- data/smoke/proc4.rb +2 -1
- data/smoke/proc5.rb +19 -0
- data/smoke/public.rb +38 -0
- data/smoke/range.rb +2 -1
- data/smoke/rbs-alias.rb +2 -1
- data/smoke/rbs-attr.rb +6 -5
- data/smoke/rbs-attr2.rb +1 -1
- data/smoke/rbs-extend.rb +2 -1
- data/smoke/rbs-interface.rb +5 -4
- data/smoke/rbs-module.rb +26 -0
- data/smoke/rbs-module.rbs +4 -0
- data/smoke/rbs-opt-and-rest.rb +10 -0
- data/smoke/rbs-opt-and-rest.rbs +3 -0
- data/smoke/rbs-proc1.rb +2 -1
- data/smoke/rbs-proc2.rb +3 -2
- data/smoke/rbs-proc3.rb +2 -1
- data/smoke/rbs-record.rb +3 -2
- data/smoke/rbs-tyvar.rb +3 -2
- data/smoke/rbs-tyvar2.rb +3 -2
- data/smoke/rbs-tyvar3.rb +3 -2
- data/smoke/rbs-tyvar4.rb +4 -3
- data/smoke/rbs-tyvar5.rb +2 -1
- data/smoke/rbs-tyvar6.rb +4 -3
- data/smoke/rbs-tyvar7.rb +2 -1
- data/smoke/rbs-vars.rb +7 -6
- data/smoke/redo1.rb +3 -2
- data/smoke/redo2.rb +3 -2
- data/smoke/req-keyword.rb +2 -1
- data/smoke/rescue1.rb +3 -2
- data/smoke/rescue2.rb +3 -2
- data/smoke/rescue3.rb +20 -0
- data/smoke/rescue4.rb +17 -0
- data/smoke/respond_to.rb +2 -1
- data/smoke/rest-farg.rb +2 -1
- data/smoke/rest1.rb +3 -2
- data/smoke/rest2.rb +2 -1
- data/smoke/rest3.rb +7 -6
- data/smoke/rest4.rb +3 -2
- data/smoke/rest5.rb +2 -1
- data/smoke/rest6.rb +2 -1
- data/smoke/retry1.rb +3 -2
- data/smoke/return.rb +2 -1
- data/smoke/simple.rb +12 -0
- data/smoke/singleton_method.rb +1 -1
- data/smoke/step.rb +4 -3
- data/smoke/string-split.rb +2 -1
- data/smoke/struct-keyword_init.rb +10 -0
- data/smoke/struct.rb +1 -1
- data/smoke/struct2.rb +5 -4
- data/smoke/struct3.rb +2 -2
- data/smoke/struct4.rb +7 -0
- data/smoke/struct5.rb +16 -0
- data/smoke/struct6.rb +15 -0
- data/smoke/struct7.rb +17 -0
- data/smoke/stub-keyword.rb +10 -0
- data/smoke/super1.rb +5 -4
- data/smoke/super2.rb +1 -1
- data/smoke/super3.rb +4 -3
- data/smoke/super4.rb +7 -5
- data/smoke/super5.rb +6 -4
- data/smoke/svar1.rb +2 -1
- data/smoke/symbol-proc-attr.rb +22 -0
- data/smoke/symbol-proc-attr2.rb +15 -0
- data/smoke/symbol-proc-bot.rb +13 -0
- data/smoke/symbol-proc.rb +4 -3
- data/smoke/tap1.rb +3 -2
- data/smoke/toplevel.rb +2 -1
- data/smoke/two-map.rb +3 -2
- data/smoke/type_var.rb +4 -3
- data/smoke/typed_method.rb +2 -1
- data/smoke/uninitialize-var.rb +2 -1
- data/smoke/union-recv.rb +2 -2
- data/smoke/user-demo.rb +3 -3
- data/smoke/wrong-extend.rb +3 -2
- data/smoke/wrong-include.rb +3 -2
- data/smoke/wrong-include2.rb +17 -0
- data/typeprof.gemspec +1 -1
- metadata +57 -5
- data/tools/stackprof-wrapper.rb +0 -10
data/lib/typeprof/iseq.rb
CHANGED
@@ -49,10 +49,18 @@ module TypeProf
|
|
49
49
|
insns[i, 0] = [[:_iseq_body_start]]
|
50
50
|
end
|
51
51
|
|
52
|
+
# rescue/ensure clauses need to have a dedicated return addresses
|
53
|
+
# because they requires to be virtually called.
|
54
|
+
# So, this preprocess adds "nop" to make a new insn for their return addresses
|
55
|
+
special_labels = {}
|
56
|
+
catch_table.map do |type, iseq, first, last, cont, stack_depth|
|
57
|
+
special_labels[cont] = true if type == :rescue || type == :ensure
|
58
|
+
end
|
59
|
+
|
52
60
|
@insns = []
|
53
61
|
@linenos = []
|
54
62
|
|
55
|
-
labels = setup_iseq(insns)
|
63
|
+
labels = setup_iseq(insns, special_labels)
|
56
64
|
|
57
65
|
# checkmatch->branch
|
58
66
|
# send->branch
|
@@ -60,7 +68,8 @@ module TypeProf
|
|
60
68
|
@catch_table = []
|
61
69
|
catch_table.map do |type, iseq, first, last, cont, stack_depth|
|
62
70
|
iseq = iseq ? ISeq.new(iseq) : nil
|
63
|
-
|
71
|
+
target = labels[special_labels[cont] ? :"#{ cont }_special" : cont]
|
72
|
+
entry = [type, iseq, target, stack_depth]
|
64
73
|
labels[first].upto(labels[last]) do |i|
|
65
74
|
@catch_table[i] ||= []
|
66
75
|
@catch_table[i] << entry
|
@@ -76,19 +85,26 @@ module TypeProf
|
|
76
85
|
@id <=> other.id
|
77
86
|
end
|
78
87
|
|
79
|
-
def setup_iseq(insns)
|
88
|
+
def setup_iseq(insns, special_labels)
|
80
89
|
i = 0
|
81
90
|
labels = {}
|
91
|
+
ninsns = []
|
82
92
|
insns.each do |e|
|
83
93
|
if e.is_a?(Symbol) && e.to_s.start_with?("label")
|
94
|
+
if special_labels[e]
|
95
|
+
labels[:"#{ e }_special"] = i
|
96
|
+
ninsns << [:nop]
|
97
|
+
i += 1
|
98
|
+
end
|
84
99
|
labels[e] = i
|
85
|
-
|
86
|
-
i += 1
|
100
|
+
else
|
101
|
+
i += 1 if e.is_a?(Array)
|
102
|
+
ninsns << e
|
87
103
|
end
|
88
104
|
end
|
89
105
|
|
90
106
|
lineno = 0
|
91
|
-
|
107
|
+
ninsns.each do |e|
|
92
108
|
case e
|
93
109
|
when Integer # lineno
|
94
110
|
lineno = e
|
@@ -191,7 +207,7 @@ module TypeProf
|
|
191
207
|
end
|
192
208
|
|
193
209
|
# find a pattern: getlocal, ..., send (is_a?, respond_to?), branch
|
194
|
-
|
210
|
+
getlocal_send_branch_list = []
|
195
211
|
(@insns.size - 1).times do |i|
|
196
212
|
insn, operands = @insns[i]
|
197
213
|
if insn == :getlocal && operands[1] == 0
|
@@ -200,7 +216,7 @@ module TypeProf
|
|
200
216
|
while @insns[j]
|
201
217
|
sp = check_send_branch(sp, j)
|
202
218
|
if sp == :match
|
203
|
-
|
219
|
+
getlocal_send_branch_list << [i, j]
|
204
220
|
break
|
205
221
|
end
|
206
222
|
break if !sp
|
@@ -208,13 +224,32 @@ module TypeProf
|
|
208
224
|
end
|
209
225
|
end
|
210
226
|
end
|
211
|
-
|
212
|
-
next if (i + 1 .. j).any? {|i| branch_targets[i] }
|
227
|
+
getlocal_send_branch_list.each do |i, j|
|
228
|
+
next if (i + 1 .. j + 1).any? {|i| branch_targets[i] }
|
213
229
|
_insn, getlocal_operands = @insns[i]
|
214
230
|
_insn, send_operands = @insns[j]
|
215
231
|
_insn, branch_operands = @insns[j + 1]
|
216
232
|
@insns[j] = [:nop]
|
217
|
-
@insns[j + 1] = [:
|
233
|
+
@insns[j + 1] = [:getlocal_send_branch, [getlocal_operands, send_operands, branch_operands]]
|
234
|
+
end
|
235
|
+
|
236
|
+
# find a pattern: send (block_given?), branch
|
237
|
+
send_branch_list = []
|
238
|
+
(@insns.size - 1).times do |i|
|
239
|
+
insn, _operands = @insns[i]
|
240
|
+
if insn == :send
|
241
|
+
insn, _operands = @insns[i + 1]
|
242
|
+
if insn == :branch
|
243
|
+
send_branch_list << i
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
send_branch_list.each do |i|
|
248
|
+
next if branch_targets[i + 1]
|
249
|
+
_insn, send_operands = @insns[i]
|
250
|
+
_insn, branch_operands = @insns[i + 1]
|
251
|
+
@insns[i] = [:nop]
|
252
|
+
@insns[i + 1] = [:send_branch, [send_operands, branch_operands]]
|
218
253
|
end
|
219
254
|
|
220
255
|
# find a pattern: getlocal, dup, branch
|
data/lib/typeprof/method.rb
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
module TypeProf
|
2
2
|
class MethodDef
|
3
|
+
attr_accessor :pub_meth
|
4
|
+
|
3
5
|
include Utils::StructuralEquality
|
4
6
|
end
|
5
7
|
|
6
8
|
class ISeqMethodDef < MethodDef
|
7
|
-
def initialize(iseq, cref, outer_ep)
|
9
|
+
def initialize(iseq, cref, outer_ep, pub_meth)
|
8
10
|
@iseq = iseq
|
9
11
|
raise if iseq.nil?
|
10
12
|
@cref = cref
|
11
13
|
@outer_ep = outer_ep
|
14
|
+
@pub_meth = pub_meth
|
12
15
|
end
|
13
16
|
|
14
17
|
def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
|
@@ -27,7 +30,7 @@ module TypeProf
|
|
27
30
|
|
28
31
|
nctx = Context.new(@iseq, @cref, mid)
|
29
32
|
callee_ep = ExecutionPoint.new(nctx, 0, @outer_ep)
|
30
|
-
nenv = Env.new(StaticEnv.new(recv, blk_ty, false), locals, [], Utils::HashWrapper.new({}))
|
33
|
+
nenv = Env.new(StaticEnv.new(recv, blk_ty, false, true), locals, [], Utils::HashWrapper.new({}))
|
31
34
|
alloc_site = AllocationSite.new(callee_ep)
|
32
35
|
locals.each_with_index do |ty, i|
|
33
36
|
alloc_site2 = alloc_site.add_id(i)
|
@@ -84,24 +87,23 @@ module TypeProf
|
|
84
87
|
# XXX: need to check .rbs msig and .rb fargs
|
85
88
|
|
86
89
|
ctx = Context.new(@iseq, @cref, mid)
|
87
|
-
callee_ep = ExecutionPoint.new(ctx, 0,
|
90
|
+
callee_ep = ExecutionPoint.new(ctx, 0, @outer_ep)
|
88
91
|
|
89
92
|
locals = [Type.nil] * @iseq.locals.size
|
90
|
-
nenv = Env.new(StaticEnv.new(recv, msig.blk_ty, false), locals, [], Utils::HashWrapper.new({}))
|
93
|
+
nenv = Env.new(StaticEnv.new(recv, msig.blk_ty, false, true), locals, [], Utils::HashWrapper.new({}))
|
91
94
|
alloc_site = AllocationSite.new(callee_ep)
|
92
95
|
idx = 0
|
93
96
|
msig.lead_tys.each_with_index do |ty, i|
|
94
97
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
95
|
-
# nenv is top-level, so it is okay to call Type#localize directly
|
96
98
|
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
97
|
-
nenv, ty =
|
99
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
98
100
|
nenv = nenv.local_update(i, ty)
|
99
101
|
end
|
100
102
|
if msig.opt_tys
|
101
103
|
msig.opt_tys.each_with_index do |ty, i|
|
102
104
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
103
105
|
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
104
|
-
nenv, ty =
|
106
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
105
107
|
nenv = nenv.local_update(lead_num + i, ty)
|
106
108
|
end
|
107
109
|
end
|
@@ -109,27 +111,27 @@ module TypeProf
|
|
109
111
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
110
112
|
ty = Type::Array.new(Type::Array::Elements.new([], msig.rest_ty), Type::Instance.new(Type::Builtin[:ary]))
|
111
113
|
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
112
|
-
nenv, rest_ty =
|
114
|
+
nenv, rest_ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
113
115
|
nenv = nenv.local_update(rest_start, rest_ty)
|
114
116
|
end
|
115
117
|
if msig.post_tys
|
116
118
|
msig.post_tys.each_with_index do |ty, i|
|
117
119
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
118
120
|
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
119
|
-
nenv, ty =
|
121
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
120
122
|
nenv = nenv.local_update(post_start + i, ty)
|
121
123
|
end
|
122
124
|
end
|
123
|
-
if msig.kw_tys
|
125
|
+
if msig.kw_tys && keyword # TODO: support the case where RBS writes kw_tys and RB method accepts **kwrest
|
124
126
|
msig.kw_tys.each do |_, key, ty|
|
125
|
-
i = keyword.index
|
127
|
+
i = keyword.index {|callee_key,| callee_key == key }
|
126
128
|
unless i
|
127
129
|
# warn
|
128
130
|
next
|
129
131
|
end
|
130
132
|
alloc_site2 = alloc_site.add_id(key)
|
131
133
|
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
132
|
-
nenv, ty =
|
134
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
133
135
|
nenv = nenv.local_update(kw_start + i, ty)
|
134
136
|
end
|
135
137
|
end
|
@@ -137,34 +139,55 @@ module TypeProf
|
|
137
139
|
ty = msig.kw_rest_ty
|
138
140
|
alloc_site2 = alloc_site.add_id(:**)
|
139
141
|
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
140
|
-
nenv, ty =
|
142
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
141
143
|
nenv = nenv.local_update(kw_rest, ty)
|
142
144
|
end
|
143
145
|
nenv = nenv.local_update(block_start, msig.blk_ty) if block_start
|
144
146
|
|
145
147
|
opt.each do |start_pc|
|
146
|
-
scratch.merge_env(
|
148
|
+
scratch.merge_env(callee_ep.jump(start_pc), nenv)
|
147
149
|
end
|
150
|
+
scratch.add_executed_iseq(@iseq)
|
148
151
|
|
149
152
|
ctx
|
150
153
|
end
|
151
154
|
end
|
152
155
|
|
156
|
+
class AliasMethodDef < MethodDef
|
157
|
+
def initialize(orig_mid, mdef, def_ep)
|
158
|
+
@orig_mid = orig_mid
|
159
|
+
@mdef = mdef
|
160
|
+
@pub_meth = mdef.pub_meth
|
161
|
+
@def_ep = def_ep
|
162
|
+
end
|
163
|
+
|
164
|
+
attr_reader :orig_mid, :mdef, :def_ep
|
165
|
+
|
166
|
+
def do_send(recv, _mid, aargs, caller_ep, caller_env, scratch, &ctn)
|
167
|
+
@mdef.do_send(recv, @orig_mid, aargs, caller_ep, caller_env, scratch, &ctn)
|
168
|
+
end
|
169
|
+
|
170
|
+
def do_check_send(msig, recv, mid, ep, scratch)
|
171
|
+
@mdef.do_check_send(msig, recv, mid, ep, scratch)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
153
175
|
class AttrMethodDef < MethodDef
|
154
|
-
def initialize(ivar, kind,
|
176
|
+
def initialize(ivar, kind, pub_meth, def_ep)
|
155
177
|
@ivar = ivar
|
156
178
|
@kind = kind # :reader | :writer
|
157
|
-
@
|
179
|
+
@pub_meth = pub_meth
|
180
|
+
@def_ep = def_ep
|
158
181
|
end
|
159
182
|
|
160
|
-
attr_reader :ivar, :kind, :
|
183
|
+
attr_reader :ivar, :kind, :def_ep
|
161
184
|
|
162
185
|
def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
|
163
186
|
case @kind
|
164
187
|
when :reader
|
165
188
|
if aargs.lead_tys.size == 0
|
166
|
-
scratch.
|
167
|
-
ctn[ty, caller_ep,
|
189
|
+
scratch.add_ivar_read!(recv, @ivar, caller_ep) do |ty, _ep|
|
190
|
+
ctn[ty, caller_ep, caller_env]
|
168
191
|
end
|
169
192
|
else
|
170
193
|
ctn[Type.any, caller_ep, caller_env]
|
@@ -182,9 +205,10 @@ module TypeProf
|
|
182
205
|
end
|
183
206
|
|
184
207
|
class TypedMethodDef < MethodDef
|
185
|
-
def initialize(sig_rets, rbs_source) # sig_rets: Array<[MethodSignature, (return)Type]>
|
208
|
+
def initialize(sig_rets, rbs_source, pub_meth) # sig_rets: Array<[MethodSignature, (return)Type]>
|
186
209
|
@sig_rets = sig_rets
|
187
210
|
@rbs_source = rbs_source
|
211
|
+
@pub_meth = pub_meth
|
188
212
|
end
|
189
213
|
|
190
214
|
attr_reader :rbs_source
|
@@ -224,7 +248,7 @@ module TypeProf
|
|
224
248
|
dummy_ep = ExecutionPoint.new(dummy_ctx, -1, caller_ep)
|
225
249
|
s_recv = recv
|
226
250
|
s_recv = s_recv.base_type while s_recv.respond_to?(:base_type)
|
227
|
-
dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false), [], [], Utils::HashWrapper.new({}))
|
251
|
+
dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false, true), [], [], Utils::HashWrapper.new({}))
|
228
252
|
if msig.blk_ty.is_a?(Type::Proc)
|
229
253
|
scratch.add_callsite!(dummy_ctx, caller_ep, ncaller_env, &ctn)
|
230
254
|
bsig = msig.blk_ty.block_body.msig
|
@@ -283,12 +307,12 @@ module TypeProf
|
|
283
307
|
end
|
284
308
|
|
285
309
|
class CustomMethodDef < MethodDef
|
286
|
-
def initialize(impl)
|
310
|
+
def initialize(impl, pub_meth)
|
287
311
|
@impl = impl
|
312
|
+
@pub_meth = pub_meth
|
288
313
|
end
|
289
314
|
|
290
315
|
def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
|
291
|
-
scratch.merge_return_env(caller_ep) {|env| env ? env.merge(caller_env) : caller_env } # for Kernel#lambda
|
292
316
|
@impl[recv, mid, aargs, caller_ep, caller_env, scratch, &ctn]
|
293
317
|
end
|
294
318
|
end
|
data/lib/typeprof/type.rb
CHANGED
@@ -315,9 +315,14 @@ module TypeProf
|
|
315
315
|
def globalize(env, visited, depth)
|
316
316
|
return Type.any if depth <= 0
|
317
317
|
tys = Utils::Set[]
|
318
|
-
|
318
|
+
if @elems
|
319
|
+
# XXX: If @elems is non nil, the Union type should global, so calling globalize against such a type should not occur.
|
320
|
+
# However, currently, ActualArguments may contain global types for flag_args_kw_splat case.
|
321
|
+
# This should be fixed in future in ActualArguments side. See Scratch#setup_actual_arguments.
|
322
|
+
#raise
|
323
|
+
end
|
319
324
|
|
320
|
-
elems = {}
|
325
|
+
elems = @elems ? @elems.dup : {}
|
321
326
|
@types.each do |ty|
|
322
327
|
ty = ty.globalize(env, visited, depth - 1)
|
323
328
|
case ty
|
@@ -435,17 +440,17 @@ module TypeProf
|
|
435
440
|
end
|
436
441
|
|
437
442
|
class Class < Type # or Module
|
438
|
-
def initialize(kind, idx, type_params, superclass,
|
443
|
+
def initialize(kind, idx, type_params, superclass, name)
|
439
444
|
@kind = kind # :class | :module
|
440
445
|
@idx = idx
|
441
446
|
@type_params = type_params
|
442
447
|
@superclass = superclass
|
443
448
|
raise if @kind == :class && !@superclass
|
444
|
-
@superclass_type_args = superclass_type_args
|
445
449
|
@_name = name
|
446
450
|
end
|
447
451
|
|
448
|
-
attr_reader :kind, :idx, :type_params, :superclass
|
452
|
+
attr_reader :kind, :idx, :type_params, :superclass
|
453
|
+
attr_accessor :superclass_type_args
|
449
454
|
|
450
455
|
def inspect
|
451
456
|
if @_name
|
@@ -492,6 +497,8 @@ module TypeProf
|
|
492
497
|
def initialize(klass)
|
493
498
|
raise unless klass
|
494
499
|
raise if klass == Type.any
|
500
|
+
raise if klass.is_a?(Type::Instance)
|
501
|
+
raise if klass.is_a?(Type::Union)
|
495
502
|
@klass = klass
|
496
503
|
end
|
497
504
|
|
@@ -682,6 +689,8 @@ module TypeProf
|
|
682
689
|
Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:int]))
|
683
690
|
when ::Rational
|
684
691
|
Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:rational]))
|
692
|
+
when ::Complex
|
693
|
+
Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:complex]))
|
685
694
|
when ::Float
|
686
695
|
Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:float]))
|
687
696
|
when ::Class
|
@@ -718,6 +727,8 @@ module TypeProf
|
|
718
727
|
Type.nil
|
719
728
|
when ::Range
|
720
729
|
Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:range]))
|
730
|
+
when ::Encoding
|
731
|
+
Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:encoding]))
|
721
732
|
else
|
722
733
|
raise "unknown object: #{ obj.inspect }"
|
723
734
|
end
|
@@ -770,31 +781,56 @@ module TypeProf
|
|
770
781
|
class Signature
|
771
782
|
include Utils::StructuralEquality
|
772
783
|
|
773
|
-
def screen_name(scratch)
|
774
|
-
|
784
|
+
def screen_name(iseq, scratch)
|
785
|
+
fargs = @lead_tys.map {|ty| ty.screen_name(scratch) }
|
786
|
+
farg_names = []
|
787
|
+
farg_names += iseq.locals[0, @lead_tys.size] if iseq
|
775
788
|
if @opt_tys
|
776
|
-
|
789
|
+
fargs += @opt_tys.map {|ty| "?" + ty.screen_name(scratch) }
|
790
|
+
farg_names += iseq.locals[@lead_tys.size, @opt_tys.size] if iseq
|
777
791
|
end
|
778
792
|
if @rest_ty
|
779
|
-
|
793
|
+
fargs << ("*" + @rest_ty.screen_name(scratch))
|
794
|
+
if iseq
|
795
|
+
rest_index = iseq.fargs_format[:rest_start]
|
796
|
+
farg_names << (rest_index ? iseq.locals[rest_index] : nil)
|
797
|
+
end
|
780
798
|
end
|
781
799
|
if @post_tys
|
782
|
-
|
800
|
+
fargs += @post_tys.map {|ty| ty.screen_name(scratch) }
|
801
|
+
if iseq
|
802
|
+
post_start = iseq.fargs_format[:post_start]
|
803
|
+
farg_names += (post_start ? iseq.locals[post_start, @post_tys.size] : [nil] * @post_tys.size)
|
804
|
+
end
|
783
805
|
end
|
784
806
|
if @kw_tys
|
785
807
|
@kw_tys.each do |req, sym, ty|
|
786
808
|
opt = req ? "" : "?"
|
787
|
-
|
809
|
+
fargs << "#{ opt }#{ sym }: #{ ty.screen_name(scratch) }"
|
788
810
|
end
|
789
811
|
end
|
790
812
|
if @kw_rest_ty
|
791
|
-
|
813
|
+
all_val_ty = Type.bot
|
814
|
+
@kw_rest_ty.each_child_global do |ty|
|
815
|
+
if ty == Type.any
|
816
|
+
val_ty = ty
|
817
|
+
else
|
818
|
+
# ty is a Type::Hash
|
819
|
+
_key_ty, val_ty = ty.elems.squash
|
820
|
+
end
|
821
|
+
all_val_ty = all_val_ty.union(val_ty)
|
822
|
+
end
|
823
|
+
fargs << ("**" + all_val_ty.screen_name(scratch))
|
792
824
|
end
|
793
|
-
|
825
|
+
if Config.options[:show_parameter_names]
|
826
|
+
farg_names = farg_names.map {|name| name == :type ? :type_ : name } # XXX: workaround of RBS parser bug
|
827
|
+
fargs = fargs.zip(farg_names).map {|farg, name| name ? "#{ farg } #{ name }" : farg }
|
828
|
+
end
|
829
|
+
fargs = fargs.empty? ? "" : "(#{ fargs.join(", ") })"
|
794
830
|
|
795
831
|
# Dirty Hack: Stop the iteration at most once!
|
796
832
|
# I'll remove this hack if RBS removes the limitation of nesting blocks
|
797
|
-
return
|
833
|
+
return fargs if caller_locations.any? {|frame| frame.label == "show_block_signature" }
|
798
834
|
|
799
835
|
optional = false
|
800
836
|
blks = []
|
@@ -807,12 +843,12 @@ module TypeProf
|
|
807
843
|
end
|
808
844
|
end
|
809
845
|
if blks != []
|
810
|
-
|
811
|
-
|
812
|
-
|
846
|
+
fargs << " " if fargs != ""
|
847
|
+
fargs << "?" if optional
|
848
|
+
fargs << scratch.show_block_signature(blks)
|
813
849
|
end
|
814
850
|
|
815
|
-
|
851
|
+
fargs
|
816
852
|
end
|
817
853
|
end
|
818
854
|
|
@@ -820,12 +856,16 @@ module TypeProf
|
|
820
856
|
def initialize(lead_tys, opt_tys, rest_ty, post_tys, kw_tys, kw_rest_ty, blk_ty)
|
821
857
|
@lead_tys = lead_tys
|
822
858
|
@opt_tys = opt_tys
|
859
|
+
raise unless opt_tys.is_a?(Array)
|
823
860
|
@rest_ty = rest_ty
|
824
861
|
@post_tys = post_tys
|
825
862
|
raise unless post_tys
|
826
863
|
@kw_tys = kw_tys
|
827
864
|
kw_tys.each {|a| raise if a.size != 3 } if kw_tys
|
828
865
|
@kw_rest_ty = kw_rest_ty
|
866
|
+
kw_rest_ty&.each_child_global do |ty|
|
867
|
+
raise ty.inspect if ty != Type.any && !ty.is_a?(Type::Hash)
|
868
|
+
end
|
829
869
|
@blk_ty = blk_ty
|
830
870
|
end
|
831
871
|
|
@@ -842,6 +882,44 @@ module TypeProf
|
|
842
882
|
MethodSignature.new(lead_tys, opt_tys, rest_ty, post_tys, kw_tys, kw_rest_ty, blk_ty)
|
843
883
|
end
|
844
884
|
|
885
|
+
def merge_as_block_arguments(other)
|
886
|
+
lead_tys1, opt_tys1, rest_ty1, post_tys1 = @lead_tys, @opt_tys, @rest_ty, @post_tys
|
887
|
+
lead_tys2, opt_tys2, rest_ty2, post_tys2 = other.lead_tys, other.opt_tys, other.rest_ty, other.post_tys
|
888
|
+
|
889
|
+
case
|
890
|
+
when lead_tys1.size > lead_tys2.size
|
891
|
+
n = lead_tys2.size
|
892
|
+
lead_tys1, opt_tys1 = lead_tys1[0, n], lead_tys1[n..] + opt_tys1
|
893
|
+
when lead_tys1.size < lead_tys2.size
|
894
|
+
n = lead_tys1.size
|
895
|
+
lead_tys2, opt_tys2 = lead_tys2[0, n], lead_tys2[n..] + opt_tys2
|
896
|
+
end
|
897
|
+
case
|
898
|
+
when post_tys1.size > post_tys2.size
|
899
|
+
i = post_tys1.size - post_tys2.size
|
900
|
+
if rest_ty1
|
901
|
+
rest_ty1 = post_tys[0, i].inject(rest_ty1) {|ty1, ty2| ty1.union(ty2) }
|
902
|
+
post_tys1 = post_tys1[i..]
|
903
|
+
else
|
904
|
+
opt_tys1, post_tys1 = opt_tys1 + post_tys1[0, i], post_tys1[i..]
|
905
|
+
end
|
906
|
+
when post_tys1.size < post_tys2.size
|
907
|
+
i = post_tys2.size - post_tys1.size
|
908
|
+
if rest_ty2
|
909
|
+
rest_ty2 = post_tys[0, i].inject(rest_ty2) {|ty1, ty2| ty1.union(ty2) }
|
910
|
+
post_tys2 = post_tys2[i..]
|
911
|
+
else
|
912
|
+
opt_tys2, post_tys2 = opt_tys2 + post_tys2[0, i], post_tys2[i..]
|
913
|
+
end
|
914
|
+
end
|
915
|
+
|
916
|
+
# XXX: tweak keywords too
|
917
|
+
|
918
|
+
msig1 = MethodSignature.new(lead_tys1, opt_tys1, rest_ty1, post_tys1, @kw_tys, @kw_rest_ty, @blk_ty)
|
919
|
+
msig2 = MethodSignature.new(lead_tys2, opt_tys2, rest_ty2, post_tys2, other.kw_tys, other.kw_rest_ty, other.blk_ty)
|
920
|
+
msig1.merge(msig2)
|
921
|
+
end
|
922
|
+
|
845
923
|
def merge(other)
|
846
924
|
raise if @lead_tys.size != other.lead_tys.size
|
847
925
|
raise if @post_tys.size != other.post_tys.size
|