typeprof 0.5.1 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
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)