typeprof 0.6.1 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3dedfe8da717afcf508820efe445a790336ab877156d5b2de3683ab5043c18ab
4
- data.tar.gz: 345fa1163af50a1b01fef26a83a835bfd7813453c6132ebb1036fe8178dd9757
3
+ metadata.gz: e8ecd99e5448a244b11714710dfbb5fd3f36274c5f72fa97da034059018fc32f
4
+ data.tar.gz: ed322065cf15d08f7bb50105cce19d74d923d4d7af7f94a563668788849d636d
5
5
  SHA512:
6
- metadata.gz: 48972d2ab935ff782a0651eda48afa301531d5c5fff4f1a9ba17d29c54323b127fc3013c29863c21b26d77e81230c2e0318d58d3cde680c57b611c5a77a1214b
7
- data.tar.gz: dc29d8282f165f9ddaabecf97f4eb81aaaa43c5defe1d63d083ef1147c2c0e6d2def961fa07f339587902d8524ee66940da742a5b30cd48dcccdcd94262883a8
6
+ metadata.gz: 528dcf83aa2ceec79ea602f3505eb48230baf87bae8409212f8f152b45e308c66490ff5d10a9153698870e02b0ee5f031ce81cbb48a4460187992269708957ef
7
+ data.tar.gz: a03594cb0b6a88ba905dc860ba9de64beb82a6cb1ebc562aad94cf20ecf14e36534bbf8a29a0b629189c62c32c26437104acb4387159c17bb222c708614cc303
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- typeprof (0.6.1)
4
+ typeprof (0.7.0)
5
5
  rbs (>= 0.17.0)
6
6
 
7
7
  GEM
@@ -17,7 +17,7 @@ GEM
17
17
  simplecov-html (~> 0.11)
18
18
  simplecov-html (0.12.3)
19
19
  stackprof (0.2.16)
20
- test-unit (3.3.6)
20
+ test-unit (3.3.7)
21
21
  power_assert
22
22
 
23
23
  PLATFORMS
@@ -35,10 +35,9 @@ $ typeprof sig/app.rbs app.rb -o sig/app.gen.rbs
35
35
  * `--exclude-dir DIR`: `DIR`以下のファイルの解析結果を出力から省略する。後に指定されているほうが優先される(`--include-dir foo --exclude-dir foo/bar`の場合う、foo/bar/baz.rbの結果は出力されず、foo/baz.rbの結果は出力される)。
36
36
  * `--include-dir DIR`: `DIR`以下のファイルの解析結果を出力に含める。後に指定されているほうが優先される(`--exclude-dir foo --include-dir foo/bar`の場合、
37
37
  foo/bar/baz.rbの結果は出力されるが、foo/baz.rbの結果は出力されない)。
38
- * `-fshow-errors`: 実行中に見つけたバグの可能性を出力します(多くの場合、大量のfalse positiveが出ます)。
39
- * `-fpedantic-output`: デフォルトでは`A | untyped`と推定されたところを単に`A`と出力しますが、より生の出力、つまり`A | untyped`と出力します。
40
- * `-fshow-container-raw-elements`: (後で書く)
41
- * `-ftype-depth-limit=NUM`: (後で書く)
38
+ * `--show-errors`: 実行中に見つけたバグの可能性を出力します(多くの場合、大量のfalse positiveが出ます)。
39
+ * `--show-untyped`: デフォルトでは`A | untyped`と推定されたところを単に`A`と出力しますが、より生の出力、つまり`A | untyped`と出力します。
40
+ * `--type-depth-limit=NUM`: (後で書く)
42
41
 
43
42
  ## TypeProfとは
44
43
 
data/doc/doc.md CHANGED
@@ -34,10 +34,9 @@ Here is a list of currently avaiable options:
34
34
  * `-r GEMNAME`: Load the RBS files of `GEMNAME`
35
35
  * `--exclude-dir DIR`: Omit the result of files that are placed under the directory `DIR`. If there are some directory specifications, the latter one is stronger. (Assuming that `--include-dir foo --exclude-dir foo/bar` is specified, the analysis result of foo/bar/baz.rb is omitted, but foo/baz.rb is shown.)
36
36
  * `--include-dir DIR`: Show the result of files that are placed under the directory `DIR`. If there are some directory specifications, the latter one is stronger. (Assuming that `--exclude-dir foo --include-dir foo/bar` is specified, the analysis result of foo/bar/baz.rb is shown, but foo/baz.rb is omitted.)
