typeprof 0.20.3 → 0.20.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ee0445d195b9ab48538b37afc382d3b48d74c4fd9c5628010a3ac5084349259
4
- data.tar.gz: 183309d5b70590396a7b0eec078b1b980b5e38877d5d756e66e03acefb971055
3
+ metadata.gz: 20dc7384f6e6cdbfd5d698a0fc91f3d4ed4a45eba3433bfa5fd9a372f24361e6
4
+ data.tar.gz: 5f5bf30af6e23ee8a3eb4afe77e6bb7cadeb87335a2ba40a309433c88341b114
5
5
  SHA512:
6
- metadata.gz: 2b43a67c81128f11a34bd3d9aeecad1763e3baf7a8498e68c411fa652579213519956a6ff4d301873b8d9291d1ce89f1c1e33f0379846df620118d47b42add0f
7
- data.tar.gz: e1768b62ac2fe976fb94abe2fbf41656002f80e8016cd8c5e634a44770a4a8eeafb1e50bc5003a774d84621a5c14fbad9fef4eb40c9c383b9b48bee74ca05907
6
+ metadata.gz: 6d1f9adf368ceaebf9ece57f50be445d9fad60c2a7f447b3a3dc6b3ff710c05cd9a59ea27dd76d620843159a28bd912c0bd78b10d02c96bfe68af1fe691b7b46
7
+ data.tar.gz: 277fca4264f3df16e3de7742e6e8c44fe42badc7d2dba7ff3fb07a8bce2eebe954e0f2e10ee570a3bf172b86fd77ecd1d39118f70eed0a1079a0e34976c94a2c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- typeprof (0.20.3)
4
+ typeprof (0.20.4)
5
5
  rbs (>= 1.6.2)
6
6
 
7
7
  GEM
@@ -1393,7 +1393,7 @@ module TypeProf
1393
1393
  num, = operands
1394
1394
  env, = env.pop(num)
1395
1395
  env = env.push(Type::Instance.new(Type::Builtin[:str]))
1396
- when :tostring, :anytostring
1396
+ when :tostring, :objtostring, :anytostring
1397
1397
  env, (_ty1, _ty2,) = env.pop(2)
1398
1398
  env = env.push(Type::Instance.new(Type::Builtin[:str]))
1399
1399
  when :freezestring
@@ -21,6 +21,7 @@ TypeProf::INSN_TABLE = {:nop=>[],
21
21
  :putstring=>["VALUE"],
22
22
  :concatstrings=>["rb_num_t"],
23
23
  :tostring=>[],
24
+ :objtostring=>[],
24
25
  :anytostring=>[],
25
26
  :freezestring=>["VALUE"],
26
27
  :toregexp=>["rb_num_t", "rb_num_t"],
data/lib/typeprof/iseq.rb CHANGED
@@ -704,7 +704,7 @@ module TypeProf
704
704
  sp += 1
705
705
  when :newhashfromarray
706
706
  raise NotImplementedError, "newhashfromarray"
707
- when :newrange, :tostring, :anytostring
707
+ when :newrange, :tostring, :objtostring, :anytostring
708
708
  sp -= 2
709
709
  return nil if sp <= 0
710
710
  sp += 1
@@ -1,3 +1,3 @@
1
1
  module TypeProf
2
- VERSION = "0.20.3"
2
+ VERSION = "0.20.4"
3
3
  end
data/typeprof.gemspec CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
  # Specify which files should be added to the gem when it is released.
25
25
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
26
26
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
27
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|smoke|testbed)/}) }
27
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(doc|test|spec|features|smoke|testbed)/}) }
28
28
  end
29
29
  spec.bindir = "exe"
30
30
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typeprof
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.3
4
+ version: 0.20.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yusuke Endoh
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-11 00:00:00.000000000 Z
11
+ date: 2021-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbs
@@ -44,14 +44,6 @@ files:
44
44
  - LICENSE
45
45
  - README.md
