typeprof 0.1.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.
Files changed (218) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +26 -0
  3. data/.gitignore +7 -0
  4. data/.gitmodules +6 -0
  5. data/Gemfile +12 -0
  6. data/Gemfile.lock +41 -0
  7. data/README.md +53 -0
  8. data/Rakefile +10 -0
  9. data/doc/doc.ja.md +415 -0
  10. data/doc/doc.md +429 -0
  11. data/doc/ppl2019.pdf +0 -0
  12. data/exe/typeprof +5 -0
  13. data/lib/typeprof.rb +13 -0
  14. data/lib/typeprof/analyzer.rb +1911 -0
  15. data/lib/typeprof/builtin.rb +554 -0
  16. data/lib/typeprof/cli.rb +110 -0
  17. data/lib/typeprof/container-type.rb +626 -0
  18. data/lib/typeprof/export.rb +203 -0
  19. data/lib/typeprof/import.rb +546 -0
  20. data/lib/typeprof/insns-def.rb +61 -0
  21. data/lib/typeprof/iseq.rb +387 -0
  22. data/lib/typeprof/method.rb +267 -0
  23. data/lib/typeprof/type.rb +1092 -0
  24. data/lib/typeprof/utils.rb +209 -0
  25. data/run.sh +3 -0
  26. data/smoke/alias.rb +30 -0
  27. data/smoke/alias2.rb +19 -0
  28. data/smoke/any-cbase.rb +5 -0
  29. data/smoke/any1.rb +15 -0
  30. data/smoke/any2.rb +17 -0
  31. data/smoke/arguments.rb +16 -0
  32. data/smoke/array-each.rb +14 -0
  33. data/smoke/array-each2.rb +15 -0
  34. data/smoke/array-each3.rb +15 -0
  35. data/smoke/array-ltlt.rb +13 -0
  36. data/smoke/array-ltlt2.rb +16 -0
  37. data/smoke/array-map.rb +11 -0
  38. data/smoke/array-map2.rb +10 -0
  39. data/smoke/array-map3.rb +22 -0
  40. data/smoke/array-mul.rb +17 -0
  41. data/smoke/array-plus1.rb +10 -0
  42. data/smoke/array-plus2.rb +15 -0
  43. data/smoke/array-pop.rb +11 -0
  44. data/smoke/array-replace.rb +12 -0
  45. data/smoke/array-s-aref.rb +11 -0
  46. data/smoke/array1.rb +26 -0
  47. data/smoke/array10.rb +14 -0
  48. data/smoke/array11.rb +13 -0
  49. data/smoke/array12.rb +24 -0
  50. data/smoke/array13.rb +30 -0
  51. data/smoke/array14.rb +13 -0
  52. data/smoke/array2.rb +27 -0
  53. data/smoke/array3.rb +25 -0
  54. data/smoke/array4.rb +14 -0
  55. data/smoke/array5.rb +13 -0
  56. data/smoke/array6.rb +14 -0
  57. data/smoke/array7.rb +13 -0
  58. data/smoke/array8.rb +13 -0
  59. data/smoke/array9.rb +12 -0
  60. data/smoke/attr.rb +28 -0
  61. data/smoke/backtrace.rb +32 -0
  62. data/smoke/block1.rb +22 -0
  63. data/smoke/block10.rb +14 -0
  64. data/smoke/block11.rb +39 -0
  65. data/smoke/block12.rb +22 -0
  66. data/smoke/block2.rb +14 -0
  67. data/smoke/block3.rb +38 -0
  68. data/smoke/block4.rb +18 -0
  69. data/smoke/block5.rb +18 -0
  70. data/smoke/block6.rb +20 -0
  71. data/smoke/block7.rb +20 -0
  72. data/smoke/block8.rb +27 -0
  73. data/smoke/block9.rb +12 -0
  74. data/smoke/blown.rb +12 -0
  75. data/smoke/break1.rb +18 -0
  76. data/smoke/break2.rb +15 -0
  77. data/smoke/case.rb +16 -0
  78. data/smoke/case2.rb +17 -0
  79. data/smoke/class.rb +5 -0
  80. data/smoke/class_instance_var.rb +9 -0
  81. data/smoke/class_method.rb +25 -0
  82. data/smoke/class_method2.rb +21 -0
  83. data/smoke/class_method3.rb +27 -0
  84. data/smoke/constant1.rb +38 -0
  85. data/smoke/constant2.rb +33 -0
  86. data/smoke/constant3.rb +9 -0
  87. data/smoke/constant4.rb +11 -0
  88. data/smoke/context-sensitive1.rb +12 -0
  89. data/smoke/cvar.rb +28 -0
  90. data/smoke/cvar2.rb +17 -0
  91. data/smoke/demo.rb +80 -0
  92. data/smoke/demo1.rb +16 -0
  93. data/smoke/demo10.rb +20 -0
  94. data/smoke/demo11.rb +11 -0
  95. data/smoke/demo2.rb +14 -0
  96. data/smoke/demo3.rb +16 -0
  97. data/smoke/demo4.rb +27 -0
  98. data/smoke/demo5.rb +13 -0
  99. data/smoke/demo6.rb +21 -0
  100. data/smoke/demo7.rb +14 -0
  101. data/smoke/demo8.rb +18 -0
  102. data/smoke/demo9.rb +18 -0
  103. data/smoke/dummy-execution1.rb +14 -0
  104. data/smoke/dummy-execution2.rb +16 -0
  105. data/smoke/ensure1.rb +20 -0
  106. data/smoke/enumerator.rb +15 -0
  107. data/smoke/expandarray1.rb +22 -0
  108. data/smoke/expandarray2.rb +23 -0
  109. data/smoke/fib.rb +28 -0
  110. data/smoke/flow1.rb +16 -0
  111. data/smoke/flow2.rb +14 -0
  112. data/smoke/flow3.rb +14 -0
  113. data/smoke/flow4.rb +5 -0
  114. data/smoke/flow5.rb +19 -0
  115. data/smoke/flow6.rb +19 -0
  116. data/smoke/flow7.rb +26 -0
  117. data/smoke/for.rb +9 -0
  118. data/smoke/freeze.rb +11 -0
  119. data/smoke/function.rb +16 -0
  120. data/smoke/gvar.rb +13 -0
  121. data/smoke/hash-fetch.rb +27 -0
  122. data/smoke/hash1.rb +18 -0
  123. data/smoke/hash2.rb +12 -0
  124. data/smoke/hash3.rb +13 -0
  125. data/smoke/hash4.rb +10 -0
  126. data/smoke/hash5.rb +14 -0
  127. data/smoke/inheritance.rb +34 -0
  128. data/smoke/inheritance2.rb +29 -0
  129. data/smoke/initialize.rb +26 -0
  130. data/smoke/instance_eval.rb +18 -0
  131. data/smoke/int_times.rb +14 -0
  132. data/smoke/integer.rb +10 -0
  133. data/smoke/ivar.rb +29 -0
  134. data/smoke/ivar2.rb +30 -0
  135. data/smoke/kernel-class.rb +12 -0
  136. data/smoke/keyword1.rb +11 -0
  137. data/smoke/keyword2.rb +11 -0
  138. data/smoke/keyword3.rb +12 -0
  139. data/smoke/keyword4.rb +11 -0
  140. data/smoke/keyword5.rb +15 -0
  141. data/smoke/kwsplat1.rb +42 -0
  142. data/smoke/kwsplat2.rb +12 -0
  143. data/smoke/manual-rbs.rb +27 -0
  144. data/smoke/manual-rbs.rbs +3 -0
  145. data/smoke/manual-rbs2.rb +20 -0
  146. data/smoke/manual-rbs2.rbs +8 -0
  147. data/smoke/masgn1.rb +13 -0
  148. data/smoke/masgn2.rb +17 -0
  149. data/smoke/masgn3.rb +12 -0
  150. data/smoke/method_in_branch.rb +22 -0
  151. data/smoke/module1.rb +29 -0
  152. data/smoke/module2.rb +28 -0
  153. data/smoke/module3.rb +33 -0
  154. data/smoke/module4.rb +29 -0
  155. data/smoke/module_function1.rb +28 -0
  156. data/smoke/module_function2.rb +28 -0
  157. data/smoke/multiple-include.rb +14 -0
  158. data/smoke/multiple-superclass.rb +16 -0
  159. data/smoke/next1.rb +20 -0
  160. data/smoke/next2.rb +16 -0
  161. data/smoke/object-send1.rb +22 -0
  162. data/smoke/once.rb +12 -0
  163. data/smoke/optional1.rb +13 -0
  164. data/smoke/optional2.rb +15 -0
  165. data/smoke/parameterizedd-self.rb +18 -0
  166. data/smoke/pathname1.rb +13 -0
  167. data/smoke/pathname2.rb +13 -0
  168. data/smoke/printf.rb +20 -0
  169. data/smoke/proc.rb +19 -0
  170. data/smoke/proc2.rb +16 -0
  171. data/smoke/proc3.rb +14 -0
  172. data/smoke/proc4.rb +11 -0
  173. data/smoke/range.rb +13 -0
  174. data/smoke/redo1.rb +21 -0
  175. data/smoke/redo2.rb +22 -0
  176. data/smoke/req-keyword.rb +12 -0
  177. data/smoke/rescue1.rb +20 -0
  178. data/smoke/rescue2.rb +22 -0
  179. data/smoke/respond_to.rb +22 -0
  180. data/smoke/rest-farg.rb +10 -0
  181. data/smoke/rest1.rb +25 -0
  182. data/smoke/rest2.rb +30 -0
  183. data/smoke/rest3.rb +36 -0
  184. data/smoke/rest4.rb +18 -0
  185. data/smoke/rest5.rb +10 -0
  186. data/smoke/rest6.rb +11 -0
  187. data/smoke/retry1.rb +20 -0
  188. data/smoke/return.rb +13 -0
  189. data/smoke/reveal.rb +13 -0
  190. data/smoke/singleton_class.rb +8 -0
  191. data/smoke/singleton_method.rb +9 -0
  192. data/smoke/step.rb +17 -0
  193. data/smoke/string-split.rb +11 -0
  194. data/smoke/struct.rb +9 -0
  195. data/smoke/struct2.rb +24 -0
  196. data/smoke/super1.rb +50 -0
  197. data/smoke/super2.rb +16 -0
  198. data/smoke/super3.rb +19 -0
  199. data/smoke/svar1.rb +12 -0
  200. data/smoke/tap1.rb +17 -0
  201. data/smoke/toplevel.rb +12 -0
  202. data/smoke/two-map.rb +17 -0
  203. data/smoke/type_var.rb +10 -0
  204. data/smoke/typed_method.rb +15 -0
  205. data/smoke/union-recv.rb +29 -0
  206. data/smoke/variadic1.rb.notyet +5 -0
  207. data/smoke/wrong-extend.rb +25 -0
  208. data/smoke/wrong-include.rb +26 -0
  209. data/smoke/wrong-rbs.rb +15 -0
  210. data/smoke/wrong-rbs.rbs +7 -0
  211. data/testbed/ao.rb +297 -0
  212. data/testbed/diff-lcs-entrypoint.rb +4 -0
  213. data/testbed/goodcheck-Gemfile.lock +51 -0
  214. data/tools/coverage.rb +14 -0
  215. data/tools/setup-insns-def.rb +30 -0
  216. data/tools/stackprof-wrapper.rb +10 -0
  217. data/typeprof.gemspec +24 -0
  218. metadata +262 -0
