typeprof 0.5.4 → 0.9.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 +7 -5
- data/doc/doc.ja.md +3 -4
- data/doc/doc.md +3 -4
- data/lib/typeprof/analyzer.rb +308 -171
- data/lib/typeprof/arguments.rb +14 -6
- data/lib/typeprof/block.rb +6 -2
- data/lib/typeprof/builtin.rb +230 -67
- data/lib/typeprof/cli.rb +33 -34
- data/lib/typeprof/config.rb +6 -4
- data/lib/typeprof/container-type.rb +159 -104
- data/lib/typeprof/export.rb +28 -22
- data/lib/typeprof/import.rb +70 -53
- data/lib/typeprof/iseq.rb +23 -7
- data/lib/typeprof/method.rb +71 -138
- data/lib/typeprof/type.rb +73 -15
- data/lib/typeprof/version.rb +1 -1
- data/smoke/alias.rb +5 -4
- data/smoke/alias2.rb +4 -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 +2 -2
- data/smoke/array-pop.rb +2 -1
- data/smoke/array-range-aref.rb +71 -0
- 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 +4 -4
- data/smoke/array4.rb +2 -1
- data/smoke/array5.rb +2 -1
- data/smoke/array6.rb +3 -2
- data/smoke/array7.rb +2 -1
- data/smoke/array8.rb +1 -1
- data/smoke/array9.rb +2 -1
- data/smoke/attr-module.rb +26 -0
- data/smoke/attr.rb +5 -5
- data/smoke/autoload.rb +14 -0
- data/smoke/backtrace.rb +4 -3
- data/smoke/block-ambiguous.rb +9 -8
- data/smoke/block-args1-rest.rb +12 -11
- data/smoke/block-args1.rb +11 -10
- data/smoke/block-args2-rest.rb +12 -11
- data/smoke/block-args2.rb +11 -10
- data/smoke/block-args3-rest.rb +14 -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 +3 -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/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 +5 -4
- data/smoke/constant3.rb +2 -1
- data/smoke/constant4.rb +2 -1
- data/smoke/context-sensitive1.rb +2 -1
- data/smoke/cvar.rb +6 -5
- data/smoke/cvar2.rb +2 -2
- data/smoke/define_method.rb +16 -0
- data/smoke/define_method2.rb +18 -0
- data/smoke/define_method3.rb +13 -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/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 +3 -3
- data/smoke/demo7.rb +2 -1
- data/smoke/demo8.rb +3 -2
- data/smoke/demo9.rb +3 -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/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/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 +3 -2
- 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 +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 +2 -1
- data/smoke/integer.rb +2 -1
- data/smoke/ivar.rb +5 -4
- data/smoke/ivar2.rb +4 -4
- data/smoke/ivar3.rb +2 -2
- 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 +12 -0
- data/smoke/kwrest.rbs +3 -0
- 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 +4 -3
- data/smoke/manual-rbs2.rb +2 -1
- data/smoke/manual-rbs3.rb +2 -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 +3 -2
- data/smoke/method_missing.rb +28 -0
- data/smoke/module1.rb +2 -2
- data/smoke/module2.rb +1 -1
- data/smoke/module3.rb +2 -2
- data/smoke/module4.rb +2 -2
- data/smoke/module5.rb +17 -0
- data/smoke/module6.rb +40 -0
- data/smoke/module_function1.rb +3 -3
- data/smoke/module_function2.rb +3 -3
- data/smoke/multiple-include.rb +1 -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 +3 -2
- data/smoke/parameterizedd-self2.rb +15 -0
- 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/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 +34 -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 +11 -0
- data/smoke/rbs-attr2.rbs +3 -0
- 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 +3 -3
- data/smoke/rbs-tyvar5.rb +2 -1
- data/smoke/rbs-tyvar6.rb +18 -0
- data/smoke/rbs-tyvar6.rbs +12 -0
- data/smoke/rbs-tyvar7.rb +12 -0
- data/smoke/rbs-tyvar7.rbs +7 -0
- data/smoke/rbs-vars.rb +7 -8
- 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 +19 -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/singleton_method.rb +1 -1
- data/smoke/step.rb +4 -3
- data/smoke/string-split.rb +2 -1
- data/smoke/struct-keyword_init.rb +20 -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 +3 -3
- data/smoke/super4.rb +43 -0
- data/smoke/super5.rb +36 -0
- 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 +2 -1
- 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 +2 -2
- data/smoke/wrong-include.rb +2 -2
- data/smoke/wrong-include2.rb +17 -0
- data/typeprof.gemspec +1 -1
- metadata +61 -6
- data/tools/stackprof-wrapper.rb +0 -10
data/lib/typeprof/export.rb
CHANGED
@@ -72,7 +72,7 @@ module TypeProf
|
|
72
72
|
gvars.dump.each do |gvar_name, entry|
|
73
73
|
next if entry.type == Type.bot
|
74
74
|
s = entry.rbs_declared ? "#" : ""
|
75
|
-
output.puts s + "#{ gvar_name }
|
75
|
+
output.puts s + "#{ gvar_name }: #{ entry.type.screen_name(scratch) }"
|
76
76
|
end
|
77
77
|
output.puts
|
78
78
|
end
|
@@ -91,9 +91,9 @@ module TypeProf
|
|
91
91
|
def conv_class(namespace, class_def, inner_classes)
|
92
92
|
@scratch.namespace = namespace
|
93
93
|
|
94
|
-
if class_def.superclass
|
95
|
-
omit =
|
96
|
-
superclass = omit ? nil : @scratch.get_class_name(
|
94
|
+
if class_def.klass_obj.superclass != :__root__ && class_def.klass_obj.superclass
|
95
|
+
omit = class_def.klass_obj.superclass == Type::Builtin[:obj] || class_def.klass_obj == Type::Builtin[:obj]
|
96
|
+
superclass = omit ? nil : @scratch.get_class_name(class_def.klass_obj.superclass)
|
97
97
|
end
|
98
98
|
|
99
99
|
@scratch.namespace = class_def.name
|
@@ -105,12 +105,12 @@ module TypeProf
|
|
105
105
|
consts[name] = ty.screen_name(@scratch)
|
106
106
|
end
|
107
107
|
|
108
|
-
included_mods = class_def.modules[false].filter_map do |mod_def, absolute_paths|
|
108
|
+
included_mods = class_def.modules[false].filter_map do |mod_def, _type_args, absolute_paths|
|
109
109
|
next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
|
110
110
|
Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
|
111
111
|
end
|
112
112
|
|
113
|
-
extended_mods = class_def.modules[true].filter_map do |mod_def, absolute_paths|
|
113
|
+
extended_mods = class_def.modules[true].filter_map do |mod_def, _type_args, absolute_paths|
|
114
114
|
next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
|
115
115
|
Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
|
116
116
|
end
|
@@ -135,11 +135,12 @@ module TypeProf
|
|
135
135
|
method_name = ctx.mid
|
136
136
|
method_name = "self.#{ method_name }" if singleton
|
137
137
|
|
138
|
-
iseq_methods[method_name] ||= []
|
139
|
-
iseq_methods[method_name]
|
138
|
+
iseq_methods[method_name] ||= [true, []]
|
139
|
+
iseq_methods[method_name][0] &&= mdef.pub_meth
|
140
|
+
iseq_methods[method_name][1] << @scratch.show_method_signature(ctx)
|
140
141
|
end
|
141
142
|
when AttrMethodDef
|
142
|
-
next if Config.check_dir_filter(mdef.absolute_path) == :exclude
|
143
|
+
next if !mdef.absolute_path || Config.check_dir_filter(mdef.absolute_path) == :exclude
|
143
144
|
mid = mid.to_s[0..-2].to_sym if mid.to_s.end_with?("=")
|
144
145
|
method_name = mid
|
145
146
|
method_name = "self.#{ mid }" if singleton
|
@@ -168,12 +169,14 @@ module TypeProf
|
|
168
169
|
next unless var.to_s.start_with?("@")
|
169
170
|
var = "self.#{ var }" if singleton
|
170
171
|
next if attr_methods[[singleton ? "self.#{ var.to_s[1..] }" : var.to_s[1..].to_sym, false]]
|
171
|
-
|
172
|
+
next if entry.rbs_declared
|
173
|
+
[var, ty.screen_name(@scratch)]
|
172
174
|
end.compact
|
173
175
|
|
174
176
|
cvars = cvars.map do |var, entry|
|
175
177
|
next if entry.absolute_paths.all? {|path| Config.check_dir_filter(path) == :exclude }
|
176
|
-
|
178
|
+
next if entry.rbs_declared
|
179
|
+
[var, entry.type.screen_name(@scratch)]
|
177
180
|
end.compact
|
178
181
|
|
179
182
|
if !class_def.absolute_path || Config.check_dir_filter(class_def.absolute_path) == :exclude
|
@@ -266,7 +269,7 @@ module TypeProf
|
|
266
269
|
output.puts indent + "#{ class_data.kind } #{ name }#{ superclass }"
|
267
270
|
first = true
|
268
271
|
class_data.consts.each do |name, ty|
|
269
|
-
output.puts indent + " #{ name }
|
272
|
+
output.puts indent + " #{ name }: #{ ty }"
|
270
273
|
first = false
|
271
274
|
end
|
272
275
|
class_data.included_mods.sort.each do |mod|
|
@@ -277,28 +280,31 @@ module TypeProf
|
|
277
280
|
output.puts indent + " extend #{ mod }"
|
278
281
|
first = false
|
279
282
|
end
|
280
|
-
class_data.ivars.each do |var, ty
|
281
|
-
|
282
|
-
output.puts indent + s + "#{ var } : #{ ty }" unless var.start_with?("_")
|
283
|
+
class_data.ivars.each do |var, ty|
|
284
|
+
output.puts indent + " #{ var }: #{ ty }" unless var.start_with?("_")
|
283
285
|
first = false
|
284
286
|
end
|
285
|
-
class_data.cvars.each do |var, ty
|
286
|
-
|
287
|
-
output.puts indent + s + "#{ var } : #{ ty }"
|
287
|
+
class_data.cvars.each do |var, ty|
|
288
|
+
output.puts indent + " #{ var }: #{ ty }"
|
288
289
|
first = false
|
289
290
|
end
|
290
291
|
class_data.attr_methods.each do |(method_name, hidden), (kind, ty)|
|
291
|
-
output.puts indent + " attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }
|
292
|
+
output.puts indent + " attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }: #{ ty }"
|
292
293
|
first = false
|
293
294
|
end
|
294
295
|
class_data.explicit_methods.each do |method_name, sigs|
|
295
296
|
sigs = sigs.sort.join("\n" + indent + "#" + " " * (method_name.size + 6) + "| ")
|
296
|
-
output.puts indent + "# def #{ method_name }
|
297
|
+
output.puts indent + "# def #{ method_name }: #{ sigs }"
|
297
298
|
first = false
|
298
299
|
end
|
299
|
-
|
300
|
+
prev_pub_meth = true
|
301
|
+
class_data.iseq_methods.each do |method_name, (pub_meth, sigs)|
|
300
302
|
sigs = sigs.sort.join("\n" + indent + " " * (method_name.size + 7) + "| ")
|
301
|
-
|
303
|
+
if prev_pub_meth != pub_meth
|
304
|
+
output.puts indent + " #{ pub_meth ? "public" : "private" }"
|
305
|
+
prev_pub_meth = pub_meth
|
306
|
+
end
|
307
|
+
output.puts indent + " def #{ method_name }: #{ sigs }"
|
302
308
|
first = false
|
303
309
|
end
|
304
310
|
show_class_hierarchy(depth + 1, class_data.inner_classes, output, first)
|
data/lib/typeprof/import.rb
CHANGED
@@ -26,6 +26,13 @@ module TypeProf
|
|
26
26
|
def load_library(lib)
|
27
27
|
loader = RBS::EnvironmentLoader.new(core_root: nil)
|
28
28
|
loader.add(library: lib)
|
29
|
+
|
30
|
+
case lib
|
31
|
+
when "yaml"
|
32
|
+
loader.add(library: "pstore")
|
33
|
+
loader.add(library: "dbm")
|
34
|
+
end
|
35
|
+
|
29
36
|
new_decls = loader.load(env: @env).map {|decl,| decl }
|
30
37
|
RBSReader.load_rbs(@env, new_decls)
|
31
38
|
end
|
@@ -100,14 +107,19 @@ module TypeProf
|
|
100
107
|
json = {}
|
101
108
|
|
102
109
|
each_class_decl do |name, decls|
|
103
|
-
super_class_name = get_super_class_name(name, decls)
|
104
110
|
klass = conv_type_name(name)
|
105
|
-
|
111
|
+
super_class_name, super_class_args = get_super_class(name, decls)
|
112
|
+
if super_class_name
|
113
|
+
name = conv_type_name(super_class_name)
|
114
|
+
type_args = super_class_args.map {|type| conv_type(type) }
|
115
|
+
superclass = [name, type_args]
|
116
|
+
end
|
106
117
|
|
107
118
|
type_params = nil
|
108
119
|
included_modules = []
|
109
120
|
extended_modules = []
|
110
121
|
methods = {}
|
122
|
+
attr_methods = {}
|
111
123
|
ivars = {}
|
112
124
|
cvars = {}
|
113
125
|
rbs_sources = {}
|
@@ -143,15 +155,15 @@ module TypeProf
|
|
143
155
|
end
|
144
156
|
when RBS::AST::Members::AttrReader
|
145
157
|
ty = conv_type(member.type)
|
146
|
-
|
158
|
+
attr_methods[[false, member.name]] = attr_method_def(:reader, member.name, ty)
|
147
159
|
when RBS::AST::Members::AttrWriter
|
148
160
|
ty = conv_type(member.type)
|
149
|
-
|
161
|
+
attr_methods[[false, member.name]] = attr_method_def(:writer, member.name, ty)
|
150
162
|
when RBS::AST::Members::AttrAccessor
|
151
163
|
ty = conv_type(member.type)
|
152
|
-
|
153
|
-
methods[[false, :"#{ member.name }="]] = attr_writer_def(ty)
|
164
|
+
attr_methods[[false, member.name]] = attr_method_def(:accessor, member.name, ty)
|
154
165
|
when RBS::AST::Members::Alias
|
166
|
+
# XXX: an alias to attr methods?
|
155
167
|
if member.instance?
|
156
168
|
method_def = methods[[false, member.old_name]]
|
157
169
|
methods[[false, member.new_name]] = method_def if method_def
|
@@ -165,7 +177,8 @@ module TypeProf
|
|
165
177
|
name = member.name
|
166
178
|
if name.kind == :class
|
167
179
|
mod = conv_type_name(name)
|
168
|
-
|
180
|
+
type_args = member.args.map {|type| conv_type(type) }
|
181
|
+
included_modules << [mod, type_args]
|
169
182
|
else
|
170
183
|
# including an interface is not supported yet
|
171
184
|
end
|
@@ -174,7 +187,8 @@ module TypeProf
|
|
174
187
|
name = member.name
|
175
188
|
if name.kind == :class
|
176
189
|
mod = conv_type_name(name)
|
177
|
-
|
190
|
+
type_args = member.args.map {|type| conv_type(type) }
|
191
|
+
extended_modules << [mod, type_args]
|
178
192
|
else
|
179
193
|
# extending a module with an interface is not supported yet
|
180
194
|
end
|
@@ -205,6 +219,7 @@ module TypeProf
|
|
205
219
|
included_modules: included_modules,
|
206
220
|
extended_modules: extended_modules,
|
207
221
|
methods: methods,
|
222
|
+
attr_methods: attr_methods,
|
208
223
|
ivars: ivars,
|
209
224
|
cvars: cvars,
|
210
225
|
rbs_sources: rbs_sources,
|
@@ -231,7 +246,7 @@ module TypeProf
|
|
231
246
|
@all_env.class_decls[name].decls.each do |decl|
|
232
247
|
decl = decl.decl
|
233
248
|
next if decl.is_a?(RBS::AST::Declarations::Module)
|
234
|
-
|
249
|
+
each_reference(decl) {|name| queue << [:visit, name] }
|
235
250
|
end
|
236
251
|
queue << [:visit, name.namespace.to_type_name] if !name.namespace.empty?
|
237
252
|
end
|
@@ -246,24 +261,32 @@ module TypeProf
|
|
246
261
|
end
|
247
262
|
end
|
248
263
|
|
249
|
-
def
|
264
|
+
def each_reference(decl, &blk)
|
250
265
|
yield decl.name
|
251
|
-
|
266
|
+
if decl.super_class
|
267
|
+
name = decl.super_class.name
|
268
|
+
else
|
269
|
+
name = RBS::BuiltinNames::Object.name
|
270
|
+
end
|
252
271
|
return if decl.name == RBS::BuiltinNames::BasicObject.name
|
253
|
-
return if decl.name ==
|
254
|
-
@all_env.class_decls[
|
255
|
-
|
272
|
+
return if decl.name == name
|
273
|
+
decls = @all_env.class_decls[name]
|
274
|
+
if decls
|
275
|
+
decls.decls.each do |decl|
|
276
|
+
each_reference(decl.decl, &blk)
|
277
|
+
end
|
256
278
|
end
|
257
279
|
end
|
258
280
|
|
259
|
-
def
|
281
|
+
def get_super_class(name, decls)
|
260
282
|
return nil if name == RBS::BuiltinNames::BasicObject.name
|
261
283
|
|
262
284
|
decls.each do |decl|
|
263
285
|
decl = decl.decl
|
264
286
|
case decl
|
265
287
|
when RBS::AST::Declarations::Class
|
266
|
-
|
288
|
+
super_class = decl.super_class
|
289
|
+
return super_class.name, super_class.args if super_class
|
267
290
|
when RBS::AST::Declarations::Module, RBS::AST::Declarations::Interface
|
268
291
|
return nil
|
269
292
|
else
|
@@ -271,7 +294,7 @@ module TypeProf
|
|
271
294
|
end
|
272
295
|
end
|
273
296
|
|
274
|
-
return RBS::BuiltinNames::Object.name
|
297
|
+
return RBS::BuiltinNames::Object.name, []
|
275
298
|
end
|
276
299
|
|
277
300
|
def conv_method_def(rbs_method_types)
|
@@ -290,7 +313,7 @@ module TypeProf
|
|
290
313
|
opt_kw_tys = func.optional_keywords.to_h {|key, type| [key, conv_type(type.type)] }
|
291
314
|
req_kw_tys = func.required_keywords.to_h {|key, type| [key, conv_type(type.type)] }
|
292
315
|
rest_kw_ty = func.rest_keywords
|
293
|
-
|
316
|
+
rest_kw_ty = conv_type(rest_kw_ty.type) if rest_kw_ty
|
294
317
|
|
295
318
|
ret_ty = conv_type(func.return_type)
|
296
319
|
|
@@ -307,32 +330,12 @@ module TypeProf
|
|
307
330
|
}
|
308
331
|
end
|
309
332
|
|
310
|
-
def
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
req_kw_tys: {},
|
317
|
-
opt_kw_tys: {},
|
318
|
-
rest_kw_ty: nil,
|
319
|
-
blk: nil,
|
320
|
-
ret_ty: ty,
|
321
|
-
}]
|
322
|
-
end
|
323
|
-
|
324
|
-
def attr_writer_def(ty)
|
325
|
-
[{
|
326
|
-
type_params: [],
|
327
|
-
lead_tys: [ty],
|
328
|
-
opt_tys: [],
|
329
|
-
rest_ty: nil,
|
330
|
-
req_kw_tys: {},
|
331
|
-
opt_kw_tys: {},
|
332
|
-
rest_kw_ty: nil,
|
333
|
-
blk: nil,
|
334
|
-
ret_ty: ty,
|
335
|
-
}]
|
333
|
+
def attr_method_def(kind, name, ty)
|
334
|
+
{
|
335
|
+
kind: kind,
|
336
|
+
ivar: name,
|
337
|
+
ty: ty,
|
338
|
+
}
|
336
339
|
end
|
337
340
|
|
338
341
|
def conv_block(rbs_block)
|
@@ -445,6 +448,8 @@ module TypeProf
|
|
445
448
|
json = scratch.rbs_reader.load_library(feature)
|
446
449
|
rescue RBS::EnvironmentLoader::UnknownLibraryError
|
447
450
|
return nil
|
451
|
+
rescue RBS::DuplicatedDeclarationError
|
452
|
+
return true
|
448
453
|
end
|
449
454
|
# need cache?
|
450
455
|
Import.new(scratch, json).import
|
@@ -467,8 +472,8 @@ module TypeProf
|
|
467
472
|
def import(explicit = false)
|
468
473
|
classes = @json[:classes].map do |classpath, cdef|
|
469
474
|
type_params = cdef[:type_params]
|
470
|
-
superclass
|
471
|
-
members
|
475
|
+
superclass, superclass_type_args = cdef[:superclass]
|
476
|
+
members = cdef[:members]
|
472
477
|
|
473
478
|
name = classpath.last
|
474
479
|
superclass = path_to_klass(superclass) if superclass
|
@@ -492,23 +497,27 @@ module TypeProf
|
|
492
497
|
end
|
493
498
|
end
|
494
499
|
|
495
|
-
[klass, members]
|
500
|
+
[klass, superclass_type_args, members]
|
496
501
|
end
|
497
502
|
|
498
|
-
classes.each do |klass, members|
|
503
|
+
classes.each do |klass, superclass_type_args, members|
|
504
|
+
@scratch.add_superclass_type_args!(klass, superclass_type_args&.map {|ty| conv_type(ty) })
|
499
505
|
included_modules = members[:included_modules]
|
500
506
|
extended_modules = members[:extended_modules]
|
501
507
|
methods = members[:methods]
|
508
|
+
attr_methods = members[:attr_methods]
|
502
509
|
ivars = members[:ivars]
|
503
510
|
cvars = members[:cvars]
|
504
511
|
rbs_sources = members[:rbs_sources]
|
505
512
|
|
506
|
-
included_modules.each do |mod|
|
507
|
-
|
513
|
+
included_modules.each do |mod, type_args|
|
514
|
+
type_args = type_args&.map {|ty| conv_type(ty) }
|
515
|
+
@scratch.include_module(klass, path_to_klass(mod), type_args, false, nil)
|
508
516
|
end
|
509
517
|
|
510
|
-
extended_modules.each do |mod|
|
511
|
-
|
518
|
+
extended_modules.each do |mod, type_args|
|
519
|
+
type_args = type_args&.map {|ty| conv_type(ty) }
|
520
|
+
@scratch.include_module(klass, path_to_klass(mod), type_args, true, nil)
|
512
521
|
end
|
513
522
|
|
514
523
|
methods.each do |(singleton, method_name), mdef|
|
@@ -517,6 +526,14 @@ module TypeProf
|
|
517
526
|
@scratch.add_method(klass, method_name, singleton, mdef)
|
518
527
|
end
|
519
528
|
|
529
|
+
attr_methods.each do |(singleton, method_name), mdef|
|
530
|
+
kind = mdef[:kind]
|
531
|
+
ivar = mdef[:ivar]
|
532
|
+
ty = conv_type(mdef[:ty]).remove_type_vars
|
533
|
+
@scratch.add_attr_method(klass, nil, ivar, :"@#{ ivar }", kind)
|
534
|
+
@scratch.add_ivar_write!(Type::Instance.new(klass), :"@#{ ivar }", ty, nil)
|
535
|
+
end
|
536
|
+
|
520
537
|
ivars.each do |ivar_name, ty|
|
521
538
|
ty = conv_type(ty).remove_type_vars
|
522
539
|
@scratch.add_ivar_write!(Type::Instance.new(klass), ivar_name, ty, nil)
|
@@ -583,7 +600,7 @@ module TypeProf
|
|
583
600
|
req, lead_tys, opt_tys, ret_ty = blk
|
584
601
|
lead_tys = lead_tys.map {|ty| conv_type(ty) }
|
585
602
|
opt_tys = opt_tys.map {|ty| conv_type(ty) }
|
586
|
-
msig = MethodSignature.new(lead_tys, opt_tys, nil,
|
603
|
+
msig = MethodSignature.new(lead_tys, opt_tys, nil, [], {}, nil, Type.nil)
|
587
604
|
ret_ty = conv_type(ret_ty)
|
588
605
|
ret = [Type::Proc.new(TypedBlock.new(msig, ret_ty), Type::Builtin[:proc])]
|
589
606
|
ret << Type.nil unless req
|
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
|
@@ -209,7 +225,7 @@ module TypeProf
|
|
209
225
|
end
|
210
226
|
end
|
211
227
|
send_branch_list.each do |i, j|
|
212
|
-
next if (i + 1 .. j).any? {|i| branch_targets[i] }
|
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]
|
data/lib/typeprof/method.rb
CHANGED
@@ -4,12 +4,16 @@ module TypeProf
|
|
4
4
|
end
|
5
5
|
|
6
6
|
class ISeqMethodDef < MethodDef
|
7
|
-
def initialize(iseq, cref)
|
7
|
+
def initialize(iseq, cref, outer_ep, pub_meth)
|
8
8
|
@iseq = iseq
|
9
9
|
raise if iseq.nil?
|
10
10
|
@cref = cref
|
11
|
+
@outer_ep = outer_ep
|
12
|
+
@pub_meth = pub_meth
|
11
13
|
end
|
12
14
|
|
15
|
+
attr_accessor :pub_meth
|
16
|
+
|
13
17
|
def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
|
14
18
|
recv = recv.base_type while recv.respond_to?(:base_type)
|
15
19
|
recv = scratch.globalize_type(recv, caller_env, caller_ep)
|
@@ -25,8 +29,8 @@ module TypeProf
|
|
25
29
|
end
|
26
30
|
|
27
31
|
nctx = Context.new(@iseq, @cref, mid)
|
28
|
-
callee_ep = ExecutionPoint.new(nctx, 0,
|
29
|
-
nenv = Env.new(StaticEnv.new(recv, blk_ty, false), locals, [], Utils::HashWrapper.new({}))
|
32
|
+
callee_ep = ExecutionPoint.new(nctx, 0, @outer_ep)
|
33
|
+
nenv = Env.new(StaticEnv.new(recv, blk_ty, false, true), locals, [], Utils::HashWrapper.new({}))
|
30
34
|
alloc_site = AllocationSite.new(callee_ep)
|
31
35
|
locals.each_with_index do |ty, i|
|
32
36
|
alloc_site2 = alloc_site.add_id(i)
|
@@ -44,6 +48,14 @@ module TypeProf
|
|
44
48
|
end
|
45
49
|
|
46
50
|
def do_check_send(msig, recv, mid, ep, scratch)
|
51
|
+
klass, singleton = recv.method_dispatch_info
|
52
|
+
cur_subst = {}
|
53
|
+
direct_method = true
|
54
|
+
scratch.adjust_substitution(klass, singleton, mid, self, recv.generate_substitution) do |subst, direct|
|
55
|
+
direct_method &&= direct
|
56
|
+
cur_subst = Type.merge_substitution(cur_subst, subst)
|
57
|
+
end
|
58
|
+
|
47
59
|
lead_num = @iseq.fargs_format[:lead_num] || 0
|
48
60
|
post_num = @iseq.fargs_format[:post_num] || 0
|
49
61
|
rest_start = @iseq.fargs_format[:rest_start]
|
@@ -67,63 +79,75 @@ module TypeProf
|
|
67
79
|
post_start = @iseq.fargs_format[:post_start]
|
68
80
|
rest_start = @iseq.fargs_format[:rest_start]
|
69
81
|
kw_start = @iseq.fargs_format[:kwbits]
|
70
|
-
|
82
|
+
keyword = @iseq.fargs_format[:keyword]
|
83
|
+
kw_start -= keyword.size if kw_start
|
71
84
|
kw_rest = @iseq.fargs_format[:kwrest]
|
72
85
|
block_start = @iseq.fargs_format[:block_start]
|
73
86
|
|
74
87
|
# XXX: need to check .rbs msig and .rb fargs
|
75
88
|
|
76
89
|
ctx = Context.new(@iseq, @cref, mid)
|
77
|
-
callee_ep = ExecutionPoint.new(ctx, 0,
|
90
|
+
callee_ep = ExecutionPoint.new(ctx, 0, @outer_ep)
|
78
91
|
|
79
92
|
locals = [Type.nil] * @iseq.locals.size
|
80
|
-
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({}))
|
81
94
|
alloc_site = AllocationSite.new(callee_ep)
|
82
95
|
idx = 0
|
83
96
|
msig.lead_tys.each_with_index do |ty, i|
|
84
97
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
85
|
-
|
86
|
-
nenv, ty =
|
98
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
99
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
87
100
|
nenv = nenv.local_update(i, ty)
|
88
101
|
end
|
89
102
|
if msig.opt_tys
|
90
103
|
msig.opt_tys.each_with_index do |ty, i|
|
91
104
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
92
|
-
|
105
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
106
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
93
107
|
nenv = nenv.local_update(lead_num + i, ty)
|
94
108
|
end
|
95
109
|
end
|
96
110
|
if msig.rest_ty
|
97
111
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
98
112
|
ty = Type::Array.new(Type::Array::Elements.new([], msig.rest_ty), Type::Instance.new(Type::Builtin[:ary]))
|
99
|
-
|
113
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
114
|
+
nenv, rest_ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
100
115
|
nenv = nenv.local_update(rest_start, rest_ty)
|
101
116
|
end
|
102
117
|
if msig.post_tys
|
103
118
|
msig.post_tys.each_with_index do |ty, i|
|
104
119
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
105
|
-
|
120
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
121
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
106
122
|
nenv = nenv.local_update(post_start + i, ty)
|
107
123
|
end
|
108
124
|
end
|
109
|
-
if msig.kw_tys
|
110
|
-
msig.kw_tys.
|
125
|
+
if msig.kw_tys && keyword # TODO: support the case where RBS writes kw_tys and RB method accepts **kwrest
|
126
|
+
msig.kw_tys.each do |_, key, ty|
|
127
|
+
i = keyword.index {|callee_key,| callee_key == key }
|
128
|
+
unless i
|
129
|
+
# warn
|
130
|
+
next
|
131
|
+
end
|
111
132
|
alloc_site2 = alloc_site.add_id(key)
|
112
|
-
|
133
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
134
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
113
135
|
nenv = nenv.local_update(kw_start + i, ty)
|
114
136
|
end
|
115
137
|
end
|
116
138
|
if msig.kw_rest_ty
|
117
139
|
ty = msig.kw_rest_ty
|
118
140
|
alloc_site2 = alloc_site.add_id(:**)
|
119
|
-
|
141
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
142
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
120
143
|
nenv = nenv.local_update(kw_rest, ty)
|
121
144
|
end
|
122
145
|
nenv = nenv.local_update(block_start, msig.blk_ty) if block_start
|
123
146
|
|
124
147
|
opt.each do |start_pc|
|
125
|
-
scratch.merge_env(
|
148
|
+
scratch.merge_env(callee_ep.jump(start_pc), nenv)
|
126
149
|
end
|
150
|
+
scratch.add_executed_iseq(@iseq)
|
127
151
|
|
128
152
|
ctx
|
129
153
|
end
|
@@ -142,8 +166,8 @@ module TypeProf
|
|
142
166
|
case @kind
|
143
167
|
when :reader
|
144
168
|
if aargs.lead_tys.size == 0
|
145
|
-
scratch.
|
146
|
-
ctn[ty, caller_ep,
|
169
|
+
scratch.add_ivar_read!(recv, @ivar, caller_ep) do |ty, _ep|
|
170
|
+
ctn[ty, caller_ep, caller_env]
|
147
171
|
end
|
148
172
|
else
|
149
173
|
ctn[Type.any, caller_ep, caller_env]
|
@@ -170,6 +194,15 @@ module TypeProf
|
|
170
194
|
|
171
195
|
def do_send(recv_orig, mid, aargs, caller_ep, caller_env, scratch, &ctn)
|
172
196
|
recv = scratch.globalize_type(recv_orig, caller_env, caller_ep)
|
197
|
+
|
198
|
+
klass, singleton = recv_orig.method_dispatch_info
|
199
|
+
cur_subst = {}
|
200
|
+
direct_method = true
|
201
|
+
scratch.adjust_substitution(klass, singleton, mid, self, recv.generate_substitution) do |subst, direct|
|
202
|
+
direct_method &&= direct
|
203
|
+
cur_subst = Type.merge_substitution(cur_subst, subst)
|
204
|
+
end
|
205
|
+
|
173
206
|
found = false
|
174
207
|
aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
|
175
208
|
@sig_rets.each do |msig, ret_ty|
|
@@ -178,56 +211,15 @@ module TypeProf
|
|
178
211
|
# XXX: support self type in msig
|
179
212
|
subst = aargs.consistent_with_method_signature?(msig)
|
180
213
|
next unless subst
|
214
|
+
|
215
|
+
if direct_method && recv_orig.is_a?(Type::Local)
|
216
|
+
ncaller_env = recv_orig.update_container_elem_type(subst, ncaller_env, caller_ep, scratch)
|
217
|
+
end
|
218
|
+
|
219
|
+
subst = Type.merge_substitution(subst, cur_subst)
|
181
220
|
# need to check self tyvar?
|
182
221
|
subst[Type::Var.new(:self)] = recv
|
183
|
-
|
184
|
-
when recv.is_a?(Type::Cell) && recv_orig.is_a?(Type::LocalCell)
|
185
|
-
tyvars = recv.base_type.klass.type_params.map {|name,| Type::Var.new(name) }
|
186
|
-
tyvars.each_with_index do |tyvar, idx|
|
187
|
-
ty = subst[tyvar]
|
188
|
-
if ty
|
189
|
-
ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
|
190
|
-
ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
|
191
|
-
elems.update(idx, ty)
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
195
|
-
tyvars.zip(recv.elems.elems) do |tyvar, elem|
|
196
|
-
if subst[tyvar]
|
197
|
-
subst[tyvar] = subst[tyvar].union(elem)
|
198
|
-
else
|
199
|
-
subst[tyvar] = elem
|
200
|
-
end
|
201
|
-
end
|
202
|
-
when recv.is_a?(Type::Array) && recv_orig.is_a?(Type::LocalArray)
|
203
|
-
tyvar_elem = Type::Var.new(:Elem)
|
204
|
-
if subst[tyvar_elem]
|
205
|
-
ty = subst[tyvar_elem]
|
206
|
-
ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
|
207
|
-
ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
|
208
|
-
elems.update(nil, ty)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
subst.merge!({ tyvar_elem => recv.elems.squash })
|
212
|
-
when recv.is_a?(Type::Hash) && recv_orig.is_a?(Type::LocalHash)
|
213
|
-
tyvar_k = Type::Var.new(:K)
|
214
|
-
tyvar_v = Type::Var.new(:V)
|
215
|
-
k_ty0, v_ty0 = recv.elems.squash
|
216
|
-
if subst[tyvar_k] && subst[tyvar_v]
|
217
|
-
k_ty = subst[tyvar_k]
|
218
|
-
v_ty = subst[tyvar_v]
|
219
|
-
k_ty0 = k_ty0.union(k_ty)
|
220
|
-
v_ty0 = v_ty0.union(v_ty)
|
221
|
-
alloc_site = AllocationSite.new(caller_ep)
|
222
|
-
ncaller_env, k_ty = scratch.localize_type(k_ty, ncaller_env, caller_ep, alloc_site.add_id(:k))
|
223
|
-
ncaller_env, v_ty = scratch.localize_type(v_ty, ncaller_env, caller_ep, alloc_site.add_id(:v))
|
224
|
-
ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
|
225
|
-
elems.update(k_ty, v_ty)
|
226
|
-
end
|
227
|
-
end
|
228
|
-
# XXX: need to heuristically replace ret type Hash[K, V] with self, instead of conversative type?
|
229
|
-
subst.merge!({ tyvar_k => k_ty0, tyvar_v => v_ty0 })
|
230
|
-
end
|
222
|
+
|
231
223
|
found = true
|
232
224
|
if aargs.blk_ty.is_a?(Type::Proc)
|
233
225
|
#raise NotImplementedError unless aargs.blk_ty.block_body.is_a?(ISeqBlock) # XXX
|
@@ -235,91 +227,33 @@ module TypeProf
|
|
235
227
|
dummy_ep = ExecutionPoint.new(dummy_ctx, -1, caller_ep)
|
236
228
|
s_recv = recv
|
237
229
|
s_recv = s_recv.base_type while s_recv.respond_to?(:base_type)
|
238
|
-
dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false), [], [], Utils::HashWrapper.new({}))
|
230
|
+
dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false, true), [], [], Utils::HashWrapper.new({}))
|
239
231
|
if msig.blk_ty.is_a?(Type::Proc)
|
240
232
|
scratch.add_callsite!(dummy_ctx, caller_ep, ncaller_env, &ctn)
|
241
|
-
|
233
|
+
bsig = msig.blk_ty.block_body.msig
|
242
234
|
alloc_site = AllocationSite.new(caller_ep).add_id(self)
|
243
|
-
nlead_tys = (
|
244
|
-
|
245
|
-
|
246
|
-
ty = ty.substitute(subst.merge({ tyvar_elem => recv.elems.squash_or_any }), Config.options[:type_depth_limit])
|
247
|
-
else
|
248
|
-
ty = ty.substitute(subst, Config.options[:type_depth_limit])
|
249
|
-
end
|
250
|
-
ty = ty.remove_type_vars
|
251
|
-
alloc_site2 = alloc_site.add_id(i)
|
252
|
-
dummy_env, ty = scratch.localize_type(ty, dummy_env, dummy_ep, alloc_site2)
|
235
|
+
nlead_tys = (bsig.lead_tys + bsig.opt_tys).map.with_index do |ty, i|
|
236
|
+
ty = ty.substitute(subst, Config.options[:type_depth_limit]).remove_type_vars
|
237
|
+
dummy_env, ty = scratch.localize_type(ty, dummy_env, dummy_ep, alloc_site.add_id(i))
|
253
238
|
ty
|
254
239
|
end
|
255
|
-
0.upto(
|
256
|
-
naargs = ActualArguments.new(nlead_tys[0,
|
240
|
+
0.upto(bsig.opt_tys.size) do |n|
|
241
|
+
naargs = ActualArguments.new(nlead_tys[0, bsig.lead_tys.size + n], nil, {}, Type.nil) # XXX: support block to block?
|
257
242
|
scratch.do_invoke_block(aargs.blk_ty, naargs, dummy_ep, dummy_env) do |blk_ret_ty, _ep, _env|
|
258
243
|
subst2 = Type.match?(blk_ret_ty, msig.blk_ty.block_body.ret_ty)
|
259
244
|
if subst2
|
260
245
|
subst2 = Type.merge_substitution(subst, subst2)
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
tyvars.each_with_index do |tyvar, idx|
|
265
|
-
ty = subst2[tyvar]
|
266
|
-
if ty
|
267
|
-
ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
|
268
|
-
ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
|
269
|
-
elems.update(idx, ty)
|
270
|
-
end
|
271
|
-
scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
|
272
|
-
end
|
273
|
-
end
|
274
|
-
tyvars.zip(recv.elems.elems) do |tyvar, elem|
|
275
|
-
if subst2[tyvar]
|
276
|
-
subst2[tyvar] = subst2[tyvar].union(elem)
|
277
|
-
else
|
278
|
-
subst2[tyvar] = elem
|
279
|
-
end
|
280
|
-
end
|
281
|
-
ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
|
282
|
-
when recv.is_a?(Type::Array) && recv_orig.is_a?(Type::LocalArray)
|
283
|
-
tyvar_elem = Type::Var.new(:Elem)
|
284
|
-
if subst2[tyvar_elem]
|
285
|
-
ty = subst2[tyvar_elem]
|
286
|
-
ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
|
287
|
-
ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
|
288
|
-
elems.update(nil, ty)
|
289
|
-
end
|
290
|
-
scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
|
291
|
-
end
|
292
|
-
ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
|
293
|
-
when recv.is_a?(Type::Hash) && recv_orig.is_a?(Type::LocalHash)
|
294
|
-
tyvar_k = Type::Var.new(:K)
|
295
|
-
tyvar_v = Type::Var.new(:V)
|
296
|
-
k_ty0, v_ty0 = recv.elems.squash
|
297
|
-
if subst2[tyvar_k] && subst2[tyvar_v]
|
298
|
-
k_ty = subst2[tyvar_k]
|
299
|
-
v_ty = subst2[tyvar_v]
|
300
|
-
k_ty0 = k_ty0.union(k_ty)
|
301
|
-
v_ty0 = v_ty0.union(v_ty)
|
302
|
-
alloc_site = AllocationSite.new(caller_ep)
|
303
|
-
ncaller_env, k_ty = scratch.localize_type(k_ty, ncaller_env, caller_ep, alloc_site.add_id(:k))
|
304
|
-
ncaller_env, v_ty = scratch.localize_type(v_ty, ncaller_env, caller_ep, alloc_site.add_id(:v))
|
305
|
-
ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
|
306
|
-
elems.update(k_ty, v_ty)
|
307
|
-
end
|
308
|
-
scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
|
309
|
-
end
|
310
|
-
ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
|
311
|
-
else
|
312
|
-
ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
|
246
|
+
if direct_method && recv_orig.is_a?(Type::Local)
|
247
|
+
ncaller_env = recv_orig.update_container_elem_type(subst2, ncaller_env, caller_ep, scratch)
|
248
|
+
scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
|
313
249
|
end
|
250
|
+
ret_ty2 = ret_ty.substitute(subst2, Config.options[:type_depth_limit]).remove_type_vars
|
314
251
|
else
|
315
|
-
|
316
|
-
# XXX: need warning
|
317
|
-
ret_ty = Type.any
|
252
|
+
ret_ty2 = Type.any
|
318
253
|
end
|
319
|
-
ret_ty = ret_ty.remove_type_vars
|
320
254
|
# XXX: check the return type from the block
|
321
255
|
# sig.blk_ty.block_body.ret_ty.eql?(_ret_ty) ???
|
322
|
-
scratch.add_return_value!(dummy_ctx,
|
256
|
+
scratch.add_return_value!(dummy_ctx, ret_ty2)
|
323
257
|
end
|
324
258
|
# scratch.add_return_value!(dummy_ctx, ret_ty) ?
|
325
259
|
# This makes `def foo; 1.times { return "str" }; end` return Integer|String
|
@@ -357,7 +291,6 @@ module TypeProf
|
|
357
291
|
end
|
358
292
|
|
359
293
|
def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
|
360
|
-
scratch.merge_return_env(caller_ep) {|env| env ? env.merge(caller_env) : caller_env } # for Kernel#lambda
|
361
294
|
@impl[recv, mid, aargs, caller_ep, caller_env, scratch, &ctn]
|
362
295
|
end
|
363
296
|
end
|