46
46
  - Rakefile
47
- - doc/demo.md
48
- - doc/doc.ja.md
49
- - doc/doc.md
50
- - doc/ide.md
51
- - doc/ppl2019.pdf
52
- - doc/todo.md
53
- - doc/typeprof-for-ide-log.png
54
- - doc/typeprof-for-ide.png
55
47
  - exe/typeprof
56
48
  - lib/typeprof.rb
57
49
  - lib/typeprof/analyzer.rb
data/doc/demo.md DELETED
@@ -1,398 +0,0 @@
1
- # TypeProf demo cases
2
-
3
- ## A simple demo with a "User" class
4
-
5
- ```ruby
6
- def hello_message(user)
7
- "The name is " + user.name
8
- end
9
-
10
- def type_error_demo(user)
11
- "The age is " + user.age
12
- end
13
-
14
- user = User.new(name: "John", age: 20)
15
-
16
- hello_message(user)
17
- type_error_demo(user)
18
- ```
19
-
20
- ```ruby
21
- class User
22
- attr_reader name: String
23
- attr_reader age: Integer
24
-
25
- def initialize: (name: String, age: Integer) -> void
26
- end
27
- ```
28
-
29
- Result:
30
- ```
31
- $ typeprof test.rb test.rbs
32
- # Errors
33
- test.rb:6: [error] failed to resolve overload: String#+
34
-
35
- # Classes
36
- class Object
37
- def hello_message : (User) -> String
38
- def type_error_demo : (User) -> untyped
39
- end
40
- ```
41
-
42
- You can [try this analysis online](https://mame.github.io/typeprof-playground/#rb=def+hello_message%28user%29%0A++%22The+name+is+%22+%2B+user.name%0Aend%0A%0Adef+type_error_demo%28user%29%0A++%22The+age+is+%22+%2B+user.age%0Aend%0A%0Auser+%3D+User.new%28name%3A+%22John%22%2C+age%3A+20%29%0A%0Ahello_message%28user%29%0Atype_error_demo%28user%29&rbs=class+User%0A++attr_reader+name%3A+String%0A++attr_reader+age%3A+Integer%0A%0A++def+initialize%3A+%28name%3A+String%2C+age%3A+Integer%29+-%3E+void%0Aend).
43
-
44
- ## A simple demo to generate the signature prototype of "User" class
45
-
46
- ```ruby
47
- class User
48
- def initialize(name:, age:)
49
- @name, @age = name, age
50
- end
51
- attr_reader :name, :age
52
- end
53
-
54
- # A test case to tell TypeProf what types are expected by the class and methods
55
- User.new(name: "John", age: 20)
56
- ```
57
-
58
- Result:
59
- ```
60
- $ typeprof -v test.rb
61
- # Classes
62
- class User
63
- attr_reader name : String
64
- attr_reader age : Integer
65
- def initialize : (name: String, age: Integer) -> [String, Integer]
66
- end
67
- ```
68
-
69
- ## Type inspection by `p` (`Kernel#p`)
70
-
71
- ```ruby
72
- p 42 #=> Integer
73
- p "str" #=> String
74
- p "str".chars #=> Array[String]
75
- ```
76
-
77
- Result:
78
- ```
79
- $ typeprof test.rb
80
- # Revealed types
81
- # test.rb:1 #=> Integer
82
- # test.rb:2 #=> String
83
- # test.rb:3 #=> Array[String]
84
- ```
85
-
86
- ## Block with builtin methods
87
-
88
- ```ruby
89
- # TypeProf runs this block only once
90
- 10000000000000.times do |n|
91
- p n #=> Integer
92
- end
93
-
94
- # "each" with Heterogeneous array yields a union type
95
- [1, 1.0, "str"].each do |e|
96
- p e #=> Float | Integer | String
97
- end
98
-
99
- # You can use the idiom `&:method_name` too
100
- p [1, 1.0, "str"].map(&:to_s) #=> Array[String]
101
- ```
102
-
103
- ## User-defined blocks
104
-
105
- ```ruby
106
- def foo(n)
107
- yield n.to_s
108
- end
109
-
110
- foo(42) do |n|
111
- p n #=> String
112
- nil
113
- end
114
- ```
115
-
116
- Result:
117
- ```
118
- $ typeprof test.rb
119
- # Revealed types
120
- # test.rb:6 #=> String
121
-
122
- # Classes
123
- class Object
124
- def foo : (Integer) { (String) -> nil } -> nil
125
- end
126
- ```
127
-
128
- ## Arrays
129
-
130
- ```ruby
131
- # A fixed-length array literal generates a "tuple" array
132
- ary = [1, 1.0]
133
-
134
- # A tuple array keeps its length, and the association between indexes and elements
135
- p ary #=> [Integer, Float]
136
- p ary[0] #=> Integer
137
- p ary[1] #=> Float
138
-
139
- # Destructive operation is well handled (in method-local analysis)
140
- ary[0] = "str"
141
- p ary #=> [String, Float]
142
-
143
- # An calculated array generates a "sequence" array
144
- ary = [1] + [1.0]
145
-
146
- # A sequence array does not keep length nor association
147
- p ary #=> Array[Float | Integer]
148
- p ary[0] #=> Float | Integer
149
-
150
- # Destructive operation is still handled (but "weak update" is applied)
151
- ary[0] = "str"
152
- p ary #=> Array[Float | Integer | String]
153
- ```
154
-
155
- ## Multiple return values by using a tuple array
156
-
157
- ```ruby
158
- def foo
159
- return 42, "str"
160
- end
161
-
162
- int, str = foo
163
- p int #=> Integer
164
- p str #=> String
165
- ```
166
-
167
- ## Delegation by using a tuple array
168
-
169
- ```ruby
170
- def foo(x, y, z)
171
- end
172
-
173
- def proxy(dummy, *args)
174
- foo(*args)
175
- end
176
-
177
- proxy(:dummy, 1, 1.0, "str")
178
- ```
179
-
180
- ## Symbols
181
-
182
- ```ruby
183
- # Symbols are handled as concrete values instead of abstract ones
184
- p [:a, :b, :c] #=> [:a, :b, :c]
185
- ```
186
-
187
- ## Hashes
188
-
189
- ```ruby
190
- # A Hash is a "type-to-type" map
191
- h = { "int" => 1, "float" => 1.0 }
192
- p h #=> {String=>Float | Integer}
193
- p h["int"] #=> Float | Integer
194
-
195
- # Symbol-key hashes (a.k.a. records) can have distinct types for each key as Symbols are concrete
196
- h = { int: 1, float: 1.0 }
197
-
198
- p h #=> {:int=>Integer, :float=>Float}
199
- p h[:int] #=> Integer
200
- p h[:float] #=> Float
201
-
202
- # Symbol-key hash can be appropriately passed to a keyword method
203
- def foo(int:, float:)
204
- p [int, float] #=> [Integer, Float]
205
- end
206
-
207
- foo(**h)
208
- ```
209
-
210
- ## Structs
211
-
212
- ```ruby
213
- FooBar = Struct.new(:foo, :bar)
214
-
215
- obj = FooBar.new(42)
216
- obj.foo = :dummy
217
- obj.bar = "str"
218
- ```
219
-
220
- Result:
221
- ```
222
- $ typeprof test.rb
223
- # Classes
224
- class FooBar < Struct
225
- attr_accessor foo() : :dummy | Integer
226
- attr_accessor bar() : String?
227
- end
228
- ```
229
-
230
- ## Exceptions
231
-
232
- ```ruby
233
- # TypeProf assumes that any exception may be raised anywhere
234
- def foo
235
- x = 1
236
- x = "str"
237
- x = :sym
238
- ensure
239
- p(x) #=> :sym | Integer | String
240
- end
241
- ```
242
-
243
- Result:
244
- ```
245
- $ typeprof test.rb
246
- # Revealed types
247
- # test.rb:6 #=> :sym | Integer | String
248
-
249
- # Classes
250
- class Object
251
- def foo : -> :sym
252
- end
253
- ```
254
-
255
- ## RBS overloaded methods
256
-
257
- ```ruby
258
- # TypeProf selects all overloaded method declarations that matches actual arguments
259
- p foo(42) #=> Integer
260
- p foo("str") #=> String
261
- p foo(1.0) #=> failed to resolve overload: Object#foo
262
- ```
263
-
264
- ```
265
- class Object
266
- def foo: (Integer) -> Integer
267
- | (String) -> String
268
- end
269
- ```
270
-
271
- ## Flow-sensitive analysis demo: case/when with class constants
272
-
273
- ```ruby
274
- def foo(n)
275
- case n
276
- when Integer
277
- p n #=> Integer
278
- when String
279
- p n #=> String
280
- else
281
- p n #=> Float
282
- end
283
- end
284
-
285
- foo(42)
286
- foo(1.0)
287
- foo("str")
288
- ```
289
-
290
- Result:
291
- ```
292
- $ typeprof test.rb
293
- # Revealed types
294
- # test.rb:4 #=> Integer
295
- # test.rb:8 #=> Float
296
- # test.rb:6 #=> String
297
-
298
- # Classes
299
- class Object
300
- def foo : (Float | Integer | String) -> (Float | Integer | String)
301
- end
302
- ```
303
-
304
- ## Flow-sensitive analysis demo: `is_a?` and `respond_to?`
305
-
306
- ```ruby
307
- def foo(n)
308
- if n.is_a?(Integer)
309
- p n #=> Integer
310
- else
311
- p n #=> Float | String
312
- end
313
-
314
- if n.respond_to?(:times)
315
- p n #=> Integer
316
- else
317
- p n #=> Float | String
318
- end
319
- end
320
-
321
- foo(42)
322
- foo(1.0)
323
- foo("str")
324
- ```
325
-
326
- ## Flow-sensitive analysis demo: `x || y`
327
-
328
- ```ruby
329
- # ENV["FOO"] returns String? (which means String | nil)
330
- p ENV["FOO"] #=> String?
331
-
332
- # Using "|| (default value)" can force it to be non-nil
333
- p ENV["FOO"] || "default" #=> String
334
- ```
335
-
336
- ## Recursion
337
-
338
- ```ruby
339
- def fib(x)
340
- if x <= 1
341
- x
342
- else
343
- fib(x - 1) + fib(x - 2)
344
- end
345
- end
346
-
347
- fib(40000)
348
- ```
349
-
350
- Result:
351
- ```
352
- $ typeprof test.rb
353
- # Classes
354
- class Object
355
- def fib : (Integer) -> Integer
356
- end
357
- ```
358
-
359
- ## "Stub-execution" that invokes methods without tests
360
-
361
- ```ruby
362
- def foo(n)
363
- # bar is invoked with Integer arguments
364
- bar(42)
365
- n
366
- end
367
-
368
- def bar(n)
369
- n
370
- end
371
-
372
- # As there is no test code to call methods foo and bar,
373
- # TypeProf tries to invoke them with "untyped" arguments
374
- ```
375
-
376
- Result:
377
- ```
378
- $ typeprof test.rb
379
- # Classes
380
- class Object
381
- def foo : (untyped) -> untyped
382
- def bar : (Integer) -> Integer
383
- end
384
- ```
385
-
386
- ## Library demo
387
-
388
- ```ruby
389
- require "pathname"
390
-
391
- p Pathname("foo") #=> Pathname
392
- p Pathname("foo").dirname #=> Pathname
393
- p Pathname("foo").ctime #=> Time
394
- ```
395
-
396
- ## More
397
-
398
- See ruby/typeprof's [smoke](https://github.com/ruby/typeprof/tree/master/smoke) directory.