37
- * `-fshow-errors`: Prints out possible bugs found during execution (often a lot of false positives).
38
- * `-fpedantic-output`: When TypeProf inferred a type `A | untyped`, it simply outputs `A` by default. But this option forces it to output `A | untyped`.
39
- * `-fshow-container-raw-elements`: (undocumented yet)
40
- * `-ftype-depth-limit=NUM`: (undocumented yet)
37
+ * `--show-errors`: Prints out possible bugs found during execution (often a lot of false positives).
38
+ * `--show-untyped`: When TypeProf infers a type `A | untyped`, it simply outputs `A` by default. But this option forces to output `A | untyped`.
39
+ * `--type-depth-limit=NUM`: (undocumented yet)
41
40
 
42
41
  ## What is a TypeProf?
43
42
 
@@ -185,18 +185,11 @@ module TypeProf
185
185
  Env.new(@static_env, Utils.array_update(@locals, idx, ty), @stack, @type_params)
186
186
  end
187
187
 
188
- def deploy_type(klass, alloc_site, elems, base_ty)
189
- local_ty = klass.new(alloc_site, base_ty)
190
- type_params = Utils::HashWrapper.new(@type_params.internal_hash.merge({ alloc_site => elems }))
191
- nenv = Env.new(@static_env, @locals, @stack, type_params)
192
- return nenv, local_ty
193
- end
194
-
195
188
  def get_container_elem_types(id)
196
189
  @type_params.internal_hash[id]
197
190
  end
198
191
 
199
- def update_container_elem_types(id, elems)
192
+ def deploy_type(id, elems)
200
193
  type_params = Utils::HashWrapper.new(@type_params.internal_hash.merge({ id => elems }))
201
194
  Env.new(@static_env, @locals, @stack, type_params)
202
195
  end
@@ -320,9 +313,9 @@ module TypeProf
320
313
  @consts[name] = [ty, absolute_path]
321
314
  end
322
315
 
323
- def generate_substitution(singleton, mid, mthd, subst, &blk)
316
+ def adjust_substitution(singleton, mid, mthd, subst, direct, &blk)
324
317
  mthds = @methods[[singleton, mid]]
325
- yield subst if mthds&.include?(mthd)
318
+ yield subst, direct if mthds&.include?(mthd)
326
319
  @modules[singleton].each do |mod_def, type_args,|
327
320
  if mod_def.klass_obj.type_params && type_args
328
321
  subst2 = {}
@@ -330,7 +323,7 @@ module TypeProf
330
323
  tyvar = Type::Var.new(tyvar)
331
324
  subst2[tyvar] = tyarg.substitute(subst, Config.options[:type_depth_limit])
332
325
  end
333
- mod_def.generate_substitution(false, mid, mthd, subst2, &blk)
326
+ mod_def.adjust_substitution(false, mid, mthd, subst2, false, &blk)
334
327
  end
335
328
  end
336
329
  end
@@ -358,8 +351,12 @@ module TypeProf
358
351
  end
359
352
 
360
353
  def set_method(mid, singleton, mdef)
361
- @methods[[singleton, mid]] = Utils::MutableSet.new
362
- @methods[[singleton, mid]] << mdef
354
+ if mdef
355
+ @methods[[singleton, mid]] = Utils::MutableSet.new
356
+ @methods[[singleton, mid]] << mdef
357
+ else
358
+ @methods.delete([singleton, mid])
359
+ end
363
360
  end
364
361
  end
365
362
 
@@ -410,7 +407,7 @@ module TypeProf
410
407
  superclass = Type::Builtin[:struct]
411
408
  name = "AnonymousStruct_generated_#{ @anonymous_struct_gen_id += 1 }"
412
409
  @class_defs[idx] = ClassDef.new(:class, [name], ep.ctx.iseq.absolute_path)
413
- klass = Type::Class.new(:class, idx, [], superclass, [], name)
410
+ klass = Type::Class.new(:class, idx, [], superclass, [Type.any], name)
414
411
  @class_defs[idx].klass_obj = klass
415
412
 
416
413
  @struct_defs[ep] = klass
@@ -440,11 +437,13 @@ module TypeProf
440
437
  end
441
438
  end
442
439
 
