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 +4 -4
- data/Gemfile.lock +2 -2
- data/doc/doc.ja.md +3 -4
- data/doc/doc.md +3 -4
- data/lib/typeprof/analyzer.rb +95 -80
- data/lib/typeprof/arguments.rb +12 -6
- data/lib/typeprof/builtin.rb +75 -20
- data/lib/typeprof/cli.rb +33 -34
- data/lib/typeprof/config.rb +4 -2
- data/lib/typeprof/container-type.rb +153 -99
- data/lib/typeprof/export.rb +9 -9
- data/lib/typeprof/import.rb +23 -32
- data/lib/typeprof/method.rb +45 -131
- data/lib/typeprof/type.rb +8 -2
- data/lib/typeprof/version.rb +1 -1
- data/smoke/array-each3.rb +1 -1
- data/smoke/array-range-aref.rb +70 -0
- data/smoke/autoload.rb +13 -0
- data/smoke/define_method.rb +16 -0
- data/smoke/define_method2.rb +18 -0
- data/smoke/kwrest.rb +12 -0
- data/smoke/kwrest.rbs +3 -0
- data/smoke/method_missing.rb +28 -0
- data/smoke/rbs-attr.rb +2 -2
- data/smoke/rbs-attr2.rb +11 -0
- data/smoke/rbs-attr2.rbs +3 -0
- data/smoke/rbs-tyvar7.rb +11 -0
- data/smoke/rbs-tyvar7.rbs +7 -0
- data/smoke/rbs-vars.rb +0 -2
- metadata +13 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8ecd99e5448a244b11714710dfbb5fd3f36274c5f72fa97da034059018fc32f
|
4
|
+
data.tar.gz: ed322065cf15d08f7bb50105cce19d74d923d4d7af7f94a563668788849d636d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 528dcf83aa2ceec79ea602f3505eb48230baf87bae8409212f8f152b45e308c66490ff5d10a9153698870e02b0ee5f031ce81cbb48a4460187992269708957ef
|
7
|
+
data.tar.gz: a03594cb0b6a88ba905dc860ba9de64beb82a6cb1ebc562aad94cf20ecf14e36534bbf8a29a0b629189c62c32c26437104acb4387159c17bb222c708614cc303
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
typeprof (0.
|
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.
|
20
|
+
test-unit (3.3.7)
|
21
21
|
power_assert
|
22
22
|
|
23
23
|
PLATFORMS
|
data/doc/doc.ja.md
CHANGED
@@ -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
|
-
*
|
39
|
-
*
|
40
|
-
*
|
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
|
-
*
|
38
|
-
*
|
39
|
-
*
|
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
|
|
data/lib/typeprof/analyzer.rb
CHANGED
@@ -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
|
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
|
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.
|
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
|
-
|
362
|
-
|
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
|
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.
|
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.
|
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.
|
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.
|
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.
|
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
|
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
|
-
|
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.
|
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,
|
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
|
-
|
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::
|
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
|
-
|
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::
|
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::
|
1721
|
-
|
1722
|
-
|
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::
|
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::
|
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
|
-
|
1977
|
-
|
1978
|
-
|
1979
|
-
|
1980
|
-
|
1981
|
-
|
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
|
-
|
1984
|
-
|
1985
|
-
|
1986
|
-
|
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
|
-
|
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
|
data/lib/typeprof/arguments.rb
CHANGED
@@ -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
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
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)]
|
data/lib/typeprof/builtin.rb
CHANGED
@@ -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::
|
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::
|
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
|
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
|
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
|
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::
|
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
|
-
|
245
|
-
|
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::
|
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::
|
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::
|
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::
|
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::
|
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::
|
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])
|