typeprof 0.5.1 → 0.6.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d55a91519761d29aaff38516b7bd079dde1d4b21349fc23786aebacf4c0eef50
4
- data.tar.gz: 61663b62730ba7405b7dbdaa2c5d662b9850f597a58439ba5d8acac287ab6b82
3
+ metadata.gz: 3dedfe8da717afcf508820efe445a790336ab877156d5b2de3683ab5043c18ab
4
+ data.tar.gz: 345fa1163af50a1b01fef26a83a835bfd7813453c6132ebb1036fe8178dd9757
5
5
  SHA512:
6
- metadata.gz: eff989005f090be43e584aaeeae68edfc67dd87d09050bff061aa1e4ed3927583359540db92702040f8ab3d5353a2d48ec9e276b519964cd0c332cfd383d15c1
7
- data.tar.gz: 386dc99ae9dfc4e5f06c8a606bf9ea5278500fb8a044d805d16b6e1a7524e39a66fbe7ba964b9604be3d9e573230f92e868aa0c357ebf8249c7af0a3f0daf656
6
+ metadata.gz: 48972d2ab935ff782a0651eda48afa301531d5c5fff4f1a9ba17d29c54323b127fc3013c29863c21b26d77e81230c2e0318d58d3cde680c57b611c5a77a1214b
7
+ data.tar.gz: dc29d8282f165f9ddaabecf97f4eb81aaaa43c5defe1d63d083ef1147c2c0e6d2def961fa07f339587902d8524ee66940da742a5b30cd48dcccdcd94262883a8
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- typeprof (0.5.1)
4
+ typeprof (0.6.1)
5
5
  rbs (>= 0.17.0)
6
6
 
7
7
  GEM
@@ -252,6 +252,8 @@ module TypeProf
252
252
  @rbs_reader = RBSReader.new
253
253
 
254
254
  @terminated = false
255
+
256
+ @anonymous_struct_gen_id = 0
255
257
  end
256
258
 
257
259
  attr_reader :return_envs, :loaded_features, :rbs_reader
@@ -279,11 +281,10 @@ module TypeProf
279
281
  attr_reader :class_defs
280
282
 
281
283
  class ClassDef # or ModuleDef
282
- def initialize(kind, name, superclass, absolute_path)
284
+ def initialize(kind, name, absolute_path)
283
285
  raise unless name.is_a?(Array)
284
286
  @kind = kind
285
- @superclass = superclass
286
- @modules = { true => {}, false => {} }
287
+ @modules = { true => [], false => [] }
287
288
  @name = name
288
289
  @consts = {}
289
290
  @methods = {}
@@ -293,23 +294,16 @@ module TypeProf
293
294
  @namespace = nil
294
295
  end
295
296
 
296
- attr_reader :kind, :superclass, :modules, :consts, :methods, :ivars, :cvars, :absolute_path
297
+ attr_reader :kind, :modules, :consts, :methods, :ivars, :cvars, :absolute_path
297
298
  attr_accessor :name, :klass_obj
298
299
 
299
- def include_module(mod, absolute_path)
300
- # XXX: need to check if mod is already included by the ancestors?
301
- absolute_paths = @modules[false][mod]
302
- unless absolute_paths
303
- @modules[false][mod] = absolute_paths = Utils::MutableSet.new
304
- end
305
- absolute_paths << absolute_path
306
- end
307
-
308
- def extend_module(mod, absolute_path)
309
- # XXX: need to check if mod is already included by the ancestors?
310
- absolute_paths = @modules[true][mod]
311
- unless absolute_paths
312
- @modules[true][mod] = absolute_paths = Utils::MutableSet.new
300
+ def include_module(mod, type_args, singleton, absolute_path)
301
+ module_type_args, _, absolute_paths = @modules[singleton].find {|m,| m == mod }
302
+ if module_type_args
303
+ raise "inconsistent include/extend type args in RBS?" if module_type_args != type_args && type_args != [] && type_args != nil
304
+ else
305
+ absolute_paths = Utils::MutableSet.new
306
+ @modules[singleton].unshift([mod, type_args, absolute_paths])
313
307
  end
