rdl 1.0.0 → 1.0.1.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/README.md +75 -12
- data/bin/rdl_query +24 -0
- data/lib/rdl.rb +2 -1
- data/lib/rdl/query.rb +96 -0
- data/lib/rdl/types/annotated_arg.rb +4 -1
- data/lib/rdl/types/dots_query.rb +26 -0
- data/lib/rdl/types/finitehash.rb +11 -3
- data/lib/rdl/types/generic.rb +8 -2
- data/lib/rdl/types/intersection.rb +10 -3
- data/lib/rdl/types/lexer.rex +4 -1
- data/lib/rdl/types/lexer.rex.rb +11 -2
- data/lib/rdl/types/method.rb +41 -4
- data/lib/rdl/types/nil.rb +8 -2
- data/lib/rdl/types/nominal.rb +8 -2
- data/lib/rdl/types/optional.rb +9 -3
- data/lib/rdl/types/parser.racc +10 -6
- data/lib/rdl/types/parser.tab.rb +305 -257
- data/lib/rdl/types/singleton.rb +10 -3
- data/lib/rdl/types/structural.rb +9 -2
- data/lib/rdl/types/top.rb +9 -3
- data/lib/rdl/types/tuple.rb +9 -3
- data/lib/rdl/types/type_query.rb +5 -0
- data/lib/rdl/types/union.rb +11 -4
- data/lib/rdl/types/var.rb +6 -0
- data/lib/rdl/types/vararg.rb +8 -2
- data/lib/rdl/types/wild_query.rb +28 -0
- data/lib/rdl/util.rb +18 -5
- data/lib/rdl/wrap.rb +3 -37
- data/rdl.gemspec +3 -2
- data/test/test_parser.rb +24 -24
- data/test/test_query.rb +108 -0
- data/test/test_rdl.rb +4 -4
- data/types/ruby-2.x/file.rb +3 -1
- data/types/ruby-2.x/fileutils.rb +2 -2
- metadata +13 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c8ba5d3f1fe3944a7eadae9366c10428470a623
|
4
|
+
data.tar.gz: d87c55ae1f8877a6cb14fafff20a38b3cc7f3137
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f31d49ff2763c501dff6093de526d6770624bae0f0e9d6c147903ade326fc8e8fecde916c7a7156f71ab218948a55334426779dfd9dc570126a2ad24a7fd7d1c
|
7
|
+
data.tar.gz: f81fbff3ac6b8348233c9a49471d99fcbd2885dbbf415a0454580109a2f24dd972944dc4f0a235ebee08b435334c25436b6932040baf3b86bd371256932aeb19
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -30,23 +30,28 @@ def m(x,y) ... end
|
|
30
30
|
|
31
31
|
This indicates that `m` is that method that returns a `String` if given two `Fixnum` arguments. Again this contract is enforced at run-time: When `m` is called, RDL checks that `m` is given exactly two arguments and both are `Fixnums`, and that `m` returns an instance of `String`. RDL supports many more complex type annotations; see below for a complete discussion and examples. We should emphasize here that RDL types are enforced as contracts at method entry and exit. There is no static checking that the method body conforms to the types.
|
32
32
|
|
33
|
-
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.
|
33
|
+
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
34
|
|
35
35
|
```
|
36
|
+
$ rdl_query String#include? # print type for instance method of another class
|
37
|
+
$ rdl_query Pathname.glob # print type for singleton method of a class
|
38
|
+
$ rdl_query Array # print types for all methods of a class
|
39
|
+
$ rdl_query "(Fixnum) -> Fixnum" # print all methods that take a Fixnum and return a Fixnum
|
40
|
+
$ rdl_query "(.) -> Fixnum" # print all methods that take a single arg of any type
|
41
|
+
$ rdl_query "(..., Fixnum, ...) -> ." # print all methods that take a Fixnum as some argument
|
42
|
+
|
43
|
+
```
|
44
|
+
|
45
|
+
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
|
+
```
|
48
|
+
$ irb
|
36
49
|
> require 'rdl'
|
37
50
|
=> true
|
38
51
|
> require 'rdl_types'
|
39
52
|
=> true
|
40
53
|
|
41
|
-
> rdl_query '
|
42
|
-
Object#hash: () -> Fixnum
|
43
|
-
=> nil
|
44
|
-
> rdl_query 'String#include?' # get type for instance method of another class
|
45
|
-
String#include?: (String) -> FalseClass or TrueClass
|
46
|
-
=> nil
|
47
|
-
> rdl_query 'Pathname.glob' # get type for singleton method of a class
|
48
|
-
Pathname.glob: (String p1, ?String p2) -> Array<Pathname>
|
49
|
-
=> nil
|
54
|
+
> rdl_query '...' # as above
|
50
55
|
```
|
51
56
|
|
52
57
|
Currently only type information is returned by `rdl_query` (and not other pre or postconditions).
|
@@ -55,7 +60,7 @@ Currently only type information is returned by `rdl_query` (and not other pre or
|
|
55
60
|
|
56
61
|
## Supported versions of Ruby
|
57
62
|
|
58
|
-
RDL currently supports Ruby 2.
|
63
|
+
RDL currently supports Ruby 2.x. It may or may not work with other versions.
|
59
64
|
|
60
65
|
## Installing RDL
|
61
66
|
|
@@ -67,7 +72,7 @@ Use `require 'rdl'` to load the RDL library. If you want to use the core and sta
|
|
67
72
|
|
68
73
|
* 2.x
|
69
74
|
|
70
|
-
(Currently all these are
|
75
|
+
(Currently all these are assumed to have the same library type signatures, which may not be correct.)
|
71
76
|
|
72
77
|
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):
|
73
78
|
|
@@ -418,6 +423,58 @@ RDL also includes a few other useful methods:
|
|
418
423
|
|
419
424
|
* `rdl_nowrap`, if called at the top-level of a class, tells RDL to record contracts and types for methods in that class but *not* enforce them. This is mostly used for the core and standard libraries, which have trustworthy behavior hence enforcing their types and contracts is not worth the overhead.
|
420
425
|
|
426
|
+
* `rdl_query` prints information about types; see below for details.
|
427
|
+
|
428
|
+
## Queries
|
429
|
+
|
430
|
+
As discussed above, RDL includes a small script, `rdl_query`, to look up type information. (Currently it does not support other pre- and postconditions.) The script takes a single argument, which should be a string. Note that when using the shell script, you may need to use quotes depending on your shell. Currently several queries are supported:
|
431
|
+
|
432
|
+
* Instance methods can be looked up as `Class#method`.
|
433
|
+
|
434
|
+
```
|
435
|
+
$ rdl_query String#include?
|
436
|
+
String#include?: (String) -> TrueClass or FalseClass
|
437
|
+
```
|
438
|
+
|
439
|
+
* Singleton (class) methods can be looked up as `Class.method`.
|
440
|
+
|
441
|
+
```
|
442
|
+
$ rdl_query Pathname.glob
|
443
|
+
Pathname.glob: (String p1, ?String p2) -> Array<Pathname>
|
444
|
+
```
|
445
|
+
|
446
|
+
* All methods of a class can be listed by passing the class name `Class`.
|
447
|
+
|
448
|
+
```
|
449
|
+
$ rdl_query Array
|
450
|
+
&: (Array<u>) -> Array<t>
|
451
|
+
*: (String) -> String
|
452
|
+
... and a lot more
|
453
|
+
```
|
454
|
+
|
455
|
+
* Methods can also be search for by their type signature:
|
456
|
+
|
457
|
+
```
|
458
|
+
$ rdl_query "(Fixnum) -> Fixnum" # print all methods of type (Fixnum) -> Fixnum
|
459
|
+
BigDecimal.limit: (Fixnum) -> Fixnum
|
460
|
+
Dir#pos=: (Fixnum) -> Fixnum
|
461
|
+
... and a lot more
|
462
|
+
```
|
463
|
+
|
464
|
+
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
|
+
|
466
|
+
```
|
467
|
+
$ rdl_query "(.) -> ." # methods that take one argument and return anything
|
468
|
+
$ rdl_query "(Fixnum, .) -> ." # methods that take two arguments, the first of which is a Fixnum
|
469
|
+
$ rdl_query "(Fixnum, ...) -> ." # methods whose first argument is a Fixnum
|
470
|
+
$ rdl_query "(..., Fixnum) -> ." # methods whose last argument is a Fixnum
|
471
|
+
$ rdl_query "(..., Fixnum, ...) -> ." # methods that take a Fixnum somewhere
|
472
|
+
$ rdl_query "(Fixnum or .) -> ." # methods that take a single argument that is a union containing a Fixnum
|
473
|
+
$ rdl_query "(.?) -> ." # methods that take one, optional argument
|
474
|
+
```
|
475
|
+
|
476
|
+
Note that aside from `.` and `...`, the matching is exact. For example `(Fixnum) -> Fixnum` will not match a method of type `(Fixnum or String) -> Fixnum`.
|
477
|
+
|
421
478
|
# Bibliography
|
422
479
|
|
423
480
|
Here are some research papers we have written exploring contracts, types, and Ruby.
|
@@ -509,3 +566,9 @@ Copyright (c) 2014-2015, University of Maryland, College Park. All rights reserv
|
|
509
566
|
* Better query facility (more kinds of searches). Contract queries?
|
510
567
|
|
511
568
|
* Write documentation on: Raw Contracts and Types, RDL Configuration, Code Overview
|
569
|
+
|
570
|
+
* Structural type queries, allow name to be unknown; same with finite hash keys, same with generic base types?
|
571
|
+
|
572
|
+
* Allow ... in named args list in queries
|
573
|
+
|
574
|
+
* Queries, include more regexp operators aside from . and ...
|
data/bin/rdl_query
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../lib/rdl.rb' # Fix for release!
|
4
|
+
require_relative '../lib/rdl_types.rb' # Fix for release!
|
5
|
+
|
6
|
+
if ARGV.length != 1 then
|
7
|
+
print <<EOF
|
8
|
+
Usage: rdl_query <query>
|
9
|
+
|
10
|
+
Valid queries:
|
11
|
+
|
12
|
+
Class#method - Display type of instance method
|
13
|
+
Class.method - Display type of class (singleton) method
|
14
|
+
(method type) - Display methods that have given type
|
15
|
+
|
16
|
+
Method type queries follow the usual syntax for RDL types,
|
17
|
+
but can also include `.' to match any type, and `...' to
|
18
|
+
match any sequence of types. See the README.md file for more
|
19
|
+
detail.
|
20
|
+
EOF
|
21
|
+
exit 0
|
22
|
+
end
|
23
|
+
|
24
|
+
rdl_query(ARGV[0])
|
data/lib/rdl.rb
CHANGED
@@ -46,6 +46,7 @@ require_rel 'rdl/types/*.rb'
|
|
46
46
|
require_rel 'rdl/contracts/*.rb'
|
47
47
|
require_rel 'rdl/util.rb'
|
48
48
|
require_rel 'rdl/wrap.rb'
|
49
|
+
require_rel 'rdl/query.rb'
|
49
50
|
#require_rel 'rdl/stats.rb'
|
50
51
|
|
51
52
|
$__rdl_parser = RDL::Type::Parser.new
|
@@ -53,4 +54,4 @@ $__rdl_parser = RDL::Type::Parser.new
|
|
53
54
|
# Hash from special type names to their values
|
54
55
|
$__rdl_special_types = {'%any' => RDL::Type::TopType.new,
|
55
56
|
'%bool' => RDL::Type::UnionType.new(RDL::Type::NominalType.new(TrueClass),
|
56
|
-
RDL::Type::NominalType.new(FalseClass)) }
|
57
|
+
RDL::Type::NominalType.new(FalseClass)) }
|
data/lib/rdl/query.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
class RDL::Query
|
2
|
+
|
3
|
+
# Return a pair [name, array of the types] for the method specified by q. Valid queries are:
|
4
|
+
# Class#method - instance method
|
5
|
+
# Class.method - class method
|
6
|
+
# method - method of self's class
|
7
|
+
def self.method_query(q)
|
8
|
+
klass = nil
|
9
|
+
klass_pref = nil
|
10
|
+
meth = nil
|
11
|
+
if q =~ /(.+)#(.+)/
|
12
|
+
klass = $1
|
13
|
+
klass_pref = "#{klass}#"
|
14
|
+
meth = $2.to_sym
|
15
|
+
elsif q =~ /(.+)\.(.+)/
|
16
|
+
klass_pref = "#{$1}."
|
17
|
+
klass = RDL::Util.add_singleton_marker($1)
|
18
|
+
meth = $2.to_sym
|
19
|
+
else
|
20
|
+
klass = self.class.to_s
|
21
|
+
klass_pref = "#{klass}#"
|
22
|
+
meth = q.to_sym
|
23
|
+
end
|
24
|
+
name = "#{klass_pref}#{meth}"
|
25
|
+
if RDL::Wrap.has_contracts?(klass, meth, :type)
|
26
|
+
return [name, RDL::Wrap.get_contracts(klass, meth, :type)]
|
27
|
+
else
|
28
|
+
raise "No type for #{name}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Return an ordered list of all method types of a class. The query should be a class name.
|
33
|
+
def self.class_query(q)
|
34
|
+
klass = q.to_s
|
35
|
+
return [] unless $__rdl_contracts.has_key? klass
|
36
|
+
cls_meths = []
|
37
|
+
cls_klass = RDL::Util.add_singleton_marker(klass)
|
38
|
+
if $__rdl_contracts.has_key? cls_klass then
|
39
|
+
$__rdl_contracts[cls_klass].each { |meth, kinds|
|
40
|
+
if kinds.has_key? :type then
|
41
|
+
kinds[:type].each { |t| cls_meths << [meth.to_s, t] }
|
42
|
+
end
|
43
|
+
}
|
44
|
+
end
|
45
|
+
inst_meths = []
|
46
|
+
if $__rdl_contracts.has_key? klass then
|
47
|
+
$__rdl_contracts[klass].each { |meth, kinds|
|
48
|
+
if kinds.has_key? :type then
|
49
|
+
kinds[:type].each { |t| inst_meths << [meth.to_s, t] }
|
50
|
+
end
|
51
|
+
}
|
52
|
+
end
|
53
|
+
cls_meths.sort! { |p1,p2| p1[0] <=> p2[0] }
|
54
|
+
cls_meths.each { |m, t| m.insert(0, "self.") }
|
55
|
+
inst_meths.sort! { |p1,p2| p1[0] <=> p2[0] }
|
56
|
+
return cls_meths + inst_meths
|
57
|
+
end
|
58
|
+
|
59
|
+
# Return . The query should be a string containing a method type query.
|
60
|
+
def self.method_type_query(q)
|
61
|
+
q = $__rdl_parser.scan_str "#Q #{q}"
|
62
|
+
$__rdl_contracts.each { |klass, meths|
|
63
|
+
meths.each { |meth, kinds|
|
64
|
+
if kinds.has_key? :type then
|
65
|
+
kinds[:type].each { |t|
|
66
|
+
if q.match(t)
|
67
|
+
puts "#{RDL::Util.pretty_name(klass, meth)}: #{t}"
|
68
|
+
end
|
69
|
+
}
|
70
|
+
end
|
71
|
+
}
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
class Object
|
78
|
+
|
79
|
+
def rdl_query(q)
|
80
|
+
$__rdl_contract_switch.off {
|
81
|
+
if q =~ /^([A-Z]\w*(#|\.))?([a-z_]\w*(!|\?|=)?|!|~|\+|\*\*|-|\*|\/|%|<<|>>|&|\||\^|<|<=|=>|>|==|===|!=|=~|!~|<=>|\[\]|\[\]=)$/
|
82
|
+
name, typs = RDL::Query.method_query(q)
|
83
|
+
typs.each { |t|
|
84
|
+
puts "#{name}: #{t}"
|
85
|
+
}
|
86
|
+
elsif q =~ /^[A-Z]\w*$/
|
87
|
+
RDL::Query.class_query(q).each { |m, t| puts "#{m}: #{t}"}
|
88
|
+
elsif q =~ /(.*)/
|
89
|
+
RDL::Query.method_type_query(q)
|
90
|
+
else
|
91
|
+
raise "Don't know how to handle query"
|
92
|
+
end
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
@@ -10,7 +10,8 @@ module RDL::Type
|
|
10
10
|
def initialize(name, type)
|
11
11
|
@name = name
|
12
12
|
@type = type
|
13
|
-
raise RuntimeError, "Attempt to create
|
13
|
+
raise RuntimeError, "Attempt to create annotated type with non-type" unless type.is_a? Type
|
14
|
+
raise RuntimeError, "Attempt to create doubly annotated type" if type.is_a? AnnotatedArgType
|
14
15
|
super()
|
15
16
|
end
|
16
17
|
|
@@ -26,6 +27,8 @@ module RDL::Type
|
|
26
27
|
return (other.instance_of? AnnotatedArgType) && (other.name == @name) && (other.type == @type)
|
27
28
|
end
|
28
29
|
|
30
|
+
# doesn't have a match method - queries shouldn't have annotations in them
|
31
|
+
|
29
32
|
def hash # :nodoc:
|
30
33
|
return (57 + @name.hash) * @type.hash
|
31
34
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative 'type_query'
|
2
|
+
|
3
|
+
module RDL::Type
|
4
|
+
class DotsQuery < TypeQuery
|
5
|
+
@@cache = nil
|
6
|
+
|
7
|
+
class << self
|
8
|
+
alias :__new__ :new
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.new
|
12
|
+
@@cache = DotsQuery.__new__ unless @@cache
|
13
|
+
return @@cache
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
"..."
|
18
|
+
end
|
19
|
+
|
20
|
+
def ==(other)
|
21
|
+
return (other.instance_of? DotsQuery)
|
22
|
+
end
|
23
|
+
|
24
|
+
# doesn't have match method---taken care of at a higher level, in MethodType#match
|
25
|
+
end
|
26
|
+
end
|
data/lib/rdl/types/finitehash.rb
CHANGED
@@ -20,6 +20,7 @@ module RDL::Type
|
|
20
20
|
return (@@cache[elts] = t) # assignment evaluates to t
|
21
21
|
end
|
22
22
|
|
23
|
+
# [+elts+] is a map from keys to types
|
23
24
|
def initialize(elts)
|
24
25
|
elts.each { |k, t|
|
25
26
|
raise RuntimeError, "Got #{t.inspect} where Type expected" unless t.is_a? Type
|
@@ -41,20 +42,27 @@ module RDL::Type
|
|
41
42
|
return (other.instance_of? FiniteHashType) && (other.elts == @elts)
|
42
43
|
end
|
43
44
|
|
45
|
+
def match(other)
|
46
|
+
other = other.type if other.instance_of? AnnotatedArgType
|
47
|
+
return true if other.instance_of? WildQuery
|
48
|
+
return (@elts.length == other.elts.length &&
|
49
|
+
@elts.all? { |k, v| (other.elts.has_key? k) && (v.match(other.elts[k]))})
|
50
|
+
end
|
51
|
+
|
44
52
|
def <=(other)
|
45
53
|
return true if other.instance_of? TopType
|
46
54
|
return self == other
|
47
55
|
# Subtyping with Hash not allowed
|
48
56
|
# All positions of HashTuple are invariant since tuples are mutable
|
49
57
|
end
|
50
|
-
|
58
|
+
|
51
59
|
def member?(obj, *args)
|
52
60
|
t = RDL::Util.rdl_type obj
|
53
61
|
return t <= self if t
|
54
62
|
rest = @elts.clone # shallow copy
|
55
63
|
|
56
64
|
return false unless obj.instance_of? Hash
|
57
|
-
|
65
|
+
|
58
66
|
# Check that every mapping in obj exists in @map and matches the type
|
59
67
|
obj.each_pair { |k, v|
|
60
68
|
return false unless @elts.has_key?(k)
|
@@ -73,7 +81,7 @@ module RDL::Type
|
|
73
81
|
def instantiate(inst)
|
74
82
|
FiniteHashType.new(Hash[@elts.map { |k, t| [k, t.instantiate(inst)] }])
|
75
83
|
end
|
76
|
-
|
84
|
+
|
77
85
|
def hash
|
78
86
|
h = 229 * @elts.hash
|
79
87
|
end
|
data/lib/rdl/types/generic.rb
CHANGED
@@ -41,6 +41,12 @@ module RDL::Type
|
|
41
41
|
return (other.instance_of? GenericType) && (other.base == @base) && (other.params == @params)
|
42
42
|
end
|
43
43
|
|
44
|
+
def match(other)
|
45
|
+
other = other.type if other.instance_of? AnnotatedArgType
|
46
|
+
return true if other.instance_of? WildQuery
|
47
|
+
return @params.length == other.params.length && @params.zip(other.params).all? { |t,o| t.match(o) }
|
48
|
+
end
|
49
|
+
|
44
50
|
def <=(other)
|
45
51
|
formals, variance, check = $__rdl_type_params[base.name]
|
46
52
|
# do check here to avoid hiding errors if generic type written
|
@@ -79,7 +85,7 @@ module RDL::Type
|
|
79
85
|
end
|
80
86
|
return false
|
81
87
|
end
|
82
|
-
|
88
|
+
|
83
89
|
def member?(obj, *args)
|
84
90
|
raise "No type parameters defined for #{base.name}" unless $__rdl_type_params[base.name]
|
85
91
|
formals = $__rdl_type_params[base.name][0]
|
@@ -92,7 +98,7 @@ module RDL::Type
|
|
92
98
|
def instantiate(inst)
|
93
99
|
GenericType.new(base, *params.map { |t| t.instantiate(inst) })
|
94
100
|
end
|
95
|
-
|
101
|
+
|
96
102
|
def hash
|
97
103
|
h = (61 + @base.hash) * @params.hash
|
98
104
|
end
|
@@ -42,7 +42,7 @@ module RDL::Type
|
|
42
42
|
def to_s # :nodoc:
|
43
43
|
"(#{@types.map { |t| t.to_s }.join(' and ')})"
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
def eql?(other)
|
47
47
|
self == other
|
48
48
|
end
|
@@ -51,14 +51,21 @@ module RDL::Type
|
|
51
51
|
return (other.instance_of? IntersectionType) && (other.types == @types)
|
52
52
|
end
|
53
53
|
|
54
|
+
def match(other)
|
55
|
+
other = other.type if other.instance_of? AnnotatedArgType
|
56
|
+
return true if other.instance_of? WildQuery
|
57
|
+
return false if @types.length != other.types.length
|
58
|
+
@types.all? { |t| other.types.any? { |ot| t.match(ot) } }
|
59
|
+
end
|
60
|
+
|
54
61
|
def member?(obj, *args)
|
55
62
|
@types.all? { |t| t.member?(obj, *args) }
|
56
63
|
end
|
57
|
-
|
64
|
+
|
58
65
|
def instantiate(inst)
|
59
66
|
return IntersectionType.new(*(@types.map { |t| t.instantiate(inst) }))
|
60
67
|
end
|
61
|
-
|
68
|
+
|
62
69
|
def hash # :nodoc:
|
63
70
|
47 + @types.hash
|
64
71
|
end
|
data/lib/rdl/types/lexer.rex
CHANGED
@@ -24,8 +24,11 @@ rule
|
|
24
24
|
, { [:COMMA, text] }
|
25
25
|
\? { [:QUERY, text] }
|
26
26
|
\* { [:STAR, text] }
|
27
|
-
|
27
|
+
\#T { [:HASH_TYPE, text] }
|
28
|
+
\#Q { [:HASH_QUERY, text] }
|
28
29
|
\$\{ { [:CONST_BEGIN, text] }
|
30
|
+
\.\.\. { [:DOTS, text] }
|
31
|
+
\. { [:DOT, text] }
|
29
32
|
{FLOAT} { [:FLOAT, text] } # Must go before FIXNUM
|
30
33
|
{FIXNUM} { [:FIXNUM, text] }
|
31
34
|
{ID} { [:ID, text] }
|