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