@@ -0,0 +1,209 @@
1
+ module TypeProf
2
+ module Utils
3
+ def self.array_update(ary, idx, elem)
4
+ idx %= ary.size
5
+ ary[0...idx] + [elem] + ary[idx+1..-1]
6
+ end
7
+
8
+ module StructuralEquality
9
+ def hash
10
+ @_hash ||=
11
+ begin
12
+ h = 0
13
+ instance_variables.each do |v|
14
+ h ^= instance_variable_get(v).hash if v != :@_hash
15
+ end
16
+ h
17
+ end
18
+ end
19
+
20
+ TABLE = {}
21
+
22
+ def self.included(klass)
23
+ def klass.new(*args)
24
+ (TABLE[self] ||= {})[args] ||= super
25
+ end
26
+ class << klass
27
+ ruby2_keywords :new
28
+ end
29
+ end
30
+ end
31
+
32
+ class Set
33
+ include StructuralEquality
34
+
35
+ attr_reader :tbl
36
+
37
+ def self.[](*values)
38
+ tbl = {}
39
+ values.each do |v|
40
+ tbl[v] = true
41
+ end
42
+ new(tbl)
43
+ end
44
+
45
+ def initialize(tbl)
46
+ @tbl = tbl
47
+ @tbl.freeze
48
+ end
49
+
50
+ def each(&blk)
51
+ @tbl.each_key(&blk)
52
+ end
53
+
54
+ include Enumerable
55
+
56
+ def sum(other)
57
+ if @tbl.size == 0
58
+ other
59
+ elsif other.tbl.size == 0
60
+ self
61
+ else
62
+ Set.new(@tbl.merge(other.tbl))
63
+ end
64
+ end
65
+
66
+ def add(new_val)
67
+ tbl = @tbl.dup
68
+ tbl[new_val] = true
69
+ Set.new(tbl)
70
+ end
71
+
72
+ def size
73
+ @tbl.size
74
+ end
75
+
76
+ def map(&blk)
77
+ tbl = {}
78
+ each do |elem|
79
+ v = yield(elem)
80
+ tbl[v] = true
81
+ end
82
+ Set.new(tbl)
83
+ end
84
+
85
+ def inspect
86
+ s = []
87
+ each {|v| s << v.inspect }
88
+ "{#{ s.join(", ") }}"
89
+ end
90
+
91
+ def include?(elem)
92
+ @tbl[elem]
93
+ end
94
+
95
+ def intersection(other)
96
+ tbl = {}
97
+ h = 0
98
+ each do |elem|
99
+ if other.include?(elem)
100
+ tbl << elem
101
+ h ^= elem.hash
102
+ end
103
+ end
104
+ Set.new(tbl, h)
105
+ end
106
+ end
107
+
108
+ class MutableSet
109
+ def initialize(*values)
110
+ @hash = {}
111
+ values.each {|v| @hash[v] = v }
112
+ end
113
+
114
+ def each(&blk)
115
+ @hash.each_key(&blk)
116
+ end
117
+
118
+ include Enumerable
119
+
120
+ def <<(v)
121
+ @hash[v] = true
122
+ end
123
+
124
+ def [](v)
125
+ @hash[v]
126
+ end
127
+
128
+ def delete(v)
129
+ @hash.delete(v)
130
+ end
131
+
132
+ def inspect
133
+ s = []
134
+ each {|v| s << v.inspect }
135
+ "{#{ s.join(", ") }}"
136
+ end
137
+
138
+ def size
139
+ @hash.size
140
+ end
141
+
142
+ def to_set
143
+ Set[*@hash.keys]
144
+ end
145
+ end
146
+
147
+ class HashWrapper
148
+ include StructuralEquality
149
+
150
+ def initialize(hash)
151
+ @internal_hash = hash.freeze
152
+ end
153
+
154
+ attr_reader :internal_hash
155
+ end
156
+
157
+ class WorkList
158
+ def initialize
159
+ @heap = []
160
+ @set = MutableSet.new
161
+ end
162
+
163
+ def insert(key, val)
164
+ i = @heap.size
165
+ @heap << [key, val]
166
+ while i > 0 && (@heap[i][0] <=> @heap[i / 2][0]) < 0
167
+ @heap[i], @heap[i / 2] = @heap[i / 2], @heap[i]
168
+ i /= 2
169
+ end
170
+ @set << val
171
+ end
172
+
173
+ def member?(val)
174
+ @set[val]
175
+ end
176
+
177
+ def deletemin
178
+ return nil if @heap.empty?
179
+ val = @heap[0][1]
180
+ @set.delete(val)
181
+ if @heap.size == 1
182
+ @heap.pop
183
+ return val
184
+ end
185
+ @heap[0] = @heap.pop
186
+ i = 0
187
+ while (j = i * 2 + 1) < @heap.size
188
+ j += 1 if j + 1 < @heap.size && (@heap[j][0] <=> @heap[j + 1][0]) >= 0
189
+ break if (@heap[i][0] <=> @heap[j][0]) < 0
190
+ @heap[i], @heap[j] = @heap[j], @heap[i]
191
+ i = j
192
+ end
193
+ return val
194
+ end
195
+
196
+ def size
197
+ @heap.size
198
+ end
199
+
200
+ def empty?
201
+ @heap.empty?
202
+ end
203
+
204
+ def inspect
205
+ "#<#{ self.class }:#{ @heap.map {|_key, val| val }.inspect }>"
206
+ end
207
+ end
208
+ end
209
+ end
data/run.sh ADDED
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ bundle exe ruby exe/type-profiler $@
@@ -0,0 +1,30 @@
1
+ def foo(x)
2
+ x
3
+ end
4
+
5
+ alias bar foo
6
+
7
+ class Test
8
+ def baz(x)
9
+ x
10
+ end
11
+
12
+ alias qux baz
13
+ end
14
+
15
+ foo(1)
16
+ bar("str")
17
+ Test.new.baz(1)
18
+ Test.new.qux("str")
19
+
20
+ __END__
21
+ # Classes
22
+ class Object
23
+ def foo : (Integer) -> Integer
24
+ def bar : (String) -> String
25
+ end
26
+
27
+ class Test
28
+ def baz : (Integer) -> Integer
29
+ def qux : (String) -> String
30
+ end
@@ -0,0 +1,19 @@
1
+ class Foo
2
+ class << self
3
+ alias [] new
4
+ end
5
+
6
+ def initialize(a, b, c)
7
+ @a, @b, @c = a, b, c
8
+ end
9
+ end
10
+
11
+ Foo[:x, :y, :z]
12
+ __END__
13
+ # Classes
14
+ class Foo
15
+ @a : :x
16
+ @b : :y
17
+ @c : :z
18
+ def initialize : (:x, :y, :z) -> [:x, :y, :z]
19
+ end
@@ -0,0 +1,5 @@
1
+ class Unknown::Foo
2
+ end
3
+
4
+ __END__
5
+ # Classes
@@ -0,0 +1,15 @@
1
+ def foo
2
+ x = 1.undefined_method
3
+ x.undefined_method2
4
+ end
5
+
6
+ foo
7
+
8
+ __END__
9
+ # Errors
10
+ smoke/any1.rb:2: [error] undefined method: Integer#undefined_method
11
+
12
+ # Classes
13
+ class Object
14
+ def foo : -> untyped
15
+ end
@@ -0,0 +1,17 @@
1
+ def foo
2
+ yield
3
+ end
4
+ def bar
5
+ yield
6
+ 1
7
+ end
8
+
9
+ foo
10
+ bar
11
+
12
+ __END__
13
+ # Classes
14
+ class Object
15
+ def foo : -> untyped
16
+ def bar : -> Integer
17
+ end
@@ -0,0 +1,16 @@
1
+ def foo(x)
2
+ end
3
+ def bar(x)
4
+ end
5
+
6
+ bar(foo(1, 2))
7
+
8
+ __END__
9
+ # Errors
10
+ smoke/arguments.rb:6: [error] wrong number of arguments (given 2, expected 1)
11
+
12
+ # Classes
13
+ class Object
14
+ def foo : (untyped) -> nil
15
+ def bar : (untyped) -> nil
16
+ end
@@ -0,0 +1,14 @@
1
+ def log(x)
2
+ end
3
+
4
+ [1, "str", :sym].each do |x|
5
+ log(x)
6
+ end
7
+
8
+ log(nil)
9
+
10
+ __END__
11
+ # Classes
12
+ class Object
13
+ def log : ((:sym | Integer | String)?) -> nil
14
+ end
@@ -0,0 +1,15 @@
1
+ def foo
2
+ x = nil
3
+ [1, "str"].each do |y|
4
+ x = y
5
+ end
6
+ x
7
+ end
8
+
9
+ foo
10
+
11
+ __END__
12
+ # Classes
13
+ class Object
14
+ def foo : -> ((Integer | String)?)
15
+ end
@@ -0,0 +1,15 @@
1
+ def log(x)
2
+ end
3
+
4
+ [].each do |x|
5
+ # Currently, x is bot. But, [].each is rarely useful.
6
+ # It would be a good guess to assume a empty receiver of Array#each means a wrong guess.
7
+ # So, it would be good to assume x as any
8
+ log(x)
9
+ end
10
+
11
+ __END__
12
+ # Classes
13
+ class Object
14
+ def log : (bot) -> nil
15
+ end
@@ -0,0 +1,13 @@
1
+ def foo
2
+ a = []
3
+ a << 1
4
+ a << "str"
5
+ a
6
+ end
7
+
8
+ foo
9
+ __END__
10
+ # Classes
11
+ class Object
12
+ def foo : -> (Array[Integer | String])
13
+ end
@@ -0,0 +1,16 @@
1
+ def foo
2
+ a = []
3
+ while true
4
+ a << 1
5
+ a << "str"
6
+ break if rand < 0.5
7
+ end
8
+ a
9
+ end
10
+
11
+ foo
12
+ __END__
13
+ # Classes
14
+ class Object
15
+ def foo : -> (Array[Integer | String])
16
+ end
@@ -0,0 +1,11 @@
1
+ def foo(a)
2
+ a.map {|n| n.to_s }
3
+ end
4
+
5
+ foo([1, 2, 3])
6
+
7
+ __END__
8
+ # Classes
9
+ class Object
10
+ def foo : ([Integer, Integer, Integer]) -> Array[String]
11
+ end
@@ -0,0 +1,10 @@
1
+ def foo(a)
2
+ a.map {|n| rand < 0.5 ? n.to_s : n }
3
+ end
4
+
5
+ foo([1, 2, 3])
6
+ __END__
7
+ # Classes
8
+ class Object
9
+ def foo : ([Integer, Integer, Integer]) -> (Array[Integer | String])
10
+ end
@@ -0,0 +1,22 @@
1
+ def map_test(a)
2
+ a.map {|n| n.to_s }
3
+ end
4
+ def map_bang_test(a)
5
+ a.map! {|n| n.to_s }
6
+ a
7
+ end
8
+ def map_bang_test_known_bug(a)
9
+ a.map! {|n| n.to_s }
10
+ end
11
+
12
+ map_test([1, 2, 3])
13
+ map_bang_test([1, 2, 3])
14
+ map_bang_test_known_bug([1, 2, 3])
15
+
16
+ __END__
17
+ # Classes
18
+ class Object
19
+ def map_test : ([Integer, Integer, Integer]) -> Array[String]
20
+ def map_bang_test : ([Integer, Integer, Integer]) -> (Array[Integer | String])
21
+ def map_bang_test_known_bug : ([Integer, Integer, Integer]) -> [Integer, Integer, Integer]
22
+ end