rdl 1.1.0 → 1.1.1.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/CHANGES.md +25 -0
  4. data/README.md +104 -64
  5. data/extras/type_tests/%.rb +171 -0
  6. data/extras/type_tests/&.rb +159 -0
  7. data/extras/type_tests/**.rb +222 -0
  8. data/extras/type_tests/*.rb +177 -0
  9. data/extras/type_tests/+.rb +170 -0
  10. data/extras/type_tests/-.rb +171 -0
  11. data/extras/type_tests/1scomp.rb +157 -0
  12. data/extras/type_tests/<.rb +170 -0
  13. data/extras/type_tests/<<.rb +159 -0
  14. data/extras/type_tests/>>.rb +159 -0
  15. data/extras/type_tests/[].rb +163 -0
  16. data/extras/type_tests/^.rb +159 -0
  17. data/extras/type_tests/abs.rb +155 -0
  18. data/extras/type_tests/abs2.rb +164 -0
  19. data/extras/type_tests/angle.rb +157 -0
  20. data/extras/type_tests/arg.rb +157 -0
  21. data/extras/type_tests/bit_length.rb +157 -0
  22. data/extras/type_tests/ceil.rb +157 -0
  23. data/extras/type_tests/ceilRational.rb +160 -0
  24. data/extras/type_tests/conj.rb +158 -0
  25. data/extras/type_tests/defwhere.rb +86 -0
  26. data/extras/type_tests/denominator.rb +157 -0
  27. data/extras/type_tests/div.rb +172 -0
  28. data/extras/type_tests/divslash.rb +179 -0
  29. data/extras/type_tests/even?.rb +157 -0
  30. data/extras/type_tests/fdiv.rb +244 -0
  31. data/extras/type_tests/finite?.rb +157 -0
  32. data/extras/type_tests/floor.rb +157 -0
  33. data/extras/type_tests/floorRational.rb +161 -0
  34. data/extras/type_tests/hash.rb +157 -0
  35. data/extras/type_tests/imag.rb +158 -0
  36. data/extras/type_tests/infinite?.rb +157 -0
  37. data/extras/type_tests/modulo.rb +171 -0
  38. data/extras/type_tests/nan?.rb +157 -0
  39. data/extras/type_tests/neg.rb +155 -0
  40. data/extras/type_tests/next.rb +157 -0
  41. data/extras/type_tests/next_float.rb +157 -0
  42. data/extras/type_tests/numerator.rb +157 -0
  43. data/extras/type_tests/phase.rb +157 -0
  44. data/extras/type_tests/prev_float.rb +157 -0
  45. data/extras/type_tests/quo.rb +179 -0
  46. data/extras/type_tests/rationalize.rb +157 -0
  47. data/extras/type_tests/rationalizeArg.rb +198 -0
  48. data/extras/type_tests/real.rb +157 -0
  49. data/extras/type_tests/real?.rb +157 -0
  50. data/extras/type_tests/round.rb +157 -0
  51. data/extras/type_tests/roundArg.rb +169 -0
  52. data/extras/type_tests/size.rb +157 -0
  53. data/extras/type_tests/to_c.rb +157 -0
  54. data/extras/type_tests/to_f.rb +155 -0
  55. data/extras/type_tests/to_i.rb +157 -0
  56. data/extras/type_tests/to_r.rb +157 -0
  57. data/extras/type_tests/to_s.rb +157 -0
  58. data/extras/type_tests/truncate.rb +157 -0
  59. data/extras/type_tests/truncateArg.rb +166 -0
  60. data/extras/type_tests/type tests +1 -0
  61. data/extras/type_tests/zero?.rb +155 -0
  62. data/extras/type_tests/|.rb +159 -0
  63. data/lib/rdl/contracts/and.rb +1 -1
  64. data/lib/rdl/contracts/flat.rb +2 -2
  65. data/lib/rdl/contracts/proc.rb +2 -1
  66. data/lib/rdl/types/.#lexer.rex +1 -0
  67. data/lib/rdl/types/dependent_arg.rb +47 -0
  68. data/lib/rdl/types/finitehash.rb +5 -5
  69. data/lib/rdl/types/generic.rb +3 -3
  70. data/lib/rdl/types/lexer.rex +5 -2
  71. data/lib/rdl/types/lexer.rex.rb +3 -0
  72. data/lib/rdl/types/method.rb +144 -15
  73. data/lib/rdl/types/nominal.rb +1 -1
  74. data/lib/rdl/types/parser.racc +6 -1
  75. data/lib/rdl/types/parser.tab.rb +272 -245
  76. data/lib/rdl/types/tuple.rb +1 -1
  77. data/lib/rdl/types/type_inferencer.rb +7 -7
  78. data/lib/rdl/wrap.rb +16 -11
  79. data/rdl.gemspec +3 -3
  80. data/test/test_dsl.rb +4 -5
  81. data/test/test_le.rb +5 -5
  82. data/test/test_lib_types.rb +34 -34
  83. data/test/test_member.rb +3 -3
  84. data/test/test_type_contract.rb +63 -1
  85. data/test/test_types.rb +2 -0
  86. data/types/ruby-2.x/_aliases.rb +2 -2
  87. data/types/ruby-2.x/bigdecimal.rb +246 -12
  88. data/types/ruby-2.x/bignum.rb +253 -0
  89. data/types/ruby-2.x/complex.rb +111 -22
  90. data/types/ruby-2.x/fixnum.rb +238 -31
  91. data/types/ruby-2.x/float.rb +217 -35
  92. data/types/ruby-2.x/integer.rb +17 -16
  93. data/types/ruby-2.x/numeric.rb +31 -21
  94. data/types/ruby-2.x/rational.rb +196 -18
  95. metadata +67 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d70ef3cc3d6edbb1cf16a849e412dc465510a606
4
- data.tar.gz: b544a1f441d5d2d5beaa023a435940b2ad332ddf
3
+ metadata.gz: 89545c8109d2fcc279258745760772a7114d6842
4
+ data.tar.gz: 308333136875d3904304c6475d2503e61adb0a8d
5
5
  SHA512:
6
- metadata.gz: c3004c7b0b1b13e4d507497bde17980ec35d80fece303666f07ceee739efeec81bc33a35e09283c222782f419ac2cfbc7d19e163d6988c485a764901e41a262d
7
- data.tar.gz: 57246478d603a49ef56bc1dd5266ecdda6f8f8331149beb96651a4d4c30c81764feae526522e7c4c73d37e48003520b54946eef732099256df26120aad084bc6
6
+ metadata.gz: b967fbe0e88dc13e802cb71c85e603d4886cb4beb98b708069507f6bafc7a4507909c8b2e003cdc73f28d926a7de45c610e3a9d3b8a0ba7708c738f25850c56f
7
+ data.tar.gz: 6f6506ddffe97004b10d01cec5fa1ed3897aa429a2d40c2cbc708440553ad6eab53b746a2084bee9d8861dc67b6b80bfcb6851c25825ddde674a7c2a104b4abe
@@ -17,4 +17,5 @@ rvm:
17
17
  - 2.2.3
18
18
  - 2.2.4
19
19
  - 2.3.0
20
+ - 2.3.1
20
21
  sudo: false
@@ -0,0 +1,25 @@
1
+ # Change log!
2
+
3
+ ## [Unreleased]
4
+
5
+ ## [1.1.1] - 2016-05-21
6
+ ### Fixed
7
+ - Update code to eliminate Ruby 2.3 warning messages
8
+ - Fixed errors in post conditions of numeric types (incorrect number of args)
9
+ - Added syntax highlighting in README.md as pointed out by jsyeo
10
+ - Comprehensive changes to types of Numeric subclass methods to make types more specific & accurate
11
+ - Changed superclasses of numeric classes to be `Numeric`
12
+
13
+ ### Added
14
+ - Higher-order types and tests for them
15
+ - Dependent types
16
+ - `/extras` directory, which contains random type tests for numeric subclass method types
17
+ - `BigDecimal` added to alias `%real`
18
+ - Changelog added!
19
+
20
+ ## [1.1.0] - 2016-01-03
21
+ ### Added
22
+ - Added much enhanced `rdl_query` facility and accompanying command-line script.
23
+
24
+ ## [1.0.0] - 2015-12-18
25
+ - First release!
data/README.md CHANGED
@@ -1,10 +1,11 @@
1
- [![Gem Version](https://badge.fury.io/rb/rdl.svg)](https://badge.fury.io/rb/rdl)
1
+ [![Gem Version](https://badge.fury.io/rb/rdl.svg)](https://badge.fury.io/rb/rdl) [![Build Status](https://travis-ci.org/plum-umd/rdl.svg?branch=master)](https://travis-ci.org/plum-umd/rdl)
2
+
2
3
 
3
4
  # Introduction
4
5
 
5
6
  RDL is a lightweight system for adding contracts to Ruby. A *contract* decorates a method with assertions describing what the method assumes about its inputs (called a *precondition*) and what the method guarantees about its outputs (called a *postcondition*). For example, using RDL we can write
6
7
 
7
- ```
8
+ ```ruby
8
9
  require 'rdl'
9
10
 
10
11
  pre { |x| x > 0 }
@@ -21,7 +22,7 @@ RDL contracts are enforced at method entry and exit. For example, if we call `sq
21
22
 
22
23
  In addition to arbitrary pre- and post-conditions, RDL also has extensive support for contracts that are *types*. For example, we can write the following in RDL:
23
24
 
24
- ```
25
+ ```ruby
25
26
  require 'rdl'
26
27
 
27
28
  type '(Fixnum, Fixnum) -> String'
@@ -32,7 +33,7 @@ This indicates that `m` is that method that returns a `String` if given two `Fix
32
33
 
33
34
  RDL contracts and types are stored in memory at run time, so it's also possible for programs to query them. RDL includes lots of contracts and types for the core and standard libraries. Since those methods are generally trustworthy, RDL doesn't actually enforce the contracts (since that would add overhead), but they are available to search and query. RDL includes a small script `rdl_query` to look up type information from the command line. Note you might need to put the argument in quotes depending on your shell.
34
35
 
35
- ```
36
+ ```shell
36
37
  $ rdl_query String#include? # print type for instance method of another class
37
38
  $ rdl_query Pathname.glob # print type for singleton method of a class
38
39
  $ rdl_query Array # print types for all methods of a class
@@ -44,7 +45,7 @@ $ rdl_query "(..., Fixnum, ...) -> ." # print all methods that take a Fixnum as
44
45
 
45
46
  See below for more details of the query format. The `rdl_query` method performs the same function as long as the gem is loaded, so you can use this in `irb`.
46
47
 
47
- ```
48
+ ```ruby
48
49
  $ irb
49
50
  > require 'rdl'
50
51
  => true
@@ -76,7 +77,7 @@ Use `require 'rdl'` to load the RDL library. If you want to use the core and sta
76
77
 
77
78
  If you're using Ruby on Rails, you can similarly `require 'rails_types'` to load in type annotations for the current `Rails::VERSION::STRING`. More specifically, add the following lines in `application.rb` after the `Bundler.require` call. (This placement is needed so the Rails version string is available and the Rails environment is loaded):
78
79
 
79
- ```
80
+ ```ruby
80
81
  require 'rdl'
81
82
  require 'rdl_types'
82
83
  require 'rails_types'
@@ -118,7 +119,7 @@ A type string generally has the form `(typ1, ..., typn) -> typ` indicating a met
118
119
 
119
120
  A nominal type is simply a class name, and it matches any object of that class or any subclass.
120
121
 
121
- ```
122
+ ```ruby
122
123
  type String, :insert, '(Fixnum, String) -> String'
123
124
  ```
124
125
 
@@ -126,12 +127,12 @@ type String, :insert, '(Fixnum, String) -> String'
126
127
 
127
128
  The nominal type `NilClass` can also be written as `nil`. The only object of this type is `nil`:
128
129
 
129
- ```
130
+ ```ruby
130
131
  type IO, :close, '() -> nil' # IO#close always returns nil
131
132
  ```
132
133
 
133
134
  Currently, `nil` is treated as if it were an instance of any class.
134
- ```
135
+ ```ruby
135
136
  x = "foo"
136
137
  x.insert(0, nil) # RDL does not report a type error
137
138
  ```
@@ -140,7 +141,7 @@ We chose this design based on prior experience with static type systems for Ruby
140
141
  ### Top Type (%any)
141
142
 
142
143
  RDL includes a special "top" type `%any` that matches any object:
143
- ```
144
+ ```ruby
144
145
  type Object, :=~, '(%any) -> nil'
145
146
  ```
146
147
  We call this the "top" type because it is the top of the subclassing hierarchy RDL uses. Note that `%any` is more general than `Object`, because not all classes inherit from `Object`, e.g., `BasicObject` does not.
@@ -149,7 +150,7 @@ We call this the "top" type because it is the top of the subclassing hierarchy R
149
150
 
150
151
  Many Ruby methods can take several different types of arguments or return different types of results. The union operator `or` can be used to indicate a position where multiple types are possible.
151
152
 
152
- ```
153
+ ```ruby
153
154
  type IO, :putc, '(Numeric or String) -> %any'
154
155
  type String, :getbyte, '(Fixnum) -> Fixnum or nil'
155
156
  ```
@@ -160,7 +161,7 @@ Note that for `getbyte`, we could leave off the `nil`, but we include it to matc
160
161
 
161
162
  Sometimes Ruby methods have several different type signatures. (In Java these would be called *overloaded* methods.) In RDL, such methods are assigned a set of type signatures:
162
163
 
163
- ```
164
+ ```ruby
164
165
  type String, :[], '(Fixnum) -> String or nil'
165
166
  type String, :[], '(Fixnum, Fixnum) -> String or nil'
166
167
  type String, :[], '(Range or Regexp) -> String or nil'
@@ -173,7 +174,7 @@ We say the method's type is the *intersection* of the types above.
173
174
 
174
175
  When this method is called at run time, RDL checks that at least one type signature matches the call:
175
176
 
176
- ```
177
+ ```ruby
177
178
  "foo"[0] # matches first type
178
179
  "foo"[0,2] # matches second type
179
180
  "foo"[0..2] # matches third type
@@ -183,7 +184,7 @@ When this method is called at run time, RDL checks that at least one type signat
183
184
 
184
185
  Notice that union types in arguments could also be written as intersection types of methods, e.g., instead of the third type of `[]` above we could have equivalently written
185
186
 
186
- ```
187
+ ```ruby
187
188
  type String, :[], '(Range) -> String or nil'
188
189
  type String, :[], '(Regexp) -> String or nil'
189
190
  ```
@@ -192,13 +193,13 @@ type String, :[], '(Regexp) -> String or nil'
192
193
 
193
194
  Optional arguments are denoted in RDL by putting `?` in front of the argument's type. For example:
194
195
 
195
- ```
196
+ ```ruby
196
197
  type String, :chomp, '(?String) -> String'
197
198
  ```
198
199
 
199
200
  This is actually just a shorthand for an equivalent intersection type:
200
201
 
201
- ```
202
+ ```ruby
202
203
  type String, :chomp, '() -> String'
203
204
  type String, :chomp, '(String) -> String'
204
205
  ```
@@ -211,7 +212,7 @@ Like Ruby, RDL allows optional arguments to appear anywhere in a method's type s
211
212
 
212
213
  In RDL, `*` is used to decorate an argument that may appear zero or more times. Currently in RDL this annotation may only appear on the rightmost argument. For example, `String#delete` takes one or more `String` arguments:
213
214
 
214
- ```
215
+ ```ruby
215
216
  type String, :delete, '(String, *String) -> String'
216
217
  ```
217
218
 
@@ -219,31 +220,73 @@ type String, :delete, '(String, *String) -> String'
219
220
 
220
221
  RDL allows arguments to be named, for documentation purposes. Names are given after the argument's type, and they do not affect type contract checking in any way. For example:
221
222
 
222
- ```
223
+ ```ruby
223
224
  type Fixnum, :to_s, '(?Fixnum base) -> String'
224
225
  ```
225
226
 
226
227
  Here we've named the first argument of `to_s` as `base` to give some extra hint as to its meaning.
227
228
 
228
- ### Block Types
229
+ ### Dependent Types
229
230
 
230
- Types signatures can include a type for a method's block argument:
231
+ RDL allows for refinement predicates to be attached to named arguments. These predicates are then checked when the method is called and returns. For instance:
231
232
 
233
+ ```ruby
234
+ type '(Float x {{ x>=0 }}) -> Float y {{ y>=0 }}'
235
+ def sqrt(x)
236
+ # return the square root of x
237
+ end
232
238
  ```
233
- type Pathname, :ascend, '() { (Pathname) -> %any } -> %any'
239
+
240
+ Here, RDL will check that the `sqrt` method is called on an argument of type `Float` which is greater than or equal to 0, and it will check the same of the return value of the method. Note that, in effect, dependent type contracts can be used in place of pre and post contracts.
241
+
242
+ Dependencies can also exist across a method's arguments and return value:
243
+
244
+ ```ruby
245
+ type '(Fixnum x {{ x>y }}, Fixnum y) -> Float z {{ z==(x+y) }}'
246
+ def m(x,y) ... end
234
247
  ```
235
248
 
236
- Here the block passed to `Pathname.ascend` must take a `Pathname` and can return any object.
249
+ Any arbitrary code can be placed between the double braces of a type refinement, and RDL will dynmically check that this predicate evaluates to true, or raise a type error if it evaluates to false.
250
+
251
+ ### Higher-Order Contracts
252
+
253
+ RDL supports contracts for arguments or return values which are themselves `Proc` objects. Simply enclose the corresponding argument's type with braces to denote that it is a `Proc`. For example:
237
254
 
238
- This is a *higher-order* contract, because it applies to a higher-order method, i.e., a method that can take a block argument.
255
+ ```ruby
256
+ type '(Fixnum, {(Fixnum) -> Fixnum}) -> Fixnum'
257
+ def m(x, y) ... end
258
+ ```
259
+
260
+ The type annotation above states that the method m takes two arguments: one of type `Fixnum`, and another which is a `Proc` which itself takes a `Fixnum` and returns a `Fixnum`. A `Proc` may be the return value of a method as well:
261
+
262
+ ```ruby
263
+ type '(Fixnum) -> {(Float) -> Float}'
264
+ def m(x) ... end
265
+ ```
266
+
267
+ These higher-order contracts are checked by wrapping the corresponding `Proc` argument/return in a new `Proc` which checks that the type contract holds.
268
+
269
+ A type contract can be provided for a method block as well. The block's type should be included after the method argument types:
270
+
271
+ ```ruby
272
+ type '(Fixnum, Float) {(Fixnum, String) -> String } -> Float'
273
+ def m(x,y,&blk) ... end
274
+ ```
239
275
 
240
- Currently higher-order contracts are not enforced. That is, RDL will not actually check contracts on block arguments.
276
+ Note that this notation will work whether or not a method block is explicitly referenced in the parameters, i.e., whether or not `&blk` is included above. Finally, dependent types work across higher order contracts:
277
+
278
+ ```ruby
279
+ type '(Fixnum x, Float y) -> {(Fixnum z {{ z>y }}) -> Fixnum}'
280
+ def m(x,y,&blk) ... end
281
+ ```
282
+
283
+ The type contract above states that method `m` returns a `Proc` which takes a `Fixnum z` which must be greater than the argument `Float y`. Whenver this `Proc` is called, it will be checked that this contract holds.
241
284
 
242
285
  ### Class/Singleton Method Types
243
286
 
244
287
  RDL method signatures can be used both for instance methods and for class methods (often called *singleton methods* in Ruby). To indicate a type signature applies to a singleton method, prefix the method name with `self.`:
245
288
 
246
- ```
289
+ ```ruby
247
290
  type File, 'self.dirname', '(String file) -> String dir'
248
291
  ```
249
292
 
@@ -251,7 +294,7 @@ type File, 'self.dirname', '(String file) -> String dir'
251
294
 
252
295
  Type signatures can be added to `initialize` by giving a type signature for `self.new`:
253
296
 
254
- ```
297
+ ```ruby
255
298
  type File, 'self.new', '(String file, ?String mode, ?String perm, ?Fixnum opt) -> File'
256
299
  ```
257
300
 
@@ -259,7 +302,7 @@ type File, 'self.new', '(String file, ?String mode, ?String perm, ?Fixnum opt) -
259
302
 
260
303
  Some Ruby methods are intended to take any object that has certain methods. RDL uses *structural types* to denote such cases:
261
304
 
262
- ```
305
+ ```ruby
263
306
  type IO, :puts, '(*[to_s: () -> String]) -> nil'
264
307
  ```
265
308
 
@@ -271,23 +314,24 @@ The actual checking that RDL does here varies depending on what type information
271
314
 
272
315
  Not to be confused with types for singleton methods, RDL includes *singleton types* that denote positions that always have one particular value; this typically happens only in return positions. For example, `Dir#mkdir` always returns the value 0:
273
316
 
274
- ```
317
+ ```ruby
275
318
  type Dir, 'self.mkdir', '(String, ?Fixnum) -> 0'
276
319
  ```
277
320
 
278
321
  In RDL, any integer or floating point number denotes a singleton type. Arbitrary values can be turned into singleton types by wrapping them in `${.}`. For example, `Float#angle` always returns 0 or pi.
279
322
 
280
- ```
323
+ ```ruby
281
324
  type Float, :angle, '() -> 0 or ${Math::PI}'
282
325
  ```
283
326
 
284
327
  RDL checks if a value matches a singleton type using `equal?`. As a consequence, singleton string types aren't currently possible.
285
328
 
329
+
286
330
  ### Self Type
287
331
 
288
332
  Consider a method that returns `self`:
289
333
 
290
- ```
334
+ ```ruby
291
335
  class A
292
336
  def id
293
337
  self
@@ -297,7 +341,7 @@ end
297
341
 
298
342
  If that method might be inherited, we can't just give it a nominal type, because it will return a different object type in a subclass:
299
343
 
300
- ```
344
+ ```ruby
301
345
  class B < A
302
346
  end
303
347
 
@@ -308,7 +352,7 @@ B.new.id # type error, returns a B
308
352
 
309
353
  To solve this problem, RDL includes a special type `self` for this situation:
310
354
 
311
- ```
355
+ ```ruby
312
356
  type A, :id, '() -> self'
313
357
  A.new.id # okay, returns self
314
358
  B.new.id # also okay, returns self
@@ -320,7 +364,7 @@ Note that type `self` means *exactly* the self object, i.e., it is a singleton t
320
364
 
321
365
  RDL allows types to be aliases to make them faster to write down and more readable. All type aliases begin with `%`. RDL has one built-in alias, `%bool`, which is shorthand for `TrueClass or FalseClass`:
322
366
 
323
- ```
367
+ ```ruby
324
368
  type String, :==, '(%any) -> %bool'
325
369
  ```
326
370
 
@@ -328,7 +372,7 @@ Note it is not a bug that `==` is typed to allow any object. Though you would th
328
372
 
329
373
  Method `type_alias(name, typ)` can be used to create a user-defined type alias, where `name` must begin with `%`:
330
374
 
331
- ```
375
+ ```ruby
332
376
  type_alias '%real', 'Integer or Float or Rational'
333
377
  type_alias '%string', '[to_str: () -> String]'
334
378
  type_alias '%path', '%string or Pathname'
@@ -340,7 +384,7 @@ Type aliases have to be created before they are used (so above, `%path` must be
340
384
 
341
385
  RDL supports *parametric polymorphism* for classes, a.k.a. *generics*. The `type_params` method names the type parameters of the class, and those parameters can then be used inside type signatures:
342
386
 
343
- ```
387
+ ```ruby
344
388
  class Array
345
389
  type_params [:t], :all?
346
390
 
@@ -352,7 +396,7 @@ Here the first argument to `type_params` is a list of symbols or strings that na
352
396
 
353
397
  Generic types are applied to type arguments using `<...>` notation, e.g., `Array<Fixnum>` is an `Array` class where `t` is replaced by `Fixnum`. Thus, for example, if `o` is an `Array<Fixnum>`, then `o.shift` returns `Fixnum`. As another example, here is the type for the `[]` method of `Array`:
354
398
 
355
- ```
399
+ ```ruby
356
400
  type Array, :[], '(Range) -> Array<t>'
357
401
  type Array, :[], '(Fixnum or Float) -> t'
358
402
  type Array, :[], '(Fixnum, Fixnum) -> Array<t>'
@@ -366,14 +410,14 @@ Thus, by default, even though `Array` is declared to take type parameters, by de
366
410
 
367
411
  To fully enforce generic types, RDL requires that the developer `instantiate!` an object with the desired type parameters:
368
412
 
369
- ```
413
+ ```ruby
370
414
  x = [1,2]
371
415
  x.instantate!('Fixnum')
372
416
  x.push("three") # type error
373
417
  ```
374
418
 
375
419
  Note that the instantiated type is associated with the object, not the variable:
376
- ```
420
+ ```ruby
377
421
  y = x
378
422
  y.push("three") # also a type error
379
423
  ```
@@ -381,7 +425,7 @@ y.push("three") # also a type error
381
425
  When RDL instantiates an object with type parameters, it needs to ensure the object's contents are consistent with the type. Currently this is enforced using the second parameter to `type_params`, which must name a method that behaves like `Array#all?`, i.e., it iterates through the contents, checking that a block argument is satisfied. As seen above, for `Array` we call `type_params(:t, :all?)`. Then at the call `x.instantiate('Fixnum')`, RDL will call `Array#all?` to iterate through the contents of `x` to check they have type `Fixnum`.
382
426
 
383
427
  RDL also includes a `deinstantiate!` method to remove the type instantiation from an object:
384
- ```
428
+ ```ruby
385
429
  x.deinstantiate!
386
430
  x.push("three") # no longer a type error
387
431
  ```
@@ -401,14 +445,14 @@ A type such as `Array<Fixnum>` is useful for homogeneous arrays, where all eleme
401
445
 
402
446
  RDL includes special *tuple types* to handle this situation. Tuple types are written `[t1, ..., tn]`, denoting an `Array` of `n` elements of types `t1` through `tn`, in that order. For example, `[1, "two"]` has type `[Fixnum, String]`. As another example, here is the type of `Process#getrlimit`, which returns a two-element array of `Fixnums`:
403
447
 
404
- ```
448
+ ```ruby
405
449
  type Process, 'self.getrlimit', '(Symbol or String or Fixnum resource) -> [Fixnum, Fixnum] cur_max_limit'
406
450
  ```
407
451
 
408
452
  ### Finite Hash Types
409
453
 
410
454
  Similarly to tuple types, RDL also supports *finite hash types* for heterogenous hashes. Finite hash types are written `{k1 => v1, ..., kn => vn}` to indicate a `Hash` with `n` mappings of type `ki` maps to `vi`. The `ki` may be strings, integers, floats, or constants denoted with `${.}`. If a key is a symbol, then the mapping should be written `ki: vi`. In the latter case, the `{}`'s can be left off:
411
- ```
455
+ ```ruby
412
456
  type MyClass, :foo, '(a: Fixnum, b: String) { () -> %any } -> %any'
413
457
  ```
414
458
  Here `foo`, takes a hash where key `:a` is mapped to a `Fixnum` and key `:b` is mapped to a `String`. Similarly, `{'a'=>Fixnum, 2=>String}` types a hash where keys `'a'` and `2` are mapped to a `Fixnum` and `String`, respectively. Both syntaxes can be used to define hash types.
@@ -431,21 +475,21 @@ As discussed above, RDL includes a small script, `rdl_query`, to look up type in
431
475
 
432
476
  * Instance methods can be looked up as `Class#method`.
433
477
 
434
- ```
478
+ ```shell
435
479
  $ rdl_query String#include?
436
480
  String#include?: (String) -> TrueClass or FalseClass
437
481
  ```
438
482
 
439
483
  * Singleton (class) methods can be looked up as `Class.method`.
440
484
 
441
- ```
485
+ ```shell
442
486
  $ rdl_query Pathname.glob
443
487
  Pathname.glob: (String p1, ?String p2) -> Array<Pathname>
444
488
  ```
445
489
 
446
490
  * All methods of a class can be listed by passing the class name `Class`.
447
491
 
448
- ```
492
+ ```shell
449
493
  $ rdl_query Array
450
494
  &: (Array<u>) -> Array<t>
451
495
  *: (String) -> String
@@ -454,7 +498,7 @@ $ rdl_query Array
454
498
 
455
499
  * Methods can also be search for by their type signature:
456
500
 
457
- ```
501
+ ```shell
458
502
  $ rdl_query "(Fixnum) -> Fixnum" # print all methods of type (Fixnum) -> Fixnum
459
503
  BigDecimal.limit: (Fixnum) -> Fixnum
460
504
  Dir#pos=: (Fixnum) -> Fixnum
@@ -463,7 +507,7 @@ Dir#pos=: (Fixnum) -> Fixnum
463
507
 
464
508
  The type signature uses the standard RDL syntax, with two extensions: `.` can be used as a wildcard to match any type, and `...` can be used to match any sequence of arguments.
465
509
 
466
- ```
510
+ ```shell
467
511
  $ rdl_query "(.) -> ." # methods that take one argument and return anything
468
512
  $ rdl_query "(Fixnum, .) -> ." # methods that take two arguments, the first of which is a Fixnum
469
513
  $ rdl_query "(Fixnum, ...) -> ." # methods whose first argument is a Fixnum
@@ -479,6 +523,10 @@ Note that aside from `.` and `...`, the matching is exact. For example `(Fixnum)
479
523
 
480
524
  Here are some research papers we have written exploring contracts, types, and Ruby.
481
525
 
526
+ * Brianna M. Ren and Jeffrey S. Foster.
527
+ [Just-in-Time Static Type Checking for Dynamic Languages](http://www.cs.umd.edu/~jfoster/papers/pldi16.pdf).
528
+ In ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI), Santa Barbara, CA, June 2016.
529
+
482
530
  * T. Stephen Strickland, Brianna Ren, and Jeffrey S. Foster.
483
531
  [Contracts for Domain-Specific Languages in Ruby](http://www.cs.umd.edu/~jfoster/papers/dls12.pdf).
484
532
  In Dynamic Languages Symposium (DLS), Portland, OR, October 2014.
@@ -513,7 +561,7 @@ In Object-Oriented Program Languages and Systems (OOPS) Track at ACM Symposium o
513
561
 
514
562
  # Copyright
515
563
 
516
- Copyright (c) 2014-2015, University of Maryland, College Park. All rights reserved.
564
+ Copyright (c) 2014-2016, University of Maryland, College Park. All rights reserved.
517
565
 
518
566
  # Contributors
519
567
 
@@ -523,17 +571,10 @@ Copyright (c) 2014-2015, University of Maryland, College Park. All rights reserv
523
571
  * [Brianna M. Ren](https://www.cs.umd.edu/~bren/)
524
572
  * [T. Stephen Strickland](https://www.cs.umd.edu/~sstrickl/)
525
573
  * Alexander T. Yu
526
-
527
- # RDL Build Status
528
-
529
- [![Build Status](https://travis-ci.org/plum-umd/rdl.svg?branch=master)](https://travis-ci.org/plum-umd/rdl)
574
+ * Milod Kazerounian
530
575
 
531
576
  # TODO list
532
577
 
533
- * ProcContract, Wrap, MethodType, support higher-order contracts for blocks
534
- * And higher-order type checking
535
- * Block passed to contracts don't work yet
536
-
537
578
  * How to check whether initialize? is user-defined? method_defined? always
538
579
  returns true, meaning wrapping isn't fully working with initialize.
539
580
 
@@ -548,27 +589,26 @@ Copyright (c) 2014-2015, University of Maryland, College Park. All rights reserv
548
589
 
549
590
  * Rails types
550
591
 
551
- * Proc types
552
-
553
592
  * Deferred contracts on new (watch for class addition)
554
593
 
555
594
  * DSL contracts
556
595
 
557
- * Documentation!
596
+ * double-splat arguments, which bind to an arbitrary set of keywords
558
597
 
559
- * double-splat arguments, which bind to an arbitrary set of keywords.
598
+ * included versus extended modules, e.g., Kernel is included in Object, so its
599
+ class methods become Object's instance methods
560
600
 
561
- * included versus extended modules, e.g., Kernel is included in
562
- + Object, so its class methods become Object's instance methods.
563
-
564
- * Better story for different types for different Ruby versions.
601
+ * Better story for different types for different Ruby versions
565
602
 
566
603
  * Better query facility (more kinds of searches). Contract queries?
567
604
 
568
605
  * Write documentation on: Raw Contracts and Types, RDL Configuration, Code Overview
569
606
 
570
- * Structural type queries, allow name to be unknown; same with finite hash keys, same with generic base types?
607
+ * Structural type queries, allow name to be unknown; same with finite hash keys,
608
+ same with generic base types?
571
609
 
572
610
  * Allow ... in named args list in queries
573
611
 
574
612
  * Queries, include more regexp operators aside from . and ...
613
+
614
+ * Queries, allow regexp in class and method names; suggested by Andreas Adamcik, Vienna