314
308
  absolute_paths << absolute_path
315
309
  end
@@ -326,13 +320,26 @@ module TypeProf
326
320
  @consts[name] = [ty, absolute_path]
327
321
  end
328
322
 
329
- def get_method(mid, singleton)
330
- @methods[[singleton, mid]] || begin
331
- @modules[singleton].each_key do |mod|
332
- meth = mod.get_method(mid, false)
333
- return meth if meth
323
+ def generate_substitution(singleton, mid, mthd, subst, &blk)
324
+ mthds = @methods[[singleton, mid]]
325
+ yield subst if mthds&.include?(mthd)
326
+ @modules[singleton].each do |mod_def, type_args,|
327
+ if mod_def.klass_obj.type_params && type_args
328
+ subst2 = {}
329
+ mod_def.klass_obj.type_params.zip(type_args) do |(tyvar, *), tyarg|
330
+ tyvar = Type::Var.new(tyvar)
331
+ subst2[tyvar] = tyarg.substitute(subst, Config.options[:type_depth_limit])
332
+ end
333
+ mod_def.generate_substitution(false, mid, mthd, subst2, &blk)
334
334
  end
335
- nil
335
+ end
336
+ end
337
+
338
+ def search_method(singleton, mid, &blk)
339
+ mthds = @methods[[singleton, mid]]
340
+ yield mthds, @klass_obj, singleton if mthds
341
+ @modules[singleton].each do |mod_def,|
342
+ mod_def.search_method(false, mid, &blk)
336
343
  end
337
344
  end
338
345
 
@@ -356,7 +363,7 @@ module TypeProf
356
363
  end
357
364
  end
358
365
 
359
- def include_module(including_mod, included_mod, absolute_path)
366
+ def include_module(including_mod, included_mod, type_args, singleton, absolute_path)
360
367
  return if included_mod == Type.any
361
368
 
362
369
  including_mod = @class_defs[including_mod.idx]
@@ -364,7 +371,7 @@ module TypeProf
364
371
  if included_mod.is_a?(Type::Class)
365
372
  included_mod = @class_defs[included_mod.idx]
366
373
  if included_mod && included_mod.kind == :module
367
- including_mod.include_module(included_mod, absolute_path)
374
+ including_mod.include_module(included_mod, type_args, singleton, absolute_path)
368
375
  else
369
376
  warn "including something that is not a module"
370
377
  end
@@ -372,43 +379,24 @@ module TypeProf
372
379
  end
373
380
  end
374
381
 
375
- def extend_module(extending_mod, extended_mod, absolute_path)
376
- extending_mod = @class_defs[extending_mod.idx]
377
- extended_mod.each_child do |extended_mod|
378
- if extended_mod.is_a?(Type::Class)
379
- extended_mod = @class_defs[extended_mod.idx]
380
- if extended_mod && extended_mod.kind == :module
381
- extending_mod.extend_module(extended_mod, absolute_path)
382
- else
383
- warn "extending something that is not a module"
384
- end
385
- end
386
- end
387
- end
388
-
389
382
  def cbase_path(cbase)
390
383
  cbase && cbase.idx != 1 ? @class_defs[cbase.idx].name : []
391
384
  end
392
385
 
393
- def new_class(cbase, name, type_params, superclass, absolute_path)
386
+ def new_class(cbase, name, type_params, superclass, superclass_type_args, absolute_path)
394
387
  show_name = cbase_path(cbase) + [name]
395
388
  idx = @class_defs.size
396
389
  if superclass
