typeprof 0.8.0 → 0.11.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 +6 -5
- data/doc/demo.md +1 -1
- data/doc/todo.md +133 -0
- data/lib/typeprof/analyzer.rb +177 -76
- data/lib/typeprof/arguments.rb +2 -0
- data/lib/typeprof/block.rb +40 -2
- data/lib/typeprof/builtin.rb +279 -111
- data/lib/typeprof/cli.rb +5 -0
- data/lib/typeprof/config.rb +15 -1
- data/lib/typeprof/container-type.rb +5 -4
- data/lib/typeprof/export.rb +115 -70
- data/lib/typeprof/import.rb +71 -33
- data/lib/typeprof/iseq.rb +46 -11
- data/lib/typeprof/method.rb +42 -21
- data/lib/typeprof/type.rb +93 -15
- data/lib/typeprof/version.rb +1 -1
- data/smoke/alias.rb +4 -4
- data/smoke/alias2.rb +6 -4
- data/smoke/any1.rb +1 -1
- data/smoke/any2.rb +2 -2
- data/smoke/arguments.rb +2 -2
- data/smoke/arguments2.rb +10 -10
- data/smoke/array-each.rb +1 -1
- data/smoke/array-each2.rb +1 -1
- data/smoke/array-each3.rb +1 -1
- data/smoke/array-ltlt.rb +1 -1
- data/smoke/array-ltlt2.rb +1 -1
- data/smoke/array-map.rb +1 -1
- data/smoke/array-map2.rb +1 -1
- data/smoke/array-map3.rb +3 -3
- data/smoke/array-mul.rb +2 -2
- data/smoke/array-plus1.rb +1 -1
- data/smoke/array-plus2.rb +3 -2
- data/smoke/array-pop.rb +1 -1
- data/smoke/array-range-aref.rb +11 -11
- data/smoke/array-replace.rb +1 -1
- data/smoke/array-s-aref.rb +1 -1
- data/smoke/array1.rb +5 -5
- data/smoke/array10.rb +1 -1
- data/smoke/array11.rb +1 -1
- data/smoke/array12.rb +3 -3
- data/smoke/array13.rb +4 -4
- data/smoke/array14.rb +1 -1
- data/smoke/array15.rb +16 -0
- data/smoke/array2.rb +3 -3
- data/smoke/array3.rb +5 -4
- data/smoke/array4.rb +1 -1
- data/smoke/array5.rb +1 -1
- data/smoke/array6.rb +3 -2
- data/smoke/array7.rb +1 -1
- data/smoke/array8.rb +1 -1
- data/smoke/array9.rb +1 -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 +1 -1
- data/smoke/backtrace.rb +3 -3
- data/smoke/block-ambiguous.rb +8 -8
- data/smoke/block-args1-rest.rb +12 -11
- data/smoke/block-args1.rb +10 -10
- data/smoke/block-args2-rest.rb +12 -11
- data/smoke/block-args2.rb +10 -10
- data/smoke/block-args3-rest.rb +14 -13
- data/smoke/block-args3.rb +12 -12
- data/smoke/block-blockarg.rb +4 -4
- data/smoke/block-kwarg.rb +10 -10
- data/smoke/block1.rb +1 -1
- data/smoke/block10.rb +1 -1
- data/smoke/block11.rb +5 -5
- data/smoke/block12.rb +2 -2
- data/smoke/block14.rb +2 -2
- data/smoke/block2.rb +1 -1
- data/smoke/block3.rb +3 -3
- data/smoke/block4.rb +2 -2
- data/smoke/block5.rb +3 -2
- data/smoke/block6.rb +2 -2
- data/smoke/block7.rb +1 -1
- data/smoke/block8.rb +3 -3
- data/smoke/block9.rb +1 -1
- data/smoke/block_given.rb +37 -0
- data/smoke/blown.rb +1 -1
- data/smoke/break1.rb +2 -2
- data/smoke/break2.rb +1 -1
- data/smoke/break3.rb +13 -0
- data/smoke/case.rb +1 -1
- data/smoke/case2.rb +1 -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 +2 -2
- data/smoke/constant1.rb +6 -6
- data/smoke/constant2.rb +5 -4
- data/smoke/constant3.rb +1 -1
- data/smoke/constant4.rb +1 -1
- data/smoke/context-sensitive1.rb +1 -1
- data/smoke/cvar.rb +6 -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 +6 -6
- data/smoke/demo1.rb +1 -1
- data/smoke/demo10.rb +2 -2
- data/smoke/demo11.rb +1 -1
- data/smoke/demo2.rb +1 -1
- data/smoke/demo3.rb +1 -1
- data/smoke/demo4.rb +3 -3
- data/smoke/demo5.rb +1 -1
- data/smoke/demo6.rb +4 -3
- data/smoke/demo7.rb +1 -1
- data/smoke/demo8.rb +2 -2
- data/smoke/demo9.rb +3 -2
- data/smoke/dummy-execution1.rb +2 -2
- data/smoke/dummy-execution2.rb +2 -2
- data/smoke/dummy_element.rb +14 -0
- data/smoke/ensure1.rb +2 -2
- data/smoke/enum_for.rb +15 -0
- data/smoke/enum_for2.rb +17 -0
- data/smoke/enumerator.rb +2 -2
- data/smoke/expandarray1.rb +1 -1
- data/smoke/expandarray2.rb +1 -1
- data/smoke/fib.rb +2 -2
- data/smoke/flip-flop.rb +28 -0
- data/smoke/flow1.rb +1 -1
- data/smoke/flow10.rb +17 -0
- data/smoke/flow2.rb +1 -1
- data/smoke/flow3.rb +1 -1
- data/smoke/flow5.rb +1 -1
- data/smoke/flow6.rb +1 -1
- data/smoke/flow7.rb +1 -1
- data/smoke/flow8.rb +1 -1
- data/smoke/flow9.rb +12 -0
- data/smoke/freeze.rb +1 -1
- data/smoke/function.rb +2 -2
- data/smoke/gvar.rb +2 -2
- data/smoke/gvar2.rb +3 -3
- data/smoke/hash-bot.rb +12 -0
- data/smoke/hash-fetch.rb +3 -3
- data/smoke/hash-merge-bang.rb +1 -1
- data/smoke/hash1.rb +2 -2
- data/smoke/hash2.rb +1 -1
- data/smoke/hash3.rb +1 -1
- data/smoke/hash4.rb +1 -1
- data/smoke/hash5.rb +1 -1
- data/smoke/inheritance.rb +4 -4
- data/smoke/inheritance2.rb +2 -2
- data/smoke/initialize.rb +6 -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 +1 -1
- data/smoke/integer.rb +1 -1
- data/smoke/ivar.rb +5 -4
- data/smoke/ivar2.rb +4 -4
- data/smoke/ivar3.rb +4 -3
- data/smoke/ivar4.rb +21 -0
- data/smoke/kernel-class.rb +1 -1
- data/smoke/keyword1.rb +1 -1
- data/smoke/keyword2.rb +1 -1
- data/smoke/keyword3.rb +1 -1
- data/smoke/keyword4.rb +1 -1
- data/smoke/keyword5.rb +1 -1
- data/smoke/kwrest.rb +3 -2
- data/smoke/kwsplat1.rb +4 -4
- data/smoke/kwsplat2.rb +1 -1
- data/smoke/lit-complex.rb +10 -0
- data/smoke/lit-encoding.rb +10 -0
- data/smoke/manual-rbs.rb +5 -4
- data/smoke/manual-rbs2.rb +1 -1
- data/smoke/manual-rbs3.rb +3 -2
- data/smoke/masgn1.rb +1 -1
- data/smoke/masgn2.rb +2 -2
- data/smoke/masgn3.rb +1 -1
- data/smoke/method_in_branch.rb +3 -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 +2 -2
- data/smoke/next2.rb +1 -1
- data/smoke/object-send1.rb +3 -3
- data/smoke/object-send2.rb +10 -0
- data/smoke/object-send3.rb +18 -0
- data/smoke/once.rb +1 -1
- data/smoke/optional1.rb +1 -1
- data/smoke/optional2.rb +1 -1
- data/smoke/optional3.rb +1 -1
- data/smoke/parameterizedd-self.rb +3 -2
- data/smoke/parameterizedd-self2.rb +1 -1
- data/smoke/pathname1.rb +1 -1
- data/smoke/pathname2.rb +1 -1
- data/smoke/pattern-match1.rb +1 -1
- data/smoke/pattern-match2.rb +1 -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 +2 -2
- data/smoke/proc2.rb +1 -1
- data/smoke/proc3.rb +1 -1
- data/smoke/proc4.rb +1 -1
- data/smoke/proc5.rb +19 -0
- data/smoke/public.rb +38 -0
- data/smoke/range.rb +1 -1
- data/smoke/rbs-alias.rb +1 -1
- data/smoke/rbs-attr.rb +5 -5
- data/smoke/rbs-attr2.rb +1 -1
- data/smoke/rbs-extend.rb +1 -1
- data/smoke/rbs-interface.rb +4 -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 +1 -1
- data/smoke/rbs-proc2.rb +2 -2
- data/smoke/rbs-proc3.rb +1 -1
- data/smoke/rbs-record.rb +2 -2
- data/smoke/rbs-tyvar.rb +2 -2
- data/smoke/rbs-tyvar2.rb +2 -2
- data/smoke/rbs-tyvar3.rb +2 -2
- data/smoke/rbs-tyvar4.rb +4 -3
- data/smoke/rbs-tyvar5.rb +1 -1
- data/smoke/rbs-tyvar6.rb +3 -3
- data/smoke/rbs-tyvar7.rb +1 -1
- data/smoke/rbs-vars.rb +6 -6
- data/smoke/redo1.rb +2 -2
- data/smoke/redo2.rb +2 -2
- data/smoke/req-keyword.rb +1 -1
- data/smoke/rescue1.rb +2 -2
- data/smoke/rescue2.rb +2 -2
- data/smoke/rescue3.rb +20 -0
- data/smoke/rescue4.rb +17 -0
- data/smoke/respond_to.rb +1 -1
- data/smoke/rest-farg.rb +1 -1
- data/smoke/rest1.rb +2 -2
- data/smoke/rest2.rb +1 -1
- data/smoke/rest3.rb +6 -6
- data/smoke/rest4.rb +2 -2
- data/smoke/rest5.rb +1 -1
- data/smoke/rest6.rb +1 -1
- data/smoke/retry1.rb +2 -2
- data/smoke/return.rb +1 -1
- data/smoke/simple.rb +12 -0
- data/smoke/singleton_method.rb +1 -1
- data/smoke/step.rb +3 -3
- data/smoke/string-split.rb +1 -1
- data/smoke/struct-keyword_init.rb +10 -0
- data/smoke/struct.rb +1 -1
- data/smoke/struct2.rb +4 -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 +4 -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 +1 -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 +3 -3
- data/smoke/tap1.rb +2 -2
- data/smoke/toplevel.rb +1 -1
- data/smoke/two-map.rb +2 -2
- data/smoke/type_var.rb +3 -3
- data/smoke/typed_method.rb +1 -1
- data/smoke/uninitialize-var.rb +1 -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 +59 -6
- 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,5 +1,7 @@
|
|
1
1
|
module TypeProf
|
2
2
|
class MethodDef
|
3
|
+
attr_accessor :pub_meth
|
4
|
+
|
3
5
|
include Utils::StructuralEquality
|
4
6
|
end
|
5
7
|
|
@@ -12,8 +14,6 @@ module TypeProf
|
|
12
14
|
@pub_meth = pub_meth
|
13
15
|
end
|
14
16
|
|
15
|
-
attr_accessor :pub_meth
|
16
|
-
|
17
17
|
def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
|
18
18
|
recv = recv.base_type while recv.respond_to?(:base_type)
|
19
19
|
recv = scratch.globalize_type(recv, caller_env, caller_ep)
|
@@ -87,7 +87,7 @@ module TypeProf
|
|
87
87
|
# XXX: need to check .rbs msig and .rb fargs
|
88
88
|
|
89
89
|
ctx = Context.new(@iseq, @cref, mid)
|
90
|
-
callee_ep = ExecutionPoint.new(ctx, 0,
|
90
|
+
callee_ep = ExecutionPoint.new(ctx, 0, @outer_ep)
|
91
91
|
|
92
92
|
locals = [Type.nil] * @iseq.locals.size
|
93
93
|
nenv = Env.new(StaticEnv.new(recv, msig.blk_ty, false, true), locals, [], Utils::HashWrapper.new({}))
|
@@ -95,16 +95,15 @@ module TypeProf
|
|
95
95
|
idx = 0
|
96
96
|
msig.lead_tys.each_with_index do |ty, i|
|
97
97
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
98
|
-
# nenv is top-level, so it is okay to call Type#localize directly
|
99
98
|
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
100
|
-
nenv, ty =
|
99
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
101
100
|
nenv = nenv.local_update(i, ty)
|
102
101
|
end
|
103
102
|
if msig.opt_tys
|
104
103
|
msig.opt_tys.each_with_index do |ty, i|
|
105
104
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
106
105
|
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
107
|
-
nenv, ty =
|
106
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
108
107
|
nenv = nenv.local_update(lead_num + i, ty)
|
109
108
|
end
|
110
109
|
end
|
@@ -112,27 +111,27 @@ module TypeProf
|
|
112
111
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
113
112
|
ty = Type::Array.new(Type::Array::Elements.new([], msig.rest_ty), Type::Instance.new(Type::Builtin[:ary]))
|
114
113
|
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
115
|
-
nenv, rest_ty =
|
114
|
+
nenv, rest_ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
116
115
|
nenv = nenv.local_update(rest_start, rest_ty)
|
117
116
|
end
|
118
117
|
if msig.post_tys
|
119
118
|
msig.post_tys.each_with_index do |ty, i|
|
120
119
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
121
120
|
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
122
|
-
nenv, ty =
|
121
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
123
122
|
nenv = nenv.local_update(post_start + i, ty)
|
124
123
|
end
|
125
124
|
end
|
126
|
-
if msig.kw_tys
|
125
|
+
if msig.kw_tys && keyword # TODO: support the case where RBS writes kw_tys and RB method accepts **kwrest
|
127
126
|
msig.kw_tys.each do |_, key, ty|
|
128
|
-
i = keyword.index
|
127
|
+
i = keyword.index {|callee_key,| callee_key == key }
|
129
128
|
unless i
|
130
129
|
# warn
|
131
130
|
next
|
132
131
|
end
|
133
132
|
alloc_site2 = alloc_site.add_id(key)
|
134
133
|
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
135
|
-
nenv, ty =
|
134
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
136
135
|
nenv = nenv.local_update(kw_start + i, ty)
|
137
136
|
end
|
138
137
|
end
|
@@ -140,34 +139,55 @@ module TypeProf
|
|
140
139
|
ty = msig.kw_rest_ty
|
141
140
|
alloc_site2 = alloc_site.add_id(:**)
|
142
141
|
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
143
|
-
nenv, ty =
|
142
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
144
143
|
nenv = nenv.local_update(kw_rest, ty)
|
145
144
|
end
|
146
145
|
nenv = nenv.local_update(block_start, msig.blk_ty) if block_start
|
147
146
|
|
148
147
|
opt.each do |start_pc|
|
149
|
-
scratch.merge_env(
|
148
|
+
scratch.merge_env(callee_ep.jump(start_pc), nenv)
|
150
149
|
end
|
150
|
+
scratch.add_executed_iseq(@iseq)
|
151
151
|
|
152
152
|
ctx
|
153
153
|
end
|
154
154
|
end
|
155
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
|
+
|
156
175
|
class AttrMethodDef < MethodDef
|
157
|
-
def initialize(ivar, kind,
|
176
|
+
def initialize(ivar, kind, pub_meth, def_ep)
|
158
177
|
@ivar = ivar
|
159
178
|
@kind = kind # :reader | :writer
|
160
|
-
@
|
179
|
+
@pub_meth = pub_meth
|
180
|
+
@def_ep = def_ep
|
161
181
|
end
|
162
182
|
|
163
|
-
attr_reader :ivar, :kind, :
|
183
|
+
attr_reader :ivar, :kind, :def_ep
|
164
184
|
|
165
185
|
def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
|
166
186
|
case @kind
|
167
187
|
when :reader
|
168
188
|
if aargs.lead_tys.size == 0
|
169
|
-
scratch.
|
170
|
-
ctn[ty, caller_ep,
|
189
|
+
scratch.add_ivar_read!(recv, @ivar, caller_ep) do |ty, _ep|
|
190
|
+
ctn[ty, caller_ep, caller_env]
|
171
191
|
end
|
172
192
|
else
|
173
193
|
ctn[Type.any, caller_ep, caller_env]
|
@@ -185,9 +205,10 @@ module TypeProf
|
|
185
205
|
end
|
186
206
|
|
187
207
|
class TypedMethodDef < MethodDef
|
188
|
-
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]>
|
189
209
|
@sig_rets = sig_rets
|
190
210
|
@rbs_source = rbs_source
|
211
|
+
@pub_meth = pub_meth
|
191
212
|
end
|
192
213
|
|
193
214
|
attr_reader :rbs_source
|
@@ -286,12 +307,12 @@ module TypeProf
|
|
286
307
|
end
|
287
308
|
|
288
309
|
class CustomMethodDef < MethodDef
|
289
|
-
def initialize(impl)
|
310
|
+
def initialize(impl, pub_meth)
|
290
311
|
@impl = impl
|
312
|
+
@pub_meth = pub_meth
|
291
313
|
end
|
292
314
|
|
293
315
|
def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
|
294
|
-
scratch.merge_return_env(caller_ep) {|env| env ? env.merge(caller_env) : caller_env } # for Kernel#lambda
|
295
316
|
@impl[recv, mid, aargs, caller_ep, caller_env, scratch, &ctn]
|
296
317
|
end
|
297
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
|
@@ -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
|