443
- def generate_substitution(klass, singleton, mid, mthd, subst, &blk)
440
+ def adjust_substitution(klass, singleton, mid, mthd, subst, &blk)
441
+ direct = true
444
442
  if klass.kind == :class
445
443
  while klass != :__root__
446
444
  class_def = @class_defs[klass.idx]
447
- class_def.generate_substitution(singleton, mid, mthd, subst, &blk)
445
+ class_def.adjust_substitution(singleton, mid, mthd, subst, direct, &blk)
446
+ direct = false
448
447
  if klass.superclass && klass.superclass_type_args
449
448
  subst2 = {}
450
449
  klass.superclass.type_params.zip(klass.superclass_type_args) do |(tyvar, *), tyarg|
@@ -458,7 +457,7 @@ module TypeProf
458
457
  else
459
458
  # module
460
459
  class_def = @class_defs[klass.idx]
461
- class_def.generate_substitution(singleton, mid, mthd, subst, &blk)
460
+ class_def.adjust_substitution(singleton, mid, mthd, subst, direct, &blk)
462
461
  end
463
462
  end
464
463
 
@@ -564,12 +563,12 @@ module TypeProf
564
563
  end
565
564
  end
566
565
 
567
- def add_iseq_method(klass, mid, iseq, cref)
568
- add_method(klass, mid, false, ISeqMethodDef.new(iseq, cref))
566
+ def add_iseq_method(klass, mid, iseq, cref, outer_ep)
567
+ add_method(klass, mid, false, ISeqMethodDef.new(iseq, cref, outer_ep))
569
568
  end
570
569
 
571
- def add_singleton_iseq_method(klass, mid, iseq, cref)
572
- add_method(klass, mid, true, ISeqMethodDef.new(iseq, cref))
570
+ def add_singleton_iseq_method(klass, mid, iseq, cref, outer_ep)
571
+ add_method(klass, mid, true, ISeqMethodDef.new(iseq, cref, outer_ep))
573
572
  end
574
573
 
575
574
  def set_custom_method(klass, mid, impl)
@@ -778,7 +777,7 @@ module TypeProf
778
777
  merge_return_env(tmp_ep) do |menv|
779
778
  elems = menv.get_container_elem_types(id)
780
779
  elems = yield elems
781
- menv = menv.update_container_elem_types(id, elems)
780
+ menv = menv.deploy_type(id, elems)
782
781
  gid = @alloc_site_to_global_id[id]
783
782
  if gid
784
783
  ty = globalize_type(elems.to_local_type(id, base_type), env, ep)
@@ -790,7 +789,7 @@ module TypeProf
790
789
  else
791
790
  elems = env.get_container_elem_types(id)
792
791
  elems = yield elems
793
- env = env.update_container_elem_types(id, elems)
792
+ env = env.deploy_type(id, elems)
794
793
  gid = @alloc_site_to_global_id[id]
795
794
  if gid
796
795
  ty = globalize_type(elems.to_local_type(id, base_type), env, ep)
@@ -831,11 +830,11 @@ module TypeProf
831
830
  ep = @worklist.deletemin
832
831
 
833
832
  iter_counter += 1
834
- if Config.verbose >= 1
833
+ if Config.options[:show_indicator]
835
834
  tick2 = Time.now
836
835
  if tick2 - tick >= 1
837
836
  tick = tick2
838
- $stderr << "\rType Profiling... (%d steps @ %s)\e[K" % [iter_counter, ep.source_location]
837
+ $stderr << "\rType Profiling... (%d instructions @ %s)\e[K" % [iter_counter, ep.source_location]
839
838
  $stderr.flush
840
839
  end
841
840
  end
@@ -851,9 +850,7 @@ module TypeProf
851
850
 
852
851
  break if @terminated
853
852
 
854
- # XXX: it would be good to provide no-dummy-execution mode.
855
- # It should work as a bit smarter "rbs prototype rb";
856
- # show all method definitions as "untyped" arguments and return values
853
+ break unless Config.options[:stub_execution]
857
854
 
858
855
  begin
859
856
  iseq, (kind, dummy_continuation) = @pending_execution.first
@@ -878,7 +875,7 @@ module TypeProf
878
875
  end
879
876
  end
880
877
  end
881
- $stderr.print "\r\e[K" if Config.verbose >= 1
878
+ $stderr.print "\r\e[K" if Config.options[:show_indicator]
882
879
 
883
880
  stat_eps
884
881
  end