397
- if superclass == :__root__
398
- superclass_idx = superclass = nil
399
- else
400
- superclass_idx = superclass.idx
401
- end
402
- @class_defs[idx] = ClassDef.new(:class, show_name, superclass_idx, absolute_path)
403
- klass = Type::Class.new(:class, idx, type_params, superclass, show_name)
390
+ @class_defs[idx] = ClassDef.new(:class, show_name, absolute_path)
391
+ klass = Type::Class.new(:class, idx, type_params, superclass, superclass_type_args, show_name)
404
392
  @class_defs[idx].klass_obj = klass
405
393
  cbase ||= klass # for bootstrap
406
394
  add_constant(cbase, name, klass, absolute_path)
407
395
  return klass
408
396
  else
409
397
  # module
410
- @class_defs[idx] = ClassDef.new(:module, show_name, nil, absolute_path)
411
- mod = Type::Class.new(:module, idx, type_params, nil, show_name)
398
+ @class_defs[idx] = ClassDef.new(:module, show_name, absolute_path)
399
+ mod = Type::Class.new(:module, idx, type_params, nil, nil, show_name)
412
400
  @class_defs[idx].klass_obj = mod
413
401
  add_constant(cbase, name, mod, absolute_path)
414
402
  return mod
@@ -420,8 +408,9 @@ module TypeProf
420
408
 
421
409
  idx = @class_defs.size
422
410
  superclass = Type::Builtin[:struct]
423
- @class_defs[idx] = ClassDef.new(:class, ["(Anonymous Struct)"], superclass.idx, ep.ctx.iseq.absolute_path)
424
- klass = Type::Class.new(:class, idx, [], superclass, "(Anonymous Struct)")
411
+ name = "AnonymousStruct_generated_#{ @anonymous_struct_gen_id += 1 }"
412
+ @class_defs[idx] = ClassDef.new(:class, [name], ep.ctx.iseq.absolute_path)
413
+ klass = Type::Class.new(:class, idx, [], superclass, [], name)
425
414
  @class_defs[idx].klass_obj = klass
426
415
 
427
416
  @struct_defs[ep] = klass
@@ -451,28 +440,75 @@ module TypeProf
451
440
  end
452
441
  end
453
442
 
443
+ def generate_substitution(klass, singleton, mid, mthd, subst, &blk)
444
+ if klass.kind == :class
445
+ while klass != :__root__
446
+ class_def = @class_defs[klass.idx]
447
+ class_def.generate_substitution(singleton, mid, mthd, subst, &blk)
448
+ if klass.superclass && klass.superclass_type_args
449
+ subst2 = {}
450
+ klass.superclass.type_params.zip(klass.superclass_type_args) do |(tyvar, *), tyarg|
451
+ tyvar = Type::Var.new(tyvar)
452
+ subst2[tyvar] = tyarg.substitute(subst, Config.options[:type_depth_limit])
453
+ end
454
+ subst = subst2
455
+ end
456
+ klass = klass.superclass
457
+ end
458
+ else
459
+ # module
460
+ class_def = @class_defs[klass.idx]
461
+ class_def.generate_substitution(singleton, mid, mthd, subst, &blk)
462
+ end
463
+ end
464
+
465
+ def search_method(klass, singleton, mid, &blk)
466
+ # XXX: support method alias correctly
467
+ klass_orig = klass
468
+ if klass.kind == :class
469
+ while klass != :__root__
470
+ class_def = @class_defs[klass.idx]
471
+ class_def.search_method(singleton, mid, &blk)
472
+ klass = klass.superclass
473
+ end
474
+ else
475
+ # module
476
+ class_def = @class_defs[klass.idx]
477
+ class_def.search_method(singleton, mid, &blk)
478
+ end
479
+ if singleton
480
+ search_method(Type::Builtin[klass_orig.kind], false, mid, &blk)
481
+ end
482
+ end
483
+
454
484
  def get_method(klass, singleton, mid)
