typeprof 0.6.1 → 0.7.0

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: 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])