typeprof 0.6.0 → 0.9.1
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 +7 -5
- data/doc/doc.ja.md +3 -4
- data/doc/doc.md +3 -4
- data/lib/typeprof/analyzer.rb +214 -133
- data/lib/typeprof/arguments.rb +14 -6
- data/lib/typeprof/block.rb +6 -2
- data/lib/typeprof/builtin.rb +223 -71
- data/lib/typeprof/cli.rb +33 -34
- data/lib/typeprof/config.rb +6 -4
- data/lib/typeprof/container-type.rb +154 -99
- data/lib/typeprof/export.rb +23 -17
- data/lib/typeprof/import.rb +49 -42
- data/lib/typeprof/iseq.rb +23 -7
- data/lib/typeprof/method.rb +63 -147
- data/lib/typeprof/type.rb +63 -7
- data/lib/typeprof/version.rb +1 -1
- data/smoke/alias.rb +5 -4
- data/smoke/alias2.rb +4 -4
- data/smoke/any1.rb +2 -1
- data/smoke/any2.rb +3 -2
- data/smoke/arguments.rb +3 -2
- data/smoke/arguments2.rb +11 -10
- data/smoke/array-each.rb +2 -1
- data/smoke/array-each2.rb +2 -1
- data/smoke/array-each3.rb +2 -1
- data/smoke/array-ltlt.rb +2 -1
- data/smoke/array-ltlt2.rb +2 -1
- data/smoke/array-map.rb +2 -1
- data/smoke/array-map2.rb +2 -1
- data/smoke/array-map3.rb +4 -3
- data/smoke/array-mul.rb +3 -2
- data/smoke/array-plus1.rb +2 -1
- data/smoke/array-plus2.rb +2 -2
- data/smoke/array-pop.rb +2 -1
- data/smoke/array-range-aref.rb +71 -0
- data/smoke/array-replace.rb +2 -1
- data/smoke/array-s-aref.rb +2 -1
- data/smoke/array1.rb +6 -5
- data/smoke/array10.rb +2 -1
- data/smoke/array11.rb +2 -1
- data/smoke/array12.rb +4 -3
- data/smoke/array13.rb +5 -4
- data/smoke/array14.rb +2 -1
- data/smoke/array15.rb +16 -0
- data/smoke/array2.rb +4 -3
- data/smoke/array3.rb +4 -4
- data/smoke/array4.rb +2 -1
- data/smoke/array5.rb +2 -1
- data/smoke/array6.rb +3 -2
- data/smoke/array7.rb +2 -1
- data/smoke/array8.rb +1 -1
- data/smoke/array9.rb +2 -1
- data/smoke/attr-module.rb +26 -0
- data/smoke/attr.rb +5 -5
- data/smoke/autoload.rb +14 -0
- data/smoke/backtrace.rb +4 -3
- data/smoke/block-ambiguous.rb +9 -8
- data/smoke/block-args1-rest.rb +12 -11
- data/smoke/block-args1.rb +11 -10
- data/smoke/block-args2-rest.rb +12 -11
- data/smoke/block-args2.rb +11 -10
- data/smoke/block-args3-rest.rb +14 -13
- data/smoke/block-args3.rb +13 -12
- data/smoke/block-blockarg.rb +5 -4
- data/smoke/block-kwarg.rb +11 -10
- data/smoke/block1.rb +2 -1
- data/smoke/block10.rb +2 -1
- data/smoke/block11.rb +6 -5
- data/smoke/block12.rb +3 -2
- data/smoke/block14.rb +3 -2
- data/smoke/block2.rb +2 -1
- data/smoke/block3.rb +3 -3
- data/smoke/block4.rb +3 -2
- data/smoke/block5.rb +3 -2
- data/smoke/block6.rb +3 -2
- data/smoke/block7.rb +2 -1
- data/smoke/block8.rb +4 -3
- data/smoke/block9.rb +2 -1
- data/smoke/blown.rb +2 -1
- data/smoke/break1.rb +3 -2
- data/smoke/break2.rb +2 -1
- data/smoke/break3.rb +13 -0
- data/smoke/case.rb +2 -1
- data/smoke/case2.rb +2 -1
- data/smoke/case3.rb +17 -0
- data/smoke/class-hierarchy.rb +5 -5
- data/smoke/class-hierarchy2.rb +3 -3
- data/smoke/class-new.rb +15 -0
- data/smoke/class_instance_var.rb +1 -1
- data/smoke/class_method.rb +2 -2
- data/smoke/class_method2.rb +2 -2
- data/smoke/class_method3.rb +4 -2
- data/smoke/constant1.rb +6 -6
- data/smoke/constant2.rb +5 -4
- data/smoke/constant3.rb +2 -1
- data/smoke/constant4.rb +2 -1
- data/smoke/context-sensitive1.rb +2 -1
- data/smoke/cvar.rb +6 -5
- data/smoke/cvar2.rb +2 -2
- data/smoke/define_method.rb +16 -0
- data/smoke/define_method2.rb +18 -0
- data/smoke/define_method3.rb +13 -0
- data/smoke/define_method3.rbs +3 -0
- data/smoke/define_method4.rb +15 -0
- data/smoke/define_method4.rbs +3 -0
- data/smoke/define_method5.rb +12 -0
- data/smoke/demo.rb +7 -6
- data/smoke/demo1.rb +2 -1
- data/smoke/demo10.rb +3 -2
- data/smoke/demo11.rb +2 -1
- data/smoke/demo2.rb +2 -1
- data/smoke/demo3.rb +2 -1
- data/smoke/demo4.rb +3 -3
- data/smoke/demo5.rb +1 -1
- data/smoke/demo6.rb +3 -3
- data/smoke/demo7.rb +2 -1
- data/smoke/demo8.rb +3 -2
- data/smoke/demo9.rb +3 -2
- data/smoke/dummy-execution1.rb +3 -2
- data/smoke/dummy-execution2.rb +2 -2
- data/smoke/dummy_element.rb +14 -0
- data/smoke/ensure1.rb +3 -2
- data/smoke/enumerator.rb +3 -2
- data/smoke/expandarray1.rb +2 -1
- data/smoke/expandarray2.rb +2 -1
- data/smoke/fib.rb +2 -2
- data/smoke/flip-flop.rb +28 -0
- data/smoke/flow1.rb +2 -1
- data/smoke/flow2.rb +2 -1
- data/smoke/flow3.rb +2 -1
- data/smoke/flow5.rb +2 -1
- data/smoke/flow6.rb +2 -1
- data/smoke/flow7.rb +2 -1
- data/smoke/flow8.rb +2 -1
- data/smoke/flow9.rb +12 -0
- data/smoke/freeze.rb +2 -1
- data/smoke/function.rb +3 -2
- data/smoke/gvar.rb +3 -2
- data/smoke/gvar2.rb +3 -2
- data/smoke/hash-bot.rb +12 -0
- data/smoke/hash-fetch.rb +4 -3
- data/smoke/hash-merge-bang.rb +2 -1
- data/smoke/hash1.rb +3 -2
- data/smoke/hash2.rb +2 -1
- data/smoke/hash3.rb +2 -1
- data/smoke/hash4.rb +2 -1
- data/smoke/hash5.rb +1 -1
- data/smoke/inheritance.rb +4 -4
- data/smoke/inheritance2.rb +2 -2
- data/smoke/initialize.rb +6 -5
- data/smoke/instance_eval.rb +2 -2
- data/smoke/instance_eval2.rb +10 -0
- data/smoke/instance_eval3.rb +25 -0
- data/smoke/int_times.rb +2 -1
- data/smoke/integer.rb +2 -1
- data/smoke/ivar.rb +5 -4
- data/smoke/ivar2.rb +4 -4
- data/smoke/ivar3.rb +2 -2
- data/smoke/ivar4.rb +20 -0
- data/smoke/kernel-class.rb +2 -1
- data/smoke/keyword1.rb +2 -1
- data/smoke/keyword2.rb +2 -1
- data/smoke/keyword3.rb +2 -1
- data/smoke/keyword4.rb +2 -1
- data/smoke/keyword5.rb +2 -1
- data/smoke/kwrest.rb +12 -0
- data/smoke/kwrest.rbs +3 -0
- data/smoke/kwsplat1.rb +5 -4
- data/smoke/kwsplat2.rb +2 -1
- data/smoke/lit-complex.rb +10 -0
- data/smoke/lit-encoding.rb +10 -0
- data/smoke/manual-rbs.rb +4 -3
- data/smoke/manual-rbs2.rb +2 -1
- data/smoke/manual-rbs3.rb +2 -2
- data/smoke/masgn1.rb +2 -1
- data/smoke/masgn2.rb +3 -2
- data/smoke/masgn3.rb +2 -1
- data/smoke/method_in_branch.rb +3 -2
- data/smoke/method_missing.rb +28 -0
- data/smoke/module1.rb +2 -2
- data/smoke/module2.rb +1 -1
- data/smoke/module3.rb +2 -2
- data/smoke/module4.rb +2 -2
- data/smoke/module5.rb +17 -0
- data/smoke/module6.rb +40 -0
- data/smoke/module_function1.rb +3 -3
- data/smoke/module_function2.rb +3 -3
- data/smoke/multiple-include.rb +1 -1
- data/smoke/multiple-superclass.rb +1 -1
- data/smoke/next1.rb +3 -2
- data/smoke/next2.rb +2 -1
- data/smoke/object-send1.rb +4 -3
- data/smoke/object-send2.rb +10 -0
- data/smoke/object-send3.rb +18 -0
- data/smoke/once.rb +2 -1
- data/smoke/optional1.rb +2 -1
- data/smoke/optional2.rb +2 -1
- data/smoke/optional3.rb +2 -1
- data/smoke/parameterizedd-self.rb +3 -2
- data/smoke/parameterizedd-self2.rb +1 -1
- data/smoke/pathname1.rb +2 -1
- data/smoke/pathname2.rb +2 -1
- data/smoke/pattern-match1.rb +2 -1
- data/smoke/pattern-match2.rb +2 -1
- data/smoke/printf.rb +2 -2
- data/smoke/proc.rb +3 -2
- data/smoke/proc2.rb +2 -1
- data/smoke/proc3.rb +2 -1
- data/smoke/proc4.rb +2 -1
- data/smoke/proc5.rb +19 -0
- data/smoke/public.rb +34 -0
- data/smoke/range.rb +2 -1
- data/smoke/rbs-alias.rb +2 -1
- data/smoke/rbs-attr.rb +6 -5
- data/smoke/rbs-attr2.rb +11 -0
- data/smoke/rbs-attr2.rbs +3 -0
- data/smoke/rbs-extend.rb +2 -1
- data/smoke/rbs-interface.rb +5 -4
- data/smoke/rbs-module.rb +26 -0
- data/smoke/rbs-module.rbs +4 -0
- data/smoke/rbs-opt-and-rest.rb +10 -0
- data/smoke/rbs-opt-and-rest.rbs +3 -0
- data/smoke/rbs-proc1.rb +2 -1
- data/smoke/rbs-proc2.rb +3 -2
- data/smoke/rbs-proc3.rb +2 -1
- data/smoke/rbs-record.rb +3 -2
- data/smoke/rbs-tyvar.rb +3 -2
- data/smoke/rbs-tyvar2.rb +3 -2
- data/smoke/rbs-tyvar3.rb +3 -2
- data/smoke/rbs-tyvar4.rb +3 -3
- data/smoke/rbs-tyvar5.rb +2 -1
- data/smoke/rbs-tyvar6.rb +4 -3
- data/smoke/rbs-tyvar7.rb +12 -0
- data/smoke/rbs-tyvar7.rbs +7 -0
- data/smoke/rbs-vars.rb +7 -8
- data/smoke/redo1.rb +3 -2
- data/smoke/redo2.rb +3 -2
- data/smoke/req-keyword.rb +2 -1
- data/smoke/rescue1.rb +3 -2
- data/smoke/rescue2.rb +3 -2
- data/smoke/rescue3.rb +19 -0
- data/smoke/rescue4.rb +17 -0
- data/smoke/respond_to.rb +2 -1
- data/smoke/rest-farg.rb +2 -1
- data/smoke/rest1.rb +3 -2
- data/smoke/rest2.rb +2 -1
- data/smoke/rest3.rb +7 -6
- data/smoke/rest4.rb +3 -2
- data/smoke/rest5.rb +2 -1
- data/smoke/rest6.rb +2 -1
- data/smoke/retry1.rb +3 -2
- data/smoke/return.rb +2 -1
- data/smoke/singleton_method.rb +1 -1
- data/smoke/step.rb +4 -3
- data/smoke/string-split.rb +2 -1
- data/smoke/struct-keyword_init.rb +20 -0
- data/smoke/struct.rb +1 -1
- data/smoke/struct2.rb +5 -4
- data/smoke/struct3.rb +2 -2
- data/smoke/struct4.rb +7 -0
- data/smoke/struct5.rb +16 -0
- data/smoke/struct6.rb +15 -0
- data/smoke/struct7.rb +17 -0
- data/smoke/stub-keyword.rb +10 -0
- data/smoke/super1.rb +5 -4
- data/smoke/super2.rb +1 -1
- data/smoke/super3.rb +3 -3
- data/smoke/super4.rb +5 -5
- data/smoke/super5.rb +4 -4
- data/smoke/svar1.rb +2 -1
- data/smoke/symbol-proc-attr.rb +22 -0
- data/smoke/symbol-proc-attr2.rb +15 -0
- data/smoke/symbol-proc-bot.rb +13 -0
- data/smoke/symbol-proc.rb +4 -3
- data/smoke/tap1.rb +3 -2
- data/smoke/toplevel.rb +2 -1
- data/smoke/two-map.rb +3 -2
- data/smoke/type_var.rb +2 -1
- data/smoke/typed_method.rb +2 -1
- data/smoke/uninitialize-var.rb +2 -1
- data/smoke/union-recv.rb +2 -2
- data/smoke/user-demo.rb +3 -3
- data/smoke/wrong-extend.rb +2 -2
- data/smoke/wrong-include.rb +2 -2
- data/smoke/wrong-include2.rb +17 -0
- data/typeprof.gemspec +1 -1
- metadata +56 -5
- data/tools/stackprof-wrapper.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 481ba91ab18504fff44772720b462a9fa302e4eecddb559c3a5942710e081fa9
|
4
|
+
data.tar.gz: 288ddfd1d6c9e198ea62e6564addf40ce851c91337801db44f2957c98b9f58f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f1eefdf5e92e2fa79a03979e36dd810ffcb337c426035acc384473e45fe6201487e8354608b4b87582515561b214e3ef339edd19e3980fab2873e6bc24cb9c5
|
7
|
+
data.tar.gz: cd74500c47328634ab7991911f795e7ea9b5cc47c15e3540c7796b39c2d1d83661cd50b45623e92cf1f33cbf1e83c4c8b5796a5e5332c8e1f475d3f1d26c043c
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
typeprof (0.
|
5
|
-
rbs (>= 0.
|
4
|
+
typeprof (0.9.1)
|
5
|
+
rbs (>= 0.20.1)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
@@ -11,13 +11,15 @@ GEM
|
|
11
11
|
docile (1.3.2)
|
12
12
|
power_assert (1.2.0)
|
13
13
|
rake (13.0.1)
|
14
|
-
rbs (0.
|
15
|
-
simplecov (0.
|
14
|
+
rbs (0.20.1)
|
15
|
+
simplecov (0.20.0)
|
16
16
|
docile (~> 1.1)
|
17
17
|
simplecov-html (~> 0.11)
|
18
|
+
simplecov_json_formatter (~> 0.1)
|
18
19
|
simplecov-html (0.12.3)
|
20
|
+
simplecov_json_formatter (0.1.2)
|
19
21
|
stackprof (0.2.16)
|
20
|
-
test-unit (3.3.
|
22
|
+
test-unit (3.3.7)
|
21
23
|
power_assert
|
22
24
|
|
23
25
|
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
@@ -34,6 +34,14 @@ module TypeProf
|
|
34
34
|
end
|
35
35
|
|
36
36
|
attr_reader :iseq, :cref, :mid
|
37
|
+
|
38
|
+
def source_location(pc)
|
39
|
+
if @iseq
|
40
|
+
@iseq.source_location(pc)
|
41
|
+
else
|
42
|
+
"<builtin>"
|
43
|
+
end
|
44
|
+
end
|
37
45
|
end
|
38
46
|
|
39
47
|
class TypedContext
|
@@ -45,6 +53,14 @@ module TypeProf
|
|
45
53
|
end
|
46
54
|
|
47
55
|
attr_reader :caller_ep, :mid
|
56
|
+
|
57
|
+
def source_location(_pc)
|
58
|
+
if @caller_ep
|
59
|
+
@caller_ep.source_location
|
60
|
+
else
|
61
|
+
"<typed-context:#{ @mid }>"
|
62
|
+
end
|
63
|
+
end
|
48
64
|
end
|
49
65
|
|
50
66
|
class ExecutionPoint
|
@@ -71,36 +87,33 @@ module TypeProf
|
|
71
87
|
end
|
72
88
|
|
73
89
|
def source_location
|
74
|
-
|
75
|
-
if iseq
|
76
|
-
iseq.source_location(@pc)
|
77
|
-
else
|
78
|
-
"<builtin>"
|
79
|
-
end
|
90
|
+
@ctx.source_location(@pc)
|
80
91
|
end
|
81
92
|
end
|
82
93
|
|
83
94
|
class StaticEnv
|
84
95
|
include Utils::StructuralEquality
|
85
96
|
|
86
|
-
def initialize(recv_ty, blk_ty, mod_func)
|
97
|
+
def initialize(recv_ty, blk_ty, mod_func, pub_meth)
|
87
98
|
@recv_ty = recv_ty
|
88
99
|
@blk_ty = blk_ty
|
89
100
|
@mod_func = mod_func
|
101
|
+
@pub_meth = pub_meth
|
90
102
|
|
91
103
|
return if recv_ty == :top #OK
|
92
104
|
recv_ty.each_child_global do |ty|
|
93
|
-
raise ty.inspect if !ty.is_a?(Type::Instance) && !ty.is_a?(Type::Class) && ty != Type.any
|
105
|
+
raise ty.inspect if !ty.is_a?(Type::Instance) && !ty.is_a?(Type::Class) && !ty.is_a?(Type::Symbol) && ty != Type.any
|
94
106
|
end
|
95
107
|
end
|
96
108
|
|
97
|
-
attr_reader :recv_ty, :blk_ty, :mod_func
|
109
|
+
attr_reader :recv_ty, :blk_ty, :mod_func, :pub_meth
|
98
110
|
|
99
111
|
def merge(other)
|
100
112
|
recv_ty = @recv_ty.union(other.recv_ty)
|
101
113
|
blk_ty = @blk_ty.union(other.blk_ty)
|
102
114
|
mod_func = @mod_func & other.mod_func # ??
|
103
|
-
|
115
|
+
pub_meth = @pub_meth & other.pub_meth # ??
|
116
|
+
StaticEnv.new(recv_ty, blk_ty, mod_func, pub_meth)
|
104
117
|
end
|
105
118
|
end
|
106
119
|
|
@@ -185,29 +198,27 @@ module TypeProf
|
|
185
198
|
Env.new(@static_env, Utils.array_update(@locals, idx, ty), @stack, @type_params)
|
186
199
|
end
|
187
200
|
|
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
201
|
def get_container_elem_types(id)
|
196
202
|
@type_params.internal_hash[id]
|
197
203
|
end
|
198
204
|
|
199
|
-
def
|
205
|
+
def deploy_type(id, elems)
|
200
206
|
type_params = Utils::HashWrapper.new(@type_params.internal_hash.merge({ id => elems }))
|
201
207
|
Env.new(@static_env, @locals, @stack, type_params)
|
202
208
|
end
|
203
209
|
|
204
210
|
def enable_module_function
|
205
|
-
senv = StaticEnv.new(@static_env.recv_ty, @static_env.blk_ty, true)
|
211
|
+
senv = StaticEnv.new(@static_env.recv_ty, @static_env.blk_ty, true, @static_env.pub_meth)
|
212
|
+
Env.new(senv, @locals, @stack, @type_params)
|
213
|
+
end
|
214
|
+
|
215
|
+
def method_public_set(flag)
|
216
|
+
senv = StaticEnv.new(@static_env.recv_ty, @static_env.blk_ty, @static_env.mod_func, flag)
|
206
217
|
Env.new(senv, @locals, @stack, @type_params)
|
207
218
|
end
|
208
219
|
|
209
220
|
def replace_recv_ty(ty)
|
210
|
-
senv = StaticEnv.new(ty, @static_env.blk_ty, @static_env.mod_func)
|
221
|
+
senv = StaticEnv.new(ty, @static_env.blk_ty, @static_env.mod_func, @static_env.pub_meth)
|
211
222
|
Env.new(senv, @locals, @stack, @type_params)
|
212
223
|
end
|
213
224
|
|
@@ -298,8 +309,8 @@ module TypeProf
|
|
298
309
|
attr_accessor :name, :klass_obj
|
299
310
|
|
300
311
|
def include_module(mod, type_args, singleton, absolute_path)
|
301
|
-
|
302
|
-
if
|
312
|
+
mod_, module_type_args, absolute_paths = @modules[singleton].find {|m,| m == mod }
|
313
|
+
if mod_
|
303
314
|
raise "inconsistent include/extend type args in RBS?" if module_type_args != type_args && type_args != [] && type_args != nil
|
304
315
|
else
|
305
316
|
absolute_paths = Utils::MutableSet.new
|
@@ -320,9 +331,9 @@ module TypeProf
|
|
320
331
|
@consts[name] = [ty, absolute_path]
|
321
332
|
end
|
322
333
|
|
323
|
-
def
|
334
|
+
def adjust_substitution(singleton, mid, mthd, subst, direct, &blk)
|
324
335
|
mthds = @methods[[singleton, mid]]
|
325
|
-
yield subst if mthds&.include?(mthd)
|
336
|
+
yield subst, direct if mthds&.include?(mthd)
|
326
337
|
@modules[singleton].each do |mod_def, type_args,|
|
327
338
|
if mod_def.klass_obj.type_params && type_args
|
328
339
|
subst2 = {}
|
@@ -330,16 +341,19 @@ module TypeProf
|
|
330
341
|
tyvar = Type::Var.new(tyvar)
|
331
342
|
subst2[tyvar] = tyarg.substitute(subst, Config.options[:type_depth_limit])
|
332
343
|
end
|
333
|
-
mod_def.
|
344
|
+
mod_def.adjust_substitution(false, mid, mthd, subst2, false, &blk)
|
334
345
|
end
|
335
346
|
end
|
336
347
|
end
|
337
348
|
|
338
|
-
def search_method(singleton, mid, &blk)
|
349
|
+
def search_method(singleton, mid, visited, &blk)
|
350
|
+
# Currently, circular inclusion of modules is allowed
|
351
|
+
return if visited[self]
|
352
|
+
visited[self] = true
|
339
353
|
mthds = @methods[[singleton, mid]]
|
340
354
|
yield mthds, @klass_obj, singleton if mthds
|
341
355
|
@modules[singleton].each do |mod_def,|
|
342
|
-
mod_def.search_method(false, mid, &blk)
|
356
|
+
mod_def.search_method(false, mid, visited, &blk)
|
343
357
|
end
|
344
358
|
end
|
345
359
|
|
@@ -358,12 +372,16 @@ module TypeProf
|
|
358
372
|
end
|
359
373
|
|
360
374
|
def set_method(mid, singleton, mdef)
|
361
|
-
|
362
|
-
|
375
|
+
if mdef
|
376
|
+
@methods[[singleton, mid]] = Utils::MutableSet.new
|
377
|
+
@methods[[singleton, mid]] << mdef
|
378
|
+
else
|
379
|
+
@methods.delete([singleton, mid])
|
380
|
+
end
|
363
381
|
end
|
364
382
|
end
|
365
383
|
|
366
|
-
def include_module(including_mod, included_mod, type_args, singleton,
|
384
|
+
def include_module(including_mod, included_mod, type_args, singleton, caller_ep)
|
367
385
|
return if included_mod == Type.any
|
368
386
|
|
369
387
|
including_mod = @class_defs[including_mod.idx]
|
@@ -371,9 +389,9 @@ module TypeProf
|
|
371
389
|
if included_mod.is_a?(Type::Class)
|
372
390
|
included_mod = @class_defs[included_mod.idx]
|
373
391
|
if included_mod && included_mod.kind == :module
|
374
|
-
including_mod.include_module(included_mod, type_args, singleton, absolute_path)
|
392
|
+
including_mod.include_module(included_mod, type_args, singleton, caller_ep ? caller_ep.ctx.iseq.absolute_path : nil)
|
375
393
|
else
|
376
|
-
warn "including something that is not a module"
|
394
|
+
warn(caller_ep, "including something that is not a module")
|
377
395
|
end
|
378
396
|
end
|
379
397
|
end
|
@@ -383,12 +401,12 @@ module TypeProf
|
|
383
401
|
cbase && cbase.idx != 1 ? @class_defs[cbase.idx].name : []
|
384
402
|
end
|
385
403
|
|
386
|
-
def new_class(cbase, name, type_params, superclass,
|
404
|
+
def new_class(cbase, name, type_params, superclass, absolute_path)
|
387
405
|
show_name = cbase_path(cbase) + [name]
|
388
406
|
idx = @class_defs.size
|
389
407
|
if superclass
|
390
408
|
@class_defs[idx] = ClassDef.new(:class, show_name, absolute_path)
|
391
|
-
klass = Type::Class.new(:class, idx, type_params, superclass,
|
409
|
+
klass = Type::Class.new(:class, idx, type_params, superclass, show_name)
|
392
410
|
@class_defs[idx].klass_obj = klass
|
393
411
|
cbase ||= klass # for bootstrap
|
394
412
|
add_constant(cbase, name, klass, absolute_path)
|
@@ -396,13 +414,17 @@ module TypeProf
|
|
396
414
|
else
|
397
415
|
# module
|
398
416
|
@class_defs[idx] = ClassDef.new(:module, show_name, absolute_path)
|
399
|
-
mod = Type::Class.new(:module, idx, type_params, nil,
|
417
|
+
mod = Type::Class.new(:module, idx, type_params, nil, show_name)
|
400
418
|
@class_defs[idx].klass_obj = mod
|
401
419
|
add_constant(cbase, name, mod, absolute_path)
|
402
420
|
return mod
|
403
421
|
end
|
404
422
|
end
|
405
423
|
|
424
|
+
def add_superclass_type_args!(klass, tyargs)
|
425
|
+
klass.superclass_type_args = tyargs
|
426
|
+
end
|
427
|
+
|
406
428
|
def new_struct(ep)
|
407
429
|
return @struct_defs[ep] if @struct_defs[ep]
|
408
430
|
|
@@ -410,7 +432,8 @@ module TypeProf
|
|
410
432
|
superclass = Type::Builtin[:struct]
|
411
433
|
name = "AnonymousStruct_generated_#{ @anonymous_struct_gen_id += 1 }"
|
412
434
|
@class_defs[idx] = ClassDef.new(:class, [name], ep.ctx.iseq.absolute_path)
|
413
|
-
klass = Type::Class.new(:class, idx, [], superclass,
|
435
|
+
klass = Type::Class.new(:class, idx, [], superclass, name)
|
436
|
+
add_superclass_type_args!(klass, [Type.any])
|
414
437
|
@class_defs[idx].klass_obj = klass
|
415
438
|
|
416
439
|
@struct_defs[ep] = klass
|
@@ -440,11 +463,13 @@ module TypeProf
|
|
440
463
|
end
|
441
464
|
end
|
442
465
|
|
443
|
-
def
|
466
|
+
def adjust_substitution(klass, singleton, mid, mthd, subst, &blk)
|
467
|
+
direct = true
|
444
468
|
if klass.kind == :class
|
445
469
|
while klass != :__root__
|
446
470
|
class_def = @class_defs[klass.idx]
|
447
|
-
class_def.
|
471
|
+
class_def.adjust_substitution(singleton, mid, mthd, subst, direct, &blk)
|
472
|
+
direct = false
|
448
473
|
if klass.superclass && klass.superclass_type_args
|
449
474
|
subst2 = {}
|
450
475
|
klass.superclass.type_params.zip(klass.superclass_type_args) do |(tyvar, *), tyarg|
|
@@ -458,7 +483,7 @@ module TypeProf
|
|
458
483
|
else
|
459
484
|
# module
|
460
485
|
class_def = @class_defs[klass.idx]
|
461
|
-
class_def.
|
486
|
+
class_def.adjust_substitution(singleton, mid, mthd, subst, direct, &blk)
|
462
487
|
end
|
463
488
|
end
|
464
489
|
|
@@ -468,13 +493,13 @@ module TypeProf
|
|
468
493
|
if klass.kind == :class
|
469
494
|
while klass != :__root__
|
470
495
|
class_def = @class_defs[klass.idx]
|
471
|
-
class_def.search_method(singleton, mid, &blk)
|
496
|
+
class_def.search_method(singleton, mid, {}, &blk)
|
472
497
|
klass = klass.superclass
|
473
498
|
end
|
474
499
|
else
|
475
500
|
# module
|
476
501
|
class_def = @class_defs[klass.idx]
|
477
|
-
class_def.search_method(singleton, mid, &blk)
|
502
|
+
class_def.search_method(singleton, mid, {}, &blk)
|
478
503
|
end
|
479
504
|
if singleton
|
480
505
|
search_method(Type::Builtin[klass_orig.kind], false, mid, &blk)
|
@@ -534,9 +559,7 @@ module TypeProf
|
|
534
559
|
end
|
535
560
|
|
536
561
|
def add_constant(klass, name, value, user_defined)
|
537
|
-
if klass
|
538
|
-
self
|
539
|
-
else
|
562
|
+
if klass.is_a?(Type::Class)
|
540
563
|
@class_defs[klass.idx].add_constant(name, value, user_defined)
|
541
564
|
end
|
542
565
|
end
|
@@ -564,12 +587,12 @@ module TypeProf
|
|
564
587
|
end
|
565
588
|
end
|
566
589
|
|
567
|
-
def add_iseq_method(klass, mid, iseq, cref)
|
568
|
-
add_method(klass, mid, false, ISeqMethodDef.new(iseq, cref))
|
590
|
+
def add_iseq_method(klass, mid, iseq, cref, outer_ep, pub_meth)
|
591
|
+
add_method(klass, mid, false, ISeqMethodDef.new(iseq, cref, outer_ep, pub_meth))
|
569
592
|
end
|
570
593
|
|
571
|
-
def add_singleton_iseq_method(klass, mid, iseq, cref)
|
572
|
-
add_method(klass, mid, true, ISeqMethodDef.new(iseq, cref))
|
594
|
+
def add_singleton_iseq_method(klass, mid, iseq, cref, outer_ep, pub_meth)
|
595
|
+
add_method(klass, mid, true, ISeqMethodDef.new(iseq, cref, outer_ep, pub_meth))
|
573
596
|
end
|
574
597
|
|
575
598
|
def set_custom_method(klass, mid, impl)
|
@@ -602,6 +625,10 @@ module TypeProf
|
|
602
625
|
@iseq_method_to_ctxs[iseq_mdef] << ctx
|
603
626
|
end
|
604
627
|
|
628
|
+
def add_executed_iseq(iseq)
|
629
|
+
@executed_iseqs << iseq
|
630
|
+
end
|
631
|
+
|
605
632
|
def add_callsite!(callee_ctx, caller_ep, caller_env, &ctn)
|
606
633
|
@executed_iseqs << callee_ctx.iseq if callee_ctx.is_a?(Context)
|
607
634
|
|
@@ -661,8 +688,10 @@ module TypeProf
|
|
661
688
|
def add_read!(site, ep, &ctn)
|
662
689
|
entry = @tbl[site] ||= Entry.new(false, {}, Type.bot, Utils::MutableSet.new)
|
663
690
|
entry.read_continuations[ep] = ctn
|
664
|
-
entry.absolute_paths << ep.ctx.iseq.absolute_path
|
665
|
-
|
691
|
+
entry.absolute_paths << ep.ctx.iseq.absolute_path if ep.ctx.is_a?(Context)
|
692
|
+
ty = entry.type
|
693
|
+
ty = Type.nil if ty == Type.bot
|
694
|
+
ctn[ty, ep]
|
666
695
|
end
|
667
696
|
|
668
697
|
def add_write!(site, ty, ep, scratch)
|
@@ -720,6 +749,7 @@ module TypeProf
|
|
720
749
|
|
721
750
|
def add_cvar_read!(klass, var, ep, &ctn)
|
722
751
|
klass.each_child do |klass|
|
752
|
+
next unless klass.is_a?(Type::Class)
|
723
753
|
class_def = @class_defs[klass.idx]
|
724
754
|
next unless class_def
|
725
755
|
class_def.cvars.add_read!(var, ep, &ctn)
|
@@ -728,6 +758,7 @@ module TypeProf
|
|
728
758
|
|
729
759
|
def add_cvar_write!(klass, var, ty, ep)
|
730
760
|
klass.each_child do |klass|
|
761
|
+
next unless klass.is_a?(Type::Class)
|
731
762
|
class_def = @class_defs[klass.idx]
|
732
763
|
next unless class_def
|
733
764
|
class_def.cvars.add_write!(var, ty, ep, self)
|
@@ -778,7 +809,7 @@ module TypeProf
|
|
778
809
|
merge_return_env(tmp_ep) do |menv|
|
779
810
|
elems = menv.get_container_elem_types(id)
|
780
811
|
elems = yield elems
|
781
|
-
menv = menv.
|
812
|
+
menv = menv.deploy_type(id, elems)
|
782
813
|
gid = @alloc_site_to_global_id[id]
|
783
814
|
if gid
|
784
815
|
ty = globalize_type(elems.to_local_type(id, base_type), env, ep)
|
@@ -790,7 +821,7 @@ module TypeProf
|
|
790
821
|
else
|
791
822
|
elems = env.get_container_elem_types(id)
|
792
823
|
elems = yield elems
|
793
|
-
env = env.
|
824
|
+
env = env.deploy_type(id, elems)
|
794
825
|
gid = @alloc_site_to_global_id[id]
|
795
826
|
if gid
|
796
827
|
ty = globalize_type(elems.to_local_type(id, base_type), env, ep)
|
@@ -831,11 +862,11 @@ module TypeProf
|
|
831
862
|
ep = @worklist.deletemin
|
832
863
|
|
833
864
|
iter_counter += 1
|
834
|
-
if Config.
|
865
|
+
if Config.options[:show_indicator]
|
835
866
|
tick2 = Time.now
|
836
867
|
if tick2 - tick >= 1
|
837
868
|
tick = tick2
|
838
|
-
$stderr << "\rType Profiling... (%d
|
869
|
+
$stderr << "\rType Profiling... (%d instructions @ %s)\e[K" % [iter_counter, ep.source_location]
|
839
870
|
$stderr.flush
|
840
871
|
end
|
841
872
|
end
|
@@ -851,9 +882,7 @@ module TypeProf
|
|
851
882
|
|
852
883
|
break if @terminated
|
853
884
|
|
854
|
-
|
855
|
-
# It should work as a bit smarter "rbs prototype rb";
|
856
|
-
# show all method definitions as "untyped" arguments and return values
|
885
|
+
break unless Config.options[:stub_execution]
|
857
886
|
|
858
887
|
begin
|
859
888
|
iseq, (kind, dummy_continuation) = @pending_execution.first
|
@@ -861,7 +890,7 @@ module TypeProf
|
|
861
890
|
@pending_execution.delete(iseq)
|
862
891
|
end while @executed_iseqs.include?(iseq)
|
863
892
|
|
864
|
-
puts "DEBUG: trigger
|
893
|
+
puts "DEBUG: trigger stub execution (#{ iseq&.name || "(nil)" }): rest #{ @pending_execution.size }" if Config.verbose >= 2
|
865
894
|
|
866
895
|
break if !iseq
|
867
896
|
case kind
|
@@ -878,7 +907,7 @@ module TypeProf
|
|
878
907
|
end
|
879
908
|
end
|
880
909
|
end
|
881
|
-
$stderr.print "\r\e[K" if Config.
|
910
|
+
$stderr.print "\r\e[K" if Config.options[:show_indicator]
|
882
911
|
|
883
912
|
stat_eps
|
884
913
|
end
|
@@ -919,9 +948,9 @@ module TypeProf
|
|
919
948
|
end
|
920
949
|
end
|
921
950
|
|
922
|
-
def pend_method_execution(iseq, meth, recv, mid, cref)
|
951
|
+
def pend_method_execution(iseq, meth, recv, mid, cref, ep)
|
923
952
|
ctx = Context.new(iseq, cref, mid)
|
924
|
-
ep = ExecutionPoint.new(ctx, 0,
|
953
|
+
ep = ExecutionPoint.new(ctx, 0, ep)
|
925
954
|
locals = [Type.nil] * iseq.locals.size
|
926
955
|
|
927
956
|
fargs_format = iseq.fargs_format
|
@@ -956,17 +985,23 @@ module TypeProf
|
|
956
985
|
locals[kwrest_index] = Type.any if kwrest_index
|
957
986
|
locals[block_index] = Type.nil if block_index
|
958
987
|
|
959
|
-
env = Env.new(StaticEnv.new(recv, Type.nil, false), locals, [], Utils::HashWrapper.new({}))
|
988
|
+
env = Env.new(StaticEnv.new(recv, Type.nil, false, true), locals, [], Utils::HashWrapper.new({}))
|
960
989
|
|
961
|
-
|
990
|
+
if !@pending_execution[iseq] || @pending_execution[iseq][0] == :block
|
991
|
+
@pending_execution[iseq] = [:method, [meth, ep, env]]
|
992
|
+
end
|
962
993
|
end
|
963
994
|
|
964
995
|
def pend_block_dummy_execution(blk, iseq, nep, nenv)
|
965
996
|
@pending_execution[iseq] ||= [:block, [blk, {}]]
|
966
|
-
if @pending_execution[iseq][
|
967
|
-
|
997
|
+
if @pending_execution[iseq][0] == :block
|
998
|
+
if @pending_execution[iseq][1][1][nep]
|
999
|
+
@pending_execution[iseq][1][1][nep] = @pending_execution[iseq][1][1][nep].merge(nenv)
|
1000
|
+
else
|
1001
|
+
@pending_execution[iseq][1][1][nep] = nenv
|
1002
|
+
end
|
968
1003
|
else
|
969
|
-
|
1004
|
+
# XXX: what to do?
|
970
1005
|
end
|
971
1006
|
end
|
972
1007
|
|
@@ -975,7 +1010,7 @@ module TypeProf
|
|
975
1010
|
alloc_site = AllocationSite.new(ep)
|
976
1011
|
nenv, ty = localize_type(ty, env, ep, alloc_site)
|
977
1012
|
case ty
|
978
|
-
when Type::
|
1013
|
+
when Type::Local
|
979
1014
|
@alloc_site_to_global_id[ty.id] = [recv, var] # need overwrite check??
|
980
1015
|
end
|
981
1016
|
yield ty, nenv
|
@@ -1015,7 +1050,7 @@ module TypeProf
|
|
1015
1050
|
block_start = iseq.fargs_format[:block_start]
|
1016
1051
|
|
1017
1052
|
lead_tys = env.locals[0, lead_num].map {|ty| globalize_type(ty, env, ep) }
|
1018
|
-
opt_tys = opt.size > 1 ? env.locals[lead_num, opt.size - 1].map {|ty| globalize_type(ty, env, ep) } :
|
1053
|
+
opt_tys = opt.size > 1 ? env.locals[lead_num, opt.size - 1].map {|ty| globalize_type(ty, env, ep) } : []
|
1019
1054
|
if rest_start # XXX:squash
|
1020
1055
|
ty = globalize_type(env.locals[lead_num + opt.size - 1], env, ep)
|
1021
1056
|
rest_ty = Type.bot
|
@@ -1141,31 +1176,7 @@ module TypeProf
|
|
1141
1176
|
|
1142
1177
|
when :definemethod
|
1143
1178
|
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
|
1179
|
+
do_define_iseq_method(ep, env, mid, iseq, nil)
|
1169
1180
|
|
1170
1181
|
when :definesmethod
|
1171
1182
|
mid, iseq = operands
|
@@ -1173,8 +1184,8 @@ module TypeProf
|
|
1173
1184
|
cref = ep.ctx.cref
|
1174
1185
|
recv.each_child do |recv|
|
1175
1186
|
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)
|
1187
|
+
meth = add_singleton_iseq_method(recv, mid, iseq, cref, nil, env.static_env.pub_meth)
|
1188
|
+
pend_method_execution(iseq, meth, recv, mid, ep.ctx.cref, nil)
|
1178
1189
|
else
|
1179
1190
|
recv = Type.any # XXX: what to do?
|
1180
1191
|
end
|
@@ -1210,11 +1221,11 @@ module TypeProf
|
|
1210
1221
|
else # module
|
1211
1222
|
superclass = nil
|
1212
1223
|
end
|
1213
|
-
if cbase
|
1214
|
-
klass =
|
1224
|
+
if cbase.is_a?(Type::Class)
|
1225
|
+
klass = new_class(cbase, id, [], superclass, ep.ctx.iseq.absolute_path)
|
1226
|
+
add_superclass_type_args!(klass, superclass.type_params.map { Type.any }) if superclass
|
1215
1227
|
else
|
1216
|
-
|
1217
|
-
klass = new_class(cbase, id, [], superclass, superclass_type_args, ep.ctx.iseq.absolute_path)
|
1228
|
+
klass = Type.any
|
1218
1229
|
end
|
1219
1230
|
end
|
1220
1231
|
singleton = false
|
@@ -1236,7 +1247,7 @@ module TypeProf
|
|
1236
1247
|
nctx = Context.new(iseq, ncref, nil)
|
1237
1248
|
nep = ExecutionPoint.new(nctx, 0, nil)
|
1238
1249
|
locals = [Type.nil] * iseq.locals.size
|
1239
|
-
nenv = Env.new(StaticEnv.new(recv, blk, false), locals, [], Utils::HashWrapper.new({}))
|
1250
|
+
nenv = Env.new(StaticEnv.new(recv, blk, false, true), locals, [], Utils::HashWrapper.new({}))
|
1240
1251
|
merge_env(nep, nenv)
|
1241
1252
|
add_callsite!(nep.ctx, ep, env) do |ret_ty, ep, env|
|
1242
1253
|
nenv, ret_ty = localize_type(ret_ty, env, ep)
|
@@ -1352,11 +1363,24 @@ module TypeProf
|
|
1352
1363
|
return
|
1353
1364
|
when :break
|
1354
1365
|
tmp_ep = ep
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1366
|
+
while true
|
1367
|
+
if tmp_ep.ctx.iseq.type == :block
|
1368
|
+
tmp_ep = tmp_ep.outer
|
1369
|
+
nenv = @return_envs[tmp_ep].push(ty)
|
1370
|
+
merge_env(tmp_ep.next, nenv)
|
1371
|
+
break
|
1372
|
+
end
|
1373
|
+
_type, _iseq, cont, stack_depth = tmp_ep.ctx.iseq.catch_table[tmp_ep.pc]&.find {|type,| type == :break }
|
1374
|
+
if cont
|
1375
|
+
nenv = @return_envs[tmp_ep]
|
1376
|
+
nenv, = nenv.pop(nenv.stack.size - stack_depth)
|
1377
|
+
nenv = nenv.push(ty)
|
1378
|
+
tmp_ep = tmp_ep.jump(cont)
|
1379
|
+
merge_env(tmp_ep, nenv)
|
1380
|
+
break
|
1381
|
+
end
|
1382
|
+
tmp_ep = tmp_ep.outer
|
1383
|
+
end
|
1360
1384
|
when :next, :redo
|
1361
1385
|
# begin; rescue; next; end
|
1362
1386
|
tmp_ep = ep.outer
|
@@ -1549,9 +1573,7 @@ module TypeProf
|
|
1549
1573
|
ret_ty.each_child do |ret_ty|
|
1550
1574
|
flow_env = env.local_update(-var_idx+2, ret_ty)
|
1551
1575
|
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)
|
1576
|
+
ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::Local)
|
1555
1577
|
if ret_ty.is_a?(Type::Instance)
|
1556
1578
|
if ret_ty.klass == pattern_ty # XXX: inheritance
|
1557
1579
|
merge_env(branchtype == :if ? ep_else : ep_then, flow_env)
|
@@ -1600,7 +1622,7 @@ module TypeProf
|
|
1600
1622
|
warn(ep, "already initialized constant #{ Type::Instance.new(cbase).screen_name(self) }::#{ name }")
|
1601
1623
|
end
|
1602
1624
|
ty.each_child do |ty|
|
1603
|
-
if ty.is_a?(Type::Class) && ty.superclass == Type::Builtin[:struct]
|
1625
|
+
if ty.is_a?(Type::Class) && cbase.is_a?(Type::Class) && ty.superclass == Type::Builtin[:struct]
|
1604
1626
|
@class_defs[ty.idx].name = cbase_path(cbase) + [name]
|
1605
1627
|
end
|
1606
1628
|
end
|
@@ -1609,7 +1631,6 @@ module TypeProf
|
|
1609
1631
|
when :getspecial
|
1610
1632
|
key, type = operands
|
1611
1633
|
if type == 0
|
1612
|
-
raise NotImplementedError
|
1613
1634
|
case key
|
1614
1635
|
when 0 # VM_SVAR_LASTLINE
|
1615
1636
|
env = env.push(Type.any) # or String | NilClass only?
|
@@ -1627,8 +1648,12 @@ module TypeProf
|
|
1627
1648
|
return
|
1628
1649
|
end
|
1629
1650
|
when :setspecial
|
1630
|
-
|
1631
|
-
|
1651
|
+
key, = operands
|
1652
|
+
if key >= 2 # flip-flop
|
1653
|
+
env, = env.pop(1)
|
1654
|
+
else
|
1655
|
+
raise "unknown setspecial key: #{ key }"
|
1656
|
+
end
|
1632
1657
|
|
1633
1658
|
when :dup
|
1634
1659
|
env, (ty,) = env.pop(1)
|
@@ -1679,10 +1704,16 @@ module TypeProf
|
|
1679
1704
|
env = env.push(Type.optional(sym_ty))
|
1680
1705
|
when :checkmatch
|
1681
1706
|
flag, = operands
|
1707
|
+
|
1708
|
+
# This flag means that the stack top is an array, and the check needs to be applied to find all elements
|
1709
|
+
# However, currently TypeProf uses very conservative interpretation (all check returns both true and false),
|
1710
|
+
# so we just ignore the flag now
|
1682
1711
|
_array = flag & 4 != 0
|
1712
|
+
|
1683
1713
|
case flag & 3
|
1684
|
-
when 1
|
1685
|
-
|
1714
|
+
when 1 # VM_CHECKMATCH_TYPE_WHEN
|
1715
|
+
env, = env.pop(2)
|
1716
|
+
env = env.push(Type.bool)
|
1686
1717
|
when 2 # VM_CHECKMATCH_TYPE_CASE
|
1687
1718
|
env, = env.pop(2)
|
1688
1719
|
env = env.push(Type.bool)
|
@@ -1717,9 +1748,13 @@ module TypeProf
|
|
1717
1748
|
from_head = flag & 2 == 0
|
1718
1749
|
ary.each_child do |ary|
|
1719
1750
|
case ary
|
1720
|
-
when Type::
|
1721
|
-
|
1722
|
-
|
1751
|
+
when Type::Local
|
1752
|
+
if ary.kind == Type::Array
|
1753
|
+
elems = get_container_elem_types(env, ep, ary.id)
|
1754
|
+
elems ||= Type::Array::Elements.new([], Type.any) # XXX
|
1755
|
+
else
|
1756
|
+
elems = Type::Array::Elements.new([], Type.any) # XXX
|
1757
|
+
end
|
1723
1758
|
do_expand_array(ep, env, elems, num, splat, from_head)
|
1724
1759
|
when Type::Any
|
1725
1760
|
nnum = num
|
@@ -1739,9 +1774,9 @@ module TypeProf
|
|
1739
1774
|
return
|
1740
1775
|
when :concatarray
|
1741
1776
|
env, (ary1, ary2) = env.pop(2)
|
1742
|
-
if ary1.is_a?(Type::
|
1777
|
+
if ary1.is_a?(Type::Local) && ary1.kind == Type::Array
|
1743
1778
|
elems1 = get_container_elem_types(env, ep, ary1.id)
|
1744
|
-
if ary2.is_a?(Type::
|
1779
|
+
if ary2.is_a?(Type::Local) && ary2.kind == Type::Array
|
1745
1780
|
elems2 = get_container_elem_types(env, ep, ary2.id)
|
1746
1781
|
elems = Type::Array::Elements.new([], elems1.squash.union(elems2.squash))
|
1747
1782
|
env = update_container_elem_types(env, ep, ary1.id, ary1.base_type) { elems }
|
@@ -1888,6 +1923,10 @@ module TypeProf
|
|
1888
1923
|
rest_ty = aargs.last
|
1889
1924
|
aargs = aargs[0..-2]
|
1890
1925
|
if flag_args_kw_splat
|
1926
|
+
# XXX: The types contained in ActualArguments are expected to be all local types.
|
1927
|
+
# This "globalize_type" breaks the invariant, and violates the assertion of Union#globalize that asserts @elems be nil.
|
1928
|
+
# To fix this issue fundamentally, ActualArguments should keep all arguments as-is (as like the VM does),
|
1929
|
+
# and globalize some types on the on-demand bases.
|
1891
1930
|
ty = globalize_type(rest_ty, env, ep)
|
1892
1931
|
if ty.is_a?(Type::Array)
|
1893
1932
|
_, (ty,) = ty.elems.take_last(1)
|
@@ -1920,6 +1959,10 @@ module TypeProf
|
|
1920
1959
|
aargs = ActualArguments.new(aargs, rest_ty, kw_tys, blk_ty)
|
1921
1960
|
elsif flag_args_kw_splat
|
1922
1961
|
last = aargs.last
|
1962
|
+
# XXX: The types contained in ActualArguments are expected to be all local types.
|
1963
|
+
# This "globalize_type" breaks the invariant, and violates the assertion of Union#globalize that asserts @elems be nil.
|
1964
|
+
# To fix this issue fundamentally, ActualArguments should keep all arguments as-is (as like the VM does),
|
1965
|
+
# and globalize some types on the on-demand bases.
|
1923
1966
|
ty = globalize_type(last, env, ep)
|
1924
1967
|
case ty
|
1925
1968
|
when Type::Hash
|
@@ -1963,7 +2006,7 @@ module TypeProf
|
|
1963
2006
|
nctx = Context.new(blk_iseq, ep.ctx.cref, ep.ctx.mid)
|
1964
2007
|
nep = ExecutionPoint.new(nctx, 0, ep)
|
1965
2008
|
nlocals = [Type.any] * blk_iseq.locals.size
|
1966
|
-
nsenv = StaticEnv.new(env.static_env.recv_ty, Type.any, env.static_env.mod_func)
|
2009
|
+
nsenv = StaticEnv.new(env.static_env.recv_ty, Type.any, env.static_env.mod_func, env.static_env.pub_meth)
|
1967
2010
|
nenv = Env.new(nsenv, nlocals, [], nil)
|
1968
2011
|
pend_block_dummy_execution(blk_ty, blk_iseq, nep, nenv)
|
1969
2012
|
merge_return_env(ep) {|tenv| tenv ? tenv.merge(env) : env }
|
@@ -1973,21 +2016,31 @@ module TypeProf
|
|
1973
2016
|
end
|
1974
2017
|
|
1975
2018
|
def do_send(recv, mid, aargs, ep, env, &ctn)
|
1976
|
-
|
1977
|
-
|
1978
|
-
|
1979
|
-
|
1980
|
-
|
1981
|
-
|
2019
|
+
case recv
|
2020
|
+
when Type::Void
|
2021
|
+
error(ep, "void's method is called: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
|
2022
|
+
ctn[Type.any, ep, env]
|
2023
|
+
when Type::Any
|
2024
|
+
ctn[Type.any, ep, env]
|
1982
2025
|
else
|
1983
|
-
|
1984
|
-
|
1985
|
-
|
1986
|
-
|
2026
|
+
klass, singleton = recv.method_dispatch_info
|
2027
|
+
meths = get_method(klass, singleton, mid) if klass
|
2028
|
+
if meths
|
2029
|
+
meths.each do |meth|
|
2030
|
+
meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
|
2031
|
+
end
|
1987
2032
|
else
|
1988
|
-
|
2033
|
+
meths = get_method(klass, singleton, :method_missing) if klass
|
2034
|
+
if meths
|
2035
|
+
aargs = aargs.for_method_missing(Type::Symbol.new(mid, Type::Instance.new(Type::Builtin[:sym])))
|
2036
|
+
meths.each do |meth|
|
2037
|
+
meth.do_send(recv, :method_missing, aargs, ep, env, self, &ctn)
|
2038
|
+
end
|
2039
|
+
else
|
2040
|
+
error(ep, "undefined method: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
|
2041
|
+
ctn[Type.any, ep, env]
|
2042
|
+
end
|
1989
2043
|
end
|
1990
|
-
ctn[Type.any, ep, env]
|
1991
2044
|
end
|
1992
2045
|
end
|
1993
2046
|
|
@@ -2002,6 +2055,34 @@ module TypeProf
|
|
2002
2055
|
end
|
2003
2056
|
end
|
2004
2057
|
|
2058
|
+
def do_define_iseq_method(ep, env, mid, iseq, outer_ep)
|
2059
|
+
cref = ep.ctx.cref
|
2060
|
+
if cref.klass.is_a?(Type::Class)
|
2061
|
+
typed_mdef = check_typed_method(cref.klass, mid, ep.ctx.cref.singleton)
|
2062
|
+
recv = cref.klass
|
2063
|
+
recv = Type::Instance.new(recv) unless ep.ctx.cref.singleton
|
2064
|
+
if typed_mdef
|
2065
|
+
mdef = ISeqMethodDef.new(iseq, cref, outer_ep, env.static_env.pub_meth)
|
2066
|
+
typed_mdef.each do |typed_mdef|
|
2067
|
+
typed_mdef.do_match_iseq_mdef(mdef, recv, mid, env, ep, self)
|
2068
|
+
end
|
2069
|
+
else
|
2070
|
+
if ep.ctx.cref.singleton
|
2071
|
+
meth = add_singleton_iseq_method(cref.klass, mid, iseq, cref, outer_ep, true)
|
2072
|
+
else
|
2073
|
+
meth = add_iseq_method(cref.klass, mid, iseq, cref, outer_ep, env.static_env.pub_meth)
|
2074
|
+
if env.static_env.mod_func
|
2075
|
+
add_singleton_iseq_method(cref.klass, mid, iseq, cref, outer_ep, true)
|
2076
|
+
end
|
2077
|
+
end
|
2078
|
+
end
|
2079
|
+
|
2080
|
+
pend_method_execution(iseq, meth, recv, mid, ep.ctx.cref, outer_ep)
|
2081
|
+
else
|
2082
|
+
# XXX: what to do?
|
2083
|
+
end
|
2084
|
+
end
|
2085
|
+
|
2005
2086
|
def show_block_signature(blks)
|
2006
2087
|
bsig = nil
|
2007
2088
|
ret_ty = Type.bot
|
@@ -2042,7 +2123,7 @@ module TypeProf
|
|
2042
2123
|
next unless @block_to_ctx[blk.block_body] # this occurs when screen_name is called before type-profiling finished (e.g., error message)
|
2043
2124
|
@block_to_ctx[blk.block_body].each do |blk_ctx|
|
2044
2125
|
if farg_tys
|
2045
|
-
farg_tys = farg_tys.
|
2126
|
+
farg_tys = farg_tys.merge_as_block_arguments(@method_signatures[blk_ctx])
|
2046
2127
|
else
|
2047
2128
|
farg_tys = @method_signatures[blk_ctx]
|
2048
2129
|
end
|