455
- idx = klass.idx
456
- while idx
457
- class_def = @class_defs[idx]
458
- mthd = class_def.get_method(mid, singleton)
459
- # Need to be conservative to include all super candidates...?
460
- return mthd if mthd
461
- idx = class_def.superclass
485
+ search_method(klass, singleton, mid) {|mthds,| return mthds }
486
+ end
487
+
488
+ def get_all_super_methods(klass, singleton, current_klass, mid)
489
+ hit = false
490
+ search_method(klass, singleton, mid) do |mthds, klass0, singleton0|
491
+ yield mthds, klass0, singleton0 if hit
492
+ hit = klass0 == current_klass
462
493
  end
463
- return get_method(Type::Builtin[:class], false, mid) if singleton
464
- nil
465
494
  end
466
495
 
467
496
  def get_super_method(ctx, singleton)
468
- idx = ctx.cref.klass.idx
497
+ klass = ctx.cref.klass
469
498
  mid = ctx.mid
470
- idx = @class_defs[idx].superclass
471
- while idx
472
- class_def = @class_defs[idx]
499
+ if klass.kind == :class
500
+ klass = klass.superclass
501
+ while klass != :__root__
502
+ class_def = @class_defs[klass.idx]
503
+ mthd = class_def.get_method(mid, singleton)
504
+ return mthd if mthd
505
+ klass = klass.superclass
506
+ end
507
+ else
508
+ # module
509
+ class_def = @class_defs[klass.idx]
473
510
  mthd = class_def.get_method(mid, singleton)
474
511
  return mthd if mthd
475
- idx = class_def.superclass
476
512
  end
477
513
  nil
478
514
  end
@@ -1155,35 +1191,30 @@ module TypeProf
1155
1191
  else
1156
1192
  if existing_klass != Type.any
1157
1193
  error(ep, "the class \"#{ id }\" is #{ existing_klass.screen_name(self) }")
1158
- id = :"#{ id }(dummy)"
1159
1194
  end
1160
- existing_klass = get_constant(cbase, id) # TODO: multiple return values
1161
- if existing_klass != Type.any
1162
- klass = existing_klass
1163
- else
1164
- if type == :class
1165
- if superclass.is_a?(Type::Class)
1166
- # okay
1167
- elsif superclass == Type.any
1168
- warn(ep, "superclass is any; Object is used instead")
1169
- superclass = Type::Builtin[:obj]
1170
- elsif superclass == Type.nil
1171
- superclass = Type::Builtin[:obj]
1172
- elsif superclass.is_a?(Type::Instance)
1173
- warn(ep, "superclass is an instance; Object is used instead")
1174
- superclass = Type::Builtin[:obj]
1175
- else
1176
- warn(ep, "superclass is not a class; Object is used instead")
1177
- superclass = Type::Builtin[:obj]
1178
- end
1179
- else # module
1180
- superclass = nil
1181
- end
1182
- if cbase == Type.any
1183
- klass = Type.any
1195
+ if type == :class
1196
+ if superclass.is_a?(Type::Class)
1197
+ # okay
1198
+ elsif superclass == Type.any
1199
+ warn(ep, "superclass is any; Object is used instead")
1200
+ superclass = Type::Builtin[:obj]
1201
+ elsif superclass == Type.nil
1202
+ superclass = Type::Builtin[:obj]
1203
+ elsif superclass.is_a?(Type::Instance)
1204
+ warn(ep, "superclass is an instance; Object is used instead")
1205
+ superclass = Type::Builtin[:obj]
1184
1206
  else
1185
- klass = new_class(cbase, id, [], superclass, ep.ctx.iseq.absolute_path)
1207
+ warn(ep, "superclass is not a class; Object is used instead")
1208
+ superclass = Type::Builtin[:obj]
1186
1209
  end
1210
+ else # module
1211
+ superclass = nil
1212
+ end
1213
+ if cbase == Type.any
1214
+ klass = Type.any
1215
+ else
1216
+ superclass_type_args = superclass.type_params.map { Type.any } if superclass
1217
+ klass = new_class(cbase, id, [], superclass, superclass_type_args, ep.ctx.iseq.absolute_path)
1187
1218
  end
