rdl 1.0.0 → 1.0.1.rc1

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.
@@ -6,7 +6,7 @@ module RDL::Type
6
6
 
7
7
  @@cache = {}
8
8
  @@cache.compare_by_identity
9
-
9
+
10
10
  class << self
11
11
  alias :__new__ :new
12
12
  end
@@ -30,6 +30,12 @@ module RDL::Type
30
30
  return (other.instance_of? self.class) && (other.val.equal? @val)
31
31
  end
32
32
 
33
+ def match(other)
34
+ other = other.type if other.instance_of? AnnotatedArgType
35
+ return true if other.instance_of? WildQuery
36
+ return self == other
37
+ end
38
+
33
39
  def hash # :nodoc:
34
40
  return @val.hash
35
41
  end
@@ -38,7 +44,8 @@ module RDL::Type
38
44
  if @val.instance_of? Symbol
39
45
  ":{@val}"
40
46
  else
41
- "Singleton(#{@val.to_s})"
47
+ @val.to_s
48
+ # "Singleton(#{@val.to_s})"
42
49
  end
43
50
  end
44
51
 
@@ -54,7 +61,7 @@ module RDL::Type
54
61
  return t <= self if t
55
62
  obj.nil? || obj.equal?(@val)
56
63
  end
57
-
64
+
58
65
  def instantiate(inst)
59
66
  return self
60
67
  end
@@ -52,11 +52,11 @@ module RDL::Type
52
52
  return t <= self if t
53
53
  return NominalType.new(obj.class) <= self
54
54
  end
55
-
55
+
56
56
  def instantiate(inst)
57
57
  StructuralType.new(Hash[*@methods.each_pair.map { |m, t| [m, t.instantiate(inst)] }.flatten])
58
58
  end
59
-
59
+
60
60
  def eql?(other)
61
61
  self == other
62
62
  end
@@ -65,6 +65,13 @@ module RDL::Type
65
65
  return (other.instance_of? StructuralType) && (other.methods == @methods)
66
66
  end
67
67
 
68
+ def match(other)
69
+ other = other.type if other.instance_of? AnnotatedArgType
70
+ return true if other.instance_of? WildQuery
71
+ return (@methods.length == other.methods.length &&
72
+ @methods.all? { |k, v| (other.methods.has_key? k) && (v.match(other.methods[k]))})
73
+ end
74
+
68
75
  def hash # :nodoc:
69
76
  @methods.hash
70
77
  end
data/lib/rdl/types/top.rb CHANGED
@@ -24,11 +24,17 @@ module RDL::Type
24
24
  def eql?(other)
25
25
  self == other
26
26
  end
27
-
27
+
28
28
  def ==(other)
29
29
  other.instance_of? TopType
30
30
  end
31
31
 
32
+ def match(other)
33
+ other = other.type if other.instance_of? AnnotatedArgType
34
+ return true if other.instance_of? WildQuery
35
+ return self == other
36
+ end
37
+
32
38
  def <=(other)
33
39
  other.instance_of? TopType
34
40
  end
@@ -38,11 +44,11 @@ module RDL::Type
38
44
  return t <= self if t
39
45
  true
40
46
  end
41
-
47
+
42
48
  def instantiate(inst)
43
49
  return self
44
50
  end
45
-
51
+
46
52
  def hash
47
53
  17
48
54
  end
@@ -14,7 +14,7 @@ module RDL::Type
14
14
  def self.new(*params)
15
15
  t = @@cache[params]
16
16
  return t if t
17
- raise RuntimeError, "Attempt to create generic type with non-type param" unless params.all? { |p| p.is_a? Type }
17
+ raise RuntimeError, "Attempt to create tuple type with non-type param" unless params.all? { |p| p.is_a? Type }
18
18
  t = TupleType.__new__(params)
19
19
  return (@@cache[params] = t) # assignment evaluates to t
20
20
  end
@@ -36,13 +36,19 @@ module RDL::Type
36
36
  return (other.instance_of? TupleType) && (other.params == @params)
37
37
  end
38
38
 