@@ -919,9 +916,9 @@ module TypeProf
919
916
  end
920
917
  end
921
918
 
922
- def pend_method_execution(iseq, meth, recv, mid, cref)
919
+ def pend_method_execution(iseq, meth, recv, mid, cref, ep)
923
920
  ctx = Context.new(iseq, cref, mid)
924
- ep = ExecutionPoint.new(ctx, 0, nil)
921
+ ep = ExecutionPoint.new(ctx, 0, ep)
925
922
  locals = [Type.nil] * iseq.locals.size
926
923
 
927
924
  fargs_format = iseq.fargs_format
@@ -958,7 +955,9 @@ module TypeProf
958
955
 
959
956
  env = Env.new(StaticEnv.new(recv, Type.nil, false), locals, [], Utils::HashWrapper.new({}))
960
957
 
961
- @pending_execution[iseq] ||= [:method, [meth, ep, env]]
958
+ if !@pending_execution[iseq] || @pending_execution[iseq][0] == :block
959
+ @pending_execution[iseq] = [:method, [meth, ep, env]]
960
+ end
962
961
  end
963
962
 
964
963
  def pend_block_dummy_execution(blk, iseq, nep, nenv)
@@ -975,7 +974,7 @@ module TypeProf
975
974
  alloc_site = AllocationSite.new(ep)
976
975
  nenv, ty = localize_type(ty, env, ep, alloc_site)
977
976
  case ty
978
- when Type::LocalCell, Type::LocalArray, Type::LocalHash
977
+ when Type::Local
979
978
  @alloc_site_to_global_id[ty.id] = [recv, var] # need overwrite check??
980
979
  end
981
980
  yield ty, nenv
@@ -1141,31 +1140,7 @@ module TypeProf
1141
1140
 
1142
1141
  when :definemethod
1143
1142
  mid, iseq = operands
1144
- cref = ep.ctx.cref
1145
- recv = env.static_env.recv_ty
1146
- if cref.klass.is_a?(Type::Class)
1147
- typed_mdef = check_typed_method(cref.klass, mid, ep.ctx.cref.singleton)
1148
- recv = Type::Instance.new(recv) if recv.is_a?(Type::Class)
1149
- if typed_mdef
1150
- mdef = ISeqMethodDef.new(iseq, cref)
1151
- typed_mdef.each do |typed_mdef|
1152
- typed_mdef.do_match_iseq_mdef(mdef, recv, mid, env, ep, self)
1153
- end
1154
- else
1155
- if ep.ctx.cref.singleton
1156
- meth = add_singleton_iseq_method(cref.klass, mid, iseq, cref)
1157
- else
1158
- meth = add_iseq_method(cref.klass, mid, iseq, cref)
1159
- if env.static_env.mod_func
1160
- add_singleton_iseq_method(cref.klass, mid, iseq, cref)
1161
- end
1162
- end
1163
-
1164
- pend_method_execution(iseq, meth, recv, mid, ep.ctx.cref)
1165
- end
1166
- else
1167
- # XXX: what to do?
1168
- end
1143
+ do_define_iseq_method(ep, env, mid, iseq, nil)
1169
1144
 
1170
1145
  when :definesmethod
1171
1146
  mid, iseq = operands
@@ -1173,8 +1148,8 @@ module TypeProf
1173
1148
  cref = ep.ctx.cref
1174
1149
  recv.each_child do |recv|
1175
1150
  if recv.is_a?(Type::Class)
1176
- meth = add_singleton_iseq_method(recv, mid, iseq, cref)
1177
- pend_method_execution(iseq, meth, recv, mid, ep.ctx.cref)
1151
+ meth = add_singleton_iseq_method(recv, mid, iseq, cref, nil)
1152
+ pend_method_execution(iseq, meth, recv, mid, ep.ctx.cref, nil)
1178
1153
  else
1179
1154
  recv = Type.any # XXX: what to do?
1180
1155
  end
@@ -1549,9 +1524,7 @@ module TypeProf
1549
1524
  ret_ty.each_child do |ret_ty|
1550
1525
  flow_env = env.local_update(-var_idx+2, ret_ty)
1551
1526
  ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::Symbol)
1552
- ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::LocalCell)
1553
- ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::LocalArray)
1554
- ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::LocalHash)
1527
+ ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::Local)
1555
1528
  if ret_ty.is_a?(Type::Instance)