1188
1219
  end
1189
1220
  singleton = false
@@ -1271,30 +1302,30 @@ module TypeProf
1271
1302
  end
1272
1303
  when :invokesuper
1273
1304
  env, recv, _, aargs = setup_actual_arguments(:method, operands, ep, env)
1274
-
1275
- env, recv = localize_type(env.static_env.recv_ty, env, ep)
1276
- mid = ep.ctx.mid
1277
- singleton = !recv.is_a?(Type::Instance) # TODO: any?
1278
- # XXX: need to support included module...
1279
- meths = get_super_method(ep.ctx, singleton) # TODO: multiple return values
1280
- if meths
1281
- meths.each do |meth|
1282
- # XXX: this decomposition is really needed??
1283
- # It calls `Object.new` with union receiver which causes an error, but
1284
- # it may be a fault of builtin Object.new implementation.
1285
- recv.each_child do |recv|
1286
- meth.do_send(recv, mid, aargs, ep, env, self) do |ret_ty, ep, env|
1287
- nenv, ret_ty, = localize_type(ret_ty, env, ep)
1288
- nenv = nenv.push(ret_ty)
1289
- merge_env(ep.next, nenv)
1305
+ mid = ep.ctx.mid
1306
+ found = false
1307
+ recv.each_child_global do |recv|
1308
+ klass, singleton = recv.method_dispatch_info
1309
+ next unless klass
1310
+ get_all_super_methods(klass, singleton, ep.ctx.cref.klass, ep.ctx.mid) do |meths, klass|
1311
+ found = true
1312
+ meths.each do |meth|
1313
+ # XXX: this decomposition is really needed??
1314
+ # It calls `Object.new` with union receiver which causes an error, but
1315
+ # it may be a fault of builtin Object.new implementation.
1316
+ recv.each_child do |recv|
1317
+ meth.do_send(recv, mid, aargs, ep, env, self) do |ret_ty, ep, env|
1318
+ nenv, ret_ty, = localize_type(ret_ty, env, ep)
1319
+ nenv = nenv.push(ret_ty)
1320
+ merge_env(ep.next, nenv)
1321
+ end
1290
1322
  end
1291
1323
  end
1292
1324
  end
1293
- return
1294
- else
1295
- error(ep, "no superclass method: #{ env.static_env.recv_ty.screen_name(self) }##{ mid }")
1296
- env = env.push(Type.any)
1297
1325
  end
1326
+ return if found
1327
+ error(ep, "no superclass method: #{ env.static_env.recv_ty.screen_name(self) }##{ mid }")
1328
+ env = env.push(Type.any)
1298
1329
  when :invokebuiltin
1299
1330
  raise NotImplementedError
1300
1331
  when :leave
@@ -1942,7 +1973,8 @@ module TypeProf
1942
1973
  end
1943
1974
 
1944
1975
  def do_send(recv, mid, aargs, ep, env, &ctn)
1945
- meths = recv.get_method(mid, self)
1976
+ klass, singleton = recv.method_dispatch_info
1977
+ meths = get_method(klass, singleton, mid) if klass
1946
1978
  if meths
1947
1979
  meths.each do |meth|
1948
1980
  meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
@@ -100,7 +100,8 @@ module TypeProf
100
100
  raise unless aargs.lead_tys.size != 0
101
101
  sym = get_sym("respond_to?", aargs.lead_tys[0], ep, scratch)
102
102
  if sym
103
- if recv.get_method(sym, scratch)
103
+ klass, singleton = recv.method_dispatch_info
104
+ if scratch.get_method(klass, singleton, sym)
104
105
  true_val = Type::Instance.new(Type::Builtin[:true])
105
106
  ctn[true_val, ep, env]
106
107
  else
@@ -143,7 +144,7 @@ module TypeProf
143
144
  def object_instance_eval(recv, mid, aargs, ep, env, scratch, &ctn)