39
+ def match(other)
40
+ other = other.type if other.instance_of? AnnotatedArgType
41
+ return true if other.instance_of? WildQuery
42
+ return @params.length == other.params.length && @params.zip(other.params).all? { |t,o| t.match(o) }
43
+ end
44
+
39
45
  def <=(other)
40
46
  return true if other.instance_of? TopType
41
47
  return self == other
42
48
  # Subtyping with Array not allowed
43
49
  # All positions of Tuple are invariant since tuples are mutable
44
50
  end
45
-
51
+
46
52
  def member?(obj, *args)
47
53
  t = RDL::Util.rdl_type obj
48
54
  return t <= self if t
@@ -53,7 +59,7 @@ module RDL::Type
53
59
  def instantiate(inst)
54
60
  TupleType.new(*@params.map { |t| t.instantiate(inst) })
55
61
  end
56
-
62
+
57
63
  def hash
58
64
  h = 73 * @params.hash
59
65
  end
@@ -0,0 +1,5 @@
1
+ module RDL::Type
2
+ class TypeQuery < Type
3
+
4
+ end
5
+ end
@@ -3,7 +3,7 @@ require_relative 'type'
3
3
  module RDL::Type
4
4
  class UnionType < Type
5
5
  attr_reader :types
6
-
6
+
7
7
  @@cache = {}
8
8
 
9
9
  class << self
@@ -26,7 +26,7 @@ module RDL::Type
26
26
  end
27
27
  }
28
28
 
29
- ts.sort! { |a,b| a.object_id <=> b.object_id }
29
+ ts.sort! { |a,b| a.object_id <=> b.object_id }
30
30
  ts.uniq!
31
31
 
32
32
  return NilType.new if ts.size == 0
@@ -55,6 +55,13 @@ module RDL::Type
55
55
  return (other.instance_of? UnionType) && (other.types == @types)
56
56
  end
57
57
 
58
+ def match(other)
59
+ other = other.type if other.instance_of? AnnotatedArgType
60
+ return true if other.instance_of? WildQuery
61
+ return false if @types.length != other.types.length
62
+ @types.all? { |t| other.types.any? { |ot| t.match(ot) } }
63
+ end
64
+
58
65
  def <=(other)
59
66
  @types.all? { |t| t <= other }
60
67
  end
@@ -62,11 +69,11 @@ module RDL::Type
62
69
  def member?(obj, *args)
63
70
  @types.any? { |t| t.member?(obj, *args) }
64
71
  end
65
-
72
+
66
73
  def instantiate(inst)
67
74
  return UnionType.new(*(@types.map { |t| t.instantiate(inst) }))
68
75
  end
69
-
76
+
70
77
  def hash # :nodoc:
71
78
  41 + @types.hash
72
79
  end
data/lib/rdl/types/var.rb CHANGED
@@ -34,6 +34,12 @@ module RDL::Type
34
34
  return (other.instance_of? self.class) && (other.name.to_s == @name.to_s)
35
35
  end
36
36
 
37
+ def match(other)
38
+ other = other.type if other.instance_of? AnnotatedArgType
39
+ return true if other.instance_of? WildQuery
40
+ return self == other
41
+ end
42
+
37
43
  def hash # :nodoc:
38
44
  return @name.to_s.hash
39
45
  end
@@ -41,12 +41,18 @@ module RDL::Type
41
41
  return (other.instance_of? VarargType) && (other.type == @type)
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 (other.instance_of? VarargType) && (@type.match(other.type))
48
+ end
49
+
44
50
  # Note: no member?, because these can only appear in MethodType, where they're handled specially
45
-
51
+
46
52
  def instantiate(inst)
47
53
  return VarargType.new(@type.instantiate(inst))
48
54
  end
49
-
55
+
50
56
  def hash # :nodoc:
51
57
  return 59 + @type.hash
52
58
  end
@@ -0,0 +1,28 @@
1
+ require_relative 'type_query'
2
+
3
+ module RDL::Type
4
+ class WildQuery < TypeQuery
5
+ @@cache = nil
6
+
7
+ class << self
8
+ alias :__new__ :new
9
+ end
10
+
11
+ def self.new
12
+ @@cache = WildQuery.__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? WildQuery)
22
+ end
23
+
24
+ def match(other)
25
+ return true
26
+ end
27
+ end
28
+ end
data/lib/rdl/util.rb CHANGED
@@ -1,4 +1,8 @@
1
1
  class RDL::Util
