typeprof 0.5.3 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +6 -4
- data/doc/doc.ja.md +3 -4
- data/doc/doc.md +3 -4
- data/lib/typeprof/analyzer.rb +248 -166
- data/lib/typeprof/arguments.rb +12 -6
- data/lib/typeprof/builtin.rb +123 -23
- data/lib/typeprof/cli.rb +33 -34
- data/lib/typeprof/config.rb +6 -4
- data/lib/typeprof/container-type.rb +175 -112
- data/lib/typeprof/export.rb +23 -17
- data/lib/typeprof/import.rb +58 -53
- data/lib/typeprof/method.rb +59 -125
- data/lib/typeprof/type.rb +26 -14
- data/lib/typeprof/version.rb +1 -1
- data/smoke/alias.rb +1 -0
- data/smoke/any1.rb +1 -0
- data/smoke/any2.rb +1 -0
- data/smoke/arguments.rb +1 -0
- data/smoke/arguments2.rb +1 -0
- data/smoke/array-each.rb +1 -0
- data/smoke/array-each2.rb +1 -0
- data/smoke/array-each3.rb +2 -1
- data/smoke/array-ltlt.rb +1 -0
- data/smoke/array-ltlt2.rb +1 -0
- data/smoke/array-map.rb +1 -0
- data/smoke/array-map2.rb +1 -0
- data/smoke/array-map3.rb +1 -0
- data/smoke/array-mul.rb +1 -0
- data/smoke/array-plus1.rb +1 -0
- data/smoke/array-pop.rb +1 -0
- data/smoke/array-range-aref.rb +71 -0
- data/smoke/array-replace.rb +1 -0
- data/smoke/array-s-aref.rb +1 -0
- data/smoke/array1.rb +1 -0
- data/smoke/array10.rb +1 -0
- data/smoke/array11.rb +2 -1
- data/smoke/array12.rb +1 -0
- data/smoke/array13.rb +1 -0
- data/smoke/array14.rb +1 -0
- data/smoke/array2.rb +1 -0
- data/smoke/array4.rb +1 -0
- data/smoke/array5.rb +1 -0
- data/smoke/array6.rb +3 -2
- data/smoke/array7.rb +1 -0
- data/smoke/array8.rb +1 -1
- data/smoke/array9.rb +1 -0
- data/smoke/autoload.rb +14 -0
- data/smoke/backtrace.rb +1 -0
- data/smoke/block-ambiguous.rb +1 -0
- data/smoke/block-args1-rest.rb +1 -0
- data/smoke/block-args1.rb +1 -0
- data/smoke/block-args2-rest.rb +1 -0
- data/smoke/block-args2.rb +4 -3
- data/smoke/block-args3-rest.rb +1 -0
- data/smoke/block-args3.rb +5 -4
- data/smoke/block-blockarg.rb +2 -1
- data/smoke/block-kwarg.rb +1 -0
- data/smoke/block1.rb +1 -0
- data/smoke/block10.rb +1 -0
- data/smoke/block11.rb +1 -0
- data/smoke/block12.rb +1 -0
- data/smoke/block14.rb +1 -0
- data/smoke/block2.rb +1 -0
- data/smoke/block4.rb +1 -0
- data/smoke/block5.rb +2 -1
- data/smoke/block6.rb +1 -0
- data/smoke/block7.rb +1 -0
- data/smoke/block8.rb +1 -0
- data/smoke/block9.rb +1 -0
- data/smoke/blown.rb +1 -0
- data/smoke/break1.rb +1 -0
- data/smoke/break2.rb +1 -0
- data/smoke/case.rb +1 -0
- data/smoke/case2.rb +1 -0
- data/smoke/class_method3.rb +2 -0
- data/smoke/constant2.rb +2 -2
- data/smoke/constant3.rb +1 -0
- data/smoke/constant4.rb +1 -0
- data/smoke/context-sensitive1.rb +1 -0
- data/smoke/cvar.rb +1 -0
- data/smoke/define_method.rb +16 -0
- data/smoke/define_method2.rb +18 -0
- data/smoke/demo.rb +1 -0
- data/smoke/demo1.rb +1 -0
- data/smoke/demo10.rb +1 -0
- data/smoke/demo11.rb +1 -0
- data/smoke/demo2.rb +1 -0
- data/smoke/demo3.rb +1 -0
- data/smoke/demo5.rb +1 -1
- data/smoke/demo7.rb +1 -0
- data/smoke/demo8.rb +1 -0
- data/smoke/demo9.rb +2 -1
- data/smoke/dummy-execution1.rb +1 -0
- data/smoke/ensure1.rb +1 -0
- data/smoke/enumerator.rb +1 -0
- data/smoke/expandarray1.rb +1 -0
- data/smoke/expandarray2.rb +1 -0
- data/smoke/flow1.rb +1 -0
- data/smoke/flow2.rb +1 -0
- data/smoke/flow3.rb +1 -0
- data/smoke/flow5.rb +1 -0
- data/smoke/flow6.rb +1 -0
- data/smoke/flow7.rb +1 -0
- data/smoke/flow8.rb +1 -0
- data/smoke/freeze.rb +1 -0
- data/smoke/function.rb +1 -0
- data/smoke/gvar.rb +1 -0
- data/smoke/gvar2.rb +1 -0
- data/smoke/hash-fetch.rb +1 -0
- data/smoke/hash-merge-bang.rb +1 -0
- data/smoke/hash1.rb +3 -1
- data/smoke/hash2.rb +1 -0
- data/smoke/hash3.rb +1 -0
- data/smoke/hash4.rb +2 -1
- data/smoke/inheritance2.rb +2 -2
- data/smoke/initialize.rb +1 -0
- data/smoke/int_times.rb +1 -0
- data/smoke/integer.rb +1 -0
- data/smoke/ivar.rb +1 -0
- data/smoke/ivar2.rb +1 -1
- data/smoke/kernel-class.rb +2 -1
- data/smoke/keyword1.rb +1 -0
- data/smoke/keyword2.rb +1 -0
- data/smoke/keyword3.rb +1 -0
- data/smoke/keyword4.rb +1 -0
- data/smoke/keyword5.rb +1 -0
- data/smoke/kwrest.rb +12 -0
- data/smoke/kwrest.rbs +3 -0
- data/smoke/kwsplat1.rb +2 -1
- data/smoke/kwsplat2.rb +1 -0
- data/smoke/manual-rbs.rb +1 -0
- data/smoke/manual-rbs2.rb +1 -0
- data/smoke/masgn1.rb +1 -0
- data/smoke/masgn2.rb +1 -0
- data/smoke/masgn3.rb +1 -0
- data/smoke/method_in_branch.rb +1 -0
- data/smoke/method_missing.rb +28 -0
- data/smoke/multiple-superclass.rb +1 -1
- data/smoke/next1.rb +1 -0
- data/smoke/next2.rb +1 -0
- data/smoke/object-send1.rb +1 -0
- data/smoke/once.rb +1 -0
- data/smoke/optional1.rb +1 -0
- data/smoke/optional2.rb +1 -0
- data/smoke/optional3.rb +1 -0
- data/smoke/parameterizedd-self.rb +3 -2
- data/smoke/parameterizedd-self2.rb +15 -0
- data/smoke/pathname1.rb +1 -0
- data/smoke/pathname2.rb +1 -0
- data/smoke/pattern-match1.rb +1 -0
- data/smoke/pattern-match2.rb +1 -0
- data/smoke/proc.rb +1 -0
- data/smoke/proc2.rb +1 -0
- data/smoke/proc3.rb +1 -0
- data/smoke/proc4.rb +1 -0
- data/smoke/range.rb +1 -0
- data/smoke/rbs-alias.rb +1 -0
- data/smoke/rbs-attr.rb +3 -2
- data/smoke/rbs-attr2.rb +11 -0
- data/smoke/rbs-attr2.rbs +3 -0
- data/smoke/rbs-extend.rb +1 -0
- data/smoke/rbs-interface.rb +1 -0
- data/smoke/rbs-proc1.rb +1 -0
- data/smoke/rbs-proc2.rb +1 -0
- data/smoke/rbs-proc3.rb +1 -0
- data/smoke/rbs-record.rb +1 -0
- data/smoke/rbs-tyvar.rb +1 -0
- data/smoke/rbs-tyvar2.rb +1 -0
- data/smoke/rbs-tyvar3.rb +1 -0
- data/smoke/rbs-tyvar5.rb +1 -0
- 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 +1 -2
- data/smoke/redo1.rb +1 -0
- data/smoke/redo2.rb +1 -0
- data/smoke/req-keyword.rb +1 -0
- data/smoke/rescue1.rb +1 -0
- data/smoke/rescue2.rb +1 -0
- data/smoke/respond_to.rb +1 -0
- data/smoke/rest-farg.rb +1 -0
- data/smoke/rest1.rb +1 -0
- data/smoke/rest2.rb +1 -0
- data/smoke/rest3.rb +1 -0
- data/smoke/rest4.rb +1 -0
- data/smoke/rest5.rb +1 -0
- data/smoke/rest6.rb +1 -0
- data/smoke/retry1.rb +1 -0
- data/smoke/return.rb +1 -0
- data/smoke/step.rb +1 -0
- data/smoke/string-split.rb +1 -0
- data/smoke/struct.rb +2 -2
- data/smoke/struct2.rb +1 -0
- data/smoke/super1.rb +1 -0
- data/smoke/super4.rb +43 -0
- data/smoke/super5.rb +36 -0
- data/smoke/svar1.rb +1 -0
- data/smoke/symbol-proc.rb +1 -0
- data/smoke/tap1.rb +1 -0
- data/smoke/toplevel.rb +1 -0
- data/smoke/two-map.rb +1 -0
- data/smoke/type_var.rb +1 -0
- data/smoke/typed_method.rb +1 -0
- data/smoke/uninitialize-var.rb +1 -0
- data/smoke/union-recv.rb +2 -2
- metadata +18 -2
data/lib/typeprof/export.rb
CHANGED
@@ -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
|
@@ -277,14 +280,12 @@ 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)|
|
@@ -296,8 +297,13 @@ module TypeProf
|
|
296
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) + "| ")
|
303
|
+
if prev_pub_meth != pub_meth
|
304
|
+
output.puts indent + " #{ pub_meth ? "public" : "private" }"
|
305
|
+
prev_pub_meth = pub_meth
|
306
|
+
end
|
301
307
|
output.puts indent + " def #{ method_name } : #{ sigs }"
|
302
308
|
first = false
|
303
309
|
end
|
data/lib/typeprof/import.rb
CHANGED
@@ -100,14 +100,19 @@ module TypeProf
|
|
100
100
|
json = {}
|
101
101
|
|
102
102
|
each_class_decl do |name, decls|
|
103
|
-
super_class_name = get_super_class_name(name, decls)
|
104
103
|
klass = conv_type_name(name)
|
105
|
-
|
104
|
+
super_class_name, super_class_args = get_super_class(name, decls)
|
105
|
+
if super_class_name
|
106
|
+
name = conv_type_name(super_class_name)
|
107
|
+
type_args = super_class_args.map {|type| conv_type(type) }
|
108
|
+
superclass = [name, type_args]
|
109
|
+
end
|
106
110
|
|
107
111
|
type_params = nil
|
108
112
|
included_modules = []
|
109
113
|
extended_modules = []
|
110
114
|
methods = {}
|
115
|
+
attr_methods = {}
|
111
116
|
ivars = {}
|
112
117
|
cvars = {}
|
113
118
|
rbs_sources = {}
|
@@ -143,15 +148,15 @@ module TypeProf
|
|
143
148
|
end
|
144
149
|
when RBS::AST::Members::AttrReader
|
145
150
|
ty = conv_type(member.type)
|
146
|
-
|
151
|
+
attr_methods[[false, member.name]] = attr_method_def(:reader, member.name, ty)
|
147
152
|
when RBS::AST::Members::AttrWriter
|
148
153
|
ty = conv_type(member.type)
|
149
|
-
|
154
|
+
attr_methods[[false, member.name]] = attr_method_def(:writer, member.name, ty)
|
150
155
|
when RBS::AST::Members::AttrAccessor
|
151
156
|
ty = conv_type(member.type)
|
152
|
-
|
153
|
-
methods[[false, :"#{ member.name }="]] = attr_writer_def(ty)
|
157
|
+
attr_methods[[false, member.name]] = attr_method_def(:accessor, member.name, ty)
|
154
158
|
when RBS::AST::Members::Alias
|
159
|
+
# XXX: an alias to attr methods?
|
155
160
|
if member.instance?
|
156
161
|
method_def = methods[[false, member.old_name]]
|
157
162
|
methods[[false, member.new_name]] = method_def if method_def
|
@@ -165,7 +170,8 @@ module TypeProf
|
|
165
170
|
name = member.name
|
166
171
|
if name.kind == :class
|
167
172
|
mod = conv_type_name(name)
|
168
|
-
|
173
|
+
type_args = member.args.map {|type| conv_type(type) }
|
174
|
+
included_modules << [mod, type_args]
|
169
175
|
else
|
170
176
|
# including an interface is not supported yet
|
171
177
|
end
|
@@ -174,7 +180,8 @@ module TypeProf
|
|
174
180
|
name = member.name
|
175
181
|
if name.kind == :class
|
176
182
|
mod = conv_type_name(name)
|
177
|
-
|
183
|
+
type_args = member.args.map {|type| conv_type(type) }
|
184
|
+
extended_modules << [mod, type_args]
|
178
185
|
else
|
179
186
|
# extending a module with an interface is not supported yet
|
180
187
|
end
|
@@ -205,6 +212,7 @@ module TypeProf
|
|
205
212
|
included_modules: included_modules,
|
206
213
|
extended_modules: extended_modules,
|
207
214
|
methods: methods,
|
215
|
+
attr_methods: attr_methods,
|
208
216
|
ivars: ivars,
|
209
217
|
cvars: cvars,
|
210
218
|
rbs_sources: rbs_sources,
|
@@ -231,7 +239,7 @@ module TypeProf
|
|
231
239
|
@all_env.class_decls[name].decls.each do |decl|
|
232
240
|
decl = decl.decl
|
233
241
|
next if decl.is_a?(RBS::AST::Declarations::Module)
|
234
|
-
|
242
|
+
each_reference(decl) {|name| queue << [:visit, name] }
|
235
243
|
end
|
236
244
|
queue << [:visit, name.namespace.to_type_name] if !name.namespace.empty?
|
237
245
|
end
|
@@ -246,24 +254,29 @@ module TypeProf
|
|
246
254
|
end
|
247
255
|
end
|
248
256
|
|
249
|
-
def
|
257
|
+
def each_reference(decl, &blk)
|
250
258
|
yield decl.name
|
251
|
-
|
259
|
+
if decl.super_class
|
260
|
+
name = decl.super_class.name
|
261
|
+
else
|
262
|
+
name = RBS::BuiltinNames::Object.name
|
263
|
+
end
|
252
264
|
return if decl.name == RBS::BuiltinNames::BasicObject.name
|
253
|
-
return if decl.name ==
|
254
|
-
@all_env.class_decls[
|
255
|
-
|
265
|
+
return if decl.name == name
|
266
|
+
@all_env.class_decls[name].decls.each do |decl|
|
267
|
+
each_reference(decl.decl, &blk)
|
256
268
|
end
|
257
269
|
end
|
258
270
|
|
259
|
-
def
|
271
|
+
def get_super_class(name, decls)
|
260
272
|
return nil if name == RBS::BuiltinNames::BasicObject.name
|
261
273
|
|
262
274
|
decls.each do |decl|
|
263
275
|
decl = decl.decl
|
264
276
|
case decl
|
265
277
|
when RBS::AST::Declarations::Class
|
266
|
-
|
278
|
+
super_class = decl.super_class
|
279
|
+
return super_class.name, super_class.args if super_class
|
267
280
|
when RBS::AST::Declarations::Module, RBS::AST::Declarations::Interface
|
268
281
|
return nil
|
269
282
|
else
|
@@ -271,7 +284,7 @@ module TypeProf
|
|
271
284
|
end
|
272
285
|
end
|
273
286
|
|
274
|
-
return RBS::BuiltinNames::Object.name
|
287
|
+
return RBS::BuiltinNames::Object.name, []
|
275
288
|
end
|
276
289
|
|
277
290
|
def conv_method_def(rbs_method_types)
|
@@ -290,7 +303,7 @@ module TypeProf
|
|
290
303
|
opt_kw_tys = func.optional_keywords.to_h {|key, type| [key, conv_type(type.type)] }
|
291
304
|
req_kw_tys = func.required_keywords.to_h {|key, type| [key, conv_type(type.type)] }
|
292
305
|
rest_kw_ty = func.rest_keywords
|
293
|
-
|
306
|
+
rest_kw_ty = conv_type(rest_kw_ty.type) if rest_kw_ty
|
294
307
|
|
295
308
|
ret_ty = conv_type(func.return_type)
|
296
309
|
|
@@ -307,32 +320,12 @@ module TypeProf
|
|
307
320
|
}
|
308
321
|
end
|
309
322
|
|
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
|
-
}]
|
323
|
+
def attr_method_def(kind, name, ty)
|
324
|
+
{
|
325
|
+
kind: kind,
|
326
|
+
ivar: name,
|
327
|
+
ty: ty,
|
328
|
+
}
|
336
329
|
end
|
337
330
|
|
338
331
|
def conv_block(rbs_block)
|
@@ -467,8 +460,8 @@ module TypeProf
|
|
467
460
|
def import(explicit = false)
|
468
461
|
classes = @json[:classes].map do |classpath, cdef|
|
469
462
|
type_params = cdef[:type_params]
|
470
|
-
superclass
|
471
|
-
members
|
463
|
+
superclass, superclass_type_args = cdef[:superclass]
|
464
|
+
members = cdef[:members]
|
472
465
|
|
473
466
|
name = classpath.last
|
474
467
|
superclass = path_to_klass(superclass) if superclass
|
@@ -492,23 +485,27 @@ module TypeProf
|
|
492
485
|
end
|
493
486
|
end
|
494
487
|
|
495
|
-
[klass, members]
|
488
|
+
[klass, superclass_type_args, members]
|
496
489
|
end
|
497
490
|
|
498
|
-
classes.each do |klass, members|
|
491
|
+
classes.each do |klass, superclass_type_args, members|
|
492
|
+
@scratch.add_superclass_type_args!(klass, superclass_type_args&.map {|ty| conv_type(ty) })
|
499
493
|
included_modules = members[:included_modules]
|
500
494
|
extended_modules = members[:extended_modules]
|
501
495
|
methods = members[:methods]
|
496
|
+
attr_methods = members[:attr_methods]
|
502
497
|
ivars = members[:ivars]
|
503
498
|
cvars = members[:cvars]
|
504
499
|
rbs_sources = members[:rbs_sources]
|
505
500
|
|
506
|
-
included_modules.each do |mod|
|
507
|
-
|
501
|
+
included_modules.each do |mod, type_args|
|
502
|
+
type_args = type_args&.map {|ty| conv_type(ty) }
|
503
|
+
@scratch.include_module(klass, path_to_klass(mod), type_args, false, nil)
|
508
504
|
end
|
509
505
|
|
510
|
-
extended_modules.each do |mod|
|
511
|
-
|
506
|
+
extended_modules.each do |mod, type_args|
|
507
|
+
type_args = type_args&.map {|ty| conv_type(ty) }
|
508
|
+
@scratch.include_module(klass, path_to_klass(mod), type_args, true, nil)
|
512
509
|
end
|
513
510
|
|
514
511
|
methods.each do |(singleton, method_name), mdef|
|
@@ -517,6 +514,14 @@ module TypeProf
|
|
517
514
|
@scratch.add_method(klass, method_name, singleton, mdef)
|
518
515
|
end
|
519
516
|
|
517
|
+
attr_methods.each do |(singleton, method_name), mdef|
|
518
|
+
kind = mdef[:kind]
|
519
|
+
ivar = mdef[:ivar]
|
520
|
+
ty = conv_type(mdef[:ty]).remove_type_vars
|
521
|
+
@scratch.add_attr_method(klass, nil, ivar, :"@#{ ivar }", kind)
|
522
|
+
@scratch.add_ivar_write!(Type::Instance.new(klass), :"@#{ ivar }", ty, nil)
|
523
|
+
end
|
524
|
+
|
520
525
|
ivars.each do |ivar_name, ty|
|
521
526
|
ty = conv_type(ty).remove_type_vars
|
522
527
|
@scratch.add_ivar_write!(Type::Instance.new(klass), ivar_name, ty, nil)
|
@@ -583,7 +588,7 @@ module TypeProf
|
|
583
588
|
req, lead_tys, opt_tys, ret_ty = blk
|
584
589
|
lead_tys = lead_tys.map {|ty| conv_type(ty) }
|
585
590
|
opt_tys = opt_tys.map {|ty| conv_type(ty) }
|
586
|
-
msig = MethodSignature.new(lead_tys, opt_tys, nil,
|
591
|
+
msig = MethodSignature.new(lead_tys, opt_tys, nil, [], {}, nil, Type.nil)
|
587
592
|
ret_ty = conv_type(ret_ty)
|
588
593
|
ret = [Type::Proc.new(TypedBlock.new(msig, ret_ty), Type::Builtin[:proc])]
|
589
594
|
ret << Type.nil unless req
|
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,7 +79,8 @@ 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
|
|
@@ -77,18 +90,20 @@ module TypeProf
|
|
77
90
|
callee_ep = ExecutionPoint.new(ctx, 0, nil)
|
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
98
|
# nenv is top-level, so it is okay to call Type#localize directly
|
99
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
86
100
|
nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
|
87
101
|
nenv = nenv.local_update(i, ty)
|
88
102
|
end
|
89
103
|
if msig.opt_tys
|
90
104
|
msig.opt_tys.each_with_index do |ty, i|
|
91
105
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
106
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
92
107
|
nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
|
93
108
|
nenv = nenv.local_update(lead_num + i, ty)
|
94
109
|
end
|
@@ -96,19 +111,27 @@ module TypeProf
|
|
96
111
|
if msig.rest_ty
|
97
112
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
98
113
|
ty = Type::Array.new(Type::Array::Elements.new([], msig.rest_ty), Type::Instance.new(Type::Builtin[:ary]))
|
114
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
99
115
|
nenv, rest_ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
|
100
116
|
nenv = nenv.local_update(rest_start, rest_ty)
|
101
117
|
end
|
102
118
|
if msig.post_tys
|
103
119
|
msig.post_tys.each_with_index do |ty, i|
|
104
120
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
121
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
105
122
|
nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
|
106
123
|
nenv = nenv.local_update(post_start + i, ty)
|
107
124
|
end
|
108
125
|
end
|
109
126
|
if msig.kw_tys
|
110
|
-
msig.kw_tys.
|
127
|
+
msig.kw_tys.each do |_, key, ty|
|
128
|
+
i = keyword.index(key)
|
129
|
+
unless i
|
130
|
+
# warn
|
131
|
+
next
|
132
|
+
end
|
111
133
|
alloc_site2 = alloc_site.add_id(key)
|
134
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
112
135
|
nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
|
113
136
|
nenv = nenv.local_update(kw_start + i, ty)
|
114
137
|
end
|
@@ -116,6 +139,7 @@ module TypeProf
|
|
116
139
|
if msig.kw_rest_ty
|
117
140
|
ty = msig.kw_rest_ty
|
118
141
|
alloc_site2 = alloc_site.add_id(:**)
|
142
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
119
143
|
nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
|
120
144
|
nenv = nenv.local_update(kw_rest, ty)
|
121
145
|
end
|
@@ -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
|