144
145
  if aargs.lead_tys.size >= 1
145
146
  scratch.warn(ep, "instance_eval with arguments are ignored")
146
- ctn[type.any, ep, env]
147
+ ctn[Type.any, ep, env]
147
148
  return
148
149
  end
149
150
  naargs = ActualArguments.new([recv], nil, {}, Type.nil)
@@ -153,16 +154,30 @@ module TypeProf
153
154
  end
154
155
 
155
156
  def module_include(recv, mid, aargs, ep, env, scratch, &ctn)
157
+ if aargs.lead_tys.size != 1
158
+ scratch.warn(ep, "Module#include without an argument are ignored")
159
+ ctn[Type.any, ep, env]
160
+ return
161
+ end
156
162
  arg = aargs.lead_tys[0]
157
- scratch.include_module(recv, arg, ep.ctx.iseq.absolute_path)
163
+ arg.each_child do |arg|
164
+ if arg.is_a?(Type::Class)
165
+ scratch.include_module(recv, arg, nil, false, ep.ctx.iseq.absolute_path)
166
+ end
167
+ end
158
168
  ctn[recv, ep, env]
159
169
  end
160
170
 
161
171
  def module_extend(recv, mid, aargs, ep, env, scratch, &ctn)
172
+ if aargs.lead_tys.size != 1
173
+ scratch.warn(ep, "Module#extend without an argument are ignored")
174
+ ctn[Type.any, ep, env]
175
+ return
176
+ end
162
177
  arg = aargs.lead_tys[0]
163
178
  arg.each_child do |arg|
164
179
  if arg.is_a?(Type::Class)
165
- scratch.extend_module(recv, arg, ep.ctx.iseq.absolute_path)
180
+ scratch.include_module(recv, arg, nil, true, ep.ctx.iseq.absolute_path)
166
181
  end
167
182
  end
168
183
  ctn[recv, ep, env]
@@ -174,7 +189,7 @@ module TypeProf
174
189
  else
175
190
  aargs.lead_tys.each do |aarg|
176
191
  sym = get_sym("module_function", aarg, ep, scratch) or next
177
- meths = Type::Instance.new(recv).get_method(sym, scratch)
192
+ meths = scratch.get_method(recv, false, sym)
178
193
  meths.each do |mdef|
179
194
  scratch.add_method(recv, sym, true, mdef)
180
195
  end
@@ -487,8 +502,8 @@ module TypeProf
487
502
  end
488
503
 
489
504
  def self.setup_initial_global_env(scratch)
490
- klass_basic_obj = scratch.new_class(nil, :BasicObject, [], :__root__, nil) # cbase, name, superclass
491
- klass_obj = scratch.new_class(nil, :Object, [], klass_basic_obj, nil)
505
+ klass_basic_obj = scratch.new_class(nil, :BasicObject, [], :__root__, nil, nil) # cbase, name, superclass
506
+ klass_obj = scratch.new_class(nil, :Object, [], klass_basic_obj, [], nil)
492
507
  scratch.add_constant(klass_obj, :Object, klass_obj, nil)
493
508
  scratch.add_constant(klass_obj, :BasicObject, klass_basic_obj, nil)
494
509
 
@@ -497,7 +512,7 @@ module TypeProf
497
512
 
498
513
  Import.import_builtin(scratch)
499
514
 
500
- Type::Builtin[:vmcore] = scratch.new_class(klass_obj, :VMCore, [], klass_obj, nil)
515
+ Type::Builtin[:vmcore] = scratch.new_class(klass_obj, :VMCore, [], klass_obj, [], nil)
501
516
  Type::Builtin[:int] = scratch.get_constant(klass_obj, :Integer)
502
517
  Type::Builtin[:float] = scratch.get_constant(klass_obj, :Float)
503
518
  Type::Builtin[:rational] = scratch.get_constant(klass_obj, :Rational)