2
+
3
+ SINGLETON_MARKER = "[s]"
4
+ SINGLETON_MARKER_REGEXP = Regexp.escape(SINGLETON_MARKER)
5
+
2
6
  def self.to_class(klass)
3
7
  return klass if klass.class == Class
4
8
  if has_singleton_marker(klass)
@@ -11,11 +15,11 @@ class RDL::Util
11
15
  end
12
16
 
13
17
  def self.has_singleton_marker(klass)
14
- return (klass =~ /^\[singleton\]/)
18
+ return (klass =~ /^#{SINGLETON_MARKER_REGEXP}/)
15
19
  end
16
-
20
+
17
21
  def self.remove_singleton_marker(klass)
18
- if klass =~ /^\[singleton\](.*)/
22
+ if klass =~ /^#{SINGLETON_MARKER_REGEXP}(.*)/
19
23
  return $1
20
24
  else
21
25
  return nil
@@ -23,9 +27,18 @@ class RDL::Util
23
27
  end
24
28
 
25
29
  def self.add_singleton_marker(klass)
26
- return "[singleton]" + klass
30
+ return SINGLETON_MARKER + klass
31
+ end
32
+
33
+ # Klass should be a string and may have a singleton marker
34
+ def self.pretty_name(klass, meth)
35
+ if klass =~ /^#{SINGLETON_MARKER_REGEXP}(.*)/
36
+ return "#{$1}.#{meth}"
37
+ else
38
+ return "#{klass}##{meth}"
39
+ end
27
40
  end
28
-
41
+
29
42
  def self.method_defined?(klass, method)
30
43
  begin
31
44
  (self.to_class klass).method_defined?(method.to_sym) ||
data/lib/rdl/wrap.rb CHANGED
@@ -418,7 +418,7 @@ class Object
418
418
  raise RuntimeError, "Receiver is of class #{klass}, which is not parameterized" unless formals
419
419
  raise RuntimeError, "Expecting #{params.size} type parameters, got #{typs.size}" unless formals.size == typs.size
420
420
  raise RuntimeError, "Instance already has type instantiation" if @__rdl_type
421
- new_typs = typs.map { |t| if t.is_a? RDL::Type::Type then t else $__rdl_parser.scan_str "## #{t}" end }
421
+ new_typs = typs.map { |t| if t.is_a? RDL::Type::Type then t else $__rdl_parser.scan_str "#T #{t}" end }
422
422
  t = RDL::Type::GenericType.new(RDL::Type::NominalType.new(klass), *new_typs)
423
423
  if all.instance_of? Symbol
424
424
  self.send(all) { |*objs|
@@ -451,7 +451,7 @@ class Object
451
451
  # Returns a new object that wraps self in a type cast. This cast is *unchecked*, so use with caution
452
452
  def type_cast(typ)
453
453
  $__rdl_contract_switch.off {
454
- new_typ = if typ.is_a? RDL::Type::Type then typ else $__rdl_parser.scan_str "## #{typ}" end
454
+ new_typ = if typ.is_a? RDL::Type::Type then typ else $__rdl_parser.scan_str "#T #{typ}" end
455
455
  obj = SimpleDelegator.new(self)
456
456
  obj.instance_variable_set('@__rdl_type', new_typ)
457
457
  return obj
@@ -467,7 +467,7 @@ class Object
467
467
  raise RuntimeError, "Attempt to redefine type #{name}" if $__rdl_special_types[name]
468
468
  case typ
469
469
  when String
470
- t = $__rdl_parser.scan_str "## #{typ}"
470
+ t = $__rdl_parser.scan_str "#T #{typ}"
471
471
  $__rdl_special_types[name] = t
472
472
  when RDL::Type::Type
473
473
  $__rdl_special_types[name] = typ
@@ -476,38 +476,4 @@ class Object
476
476
  end
477
477
  }
478
478
  end
479
-
480
- def rdl_query(q)
481
- $__rdl_contract_switch.off {
482
- if q =~ /^(\w+(#|\.))?(\w+(!|\?|=)?|!|~|\+|\*\*|-|\*|\/|%|<<|>>|&|\||\^|<|<=|=>|>|==|===|!=|=~|!~|<=>|\[\]|\[\]=)$/
483
- klass = nil
484
- klass_pref = nil
485
- meth = nil
486
- if q =~ /(.+)#(.+)/
487
- klass = $1
488
- klass_pref = "#{klass}#"
489
- meth = $2.to_sym
490
- elsif q =~ /(.+)\.(.+)/
491
- klass_pref = "#{$1}."
492
- klass = RDL::Util.add_singleton_marker($1)
493
- meth = $2.to_sym
494
- else
495
- klass = self.class.to_s
496
- klass_pref = "#{klass}#"
497
- meth = q.to_sym
498
- end
499
- if RDL::Wrap.has_contracts?(klass, meth, :type)
500
- typs = RDL::Wrap.get_contracts(klass, meth, :type)
501
- typs.each { |t|
502
- puts "#{klass_pref}#{meth}: #{t}"
503
- }
504
- nil
505
- else
506
- puts "No type for #{klass_pref}#{meth}"
507
- end
508
- else
509
- puts "Not implemented"
510
- end
511
- }
512
- end
513
479
  end
data/rdl.gemspec CHANGED
@@ -4,8 +4,8 @@
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'rdl'
7
- s.version = '1.0.0'
8
- s.date = '2015-12-18'
7
+ s.version = '1.0.1.rc1'
8
+ s.date = '2016-01-01'
9
9
  s.summary = 'Ruby type and contract system'
10
10
  s.description = <<-EOF
11
11
  RDL is a gem that allows contracts (pre- and postconditions) to be added to methods.
@@ -17,6 +17,7 @@ EOF
17
17
  s.authors = ['Jeffrey S. Foster', 'Brianna M. Ren', 'T. Stephen Strickland', 'Alexander T. Yu']
18
18
  s.email = ['rdl-users@googlegroups.com']
19
19
  s.files = `git ls-files`.split($/)
20
+ s.executables << 'rdl_query'
20
21
  s.homepage = 'https://github.com/plum-umd/rdl'
21
22
  s.license = 'BSD-3-Clause'
22
23
  s.add_runtime_dependency 'require_all', '~> 1.3', '>= 1.3.3'
data/test/test_parser.rb CHANGED
@@ -72,16 +72,16 @@ class TestParser < Minitest::Test
72
72
  end
73
73
 
74
74
  def test_bare
75
- t1 = @p.scan_str "## nil"
75
+ t1 = @p.scan_str "#T nil"
76
76
  assert_equal @tnil, t1
77
- t2 = @p.scan_str "## %any"
77
+ t2 = @p.scan_str "#T %any"
78
78
  assert_equal @ttop, t2
79
- t3 = @p.scan_str "## A"
79
+ t3 = @p.scan_str "#T A"
80
80
  assert_equal NominalType.new("A"), t3
81
81
  end
82
82
 
83
83
  def test_symbol
84
- t1 = @p.scan_str "## :symbol"
84
+ t1 = @p.scan_str "#T :symbol"
85
85
  assert_equal @tsymbol, t1
86
86
  end
87
87
 
@@ -109,66 +109,66 @@ class TestParser < Minitest::Test
109
109
  end
110
110
 
111
111
  def test_generic
112
- t1 = @p.scan_str "## t"
112
+ t1 = @p.scan_str "#T t"
113
113
  assert_equal (VarType.new "t"), t1
114
- t2 = @p.scan_str "## Array"
114
+ t2 = @p.scan_str "#T Array"
115
115
  assert_equal (NominalType.new "Array"), t2
116
- t3 = @p.scan_str "## Array<t>"
116
+ t3 = @p.scan_str "#T Array<t>"
117
117
  assert_equal (GenericType.new(t2, t1)), t3
118
- t4 = @p.scan_str "## Array<Array<t>>"
118
+ t4 = @p.scan_str "#T Array<Array<t>>"
119
119
  assert_equal (GenericType.new(t2, t3)), t4
120
- t5 = @p.scan_str "## Hash"
120
+ t5 = @p.scan_str "#T Hash"
121
121
  assert_equal (NominalType.new "Hash"), t5
122
- t6 = @p.scan_str "## Hash<u, v>"
122
+ t6 = @p.scan_str "#T Hash<u, v>"
123
123
  assert_equal (GenericType.new(t5, VarType.new("u"), VarType.new("v"))), t6
124
- t7 = @p.scan_str "## Foo<String, Array<t>, Array<Array<t>>>"
124
+ t7 = @p.scan_str "#T Foo<String, Array<t>, Array<Array<t>>>"
125
125
  assert_equal (GenericType.new(NominalType.new("Foo"), @tstring, t3, t4)), t7
126
126
  end
127
127
 
128
128
  def test_tuple
129
- t1 = @p.scan_str "## [Fixnum, String]"
129
+ t1 = @p.scan_str "#T [Fixnum, String]"
130
130
  assert_equal (TupleType.new(@tfixnum, @tstring)), t1
131
- t2 = @p.scan_str "## [String]"
131
+ t2 = @p.scan_str "#T [String]"
132
132
  assert_equal (TupleType.new(@tstring)), t2
133
- end
133
+ end
134
134
 
135
135
  def test_fixnum
136
- t1 = @p.scan_str "## 42"
136
+ t1 = @p.scan_str "#T 42"
137
137
  assert_equal (SingletonType.new(42)), t1
138
- t2 = @p.scan_str "## -42"
138
+ t2 = @p.scan_str "#T -42"
139
139
  assert_equal (SingletonType.new(-42)), t2
140
140
  end
141
141
 
142
142
  def test_float
143
- t1 = @p.scan_str "## 3.14"
143
+ t1 = @p.scan_str "#T 3.14"
144
144
  assert_equal (SingletonType.new(3.14)), t1
145
145
  end
146
146
 
147
147
  def test_const
148
- t1 = @p.scan_str "## ${Math::PI}"
148
+ t1 = @p.scan_str "#T ${Math::PI}"
149
149
  assert_equal (SingletonType.new(Math::PI)), t1
150
150
  end
151
151
 
152
152
  def test_type_alias
153
153
  type_alias '%foobarbaz', @tnil
154
- assert_equal @tnil, (@p.scan_str "## %foobarbaz")
154
+ assert_equal @tnil, (@p.scan_str "#T %foobarbaz")
155
155
  type_alias '%quxquxqux', 'nil'
156
- assert_equal @tnil, (@p.scan_str "## %quxquxqux")
156
+ assert_equal @tnil, (@p.scan_str "#T %quxquxqux")
157
157
  assert_raises(RuntimeError) { type_alias '%quxquxqux', 'nil' }
158
- assert_raises(RuntimeError) { @p.scan_str "## %qux" }
158
+ assert_raises(RuntimeError) { @p.scan_str "#T %qux" }
159
159
  end
160
160
 
161
161
  def test_structural
162
- t1 = @p.scan_str "## [to_str: () -> String]"
162
+ t1 = @p.scan_str "#T [to_str: () -> String]"
163
163
  tm1 = MethodType.new [], nil, @tstring
164
164
  ts1 = StructuralType.new(to_str: tm1)
165
165
  assert_equal ts1, t1
166
166
  end
167
167
 
168
168
  def test_finite_hash
169
- t1 = @p.scan_str "## {a: Fixnum, b: String}"
169
+ t1 = @p.scan_str "#T {a: Fixnum, b: String}"
170
170
  assert_equal (FiniteHashType.new({a: @tfixnum, b: @tstring})), t1
171
- t2 = @p.scan_str "## {'a'=>Fixnum, 2=>String}"
171
+ t2 = @p.scan_str "#T {'a'=>Fixnum, 2=>String}"
172
172
  assert_equal (FiniteHashType.new({"a"=>@tfixnum, 2=>@tstring})), t2
173
173
  end
174
174