rdl 1.0.0.rc3 → 1.0.0.rc4
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.
- checksums.yaml +4 -4
- data/.gitignore +44 -0
- data/.travis.yml +19 -0
- data/LICENSE +29 -0
- data/README.md +509 -0
- data/Rakefile +27 -0
- data/gemfiles/Gemfile.travis +5 -0
- data/lib/rdl/wrap.rb +1 -1
- data/lib/rdl_types.rb +4 -2
- data/rdl.gemspec +23 -0
- data/test/disabled_test_coverage.rb +156 -0
- data/test/disabled_test_rdoc.rb +116 -0
- data/test/test_alias.rb +66 -0
- data/test/test_contract.rb +70 -0
- data/test/test_dsl.rb +85 -0
- data/test/test_generic.rb +188 -0
- data/test/test_intersection.rb +41 -0
- data/test/test_le.rb +193 -0
- data/test/test_lib_types.rb +194 -0
- data/test/test_member.rb +148 -0
- data/test/test_parser.rb +196 -0
- data/test/test_rdl.rb +301 -0
- data/test/test_rdl_type.rb +70 -0
- data/test/test_type_contract.rb +187 -0
- data/test/test_types.rb +221 -0
- data/test/test_wrap.rb +46 -0
- data/types/{ruby-2.2.0 → ruby-2.x}/_aliases.rb +0 -0
- data/types/{ruby-2.2.0 → ruby-2.x}/abbrev.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/array.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/base64.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/basic_object.rb +2 -1
- data/types/{ruby-2.2.0 → ruby-2.x}/benchmark.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/bigdecimal.rb +4 -4
- data/types/{ruby-2.2.0 → ruby-2.x}/bigmath.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/class.rb +3 -3
- data/types/{ruby-2.2.0 → ruby-2.x}/complex.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/coverage.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/csv.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/date.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/dir.rb +3 -3
- data/types/{ruby-2.2.0 → ruby-2.x}/encoding.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/enumerable.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/enumerator.rb +1 -1
- data/types/{ruby-2.2.0 → ruby-2.x}/exception.rb +2 -0
- data/types/{ruby-2.2.0 → ruby-2.x}/file.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/fileutils.rb +1 -1
- data/types/{ruby-2.2.0 → ruby-2.x}/fixnum.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/float.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/gem.rb +3 -1
- data/types/{ruby-2.2.0 → ruby-2.x}/hash.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/integer.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/io.rb +1 -1
- data/types/{ruby-2.2.0 → ruby-2.x}/kernel.rb +1 -1
- data/types/{ruby-2.2.0 → ruby-2.x}/marshal.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/matchdata.rb +3 -3
- data/types/{ruby-2.2.0 → ruby-2.x}/math.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/numeric.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/object.rb +1 -1
- data/types/{ruby-2.2.0 → ruby-2.x}/pathname.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/process.rb +8 -8
- data/types/{ruby-2.2.0 → ruby-2.x}/random.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/range.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/rational.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/regexp.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/set.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/string.rb +1 -1
- data/types/{ruby-2.2.0 → ruby-2.x}/strscan.rb +3 -3
- data/types/{ruby-2.2.0 → ruby-2.x}/symbol.rb +2 -2
- data/types/{ruby-2.2.0 → ruby-2.x}/time.rb +2 -2
- data/types/ruby-2.x/uri.rb +20 -0
- data/types/{ruby-2.2.0 → ruby-2.x}/yaml.rb +3 -3
- metadata +70 -51
- data/lib/rdl/types/wild.rb +0 -26
- data/types/other/chronic.rb +0 -5
- data/types/other/paperclip_attachment.rb +0 -7
- data/types/other/securerandom.rb +0 -4
- data/types/ruby-2.2.0/uri.rb +0 -18
data/test/test_dsl.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require_relative '../lib/rdl.rb'
|
3
|
+
|
4
|
+
class TestDsl < Minitest::Test
|
5
|
+
|
6
|
+
class Pair
|
7
|
+
|
8
|
+
# dsl {
|
9
|
+
# type :left, '(Fixnum) -> Fixnum'
|
10
|
+
# type :right, '(Fixnum) -> Fixnum'
|
11
|
+
# }
|
12
|
+
def entry(&blk)
|
13
|
+
instance_eval(&blk)
|
14
|
+
end
|
15
|
+
|
16
|
+
def left(x)
|
17
|
+
@left = x
|
18
|
+
end
|
19
|
+
|
20
|
+
def right(x)
|
21
|
+
@right = x
|
22
|
+
end
|
23
|
+
|
24
|
+
def get
|
25
|
+
[@left, @right]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Tree
|
30
|
+
|
31
|
+
# dsl :tree { # recursive DSL
|
32
|
+
# type :left, '(Fixnum) -> Fixnum'
|
33
|
+
# dsl :left, :tree
|
34
|
+
# type :right, '(Fixnum) -> Fixnum'
|
35
|
+
# dsl :right, :tree
|
36
|
+
# }
|
37
|
+
def entry(val, &blk)
|
38
|
+
@val = val
|
39
|
+
instance_eval(&blk)
|
40
|
+
end
|
41
|
+
|
42
|
+
def left(x, &blk)
|
43
|
+
if blk
|
44
|
+
@left = Tree.new.entry(x, &blk)
|
45
|
+
else
|
46
|
+
@left = x
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def right(x, &blk)
|
51
|
+
if blk
|
52
|
+
@right = Tree.new.entry(x, &blk)
|
53
|
+
else
|
54
|
+
@right = x
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def get
|
59
|
+
l = @left.instance_of?(Tree) ? @left.get : @left
|
60
|
+
r = @right.instance_of?(Tree) ? @right.get : @right
|
61
|
+
[@val, l, r]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_pair
|
66
|
+
p = Pair.new.entry {
|
67
|
+
left 3
|
68
|
+
right 4
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_tree
|
73
|
+
t = Tree.new.entry(2) {
|
74
|
+
left(3)
|
75
|
+
right(4) {
|
76
|
+
left(5) {
|
77
|
+
left(6)
|
78
|
+
right(7)
|
79
|
+
}
|
80
|
+
right(8)
|
81
|
+
}
|
82
|
+
}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require_relative '../lib/rdl.rb'
|
3
|
+
|
4
|
+
class TestGeneric < Minitest::Test
|
5
|
+
|
6
|
+
# Make two classes that wrap Array and Hash, so we don't mess with their
|
7
|
+
# implementations in test case evaluation.
|
8
|
+
class A
|
9
|
+
type_params [:t], :all?
|
10
|
+
def initialize(a); @a = a end
|
11
|
+
def all?(&blk)
|
12
|
+
@a.all?(&blk)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class H
|
17
|
+
type_params [:k, :v], :all?
|
18
|
+
def initialize(h); @h = h end
|
19
|
+
def all?(&blk)
|
20
|
+
@h.all? { |x, y| blk.call(x, y) } # have to do extra wrap to avoid splat issues
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class B
|
25
|
+
# class for checking other variance annotations
|
26
|
+
type_params [:a, :b], nil, variance: [:+, :-] { |a, b| true }
|
27
|
+
type "(a) -> nil"
|
28
|
+
def m1(x)
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
def m2(x) # no type annotation
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def setup
|
37
|
+
@ta = RDL::Type::NominalType.new "TestGeneric::A"
|
38
|
+
@th = RDL::Type::NominalType.new "TestGeneric::H"
|
39
|
+
@tstring = RDL::Type::NominalType.new "String"
|
40
|
+
@tobject = RDL::Type::NominalType.new "Object"
|
41
|
+
@tfixnum = RDL::Type::NominalType.new "Fixnum"
|
42
|
+
@tas = RDL::Type::GenericType.new(@ta, @tstring)
|
43
|
+
@tao = RDL::Type::GenericType.new(@ta, @tobject)
|
44
|
+
@taas = RDL::Type::GenericType.new(@ta, @tas)
|
45
|
+
@taao = RDL::Type::GenericType.new(@ta, @tao)
|
46
|
+
@thss = RDL::Type::GenericType.new(@th, @tstring, @tstring)
|
47
|
+
@thoo = RDL::Type::GenericType.new(@th, @tobject, @tobject)
|
48
|
+
@thsf = RDL::Type::GenericType.new(@th, @tstring, @tfixnum)
|
49
|
+
@tb = RDL::Type::NominalType.new "TestGeneric::B"
|
50
|
+
@tnil = RDL::Type::NilType.new
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_le
|
54
|
+
# Check invariance for A and H
|
55
|
+
assert (@tas <= @tas)
|
56
|
+
assert (@tao <= @tao)
|
57
|
+
assert (@taas <= @taas)
|
58
|
+
assert (@thss <= @thss)
|
59
|
+
assert (@thoo <= @thoo)
|
60
|
+
assert (not (@tas <= @tao))
|
61
|
+
assert (not (@tao <= @tas))
|
62
|
+
assert (not (@thss <= @thoo))
|
63
|
+
assert (not (@thoo <= @thss))
|
64
|
+
|
65
|
+
# Check "raw" class subtyping is forbidden
|
66
|
+
assert (not (@ta <= @tas))
|
67
|
+
assert (not (@tas <= @ta))
|
68
|
+
assert (not (@ta <= @taas))
|
69
|
+
assert (not (@taas <= @ta))
|
70
|
+
assert (not (@th <= @thss))
|
71
|
+
assert (not (@thss <= @th))
|
72
|
+
|
73
|
+
# Check co- and contravariance using B
|
74
|
+
tbss = RDL::Type::GenericType.new(@tb, @tstring, @tstring)
|
75
|
+
tbso = RDL::Type::GenericType.new(@tb, @tstring, @tobject)
|
76
|
+
tbos = RDL::Type::GenericType.new(@tb, @tobject, @tstring)
|
77
|
+
tboo = RDL::Type::GenericType.new(@tb, @tobject, @tobject)
|
78
|
+
assert (tbss <= tbss)
|
79
|
+
assert (not (tbss <= tbso))
|
80
|
+
assert (tbss <= tbos)
|
81
|
+
assert (not (tbss <= tboo))
|
82
|
+
assert (tbso <= tbss)
|
83
|
+
assert (tbso <= tbso)
|
84
|
+
assert (tbso <= tbos)
|
85
|
+
assert (tbso <= tboo)
|
86
|
+
assert (not (tbos <= tbss))
|
87
|
+
assert (not (tbos <= tbso))
|
88
|
+
assert (tbos <= tbos)
|
89
|
+
assert (not (tbos <= tboo))
|
90
|
+
assert (not (tboo <= tbss))
|
91
|
+
assert (not (tboo <= tbso))
|
92
|
+
assert (tboo <= tbos)
|
93
|
+
assert (tboo <= tboo)
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_le_structural
|
97
|
+
tbss = RDL::Type::GenericType.new(@tb, @tstring, @tstring)
|
98
|
+
tma = RDL::Type::MethodType.new([], nil, @tnil)
|
99
|
+
tmb = RDL::Type::MethodType.new([@tstring], nil, @tnil)
|
100
|
+
tmc = RDL::Type::MethodType.new([@tfixnum], nil, @tnil)
|
101
|
+
ts1 = RDL::Type::StructuralType.new(m2: tma)
|
102
|
+
assert (tbss <= ts1)
|
103
|
+
ts2 = RDL::Type::StructuralType.new(m1: tmb)
|
104
|
+
assert (tbss <= ts2)
|
105
|
+
ts3 = RDL::Type::StructuralType.new(m1: tmb, m2: tma)
|
106
|
+
assert (tbss <= ts3)
|
107
|
+
ts4 = RDL::Type::StructuralType.new(m1: tmc, m2: tma)
|
108
|
+
assert (not (tbss <= ts4))
|
109
|
+
ts5 = RDL::Type::StructuralType.new(m1: tmb, m2: tmc)
|
110
|
+
assert (tbss <= ts5)
|
111
|
+
end
|
112
|
+
|
113
|
+
class C
|
114
|
+
type "() -> self"
|
115
|
+
def m1() return self; end
|
116
|
+
type "() -> self"
|
117
|
+
def m2() return C.new; end
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_self_type
|
121
|
+
c = C.new
|
122
|
+
assert(c.m1)
|
123
|
+
assert_raises(RDL::Type::TypeError) { c.m2 }
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_member
|
127
|
+
# member? should only check the base types
|
128
|
+
assert (@ta.member?(A.new([1, 2, 3])))
|
129
|
+
assert (@ta.member?(A.new([])))
|
130
|
+
assert (@ta.member?(A.new(["a", "b", "c"])))
|
131
|
+
assert (@tas.member?(A.new([1, 2, 3])))
|
132
|
+
assert (@tas.member?(A.new([])))
|
133
|
+
assert (@tas.member?(A.new(["a", "b", "c"])))
|
134
|
+
assert (@taas.member?(A.new([1, 2, 3])))
|
135
|
+
assert (@taas.member?(A.new([])))
|
136
|
+
assert (@taas.member?(A.new(["a", "b", "c"])))
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_instantiate
|
140
|
+
assert_raises(RuntimeError) { Object.new.instantiate!(@tstring) }
|
141
|
+
|
142
|
+
# Array<String>
|
143
|
+
assert (A.new([]).instantiate!('String'))
|
144
|
+
assert (A.new(["a", "b", "c"]).instantiate!(@tstring))
|
145
|
+
assert (A.new(["a", "b", "c"]).instantiate!('String'))
|
146
|
+
assert_raises(RDL::Type::TypeError) { A.new([1, 2, 3]).instantiate!('String') }
|
147
|
+
|
148
|
+
# Array<Object>
|
149
|
+
assert (A.new([])).instantiate!('Object')
|
150
|
+
assert (A.new(["a", "b", "c"]).instantiate!(@tobject))
|
151
|
+
assert (A.new(["a", "b", "c"]).instantiate!('Object'))
|
152
|
+
assert (A.new([1, 2, 3]).instantiate!('Object'))
|
153
|
+
|
154
|
+
# Hash<String, Fixnum>
|
155
|
+
assert (H.new({}).instantiate!('String', 'Fixnum'))
|
156
|
+
assert (H.new({"one"=>1, "two"=>2}).instantiate!('String', 'Fixnum'))
|
157
|
+
assert_raises(RDL::Type::TypeError) {
|
158
|
+
H.new(one: 1, two: 2).instantiate!('String', 'Fixnum')
|
159
|
+
}
|
160
|
+
assert_raises(RDL::Type::TypeError){
|
161
|
+
H.new({"one"=>:one, "two"=>:two}).instantiate!('String', 'Fixnum')
|
162
|
+
}
|
163
|
+
|
164
|
+
# Hash<Object, Object>
|
165
|
+
assert (H.new({}).instantiate!('Object', 'Object'))
|
166
|
+
assert (H.new({"one"=>1, "two"=>2}).instantiate!('Object', 'Object'))
|
167
|
+
assert (H.new(one: 1, two: 2).instantiate!('Object', 'Object'))
|
168
|
+
assert (H.new({"one"=>:one, "two"=>:two}).instantiate!('Object', 'Object'))
|
169
|
+
|
170
|
+
# A<A<String>>
|
171
|
+
assert (A.new([A.new(["a", "b"]).instantiate!('String'),
|
172
|
+
A.new(["c"]).instantiate!('String')]).instantiate!('TestGeneric::A<String>'))
|
173
|
+
assert_raises(RDL::Type::TypeError) {
|
174
|
+
# Must instantiate all members
|
175
|
+
A.new([A.new(["a", "b"]).instantiate!('String'), A.new([])]).instantiate!('TestGeneric::A<String>')
|
176
|
+
}
|
177
|
+
assert_raises(RDL::Type::TypeError) {
|
178
|
+
# All members must be of same type
|
179
|
+
A.new([A.new(["a", "b"]).instantiate!('String'), "A"]).instantiate!('TestGeneric::A<String>')
|
180
|
+
}
|
181
|
+
assert_raises(RDL::Type::TypeError) {
|
182
|
+
# All members must be instantiated and of same type
|
183
|
+
A.new([A.new(["a", "b"]).instantiate!('String'),
|
184
|
+
H.new({a: 1, b: 2}).instantiate!('Object', 'Object')]).instantiate!('TestGeneric::A<String>')
|
185
|
+
}
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require_relative '../lib/rdl.rb'
|
3
|
+
|
4
|
+
class TestIntersection < Minitest::Test
|
5
|
+
include RDL::Type
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@parser = RDL::Type::Parser.new
|
9
|
+
|
10
|
+
@fixnum = NominalType.new(Fixnum)
|
11
|
+
@string = NominalType.new(String)
|
12
|
+
@array = NominalType.new(Array)
|
13
|
+
@hash = NominalType.new(Hash)
|
14
|
+
@true_n = NominalType.new(TrueClass)
|
15
|
+
|
16
|
+
@tparam_t = VarType.new(:t)
|
17
|
+
|
18
|
+
@f_or_s = UnionType.new(@fixnum, @string)
|
19
|
+
@string_or_true = UnionType.new(@string, @true_n)
|
20
|
+
|
21
|
+
@array_of_fixnum = GenericType.new(@array, @fixnum)
|
22
|
+
@array_of_true = GenericType.new(@array, @true_n)
|
23
|
+
@array_of_fixnum_string = GenericType.new(@array, @f_or_s)
|
24
|
+
@array_of_true_string = GenericType.new(@array, @string_or_true)
|
25
|
+
@hash_of_string_fixnum = GenericType.new(@hash, @string, @fixnum)
|
26
|
+
@hash_of_string_true_fixnum = GenericType.new(@hash, @string_or_true, @fixnum)
|
27
|
+
@a_a_f = GenericType.new(@array, @array_of_fixnum)
|
28
|
+
@a_a_a_f = GenericType.new(@array, @a_a_f)
|
29
|
+
@a_a_a_a_f = GenericType.new(@array, @a_a_a_f)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_intersection_same
|
33
|
+
t1 = @parser.scan_str "(Fixnum) -> Fixnum"
|
34
|
+
t2 = @parser.scan_str "(Fixnum) -> Fixnum"
|
35
|
+
t3 = @parser.scan_str "(Fixnum) -> Fixnum"
|
36
|
+
i = IntersectionType.new(t1, t2, t3)
|
37
|
+
|
38
|
+
assert_equal(t1, i)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
data/test/test_le.rb
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require_relative '../lib/rdl.rb'
|
3
|
+
|
4
|
+
class TestLe < Minitest::Test
|
5
|
+
include RDL::Type
|
6
|
+
|
7
|
+
class A
|
8
|
+
end
|
9
|
+
|
10
|
+
class B < A
|
11
|
+
end
|
12
|
+
|
13
|
+
class C < B
|
14
|
+
end
|
15
|
+
|
16
|
+
def setup
|
17
|
+
@tnil = NilType.new
|
18
|
+
@ttop = TopType.new
|
19
|
+
@tstring = NominalType.new "String"
|
20
|
+
@tobject = NominalType.new "Object"
|
21
|
+
@tbasicobject = NominalType.new "BasicObject"
|
22
|
+
@tsymfoo = SingletonType.new :foo
|
23
|
+
@tsym = NominalType.new Symbol
|
24
|
+
@ta = NominalType.new A
|
25
|
+
@tb = NominalType.new B
|
26
|
+
@tc = NominalType.new C
|
27
|
+
@tfixnum = NominalType.new "Fixnum"
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_nil
|
31
|
+
assert (@tnil <= @ttop)
|
32
|
+
assert (@tnil <= @tstring)
|
33
|
+
assert (@tnil <= @tobject)
|
34
|
+
assert (@tnil <= @tbasicobject)
|
35
|
+
assert (@tnil <= @tsymfoo)
|
36
|
+
assert (not (@ttop <= @tnil))
|
37
|
+
assert (not (@tstring <= @tnil))
|
38
|
+
assert (not (@tobject <= @tnil))
|
39
|
+
assert (not (@tbasicobject <= @tnil))
|
40
|
+
assert (not (@tsymfoo <= @tnil))
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_top
|
44
|
+
assert (not (@ttop <= @tnil))
|
45
|
+
assert (not (@ttop <= @tstring))
|
46
|
+
assert (not (@ttop <= @tobject))
|
47
|
+
assert (not (@ttop <= @tbasicobject))
|
48
|
+
assert (not (@ttop <= @tsymfoo))
|
49
|
+
assert (@ttop <= @ttop)
|
50
|
+
assert (@tstring <= @ttop)
|
51
|
+
assert (@tobject <= @ttop)
|
52
|
+
assert (@tbasicobject <= @ttop)
|
53
|
+
assert (@tsymfoo <= @ttop)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_sym
|
57
|
+
assert (@tsym <= @tsym)
|
58
|
+
assert (@tsymfoo <= @tsymfoo)
|
59
|
+
assert (@tsymfoo <= @tsym)
|
60
|
+
assert (not (@tsym <= @tsymfoo))
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_nominal
|
64
|
+
assert (@tstring <= @tstring)
|
65
|
+
assert (@tsym <= @tsym)
|
66
|
+
assert (not (@tstring <= @tsym))
|
67
|
+
assert (not (@tsym <= @tstring))
|
68
|
+
assert (@tstring <= @tobject)
|
69
|
+
assert (@tstring <= @tbasicobject)
|
70
|
+
assert (@tobject <= @tbasicobject)
|
71
|
+
assert (not (@tobject <= @tstring))
|
72
|
+
assert (not (@tbasicobject <= @tstring))
|
73
|
+
assert (not (@tbasicobject <= @tobject))
|
74
|
+
assert (@ta <= @ta)
|
75
|
+
assert (@tb <= @ta)
|
76
|
+
assert (@tc <= @ta)
|
77
|
+
assert (not (@ta <= @tb))
|
78
|
+
assert (@tb <= @tb)
|
79
|
+
assert (@tc <= @tb)
|
80
|
+
assert (not (@ta <= @tc))
|
81
|
+
assert (not (@tb <= @tc))
|
82
|
+
assert (@tc <= @tc)
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_union
|
86
|
+
tstring_or_sym = UnionType.new(@tstring, @tsym)
|
87
|
+
assert (tstring_or_sym <= @tobject)
|
88
|
+
assert (not (@tobject <= @tstring_or_sym))
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_tuple
|
92
|
+
t1 = TupleType.new(@tsym, @tstring)
|
93
|
+
t2 = TupleType.new(@tobject, @tobject)
|
94
|
+
tarray = NominalType.new("Array")
|
95
|
+
assert (t1 <= t1)
|
96
|
+
assert (t2 <= t2)
|
97
|
+
assert (not (t1 <= t2)) # invariant subtyping since tuples are mutable
|
98
|
+
assert (not (t2 <= t1))
|
99
|
+
assert (not (t1 <= tarray)) # no convertability to arrays due to mutability
|
100
|
+
assert (not (tarray <= t1))
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_method
|
104
|
+
tss = MethodType.new([@tstring], nil, @tstring)
|
105
|
+
tso = MethodType.new([@tstring], nil, @tobject)
|
106
|
+
tos = MethodType.new([@tobject], nil, @tstring)
|
107
|
+
too = MethodType.new([@tobject], nil, @tobject)
|
108
|
+
assert (tss <= tss)
|
109
|
+
assert (tss <= tso)
|
110
|
+
assert (not (tss <= tos))
|
111
|
+
assert (not (tss <= too))
|
112
|
+
assert (not (tso <= tss))
|
113
|
+
assert (tso <= tso)
|
114
|
+
assert (not (tso <= tos))
|
115
|
+
assert (not (tso <= too))
|
116
|
+
assert (tos <= tss)
|
117
|
+
assert (tos <= tso)
|
118
|
+
assert (tos <= tos)
|
119
|
+
assert (tos <= too)
|
120
|
+
assert (not (too <= tss))
|
121
|
+
assert (too <= tso)
|
122
|
+
assert (not (too <= tos))
|
123
|
+
assert (too <= too)
|
124
|
+
tbos = MethodType.new([], tos, @tobject)
|
125
|
+
tbso = MethodType.new([], tso, @tobject)
|
126
|
+
assert (tbos <= tbos)
|
127
|
+
assert (not (tbos <= tbso))
|
128
|
+
assert (tbso <= tbso)
|
129
|
+
assert (tbso <= tbos)
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_structural
|
133
|
+
tso = MethodType.new([@tstring], nil, @tobject)
|
134
|
+
tos = MethodType.new([@tobject], nil, @tstring)
|
135
|
+
ts1 = StructuralType.new(m1: tso)
|
136
|
+
ts2 = StructuralType.new(m1: tos)
|
137
|
+
assert (ts1 <= @ttop)
|
138
|
+
assert (ts1 <= ts1)
|
139
|
+
assert (ts2 <= ts2)
|
140
|
+
assert (ts2 <= ts1)
|
141
|
+
assert (not (ts1 <= ts2))
|
142
|
+
ts3 = StructuralType.new(m1: tso, m2: tso) # width subtyping
|
143
|
+
assert (ts3 <= ts1)
|
144
|
+
assert (not (ts1 <= ts3))
|
145
|
+
end
|
146
|
+
|
147
|
+
class Nom
|
148
|
+
def m1()
|
149
|
+
nil
|
150
|
+
end
|
151
|
+
def m2()
|
152
|
+
nil
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
class NomT
|
157
|
+
type "() -> nil"
|
158
|
+
def m1()
|
159
|
+
nil
|
160
|
+
end
|
161
|
+
type "() -> nil"
|
162
|
+
def m2()
|
163
|
+
nil
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_nominal_structural
|
168
|
+
tnom = NominalType.new(Nom)
|
169
|
+
tnomt = NominalType.new(NomT)
|
170
|
+
tma = MethodType.new([], nil, @tnil)
|
171
|
+
tmb = MethodType.new([@tfixnum], nil, @tnil)
|
172
|
+
ts1 = StructuralType.new(m1: tma)
|
173
|
+
assert (tnom <= ts1)
|
174
|
+
assert (tnomt <= ts1)
|
175
|
+
ts2 = StructuralType.new(m1: tma, m2: tma)
|
176
|
+
assert (tnom <= ts2)
|
177
|
+
assert (tnomt <= ts2)
|
178
|
+
ts3 = StructuralType.new(m1: tma, m2: tma, m3: tma)
|
179
|
+
assert (not (tnom <= ts3))
|
180
|
+
assert (not (tnomt <= ts3))
|
181
|
+
ts4 = StructuralType.new(m1: tmb)
|
182
|
+
assert (tnom <= ts4) # types don't matter, only methods
|
183
|
+
assert (not (tnomt <= ts4))
|
184
|
+
end
|
185
|
+
|
186
|
+
# def test_intersection
|
187
|
+
# skip "<= not defined on intersection"
|
188
|
+
# tobject_and_basicobject = IntersectionType.new(@tobject, @tbasicobject)
|
189
|
+
# assert (not (tobject_and_basicobject <= @tobject))
|
190
|
+
# assert (@tobject <= tobject_and_basicobject)
|
191
|
+
# end
|
192
|
+
|
193
|
+
end
|