1556
1529
  if ret_ty.klass == pattern_ty # XXX: inheritance
1557
1530
  merge_env(branchtype == :if ? ep_else : ep_then, flow_env)
@@ -1717,9 +1690,13 @@ module TypeProf
1717
1690
  from_head = flag & 2 == 0
1718
1691
  ary.each_child do |ary|
1719
1692
  case ary
1720
- when Type::LocalArray
1721
- elems = get_container_elem_types(env, ep, ary.id)
1722
- elems ||= Type::Array::Elements.new([], Type.any) # XXX
1693
+ when Type::Local
1694
+ if ary.kind == Type::Array
1695
+ elems = get_container_elem_types(env, ep, ary.id)
1696
+ elems ||= Type::Array::Elements.new([], Type.any) # XXX
1697
+ else
1698
+ elems = Type::Array::Elements.new([], Type.any) # XXX
1699
+ end
1723
1700
  do_expand_array(ep, env, elems, num, splat, from_head)
1724
1701
  when Type::Any
1725
1702
  nnum = num
@@ -1739,9 +1716,9 @@ module TypeProf
1739
1716
  return
1740
1717
  when :concatarray
1741
1718
  env, (ary1, ary2) = env.pop(2)
1742
- if ary1.is_a?(Type::LocalArray)
1719
+ if ary1.is_a?(Type::Local) && ary1.kind == Type::Array
1743
1720
  elems1 = get_container_elem_types(env, ep, ary1.id)
1744
- if ary2.is_a?(Type::LocalArray)
1721
+ if ary2.is_a?(Type::Local) && ary2.kind == Type::Array
1745
1722
  elems2 = get_container_elem_types(env, ep, ary2.id)
1746
1723
  elems = Type::Array::Elements.new([], elems1.squash.union(elems2.squash))
1747
1724
  env = update_container_elem_types(env, ep, ary1.id, ary1.base_type) { elems }
@@ -1973,21 +1950,31 @@ module TypeProf
1973
1950
  end
1974
1951
 
1975
1952
  def do_send(recv, mid, aargs, ep, env, &ctn)
1976
- klass, singleton = recv.method_dispatch_info
1977
- meths = get_method(klass, singleton, mid) if klass
1978
- if meths
1979
- meths.each do |meth|
1980
- meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
1981
- end
1953
+ case recv
1954
+ when Type::Void
1955
+ error(ep, "void's method is called: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
1956
+ ctn[Type.any, ep, env]
1957
+ when Type::Any
1958
+ ctn[Type.any, ep, env]
1982
1959
  else
1983
- case recv
1984
- when Type::Void
1985
- error(ep, "void's method is called: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
1986
- when Type::Any
1960
+ klass, singleton = recv.method_dispatch_info
1961
+ meths = get_method(klass, singleton, mid) if klass
1962
+ if meths
1963
+ meths.each do |meth|
1964
+ meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
1965
+ end
1987
1966
  else
1988
- error(ep, "undefined method: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
1967
+ meths = get_method(klass, singleton, :method_missing) if klass
1968
+ if meths
1969
+ aargs = aargs.for_method_missing(Type::Symbol.new(mid, Type::Instance.new(Type::Builtin[:sym])))
1970
+ meths.each do |meth|
1971
+ meth.do_send(recv, :method_missing, aargs, ep, env, self, &ctn)
1972
+ end
1973
+ else
1974
+ error(ep, "undefined method: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
1975
+ ctn[Type.any, ep, env]
1976
+ end
1989
1977
  end
1990
- ctn[Type.any, ep, env]
1991
1978
  end
1992
1979
  end
1993
1980
 
@@ -2002,6 +1989,34 @@ module TypeProf
2002
1989
  end
2003
1990
  end
2004
1991
 
1992
+ def do_define_iseq_method(ep, env, mid, iseq, outer_ep)
1993
+ cref = ep.ctx.cref
1994
+ recv = env.static_env.recv_ty
1995
+ if cref.klass.is_a?(Type::Class)
1996
+ typed_mdef = check_typed_method(cref.klass, mid, ep.ctx.cref.singleton)
1997
+ recv = Type::Instance.new(recv) if recv.is_a?(Type::Class)
1998
+ if typed_mdef
1999
+ mdef = ISeqMethodDef.new(iseq, cref, outer_ep)
2000
+ typed_mdef.each do |typed_mdef|
2001
+ typed_mdef.do_match_iseq_mdef(mdef, recv, mid, env, ep, self)
2002
+ end
2003
+ else
2004
+ if ep.ctx.cref.singleton
2005
+ meth = add_singleton_iseq_method(cref.klass, mid, iseq, cref, outer_ep)
2006
+ else
2007
+ meth = add_iseq_method(cref.klass, mid, iseq, cref, outer_ep)
2008
+ if env.static_env.mod_func
2009
+ add_singleton_iseq_method(cref.klass, mid, iseq, cref, outer_ep)
2010
+ end
2011
+ end
2012
+
2013
+ pend_method_execution(iseq, meth, recv, mid, ep.ctx.cref, outer_ep)
2014
+ end
2015
+ else
2016
+ # XXX: what to do?
2017
+ end
2018
+ end
2019
+
2005
2020
  def show_block_signature(blks)
2006
2021
  bsig = nil
2007
2022
  ret_ty = Type.bot
@@ -10,6 +10,10 @@ module TypeProf
10
10
  raise unless blk_ty
11
11
  end
12
12
 
13
+ def for_method_missing(mid)
14
+ ActualArguments.new([mid] + @lead_tys, @rest_ty, @kw_tys, @blk_ty)
15
+ end
16
+
13
17
  attr_reader :lead_tys, :rest_ty, :kw_tys, :blk_ty
14
18
 
15
19
  def globalize(caller_env, visited, depth)
@@ -148,12 +152,14 @@ module TypeProf
148
152
  lead_tys = ty.elems.lead_tys
149
153
  rest_ty = ty.elems.rest_ty
150
154
  when Type::Union
151
- other_elems = nil
152
- ty.elems&.each do |(container_kind, base_type), elems|
153
- if container_kind == Type::Array
154
- rest_ty = rest_ty ? rest_ty.union(elems.squash) : elems.squash
155
- else
156
- other_elems = other_elems ? other_elems.union(elems) : elems
155
+ if ty.elems
156
+ other_elems = {}
157
+ ty.elems.each do |(container_kind, base_type), elems|
158
+ if container_kind == Type::Array
159
+ rest_ty = rest_ty ? rest_ty.union(elems.squash) : elems.squash
160
+ else
161
+ other_elems[[container_kind, base_type]] = elems
162
+ end
157
163
  end
158
164
  end
159
165
  lead_tys = [Type::Union.new(ty.types, other_elems)]
@@ -33,10 +33,10 @@ module TypeProf
33
33
  h2 = aargs.lead_tys[1]
34
34
  elems = nil
35
35
  h1.each_child do |h1|
36
- if h1.is_a?(Type::LocalHash)
36
+ if h1.is_a?(Type::Local) && h1.kind == Type::Hash
37
37
  h1_elems = scratch.get_container_elem_types(env, ep, h1.id)
38
38
  h2.each_child do |h2|
39
- if h2.is_a?(Type::LocalHash)
39
+ if h2.is_a?(Type::Local) && h2.kind == Type::Hash
40
40
  h2_elems = scratch.get_container_elem_types(env, ep, h2.id)
41
41
  elems0 = h1_elems.union(h2_elems)
42
42
  if elems
@@ -143,7 +143,7 @@ module TypeProf
143
143
 
144
144
  def object_instance_eval(recv, mid, aargs, ep, env, scratch, &ctn)
145
145
  if aargs.lead_tys.size >= 1
146
- scratch.warn(ep, "instance_eval with arguments are ignored")
146
+ scratch.warn(ep, "instance_eval with arguments is ignored")
147
147
  ctn[Type.any, ep, env]
148
148
  return
149
149
  end
@@ -155,7 +155,7 @@ module TypeProf
155
155
 
156
156
  def module_include(recv, mid, aargs, ep, env, scratch, &ctn)
157
157
  if aargs.lead_tys.size != 1
158
- scratch.warn(ep, "Module#include without an argument are ignored")
158
+ scratch.warn(ep, "Module#include without an argument is ignored")
159
159
  ctn[Type.any, ep, env]
160
160
  return
161
161
  end
@@ -170,7 +170,7 @@ module TypeProf
170
170
 
171
171
  def module_extend(recv, mid, aargs, ep, env, scratch, &ctn)
172
172
  if aargs.lead_tys.size != 1
173
- scratch.warn(ep, "Module#extend without an argument are ignored")
173
+ scratch.warn(ep, "Module#extend without an argument is ignored")
174
174
  ctn[Type.any, ep, env]
175
175
  return
176
176
  end
@@ -198,6 +198,35 @@ module TypeProf
198
198
  end
199
199
  end
200
200
 
201
+ def module_define_method(recv, mid, aargs, ep, env, scratch, &ctn)
202
+ if aargs.lead_tys.size != 1
203
+ scratch.warn(ep, "Module#define with #{ aargs.lead_tys.size } argument is ignored")
204
+ ctn[Type.any, ep, env]
205
+ return
206
+ end
207
+
208
+ mid, = aargs.lead_tys
209
+ if mid.is_a?(Type::Symbol)
210
+ mid = mid.sym
211
+ aargs.blk_ty.each_child do |blk_ty|
212
+ if blk_ty.is_a?(Type::Proc)
213
+ blk = blk_ty.block_body
214
+ case blk
215
+ when ISeqBlock
216
+ scratch.do_define_iseq_method(ep, env, mid, blk.iseq, ep)
217
+ else
218
+ # XXX: what to do?
219
+ end
220
+ else
221
+ # XXX: what to do?
222
+ end
223
+ end
224
+ else
225
+ # XXX: what to do?
226
+ end
227
+ ctn[Type.any, ep, env]
228
+ end
229
+
201
230
  def module_attr_accessor(recv, mid, aargs, ep, env, scratch, &ctn)
202
231
  aargs.lead_tys.each do |aarg|
203
232
  sym = get_sym("attr_accessor", aarg, ep, scratch) or next
@@ -233,21 +262,16 @@ module TypeProf
233
262
  end
234
263
 
235
264
  def array_aref(recv, mid, aargs, ep, env, scratch, &ctn)
236
- return ctn[Type.any, ep, env] unless recv.is_a?(Type::LocalArray)
265
+ return ctn[Type.any, ep, env] unless recv.is_a?(Type::Local) && recv.kind == Type::Array
237
266
 
238
267
  case aargs.lead_tys.size
239
268
  when 1
240
269
  idx = aargs.lead_tys.first
241
270
  if idx.is_a?(Type::Literal)
242
271
  idx = idx.lit
243
- if idx.is_a?(Range)
244
- ty = scratch.get_array_elem_type(env, ep, recv.id)
245
- base_ty = Type::Instance.new(Type::Builtin[:ary])
246
- ret_ty = Type::Array.new(Type::Array::Elements.new([], ty), base_ty)
247
- ctn[ret_ty, ep, env]
248
- return
249
- end
250
- idx = nil if !idx.is_a?(Integer)
272
+ idx = nil if !idx.is_a?(Integer) && !idx.is_a?(Range)
273
+ elsif idx == Type::Instance.new(Type::Builtin[:range])
274
+ idx = (nil..nil)
251
275
  else
252
276
  idx = nil
253
277
  end
@@ -264,7 +288,7 @@ module TypeProf
264
288
  end
265
289
 
266
290
  def array_aset(recv, mid, aargs, ep, env, scratch, &ctn)
267
- return ctn[Type.any, ep, env] unless recv.is_a?(Type::LocalArray)
291
+ return ctn[Type.any, ep, env] unless recv.is_a?(Type::Local) && recv.kind == Type::Array
268
292
 
269
293
  if aargs.lead_tys.size != 2
270
294
  #raise NotImplementedError # XXX
@@ -289,7 +313,7 @@ module TypeProf
289
313
  end
290
314
 
291
315
  def array_pop(recv, mid, aargs, ep, env, scratch, &ctn)
292
- return ctn[Type.any, ep, env] unless recv.is_a?(Type::LocalArray)
316
+ return ctn[Type.any, ep, env] unless recv.is_a?(Type::Local) && recv.kind == Type::Array
293
317
 
294
318
  if aargs.lead_tys.size != 0
295
319
  ctn[Type.any, ep, env]
@@ -301,7 +325,7 @@ module TypeProf
301
325
  end
302
326
 
303
327
  def hash_aref(recv, mid, aargs, ep, env, scratch, &ctn)
304
- return ctn[Type.any, ep, env] unless recv.is_a?(Type::LocalHash)
328
+ return ctn[Type.any, ep, env] unless recv.is_a?(Type::Local) && recv.kind == Type::Hash
305
329
 
306
330
  if aargs.lead_tys.size != 1
307
331
  ctn[Type.any, ep, env]
@@ -309,7 +333,7 @@ module TypeProf
309
333
  end
310
334
  idx = aargs.lead_tys.first
311
335
  recv.each_child do |recv|
312
- if recv.is_a?(Type::LocalHash)
336
+ if recv.is_a?(Type::Local) && recv.kind == Type::Hash
313
337
  ty = scratch.get_hash_elem_type(env, ep, recv.id, idx)
314
338
  else
315
339
  ty = Type.any
@@ -319,7 +343,7 @@ module TypeProf
319
343
  end
320
344
 
321
345
  def hash_aset(recv, mid, aargs, ep, env, scratch, &ctn)
322
- return ctn[Type.any, ep, env] unless recv.is_a?(Type::LocalHash)
346
+ return ctn[Type.any, ep, env] unless recv.is_a?(Type::Local) && recv.kind == Type::Hash
323
347
 
324
348
  raise NotImplementedError if aargs.lead_tys.size != 2
325
349
 
@@ -327,7 +351,7 @@ module TypeProf
327
351
  idx = scratch.globalize_type(idx, env, ep)
328
352
  ty = aargs.lead_tys.last
329
353
 
330
- unless recv.is_a?(Type::LocalHash)
354
+ unless recv.is_a?(Type::Local) && recv.kind == Type::Hash
331
355
  # to ignore: class OptionMap < Hash
332
356
  return ctn[ty, ep, env]
333
357
  end
@@ -484,6 +508,31 @@ module TypeProf
484
508
  ctn[result, ep, env]
485
509
  end
486
510
 
511
+ def kernel_autoload(recv, mid, aargs, ep, env, scratch, &ctn)
512
+ raise NotImplementedError if aargs.lead_tys.size != 2
513
+ feature = aargs.lead_tys[1]
514
+ if feature.is_a?(Type::Literal)
515
+ feature = feature.lit
516
+
517
+ action, arg = Builtin.file_require(feature, scratch)
518
+ case action
519
+ when :do
520
+ Builtin.file_load(arg, ep, env, scratch, &ctn)
521
+ when :done
522
+ when :error
523
+ scratch.warn(ep, arg)
524
+ end
525
+ ctn[Type.nil, ep, env]
526
+ else
527
+ scratch.warn(ep, "autoload target cannot be identified statically")
528
+ ctn[Type.nil, ep, env]
529
+ end
530
+ end
531
+
532
+ def module_autoload(recv, mid, aargs, ep, env, scratch, &ctn)
533
+ kernel_autoload(recv, mid, aargs, ep, env, scratch, &ctn)
534
+ end
535
+
487
536
  def kernel_Array(recv, mid, aargs, ep, env, scratch, &ctn)
488
537
  raise NotImplementedError if aargs.lead_tys.size != 1
489
538
  ty = aargs.lead_tys.first
@@ -557,6 +606,7 @@ module TypeProf
557
606
  scratch.set_custom_method(klass_module, :include, Builtin.method(:module_include))
558
607
  scratch.set_custom_method(klass_module, :extend, Builtin.method(:module_extend))
559
608
  scratch.set_custom_method(klass_module, :module_function, Builtin.method(:module_module_function))
609
+ scratch.set_custom_method(klass_module, :define_method, Builtin.method(:module_define_method))
560
610
 
561
611
  scratch.set_custom_method(klass_proc, :[], Builtin.method(:proc_call))
562
612
  scratch.set_custom_method(klass_proc, :call, Builtin.method(:proc_call))
@@ -574,6 +624,11 @@ module TypeProf
574
624
  scratch.set_custom_method(klass_obj, :require, Builtin.method(:kernel_require))
575
625
  scratch.set_custom_method(klass_obj, :require_relative, Builtin.method(:kernel_require_relative))
576
626
  scratch.set_custom_method(klass_obj, :Array, Builtin.method(:kernel_Array))
627
+ scratch.set_custom_method(klass_obj, :autoload, Builtin.method(:kernel_autoload))
628
+ scratch.set_custom_method(klass_module, :autoload, Builtin.method(:module_autoload))
629
+
630
+ # remove BasicObject#method_missing
631
+ scratch.set_method(klass_basic_obj, :method_missing, false, nil)
577
632
 
578
633
  # ENV: Hash[String, String]
579
634
  str_ty = Type::Instance.new(Type::Builtin[:str])