rdl 2.1.0 → 2.2.0
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 +5 -5
- data/.gitignore +1 -0
- data/.travis.yml +7 -6
- data/CHANGES.md +29 -0
- data/README.md +94 -26
- data/lib/rdl/boot.rb +82 -41
- data/lib/rdl/boot_rails.rb +5 -0
- data/lib/rdl/config.rb +9 -1
- data/lib/rdl/query.rb +2 -2
- data/lib/rdl/typecheck.rb +972 -225
- data/lib/rdl/types/annotated_arg.rb +8 -0
- data/lib/rdl/types/ast_node.rb +73 -0
- data/lib/rdl/types/bot.rb +8 -0
- data/lib/rdl/types/bound_arg.rb +63 -0
- data/lib/rdl/types/computed.rb +48 -0
- data/lib/rdl/types/dependent_arg.rb +9 -0
- data/lib/rdl/types/dynamic.rb +61 -0
- data/lib/rdl/types/finite_hash.rb +54 -9
- data/lib/rdl/types/generic.rb +33 -0
- data/lib/rdl/types/intersection.rb +8 -0
- data/lib/rdl/types/lexer.rex +6 -1
- data/lib/rdl/types/lexer.rex.rb +13 -1
- data/lib/rdl/types/method.rb +14 -0
- data/lib/rdl/types/nominal.rb +8 -0
- data/lib/rdl/types/non_null.rb +8 -0
- data/lib/rdl/types/optional.rb +8 -0
- data/lib/rdl/types/parser.racc +31 -5
- data/lib/rdl/types/parser.tab.rb +540 -302
- data/lib/rdl/types/rdl_types.rb +45 -0
- data/lib/rdl/types/singleton.rb +14 -1
- data/lib/rdl/types/string.rb +104 -0
- data/lib/rdl/types/structural.rb +8 -0
- data/lib/rdl/types/top.rb +8 -0
- data/lib/rdl/types/tuple.rb +32 -8
- data/lib/rdl/types/type.rb +54 -11
- data/lib/rdl/types/union.rb +41 -2
- data/lib/rdl/types/var.rb +10 -0
- data/lib/rdl/types/vararg.rb +8 -0
- data/lib/rdl/util.rb +13 -10
- data/lib/rdl/wrap.rb +271 -27
- data/lib/rdl_disable.rb +16 -2
- data/lib/types/active_record.rb +1 -0
- data/lib/types/core/array.rb +442 -23
- data/lib/types/core/basic_object.rb +3 -3
- data/lib/types/core/bigdecimal.rb +5 -0
- data/lib/types/core/class.rb +2 -0
- data/lib/types/core/dir.rb +3 -3
- data/lib/types/core/enumerable.rb +4 -4
- data/lib/types/core/enumerator.rb +1 -1
- data/lib/types/core/file.rb +4 -4
- data/lib/types/core/float.rb +203 -0
- data/lib/types/core/hash.rb +390 -15
- data/lib/types/core/integer.rb +223 -10
- data/lib/types/core/io.rb +2 -2
- data/lib/types/core/kernel.rb +8 -5
- data/lib/types/core/marshal.rb +3 -0
- data/lib/types/core/module.rb +3 -3
- data/lib/types/core/numeric.rb +0 -2
- data/lib/types/core/object.rb +5 -5
- data/lib/types/core/pathname.rb +2 -2
- data/lib/types/core/process.rb +1 -3
- data/lib/types/core/range.rb +1 -1
- data/lib/types/core/regexp.rb +2 -2
- data/lib/types/core/set.rb +1 -1
- data/lib/types/core/string.rb +408 -16
- data/lib/types/core/symbol.rb +3 -3
- data/lib/types/core/time.rb +1 -1
- data/lib/types/core/uri.rb +13 -13
- data/lib/types/rails/_helpers.rb +7 -1
- data/lib/types/rails/action_controller/mime_responds.rb +2 -0
- data/lib/types/rails/active_record/associations.rb +42 -30
- data/lib/types/rails/active_record/comp_types.rb +637 -0
- data/lib/types/rails/active_record/finder_methods.rb +1 -1
- data/lib/types/rails/active_record/model_schema.rb +28 -16
- data/lib/types/rails/active_record/relation.rb +5 -3
- data/lib/types/rails/active_record/sql-strings.rb +166 -0
- data/lib/types/rails/string.rb +1 -1
- data/lib/types/sequel.rb +1 -0
- data/lib/types/sequel/comp_types.rb +581 -0
- data/rdl.gemspec +5 -4
- data/test/test_alias.rb +4 -0
- data/test/test_array_types.rb +244 -0
- data/test/test_bound_types.rb +80 -0
- data/test/test_contract.rb +4 -0
- data/test/test_dsl.rb +5 -0
- data/test/test_dyn_comptype_checks.rb +206 -0
- data/test/test_generic.rb +21 -20
- data/test/test_hash_types.rb +322 -0
- data/test/test_intersection.rb +1 -0
- data/test/test_le.rb +29 -4
- data/test/test_member.rb +3 -1
- data/test/test_parser.rb +5 -0
- data/test/test_query.rb +1 -0
- data/test/test_rdl.rb +63 -28
- data/test/test_rdl_type.rb +4 -0
- data/test/test_string_types.rb +102 -0
- data/test/test_type_contract.rb +59 -37
- data/test/test_typecheck.rb +480 -75
- data/test/test_types.rb +17 -0
- data/test/test_wrap.rb +5 -0
- metadata +35 -5
- data/lib/types/rails/active_record/schema_types.rb +0 -51
data/test/test_member.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'minitest/autorun'
|
2
2
|
$LOAD_PATH << File.dirname(__FILE__) + "/../lib"
|
3
3
|
require 'rdl'
|
4
|
+
RDL.reset
|
4
5
|
|
5
6
|
class TestMember < Minitest::Test
|
6
7
|
include RDL::Type
|
@@ -15,6 +16,7 @@ class TestMember < Minitest::Test
|
|
15
16
|
end
|
16
17
|
|
17
18
|
def setup
|
19
|
+
RDL.reset
|
18
20
|
@tbasicobject = NominalType.new "BasicObject"
|
19
21
|
@tsymfoo = SingletonType.new :foo
|
20
22
|
@tarraystring = GenericType.new(RDL::Globals.types[:array], RDL::Globals.types[:string])
|
@@ -84,7 +86,7 @@ class TestMember < Minitest::Test
|
|
84
86
|
assert (@tsymfoo.member? :foo)
|
85
87
|
assert (not (@tsymfoo.member? :bar))
|
86
88
|
assert (not (@tsymfoo.member? "foo"))
|
87
|
-
assert (not(@tsymfoo.member? nil)) # nil no longer subtype of other singletons
|
89
|
+
#assert (not(@tsymfoo.member? nil)) # nil no longer subtype of other singletons
|
88
90
|
end
|
89
91
|
|
90
92
|
def test_union_intersection
|
data/test/test_parser.rb
CHANGED
@@ -10,6 +10,7 @@ class TestParser < Minitest::Test
|
|
10
10
|
class C; end
|
11
11
|
|
12
12
|
def setup
|
13
|
+
RDL.reset
|
13
14
|
@tintegeropt = OptionalType.new RDL::Globals.types[:integer]
|
14
15
|
@tintegervararg = VarargType.new RDL::Globals.types[:integer]
|
15
16
|
@tstringopt = OptionalType.new RDL::Globals.types[:string]
|
@@ -170,6 +171,10 @@ class TestParser < Minitest::Test
|
|
170
171
|
tm1 = MethodType.new [], nil, RDL::Globals.types[:string]
|
171
172
|
ts1 = StructuralType.new(to_str: tm1)
|
172
173
|
assert_equal ts1, t1
|
174
|
+
t2 = tt "[[]: (String) -> %any]"
|
175
|
+
tm2 = MethodType.new [RDL::Globals.types[:string]], nil, RDL::Globals.special_types['%any']
|
176
|
+
ts2 = StructuralType.new(:[] => tm2)
|
177
|
+
assert_equal ts2, t2
|
173
178
|
end
|
174
179
|
|
175
180
|
def test_finite_hash
|
data/test/test_query.rb
CHANGED
data/test/test_rdl.rb
CHANGED
@@ -5,6 +5,10 @@ require 'rdl'
|
|
5
5
|
class TestRDL < Minitest::Test
|
6
6
|
extend RDL::Annotate
|
7
7
|
|
8
|
+
def setup
|
9
|
+
RDL.reset
|
10
|
+
end
|
11
|
+
|
8
12
|
# Test wrapping with no types or contracts
|
9
13
|
def test_wrap
|
10
14
|
def m1(x) return x; end
|
@@ -239,27 +243,27 @@ RUBY
|
|
239
243
|
end
|
240
244
|
|
241
245
|
def test_wrap_new
|
242
|
-
self.class.class_eval "class
|
243
|
-
RDL.pre("TestRDL::
|
244
|
-
assert_equal 3, TestRDL::
|
245
|
-
assert_raises(RDL::Contract::ContractError) { TestRDL::
|
246
|
+
self.class.class_eval "class WrapB; def initialize(x); @x = x end; def get(); return @x end end"
|
247
|
+
RDL.pre("TestRDL::WrapB", "self.new") { |x| x > 0 }
|
248
|
+
assert_equal 3, TestRDL::WrapB.new(3).get
|
249
|
+
assert_raises(RDL::Contract::ContractError) { TestRDL::WrapB.new(-3) }
|
246
250
|
|
247
|
-
self.class.class_eval "class
|
248
|
-
assert_equal 3, TestRDL::
|
249
|
-
assert_raises(RDL::Contract::ContractError) { TestRDL::
|
251
|
+
self.class.class_eval "class WrapC; extend RDL::Annotate; pre { |x| x > 0 }; def initialize(x); @x = x end; def get(); return @x end end"
|
252
|
+
assert_equal 3, TestRDL::WrapC.new(3).get
|
253
|
+
assert_raises(RDL::Contract::ContractError) { TestRDL::WrapC.new(-3) }
|
250
254
|
|
251
|
-
self.class.class_eval "class
|
252
|
-
RDL.pre("TestRDL::
|
253
|
-
self.class.class_eval "class
|
254
|
-
assert_equal 3, TestRDL::
|
255
|
-
assert_raises(RDL::Contract::ContractError) { TestRDL::
|
255
|
+
self.class.class_eval "class WrapD; def get(); return @x end end"
|
256
|
+
RDL.pre("TestRDL::WrapD", "self.new") { |x| x > 0 }
|
257
|
+
self.class.class_eval "class WrapD; def initialize(x); @x = x end end"
|
258
|
+
assert_equal 3, TestRDL::WrapD.new(3).get
|
259
|
+
assert_raises(RDL::Contract::ContractError) { TestRDL::WrapD.new(-3) }
|
256
260
|
|
257
261
|
skip "Can't defer contracts on new yet"
|
258
262
|
RDL.
|
259
|
-
pre("TestRDL::
|
260
|
-
self.class.class_eval "class
|
261
|
-
assert (TestRDL::
|
262
|
-
assert_raises(RDL::Contract::ContractError) { TestRDL::
|
263
|
+
pre("TestRDL::WrapE", "self.new") { |x| x > 0 }
|
264
|
+
self.class.class_eval "class WrapE; def initialize(x); @x = x end end"
|
265
|
+
assert (TestRDL::WrapE.new(3))
|
266
|
+
assert_raises(RDL::Contract::ContractError) { TestRDL::WrapE.new(-3) }
|
263
267
|
end
|
264
268
|
|
265
269
|
def test_class_method
|
@@ -388,25 +392,56 @@ RUBY
|
|
388
392
|
assert !(RDL::Globals.info.has? "TestRDL::TestVersion", "m4", :post)
|
389
393
|
end
|
390
394
|
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
def m1(x) return x; end
|
396
|
-
|
397
|
-
rdl_post { |x| x < 0 }
|
398
|
-
def m2(x) return 3; end
|
395
|
+
def test_pre_rdl_annotate_contract
|
396
|
+
self.class.class_eval <<-RUBY, __FILE__, __LINE__
|
397
|
+
class TestRDLAnnotate
|
398
|
+
extend RDL::RDLAnnotate
|
399
399
|
|
400
|
-
|
401
|
-
|
400
|
+
rdl_pre { |x| x > 0 }
|
401
|
+
def m1(x) return x; end
|
402
402
|
|
403
|
-
|
403
|
+
rdl_post { |x| x < 0 }
|
404
|
+
def m2(x) return 3; end
|
404
405
|
|
405
|
-
|
406
|
+
rdl_type '(Integer) -> Integer'
|
407
|
+
def m3(x) return x; end
|
408
|
+
end
|
409
|
+
RUBY
|
406
410
|
assert_equal 3, TestRDLAnnotate.new.m1(3)
|
407
411
|
assert_raises(RDL::Contract::ContractError) { TestRDLAnnotate.new.m1(-1) }
|
408
412
|
assert_raises(RDL::Contract::ContractError) { TestRDLAnnotate.new.m2(42) }
|
409
413
|
assert_raises(RDL::Type::TypeError) { TestRDLAnnotate.new.m3('one') }
|
410
414
|
end
|
411
415
|
|
416
|
+
class TC0
|
417
|
+
def foo
|
418
|
+
's'
|
419
|
+
end
|
420
|
+
|
421
|
+
def bar
|
422
|
+
0
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
class TC1 < TC0
|
427
|
+
def foo
|
428
|
+
's'
|
429
|
+
end
|
430
|
+
|
431
|
+
def bar
|
432
|
+
0
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
def test_wrap_inheritance
|
437
|
+
RDL.type TC0, :foo, '() -> Integer', typecheck: :call
|
438
|
+
RDL.type TC0, :bar, '() -> Integer', typecheck: :call
|
439
|
+
RDL.type TC1, :foo, '() -> String', typecheck: :call
|
440
|
+
RDL.type TC1, :bar, '() -> String', typecheck: :call
|
441
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { TC0.new.foo }
|
442
|
+
assert_equal 0, TC0.new.bar
|
443
|
+
assert_equal 's', TC1.new.foo
|
444
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { TC1.new.bar }
|
445
|
+
end
|
446
|
+
|
412
447
|
end
|
data/test/test_rdl_type.rb
CHANGED
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
$LOAD_PATH << File.dirname(__FILE__) + "/../lib"
|
3
|
+
require 'rdl'
|
4
|
+
require 'types/core'
|
5
|
+
|
6
|
+
|
7
|
+
class TestStringTypes < Minitest::Test
|
8
|
+
extend RDL::Annotate
|
9
|
+
|
10
|
+
def setup
|
11
|
+
RDL.reset
|
12
|
+
RDL.readd_comp_types
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_string_methods
|
16
|
+
self.class.class_eval {
|
17
|
+
|
18
|
+
type '(String) -> "hello"', typecheck: :append_fail1
|
19
|
+
def append_fail_test1(x)
|
20
|
+
"he" << x
|
21
|
+
end
|
22
|
+
|
23
|
+
type '("hello") -> Integer', typecheck: :append_fail2
|
24
|
+
def append_fail_test2(x)
|
25
|
+
takes_hello(x)
|
26
|
+
x << 'blah'
|
27
|
+
1
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
type "('he') -> 'hello'", typecheck: :now
|
32
|
+
def append_test1(x)
|
33
|
+
x << "llo"
|
34
|
+
end
|
35
|
+
|
36
|
+
type '(String) -> String', typecheck: :now
|
37
|
+
def append_test2(x)
|
38
|
+
"he" << x
|
39
|
+
end
|
40
|
+
|
41
|
+
type '("llo") -> String', typecheck: :now
|
42
|
+
def append_test3(x)
|
43
|
+
"he" << x
|
44
|
+
end
|
45
|
+
|
46
|
+
type :takes_hello, "('hello') -> Integer"
|
47
|
+
|
48
|
+
type '("he") -> Integer', typecheck: :now
|
49
|
+
def append_test4(y)
|
50
|
+
takes_hello(y << "llo")
|
51
|
+
end
|
52
|
+
|
53
|
+
type '("hello") -> "Hello"', typecheck: :now
|
54
|
+
def capitalize_test1(x)
|
55
|
+
x.capitalize
|
56
|
+
end
|
57
|
+
|
58
|
+
type '("hello") -> "Hello"', typecheck: :now
|
59
|
+
def capitalize_test2(x)
|
60
|
+
x.capitalize!
|
61
|
+
end
|
62
|
+
|
63
|
+
type '("hello") -> "o"', typecheck: :now
|
64
|
+
def access_test1(x)
|
65
|
+
x[4]
|
66
|
+
end
|
67
|
+
|
68
|
+
type '("he") -> "hello"', typecheck: :now
|
69
|
+
def concat_test1(x)
|
70
|
+
x + "llo"
|
71
|
+
end
|
72
|
+
|
73
|
+
type '("hello") -> 5', typecheck: :now
|
74
|
+
def size_test1(x)
|
75
|
+
x.size
|
76
|
+
end
|
77
|
+
|
78
|
+
type '(String) -> Integer', typecheck: :now
|
79
|
+
def size_test2(x)
|
80
|
+
x.size
|
81
|
+
end
|
82
|
+
|
83
|
+
type '(:world) -> "hello, world!"', typecheck: :now
|
84
|
+
def interp_test1(y)
|
85
|
+
"hello, #{y}!"
|
86
|
+
end
|
87
|
+
|
88
|
+
type '(Symbol) -> String', typecheck: :now
|
89
|
+
def interp_test2(y)
|
90
|
+
"hello, #{y}!"
|
91
|
+
end
|
92
|
+
|
93
|
+
type '("hi") -> "bye"', typecheck: :now
|
94
|
+
def replace_test1(x)
|
95
|
+
x.replace "bye"
|
96
|
+
x
|
97
|
+
end
|
98
|
+
}
|
99
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { RDL.do_typecheck :append_fail1 }
|
100
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { RDL.do_typecheck :append_fail2 }
|
101
|
+
end
|
102
|
+
end
|
data/test/test_type_contract.rb
CHANGED
@@ -8,6 +8,7 @@ class TestTypeContract < Minitest::Test
|
|
8
8
|
extend RDL::Annotate
|
9
9
|
|
10
10
|
def setup
|
11
|
+
RDL.reset
|
11
12
|
@p = Parser.new
|
12
13
|
end
|
13
14
|
|
@@ -23,6 +24,28 @@ class TestTypeContract < Minitest::Test
|
|
23
24
|
end
|
24
25
|
|
25
26
|
def test_proc
|
27
|
+
self.class.class_eval <<-RUBY, __FILE__, __LINE__
|
28
|
+
type '(Integer) { (Integer) -> Integer } -> Integer'
|
29
|
+
def block_contract_test1(x)
|
30
|
+
x+yield(5)
|
31
|
+
end
|
32
|
+
|
33
|
+
type '(Integer) { (Integer) -> Integer } -> Float'
|
34
|
+
def block_contract_test2(x)
|
35
|
+
x+yield(4.5)
|
36
|
+
end
|
37
|
+
|
38
|
+
type '(Integer) -> Integer'
|
39
|
+
def block_contract_test3(x)
|
40
|
+
42
|
41
|
+
end
|
42
|
+
|
43
|
+
type '(Integer) ?{(Integer) -> Integer} -> Integer'
|
44
|
+
def block_contract_test4(x,&blk)
|
45
|
+
return yield(x) if blk
|
46
|
+
return x
|
47
|
+
end
|
48
|
+
RUBY
|
26
49
|
t1 = @p.scan_str "(nil) -> nil"
|
27
50
|
p1 = t1.to_contract.wrap(self) { |x| nil }
|
28
51
|
assert_nil p1.call(nil)
|
@@ -187,29 +210,6 @@ class TestTypeContract < Minitest::Test
|
|
187
210
|
assert_raises(TypeError) { p18.call(41, Proc.new {|x| x+1.5}) }
|
188
211
|
p18b = t18.to_higher_contract(self) { |x,p=nil| if p then p.call(x+0.5) else x end }
|
189
212
|
assert_raises(TypeError) { p18b.call(41, Proc.new {|x| x+1}) }
|
190
|
-
|
191
|
-
|
192
|
-
end
|
193
|
-
|
194
|
-
type '(Integer) { (Integer) -> Integer } -> Integer'
|
195
|
-
def block_contract_test1(x)
|
196
|
-
x+yield(5)
|
197
|
-
end
|
198
|
-
|
199
|
-
type '(Integer) { (Integer) -> Integer } -> Float'
|
200
|
-
def block_contract_test2(x)
|
201
|
-
x+yield(4.5)
|
202
|
-
end
|
203
|
-
|
204
|
-
type '(Integer) -> Integer'
|
205
|
-
def block_contract_test3(x)
|
206
|
-
42
|
207
|
-
end
|
208
|
-
|
209
|
-
type '(Integer) ?{(Integer) -> Integer} -> Integer'
|
210
|
-
def block_contract_test4(x,&blk)
|
211
|
-
return yield(x) if blk
|
212
|
-
return x
|
213
213
|
end
|
214
214
|
|
215
215
|
def test_proc_names
|
@@ -298,23 +298,45 @@ class TestTypeContract < Minitest::Test
|
|
298
298
|
assert_raises(TypeError) { p9.call(43, x: "foo", y: 44, pi: 3.14, e: 3) }
|
299
299
|
end
|
300
300
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
301
|
+
def test_initialize
|
302
|
+
self.class.class_eval <<-RUBY, __FILE__, __LINE__
|
303
|
+
class TestTypeContract_A
|
304
|
+
extend RDL::Annotate
|
305
|
+
type "(Integer) -> self"
|
306
|
+
def initialize(x)
|
307
|
+
x
|
308
|
+
end
|
309
|
+
end
|
310
|
+
class TestTypeContract_B
|
311
|
+
extend RDL::Annotate
|
312
|
+
type "(Integer) -> Integer"
|
313
|
+
def initialize(x)
|
314
|
+
x
|
315
|
+
end
|
316
|
+
end
|
317
|
+
RUBY
|
318
|
+
assert TestTypeContract_A.new(1)
|
319
|
+
assert_raises(ArgumentError) { TestTypeContract_B.new(1) }
|
315
320
|
end
|
316
321
|
|
317
322
|
def test_block
|
323
|
+
self.class.class_eval <<-RUBY, __FILE__, __LINE__
|
324
|
+
type '() { () -> nil } -> nil'
|
325
|
+
def _test_with_block
|
326
|
+
nil
|
327
|
+
end
|
328
|
+
|
329
|
+
type '() -> nil'
|
330
|
+
def _test_without_block
|
331
|
+
nil
|
332
|
+
end
|
333
|
+
|
334
|
+
type '() -> nil'
|
335
|
+
type '() { () -> nil } -> nil'
|
336
|
+
def _test_with_without_block
|
337
|
+
nil
|
338
|
+
end
|
339
|
+
RUBY
|
318
340
|
assert_nil(_test_with_block { nil })
|
319
341
|
assert_raises(TypeError) { _test_with_block }
|
320
342
|
|
data/test/test_typecheck.rb
CHANGED
@@ -67,10 +67,6 @@ end
|
|
67
67
|
|
68
68
|
class TestTypecheckC
|
69
69
|
extend RDL::Annotate
|
70
|
-
type 'self.bar', '() -> Integer or String ret'
|
71
|
-
type 'self.foo', '() -> :A'
|
72
|
-
type 'foo', '() -> Integer'
|
73
|
-
type '(Integer) -> self'
|
74
70
|
def initialize(x); end
|
75
71
|
end
|
76
72
|
|
@@ -79,7 +75,6 @@ end
|
|
79
75
|
|
80
76
|
class TestTypecheckE
|
81
77
|
extend RDL::Annotate
|
82
|
-
type '(Integer) -> self', typecheck: :einit
|
83
78
|
def initialize(x)
|
84
79
|
x
|
85
80
|
end
|
@@ -87,7 +82,6 @@ end
|
|
87
82
|
|
88
83
|
class TestTypecheckF
|
89
84
|
extend RDL::Annotate
|
90
|
-
type '(Integer) -> F', typecheck: :finit
|
91
85
|
def initialize(x)
|
92
86
|
x
|
93
87
|
end
|
@@ -95,7 +89,6 @@ end
|
|
95
89
|
|
96
90
|
module TestTypecheckM
|
97
91
|
extend RDL::Annotate
|
98
|
-
type 'self.foo', '() -> :B'
|
99
92
|
end
|
100
93
|
|
101
94
|
class TestTypecheckOuter
|
@@ -140,12 +133,67 @@ class MethodMissing2
|
|
140
133
|
end
|
141
134
|
end
|
142
135
|
|
136
|
+
class SingletonInheritA
|
137
|
+
extend RDL::Annotate
|
138
|
+
end
|
139
|
+
|
140
|
+
class SingletonInheritB < SingletonInheritA; end
|
141
|
+
|
143
142
|
|
144
143
|
class TestTypecheck < Minitest::Test
|
145
144
|
extend RDL::Annotate
|
146
|
-
type :_any_object, "() -> Object" # a method that could return true or false
|
147
145
|
|
148
146
|
def setup
|
147
|
+
RDL.reset
|
148
|
+
RDL.type TestTypecheck, :_any_object, '() -> Object', wrap: false # a method that could return true or false
|
149
|
+
RDL.readd_comp_types
|
150
|
+
RDL.type_params :Hash, [:k, :v], :all? unless RDL::Globals.type_params["Hash"]
|
151
|
+
RDL.type_params :Array, [:t], :all? unless RDL::Globals.type_params["Array"]
|
152
|
+
RDL.rdl_alias :Array, :size, :length
|
153
|
+
RDL.type_params 'RDL::Type::SingletonType', [:t], :satisfies? unless RDL::Globals.type_params["RDL::Type::SingletonType"]
|
154
|
+
=begin
|
155
|
+
RDL.type_params :Array, [:t], :all?
|
156
|
+
RDL.type :Array, :[]=, '(Integer, t) -> t', wrap: false
|
157
|
+
RDL.type :Array, :[]=, '(Integer, Integer, t) -> t', wrap: false
|
158
|
+
RDL.type :Array, :[]=, '(Range<Integer>, t) -> t', wrap: false
|
159
|
+
RDL.type :Array, :each, '() -> Enumerator<t>', wrap: false
|
160
|
+
RDL.type :Array, :each, '() { (t) -> %any } -> Array<t>', wrap: false
|
161
|
+
RDL.type :Array, :length, '() -> Integer', wrap: false
|
162
|
+
RDL.type :Array, :index, '(u) -> Integer', wrap: false
|
163
|
+
RDL.type :Array, :index, '() { (t) -> %bool } -> Integer', wrap: false
|
164
|
+
RDL.type :Array, :index, '() -> Enumerator<t>', wrap: false
|
165
|
+
RDL.type :Array, :map, '() {(t) -> u} -> Array<u>', wrap: false
|
166
|
+
RDL.type :Array, :map, '() -> Enumerator<t>', wrap: false
|
167
|
+
RDL.type_params :Hash, [:k, :v], :all?
|
168
|
+
RDL.type :Hash, :length, '() -> Integer', wrap: false
|
169
|
+
RDL.rdl_alias :Array, :size, :length
|
170
|
+
RDL.type :Hash, :[], '(k) -> v', wrap: false
|
171
|
+
RDL.type :Hash, :[]=, '(k, v) -> v', wrap: false
|
172
|
+
=end
|
173
|
+
RDL.type_params(:Range, [:t], nil, variance: [:+]) { |t| t.member?(self.begin) && t.member?(self.end) } unless RDL::Globals.type_params["Range"]
|
174
|
+
RDL.type :Range, :each, '() { (t) -> %any } -> self'
|
175
|
+
RDL.type :Range, :each, '() -> Enumerator<t>'
|
176
|
+
=begin
|
177
|
+
RDL.type :Integer, :<, '(Integer) -> %bool', wrap: false
|
178
|
+
RDL.type :Integer, :>, '(Integer) -> %bool', wrap: false
|
179
|
+
RDL.type :Integer, :>=, '(Integer) -> %bool', wrap: false
|
180
|
+
RDL.type :Integer, :+, '(Integer) -> Integer', wrap: false
|
181
|
+
RDL.type :Integer, :&, '(Integer) -> Integer', wrap: false
|
182
|
+
RDL.type :Integer, :*, '(Integer) -> Integer', wrap: false
|
183
|
+
=end
|
184
|
+
RDL.type :Integer, :to_s, '() -> String', wrap: false
|
185
|
+
RDL.type :Kernel, 'self.puts', '(*[to_s : () -> String]) -> nil', wrap: false
|
186
|
+
RDL.type :Kernel, :raise, '() -> %bot', wrap: false
|
187
|
+
RDL.type :Kernel, :raise, '(String) -> %bot', wrap: false
|
188
|
+
RDL.type :Kernel, :raise, '(Class, ?String, ?Array<String>) -> %bot', wrap: false
|
189
|
+
RDL.type :Kernel, :raise, '(Exception, ?String, ?Array<String>) -> %bot', wrap: false
|
190
|
+
RDL.type :Object, :===, '(%any other) -> %bool', wrap: false
|
191
|
+
RDL.type :Object, :clone, '() -> self', wrap: false
|
192
|
+
# RDL.type :String, :*, '(Integer) -> String', wrap: false
|
193
|
+
# RDL.type :String, :+, '(String) -> String', wrap: false
|
194
|
+
# RDL.type :String, :===, '(%any) -> %bool', wrap: false
|
195
|
+
# RDL.type :String, :length, '() -> Integer', wrap: false
|
196
|
+
RDL.type :NilClass, :&, '(%any obj) -> false', wrap: false
|
149
197
|
@t3 = RDL::Type::SingletonType.new 3
|
150
198
|
@t4 = RDL::Type::SingletonType.new 4
|
151
199
|
@t5 = RDL::Type::SingletonType.new 5
|
@@ -161,6 +209,8 @@ class TestTypecheck < Minitest::Test
|
|
161
209
|
@scopef = { tret: RDL::Globals.types[:integer] }
|
162
210
|
@tfs = RDL::Type::UnionType.new(RDL::Globals.types[:integer], RDL::Globals.types[:string])
|
163
211
|
@scopefs = { tret: @tfs, tblock: nil }
|
212
|
+
### Uncomment below to see test names. Useful for hanging tests.
|
213
|
+
#puts "Start #{@NAME}"
|
164
214
|
end
|
165
215
|
|
166
216
|
# [+ a +] is the environment, a map from symbols to types; empty if omitted
|
@@ -400,6 +450,20 @@ class TestTypecheck < Minitest::Test
|
|
400
450
|
assert_equal t, do_tc("TestTypecheckOuter::A", env: @env)
|
401
451
|
t = RDL::Type::SingletonType.new(TestTypecheckOuter::A::B::C)
|
402
452
|
assert_equal t, do_tc("TestTypecheckOuter::A::B::C", env: @env)
|
453
|
+
|
454
|
+
self.class.class_eval {
|
455
|
+
const_set(:CONST_STRING, 'string')
|
456
|
+
|
457
|
+
type '() -> String', typecheck: :now
|
458
|
+
def const1() CONST_STRING; end
|
459
|
+
}
|
460
|
+
|
461
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
462
|
+
self.class.class_eval {
|
463
|
+
type '() -> Integer', typecheck: :now
|
464
|
+
def const2() CONST_STRING; end
|
465
|
+
}
|
466
|
+
}
|
403
467
|
end
|
404
468
|
|
405
469
|
def test_defined
|
@@ -505,33 +569,14 @@ class TestTypecheck < Minitest::Test
|
|
505
569
|
end
|
506
570
|
|
507
571
|
class A
|
508
|
-
extend RDL::Annotate
|
509
|
-
type :_send_inherit1, "() -> Integer"
|
510
572
|
end
|
511
573
|
class B < A
|
512
574
|
end
|
513
575
|
|
514
|
-
class A1
|
515
|
-
extend RDL::Annotate
|
516
|
-
type "() -> nil"
|
517
|
-
def _send_inherit2; end
|
518
|
-
end
|
519
|
-
class A2 < A1
|
520
|
-
def _send_inherit2; end
|
521
|
-
end
|
522
|
-
class A3 < A2
|
523
|
-
end
|
524
|
-
|
525
|
-
def test_send_inherit
|
526
|
-
assert do_tc("B.new._send_inherit1", env: @env) <= RDL::Globals.types[:integer]
|
527
|
-
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("A3.new._send_inherit2", env: @env) }
|
528
|
-
end
|
529
|
-
|
530
576
|
def test_send_inter
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
}
|
577
|
+
RDL.type A, :_send_inherit1, "() -> Integer", wrap: false
|
578
|
+
RDL.type TestTypecheck, :_send_inter1, "(Integer) -> Integer", wrap: false
|
579
|
+
RDL.type TestTypecheck, :_send_inter1, "(String) -> String", wrap: false
|
535
580
|
assert do_tc("_send_inter1(42)", env: @env) <= RDL::Globals.types[:integer]
|
536
581
|
assert do_tc("_send_inter1('42')", env: @env) <= RDL::Globals.types[:string]
|
537
582
|
|
@@ -540,15 +585,13 @@ class TestTypecheck < Minitest::Test
|
|
540
585
|
|
541
586
|
def test_send_opt_varargs
|
542
587
|
# from test_type_contract.rb
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
type :_send_opt_varargs7, "(Integer, *String, Integer) -> Integer"
|
551
|
-
}
|
588
|
+
RDL.type TestTypecheck, :_send_opt_varargs1, "(Integer, ?Integer) -> Integer", wrap: false
|
589
|
+
RDL.type TestTypecheck, :_send_opt_varargs2, "(Integer, *Integer) -> Integer", wrap: false
|
590
|
+
RDL.type TestTypecheck, :_send_opt_varargs3, "(Integer, ?Integer, ?Integer, *Integer) -> Integer", wrap: false
|
591
|
+
RDL.type TestTypecheck, :_send_opt_varargs4, "(?Integer) -> Integer", wrap: false
|
592
|
+
RDL.type TestTypecheck, :_send_opt_varargs5, "(*Integer) -> Integer", wrap: false
|
593
|
+
RDL.type TestTypecheck, :_send_opt_varargs6, "(?Integer, String) -> Integer", wrap: false
|
594
|
+
RDL.type TestTypecheck, :_send_opt_varargs7, "(Integer, *String, Integer) -> Integer", wrap: false
|
552
595
|
assert do_tc("_send_opt_varargs1(42)", env: @env) <= RDL::Globals.types[:integer]
|
553
596
|
assert do_tc("_send_opt_varargs1(42, 43)", env: @env) <= RDL::Globals.types[:integer]
|
554
597
|
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs1()", env: @env) }
|
@@ -679,7 +722,7 @@ class TestTypecheck < Minitest::Test
|
|
679
722
|
end
|
680
723
|
|
681
724
|
def test_send_singleton
|
682
|
-
RDL.type Integer, :_send_singleton, "() -> String"
|
725
|
+
RDL.type Integer, :_send_singleton, "() -> String", wrap: false
|
683
726
|
assert do_tc("3._send_singleton", env: @env) <= RDL::Globals.types[:string]
|
684
727
|
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("3._send_singleton_nexists", env: @env) }
|
685
728
|
end
|
@@ -696,10 +739,8 @@ class TestTypecheck < Minitest::Test
|
|
696
739
|
end
|
697
740
|
|
698
741
|
def test_send_block
|
699
|
-
|
700
|
-
|
701
|
-
type :_send_block2, "(Integer) -> Integer"
|
702
|
-
}
|
742
|
+
RDL.type TestTypecheck, :_send_block1, "(Integer) { (Integer) -> Integer } -> Integer"
|
743
|
+
RDL.type TestTypecheck, :_send_block2, "(Integer) -> Integer"
|
703
744
|
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("_send_block1(42)", env: @env) }
|
704
745
|
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("_send_block2(42) { |x| x + 1 }", env: @env) }
|
705
746
|
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("_send_block1(42) { |x, y| x + y }", env: @env) }
|
@@ -733,7 +774,7 @@ class TestTypecheck < Minitest::Test
|
|
733
774
|
type :_send_method_generic4, '(t) { (t) -> t } -> t'
|
734
775
|
type :_send_method_generic5, '() { (u) -> u } -> u'
|
735
776
|
type :_send_method_generic6, '() { (Integer) -> u } -> u'
|
736
|
-
}
|
777
|
+
}
|
737
778
|
assert do_tc('_send_method_generic1 3', env: @env) <= @t3
|
738
779
|
assert do_tc('_send_method_generic1 "foo"', env: @env) <= RDL::Globals.types[:string]
|
739
780
|
assert do_tc('_send_method_generic2 3, "foo"', env: @env) <= tt("3 or String")
|
@@ -912,7 +953,7 @@ class TestTypecheck < Minitest::Test
|
|
912
953
|
# end
|
913
954
|
|
914
955
|
def test_new
|
915
|
-
assert do_tc("B.new", env: @env) <= RDL::Type::NominalType.new(B)
|
956
|
+
assert do_tc("B.new", env: @env) <= RDL::Type::NominalType.new(TestTypecheck::B)
|
916
957
|
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("B.new(3)", env: @env) }
|
917
958
|
end
|
918
959
|
|
@@ -961,16 +1002,14 @@ class TestTypecheck < Minitest::Test
|
|
961
1002
|
end
|
962
1003
|
|
963
1004
|
class C
|
964
|
-
extend RDL::Annotate
|
965
|
-
type :===, "(Object) -> %bool"
|
966
1005
|
end
|
967
1006
|
|
968
1007
|
class D
|
969
|
-
extend RDL::Annotate
|
970
|
-
type :===, "(String) -> %bool"
|
971
1008
|
end
|
972
1009
|
|
973
1010
|
def test_when
|
1011
|
+
RDL.type C, :===, "(Object) -> %bool"
|
1012
|
+
RDL.type D, :===, "(String) -> %bool"
|
974
1013
|
assert do_tc("case when C.new then 3 end", env: @env) <= @t3
|
975
1014
|
assert do_tc("x = 4; case when _any_object then x = 3 end; x", env: @env) <= @t34
|
976
1015
|
assert do_tc("case when _any_object then 3 else 'foo' end", env: @env) <= @ts3
|
@@ -998,6 +1037,7 @@ class TestTypecheck < Minitest::Test
|
|
998
1037
|
assert do_tc("until false do end") <= RDL::Globals.types[:nil]
|
999
1038
|
assert do_tc("begin end while true") <= RDL::Globals.types[:nil]
|
1000
1039
|
assert do_tc("begin end until false") <= RDL::Globals.types[:nil]
|
1040
|
+
|
1001
1041
|
assert do_tc("i = 0; while i < 5 do i = 1 + i end; i") <= RDL::Globals.types[:integer]
|
1002
1042
|
assert do_tc("i = 0; while i < 5 do i = i + 1 end; i") <= RDL::Globals.types[:integer]
|
1003
1043
|
assert do_tc("i = 0; until i >= 5 do i = 1 + i end; i") <= RDL::Globals.types[:integer]
|
@@ -1008,10 +1048,10 @@ class TestTypecheck < Minitest::Test
|
|
1008
1048
|
assert do_tc("i = 0; begin i = i + 1 end until i >= 5; i") <= RDL::Globals.types[:integer]
|
1009
1049
|
|
1010
1050
|
# break, redo, next, no args
|
1011
|
-
assert do_tc("i = 0; while i < 5 do if i > 2 then break end; i = 1 + i end; i") <= RDL::Globals.types[:integer]
|
1012
|
-
assert do_tc("i = 0; while i < 5 do break end; i") <= tt("0")
|
1013
|
-
assert do_tc("i = 0; while i < 5 do redo end; i") # infinite loop, ok for typing <= tt("0")
|
1014
|
-
|
1051
|
+
# assert do_tc("i = 0; while i < 5 do if i > 2 then break end; i = 1 + i end; i") <= RDL::Globals.types[:integer]
|
1052
|
+
# assert do_tc("i = 0; while i < 5 do break end; i") <= tt("0")
|
1053
|
+
# assert do_tc("i = 0; while i < 5 do redo end; i") # infinite loop, ok for typing <= tt("0")
|
1054
|
+
# assert do_tc("i = 0; while i < 5 do next end; i") # infinite loop, ok for typing <= tt("0")
|
1015
1055
|
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("i = 0; while i < 5 do retry end; i") }
|
1016
1056
|
assert do_tc("i = 0; begin i = i + 1; break if i > 2; end while i < 5; i") <= RDL::Globals.types[:integer]
|
1017
1057
|
assert do_tc("i = 0; begin i = i + 1; redo if i > 2; end while i < 5; i") <= RDL::Globals.types[:integer]
|
@@ -1023,16 +1063,21 @@ class TestTypecheck < Minitest::Test
|
|
1023
1063
|
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("while _any_object do next 3 end", env: @env) }
|
1024
1064
|
assert do_tc("begin break 3 end while _any_object", env: @env) <= @t3n
|
1025
1065
|
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("begin next 3 end while _any_object", env: @env) }
|
1066
|
+
|
1026
1067
|
end
|
1027
1068
|
|
1028
1069
|
def test_for
|
1029
1070
|
assert do_tc("for i in 1..5 do end; i") <= RDL::Globals.types[:integer]
|
1030
1071
|
assert do_tc("for i in [1,2,3,4,5] do end; i") <= tt("1 or 2 or 3 or 4 or 5")
|
1072
|
+
## TODO: figure out why above fails to terminate
|
1031
1073
|
assert do_tc("for i in 1..5 do break end", env: @env) <= tt("Range<Integer>")
|
1032
1074
|
assert do_tc("for i in 1..5 do next end", env: @env) <= tt("Range<Integer>")
|
1033
1075
|
assert do_tc("for i in 1..5 do redo end", env: @env) <= tt("Range<Integer>") #infinite loop, ok for typing
|
1034
1076
|
assert do_tc("for i in 1..5 do break 3 end", env: @env) <= tt("Range<Integer> or 3")
|
1035
|
-
assert do_tc("for i in 1..5 do next 'three' end; i", env: @env) <= @tfs
|
1077
|
+
#assert do_tc("for i in 1..5 do next 'three' end; i", env: @env) <= @tfs
|
1078
|
+
## Commented out above after implementing PreciseStringType. It no longer holds because 'three'
|
1079
|
+
## gets upper bound(s) of 'three', but then is promote!-ed to be compared to String, and because
|
1080
|
+
## String is not <= 'three', the previous bounds do not hold and this case fails.
|
1036
1081
|
end
|
1037
1082
|
|
1038
1083
|
def test_return
|
@@ -1060,12 +1105,11 @@ class TestTypecheck < Minitest::Test
|
|
1060
1105
|
end
|
1061
1106
|
|
1062
1107
|
class E
|
1063
|
-
extend RDL::Annotate
|
1064
|
-
type :f, '() -> Integer'
|
1065
|
-
type :f=, '(Integer) -> nil'
|
1066
1108
|
end
|
1067
1109
|
|
1068
1110
|
def test_op_asgn
|
1111
|
+
RDL.type E, :f, '() -> Integer', wrap: false
|
1112
|
+
RDL.type E, :f=, '(Integer) -> nil', wrap: false
|
1069
1113
|
assert RDL::Globals.types[:integer], do_tc("x = 0; x += 1")
|
1070
1114
|
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x += 1") }
|
1071
1115
|
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = Object.new; x += 1", env: @env) }
|
@@ -1075,9 +1119,12 @@ class TestTypecheck < Minitest::Test
|
|
1075
1119
|
end
|
1076
1120
|
|
1077
1121
|
def test_and_or_asgn
|
1122
|
+
RDL.type E, :f, '() -> Integer', wrap: false
|
1123
|
+
RDL.type E, :f=, '(Integer) -> nil', wrap: false
|
1078
1124
|
self.class.class_eval {
|
1079
1125
|
var_type :@f_and_or_asgn, "Integer"
|
1080
1126
|
}
|
1127
|
+
RDL.type TestTypecheckE, :initialize, '(Integer) -> self', wrap: false, typecheck: :einit
|
1081
1128
|
assert do_tc("x ||= 3") <= @t3 # weird
|
1082
1129
|
assert do_tc("x &&= 3") <= RDL::Globals.types[:nil] # weirder
|
1083
1130
|
assert do_tc("@f_and_or_asgn &&= 4", env: @env) <= RDL::Globals.types[:integer]
|
@@ -1088,6 +1135,8 @@ class TestTypecheck < Minitest::Test
|
|
1088
1135
|
end
|
1089
1136
|
|
1090
1137
|
def test_masgn
|
1138
|
+
RDL.type E, :f, '() -> Integer', wrap: false
|
1139
|
+
RDL.type E, :f=, '(Integer) -> nil', wrap: false
|
1091
1140
|
self.class.class_eval {
|
1092
1141
|
var_type :@f_masgn, "Array<Integer>"
|
1093
1142
|
}
|
@@ -1101,7 +1150,8 @@ class TestTypecheck < Minitest::Test
|
|
1101
1150
|
assert do_tc("a, b = 3, 'two'; b") <= RDL::Globals.types[:string]
|
1102
1151
|
assert do_tc("a = [3, 'two']; x, y = a; x") <= @t3
|
1103
1152
|
assert do_tc("a = [3, 'two']; x, y = a; y") <= RDL::Globals.types[:string]
|
1104
|
-
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("a = [3, 'two']; x, y = a; a.length", env: @env) }
|
1153
|
+
#assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("a = [3, 'two']; x, y = a; a.length", env: @env) }
|
1154
|
+
## the above works after computational type changes
|
1105
1155
|
|
1106
1156
|
# w/send
|
1107
1157
|
assert do_tc("e = E.new; e.f, b = 1, 2; b", env: @env) <= tt("2")
|
@@ -1154,9 +1204,14 @@ class TestTypecheck < Minitest::Test
|
|
1154
1204
|
assert do_tc("RDL.type_cast(1 + 2, 'Integer', force: :blah)", env: @env) <= RDL::Globals.types[:integer]
|
1155
1205
|
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("RDL.type_cast(1 + 2, 'Integer', forc: true)", env: @env) }
|
1156
1206
|
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("RDL.type_cast(1 + 2, 'Fluffy Bunny')") }
|
1207
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("RDL.type_cast(:nonsense + 2, 'Integer')") }
|
1208
|
+
assert do_tc("RDL.type_cast(RDL.type_cast(:nonsense, 'Integer') + 2, 'Integer')")
|
1157
1209
|
end
|
1158
1210
|
|
1159
1211
|
def test_instantiate
|
1212
|
+
RDL.type :Array, :initialize, '() -> self', wrap: false
|
1213
|
+
RDL.type :Array, :initialize, '(Integer) -> self', wrap: false
|
1214
|
+
RDL.type :Array, :initialize, '(Integer, t) -> self<t>', wrap: false
|
1160
1215
|
assert_raises(RDL::Typecheck::StaticTypeError) {
|
1161
1216
|
self.class.class_eval {
|
1162
1217
|
type "(Integer, Integer) -> Array<Integer>", typecheck: :now
|
@@ -1169,18 +1224,26 @@ class TestTypecheck < Minitest::Test
|
|
1169
1224
|
def def_inst_pass(x, y) a = Array.new(x,y); RDL.instantiate!(a, "Integer"); a; end
|
1170
1225
|
}
|
1171
1226
|
)
|
1172
|
-
|
1227
|
+
|
1228
|
+
# below works with computational types
|
1229
|
+
#assert_raises(RDL::Typecheck::StaticTypeError) {
|
1230
|
+
assert (
|
1173
1231
|
self.class.class_eval {
|
1174
1232
|
type "(Integer) -> Integer", typecheck: :now
|
1175
1233
|
def def_inst_hash_fail(x) hash = {}; hash["test"] = x; hash["test"]; end
|
1176
1234
|
}
|
1177
|
-
|
1235
|
+
)
|
1236
|
+
# }
|
1237
|
+
|
1238
|
+
=begin
|
1239
|
+
# below works with computational types
|
1178
1240
|
assert_raises(RDL::Typecheck::StaticTypeError) {
|
1179
1241
|
self.class.class_eval {
|
1180
1242
|
type "(Integer) -> Integer", typecheck: :now
|
1181
1243
|
def def_inst_hash_fail2(x) hash = {}; hash.instantiate("Integer", "String") ; hash["test"] = x; hash["test"]; end
|
1182
1244
|
}
|
1183
1245
|
}
|
1246
|
+
=end
|
1184
1247
|
assert(
|
1185
1248
|
self.class.class_eval {
|
1186
1249
|
type "(Integer) -> Integer", typecheck: :now
|
@@ -1203,11 +1266,11 @@ class TestTypecheck < Minitest::Test
|
|
1203
1266
|
end
|
1204
1267
|
|
1205
1268
|
def test_rescue_ensure
|
1269
|
+
|
1206
1270
|
assert do_tc("begin 3; rescue; 4; end") <= @t3 # rescue clause can never be executed
|
1207
1271
|
assert do_tc("begin puts 'foo'; 3; rescue; 4; end", env: @env) <= @t34
|
1208
1272
|
assert do_tc("begin puts 'foo'; 3; rescue => e; e; end", env: @env) <= tt("StandardError or 3")
|
1209
1273
|
assert do_tc("begin puts 'foo'; 3; rescue RuntimeError => e; e; end", env: @env) <= tt("RuntimeError or 3")
|
1210
|
-
assert do_tc("begin puts 'foo'; 3; else; 4; end", env: @env) <= tt("4") # parser discards else clause!
|
1211
1274
|
assert do_tc("begin puts 'foo'; 3; rescue RuntimeError => e; e; rescue ArgumentError => x; x; end", env: @env) <= tt("RuntimeError or ArgumentError or 3")
|
1212
1275
|
assert do_tc("begin puts 'foo'; 3; rescue RuntimeError => e; e; rescue ArgumentError => x; x; else 42; end", env: @env) <= tt("RuntimeError or ArgumentError or 42 or 3")
|
1213
1276
|
assert do_tc("begin puts 'foo'; 3; rescue RuntimeError, ArgumentError => e; e; end", env: @env) <= tt("RuntimeError or ArgumentError or 3")
|
@@ -1216,6 +1279,7 @@ class TestTypecheck < Minitest::Test
|
|
1216
1279
|
assert do_tc("begin x = 3; ensure x = 4; end; x", env: @env) <= @t4
|
1217
1280
|
assert do_tc("begin puts 'foo'; x = 3; rescue; x = 4; ensure x = 5; end; x", env: @env) <= @t5
|
1218
1281
|
assert do_tc("begin puts 'foo'; 3; rescue; 4; ensure 5; end", env: @env) <= @t34
|
1282
|
+
|
1219
1283
|
end
|
1220
1284
|
|
1221
1285
|
class SubArray < Array
|
@@ -1225,11 +1289,9 @@ class TestTypecheck < Minitest::Test
|
|
1225
1289
|
end
|
1226
1290
|
|
1227
1291
|
def test_array_splat
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
type :_splathsf, "() -> Hash<Symbol, Integer>"
|
1232
|
-
}
|
1292
|
+
RDL.type TestTypecheck, :_splataf, "() -> Array<Integer>", wrap: false
|
1293
|
+
RDL.type TestTypecheck, :_splatas, "() -> Array<String>", wrap: false
|
1294
|
+
RDL.type TestTypecheck, :_splathsf, "() -> Hash<Symbol, Integer>", wrap: false
|
1233
1295
|
assert do_tc("x = *1") <= tt("[1]")
|
1234
1296
|
assert do_tc("x = [1, *2, 3]") <= tt("[1, 2, 3]")
|
1235
1297
|
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = [1, *Object.new, 3]", env: @env) } # the Object might or might not be an array...
|
@@ -1248,9 +1310,11 @@ class TestTypecheck < Minitest::Test
|
|
1248
1310
|
assert do_tc("x = *{a: 1, b: 2, c: 3}") <= tt("[[:a, 1], [:b, 2], [:c, 3]]")
|
1249
1311
|
assert do_tc("x = [1, *{a: 2}, 3]") <= tt("[1, [:a, 2], 3]")
|
1250
1312
|
assert do_tc("y = [2]; x = [1, *y, 3]; ") <= tt("[1, 2, 3]")
|
1251
|
-
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("y = [2]; x = [1, *y, 3]; y.length") }
|
1313
|
+
#assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("y = [2]; x = [1, *y, 3]; y.length") }
|
1314
|
+
# the above works after computational type changes
|
1252
1315
|
assert do_tc("y = {a: 2}; x = [1, *y, 3]") <= tt("[1, [:a, 2], 3]")
|
1253
|
-
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("y = {a: 2}; x = [1, *y, 3]; y.length") }
|
1316
|
+
#assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("y = {a: 2}; x = [1, *y, 3]; y.length") }
|
1317
|
+
# the above works after computational type changes
|
1254
1318
|
|
1255
1319
|
assert do_tc("x = *_splataf", env: @env) <= tt("Array<Integer>")
|
1256
1320
|
assert do_tc("x = [1, *_splataf, 2]", env: @env) <= tt("Array<Integer>")
|
@@ -1275,7 +1339,8 @@ class TestTypecheck < Minitest::Test
|
|
1275
1339
|
assert do_tc("x = {**{a: 1}, b: 2, **{c: 3}}") <= tt("{a: 1, b: 2, c: 3}")
|
1276
1340
|
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = {a: 1, **Object.new}", env: @env) } # may or may not be hash
|
1277
1341
|
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = {a: 1, **SubHash.new}", env: @env) } # is a how, but unclear how to splat
|
1278
|
-
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("y = {b: 2}; x = {a: 1, **y}; y.length") }
|
1342
|
+
#assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("y = {b: 2}; x = {a: 1, **y}; y.length") }
|
1343
|
+
# the above works after computational type changes
|
1279
1344
|
|
1280
1345
|
assert do_tc("x = {**_kwsplathsf}", env: @env) <= tt("Hash<Symbol, Integer>")
|
1281
1346
|
assert do_tc("x = {**_kwsplathsf, **_kwsplathos}", env: @env) <= tt("Hash<Symbol or Float, Integer or String>")
|
@@ -1403,6 +1468,22 @@ class TestTypecheck < Minitest::Test
|
|
1403
1468
|
end
|
1404
1469
|
}
|
1405
1470
|
|
1471
|
+
self.class.class_eval {
|
1472
|
+
type '(?Integer x) -> Integer', typecheck: :now
|
1473
|
+
def _optional_varargs_mapping9(x=42)
|
1474
|
+
x
|
1475
|
+
end
|
1476
|
+
}
|
1477
|
+
|
1478
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
1479
|
+
self.class.class_eval {
|
1480
|
+
type '(?Integer x) -> Integer', typecheck: :now
|
1481
|
+
def _optional_varargs_mapping10(x='hi')
|
1482
|
+
x
|
1483
|
+
end
|
1484
|
+
}
|
1485
|
+
}
|
1486
|
+
|
1406
1487
|
end
|
1407
1488
|
|
1408
1489
|
def test_kw_mapping
|
@@ -1508,6 +1589,7 @@ class TestTypecheck < Minitest::Test
|
|
1508
1589
|
|
1509
1590
|
def test_class_call
|
1510
1591
|
TestTypecheckE.class_eval {
|
1592
|
+
type :initialize, '(Integer) -> self', wrap: false
|
1511
1593
|
type '(Integer) -> Class', typecheck: :now
|
1512
1594
|
def call_class1(x)
|
1513
1595
|
x.class
|
@@ -1526,19 +1608,32 @@ class TestTypecheck < Minitest::Test
|
|
1526
1608
|
end
|
1527
1609
|
|
1528
1610
|
def test_singleton
|
1611
|
+
TestTypecheckC.class_eval {
|
1612
|
+
type :'self.foo', '() -> :A'
|
1613
|
+
}
|
1614
|
+
TestTypecheckM.class_eval {
|
1615
|
+
type :'self.foo', '() -> :B'
|
1616
|
+
}
|
1529
1617
|
assert_equal ':A', do_tc("TestTypecheckC.foo", env: @env).to_s
|
1530
1618
|
assert_equal ':B', do_tc("TestTypecheckM.foo", env: @env).to_s
|
1531
1619
|
end
|
1532
1620
|
|
1533
1621
|
def test_annotated_ret
|
1622
|
+
TestTypecheckC.class_eval {
|
1623
|
+
type 'self.bar', '() -> Integer or String ret'
|
1624
|
+
}
|
1534
1625
|
assert do_tc("TestTypecheckC.bar", env: @env) <= tt('Integer or String')
|
1535
1626
|
end
|
1536
1627
|
|
1537
1628
|
def test_constructor
|
1629
|
+
RDL.type TestTypecheckC, :'self.bar', '() -> Integer or String ret'
|
1630
|
+
RDL.type TestTypecheckC, :'self.foo', '() -> :A'
|
1631
|
+
RDL.type TestTypecheckC, :foo, '() -> Integer'
|
1632
|
+
RDL.type TestTypecheckC, :initialize, '(Integer) -> self'
|
1633
|
+
RDL.type TestTypecheckF, :initialize, '(Integer) -> F', typecheck: :finit
|
1538
1634
|
t = do_tc("TestTypecheckC.new(1)", env: @env)
|
1539
1635
|
assert_equal 'TestTypecheckC', t.to_s
|
1540
1636
|
|
1541
|
-
|
1542
1637
|
assert_raises(RDL::Typecheck::StaticTypeError) {
|
1543
1638
|
self.class.class_eval {
|
1544
1639
|
type '(Integer) -> Integer', typecheck: :now
|
@@ -1583,6 +1678,80 @@ class TestTypecheck < Minitest::Test
|
|
1583
1678
|
}
|
1584
1679
|
end
|
1585
1680
|
|
1681
|
+
def test_dyn
|
1682
|
+
# any method call on %dyn type return %dyn
|
1683
|
+
self.class.class_eval {
|
1684
|
+
type "(%dyn) -> %dyn", typecheck: :now
|
1685
|
+
def self.do_add(x); x + 1; end
|
1686
|
+
}
|
1687
|
+
|
1688
|
+
# any method can return a %dyn type
|
1689
|
+
self.class.class_eval {
|
1690
|
+
type "() -> %dyn", typecheck: :now
|
1691
|
+
def self.ret_dyn; "blah"; end
|
1692
|
+
}
|
1693
|
+
|
1694
|
+
# somewhat larger program
|
1695
|
+
self.class.class_eval {
|
1696
|
+
def inc(x); x + 1; end
|
1697
|
+
def use_val; v = get_val; inc(v); end
|
1698
|
+
def get_val; return "blah"; end
|
1699
|
+
|
1700
|
+
type :inc, '(Integer) -> Integer', typecheck: :dyntest
|
1701
|
+
type :use_val, '() -> Integer', typecheck: :dyntest
|
1702
|
+
type :get_val, '() -> %dyn', typecheck: :dyntest
|
1703
|
+
|
1704
|
+
RDL.do_typecheck :dyntest
|
1705
|
+
}
|
1706
|
+
end
|
1707
|
+
|
1708
|
+
def test_assume_dynamic
|
1709
|
+
RDL.config { |config| config.assume_dyn_type = true }
|
1710
|
+
|
1711
|
+
dynamic = do_tc('unknown', env: @env)
|
1712
|
+
assert dynamic <= tt('Integer')
|
1713
|
+
assert tt('Integer') <= dynamic
|
1714
|
+
assert dynamic <= tt('Array<Integer>')
|
1715
|
+
assert tt('Array<Integer>') <= dynamic
|
1716
|
+
|
1717
|
+
tuple_of_dynamic = do_tc('[unknown]', env: @env)
|
1718
|
+
refute tuple_of_dynamic <= tt('Integer')
|
1719
|
+
assert tuple_of_dynamic <= tt('[Integer]')
|
1720
|
+
refute tt('Integer') <= tuple_of_dynamic
|
1721
|
+
assert tt('[Integer]') <= tuple_of_dynamic
|
1722
|
+
|
1723
|
+
assert_equal(dynamic, do_tc('unknown.unknown', env: @env))
|
1724
|
+
assert_equal(dynamic, do_tc('a,b = unknown', env: @env))
|
1725
|
+
assert_equal(dynamic, do_tc('(a,b = unknown).unknown', env: @env))
|
1726
|
+
assert_equal(dynamic, do_tc('unknown[1]', env: @env))
|
1727
|
+
|
1728
|
+
self.class.class_eval {
|
1729
|
+
type "() -> String", typecheck: :now
|
1730
|
+
def dynamic_1()
|
1731
|
+
unknown
|
1732
|
+
end
|
1733
|
+
type "() -> Array<Integer>", typecheck: :now
|
1734
|
+
def dynamic_2()
|
1735
|
+
unknown(unknown)
|
1736
|
+
end
|
1737
|
+
type "() -> %bot", typecheck: :now
|
1738
|
+
def dynamic_3()
|
1739
|
+
unknown(3)
|
1740
|
+
end
|
1741
|
+
}
|
1742
|
+
|
1743
|
+
RDL.config { |config| config.assume_dyn_type = false }
|
1744
|
+
|
1745
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
1746
|
+
self.class.class_eval {
|
1747
|
+
type "() -> String", typecheck: :now
|
1748
|
+
def dynamic_4()
|
1749
|
+
unknown
|
1750
|
+
end
|
1751
|
+
}
|
1752
|
+
}
|
1753
|
+
end
|
1754
|
+
|
1586
1755
|
def test_method_missing
|
1587
1756
|
skip "method_missing not supported yet"
|
1588
1757
|
RDL.do_typecheck :later_mm1
|
@@ -1616,8 +1785,8 @@ class TestTypecheck < Minitest::Test
|
|
1616
1785
|
def bar(x); 1 + x; end
|
1617
1786
|
def baz(x); 1 + x; end
|
1618
1787
|
type 'self.foo', '() -> :a0'
|
1619
|
-
type 'bar', '(
|
1620
|
-
type 'baz', '(
|
1788
|
+
type 'bar', '(Integer) -> Integer'
|
1789
|
+
type 'baz', '(Integer) -> Integer'
|
1621
1790
|
end
|
1622
1791
|
TestTypecheck::SA1.class_eval do
|
1623
1792
|
extend RDL::Annotate
|
@@ -1625,8 +1794,8 @@ class TestTypecheck < Minitest::Test
|
|
1625
1794
|
def bar(x); super(x); end
|
1626
1795
|
def baz(x); super; end
|
1627
1796
|
type 'self.foo', '() -> :a0', typecheck: :call
|
1628
|
-
type :bar, '(
|
1629
|
-
type :baz, '(
|
1797
|
+
type :bar, '(Integer) -> Integer', typecheck: :call
|
1798
|
+
type :baz, '(Integer) -> Integer', typecheck: :call
|
1630
1799
|
end
|
1631
1800
|
|
1632
1801
|
r = TestTypecheck::SA1.foo
|
@@ -1655,4 +1824,240 @@ class TestTypecheck < Minitest::Test
|
|
1655
1824
|
|
1656
1825
|
assert_nil TestTypecheck::A5.new.foo(:a)
|
1657
1826
|
end
|
1827
|
+
|
1828
|
+
module ModuleNesting
|
1829
|
+
module Foo
|
1830
|
+
extend RDL::Annotate
|
1831
|
+
MYFOO = 'foo'
|
1832
|
+
type '() -> String', :typecheck => :call
|
1833
|
+
def self.foo
|
1834
|
+
MYFOO
|
1835
|
+
end
|
1836
|
+
end
|
1837
|
+
module Bar
|
1838
|
+
extend RDL::Annotate
|
1839
|
+
type '() -> NilClass', :typecheck => :call
|
1840
|
+
def self.bar
|
1841
|
+
TestTypecheck::ModuleNesting::Foo.foo
|
1842
|
+
Foo.foo
|
1843
|
+
Foo::MYFOO
|
1844
|
+
nil
|
1845
|
+
end
|
1846
|
+
end
|
1847
|
+
class Baz
|
1848
|
+
extend RDL::Annotate
|
1849
|
+
type '() -> NilClass', :typecheck => :call
|
1850
|
+
def self.baz
|
1851
|
+
TestTypecheck::ModuleNesting::Foo.foo
|
1852
|
+
Foo.foo
|
1853
|
+
Foo::MYFOO
|
1854
|
+
nil
|
1855
|
+
end
|
1856
|
+
type '() -> NilClass', :typecheck => :call
|
1857
|
+
def baz
|
1858
|
+
TestTypecheck::ModuleNesting::Foo.foo
|
1859
|
+
Foo.foo
|
1860
|
+
Foo::MYFOO
|
1861
|
+
nil
|
1862
|
+
end
|
1863
|
+
end
|
1864
|
+
|
1865
|
+
class Parent
|
1866
|
+
MY_CONST = 'foo'
|
1867
|
+
end
|
1868
|
+
module Mixin
|
1869
|
+
MY_MIXIN_CONST = 'bar'
|
1870
|
+
end
|
1871
|
+
class Child < Parent
|
1872
|
+
include Mixin
|
1873
|
+
extend RDL::Annotate
|
1874
|
+
type '() -> String', :typecheck => :call
|
1875
|
+
def self.no_context
|
1876
|
+
MY_CONST
|
1877
|
+
end
|
1878
|
+
type '() -> String', :typecheck => :call
|
1879
|
+
def self.parent_context
|
1880
|
+
Parent::MY_CONST
|
1881
|
+
end
|
1882
|
+
type '() -> String', :typecheck => :call
|
1883
|
+
def self.mixin
|
1884
|
+
MY_MIXIN_CONST
|
1885
|
+
end
|
1886
|
+
end
|
1887
|
+
end
|
1888
|
+
|
1889
|
+
def test_module_nesting
|
1890
|
+
assert_nil ModuleNesting::Bar.bar
|
1891
|
+
assert_nil ModuleNesting::Baz.baz
|
1892
|
+
assert_nil ModuleNesting::Baz.new.baz
|
1893
|
+
assert_equal 'foo', ModuleNesting::Child.no_context
|
1894
|
+
assert_equal 'foo', ModuleNesting::Child.parent_context
|
1895
|
+
assert_equal 'bar', ModuleNesting::Child.mixin
|
1896
|
+
end
|
1897
|
+
|
1898
|
+
def test_module_fully_qualfieds_calls
|
1899
|
+
self.class.class_eval "module FullyQualfied; end"
|
1900
|
+
FullyQualfied.class_eval do
|
1901
|
+
extend RDL::Annotate
|
1902
|
+
type '() -> nil', :typecheck => :call
|
1903
|
+
def self.foo
|
1904
|
+
TestTypecheck::FullyQualfied.bar
|
1905
|
+
end
|
1906
|
+
type '() -> nil', :typecheck => :call
|
1907
|
+
def self.bar
|
1908
|
+
end
|
1909
|
+
end
|
1910
|
+
|
1911
|
+
assert_nil FullyQualfied.foo
|
1912
|
+
end
|
1913
|
+
|
1914
|
+
def test_grandparent_with_type
|
1915
|
+
self.class.class_eval "class GrandParentWithType; end"
|
1916
|
+
self.class.class_eval "class ParentWithoutType < GrandParentWithType; end"
|
1917
|
+
self.class.class_eval "class ChildWithoutType < ParentWithoutType; end"
|
1918
|
+
GrandParentWithType.class_eval do
|
1919
|
+
extend RDL::Annotate
|
1920
|
+
type '(Integer) -> nil', typecheck: :call
|
1921
|
+
def foo(x); end
|
1922
|
+
end
|
1923
|
+
|
1924
|
+
ParentWithoutType.class_eval do
|
1925
|
+
def foo(x); end
|
1926
|
+
end
|
1927
|
+
|
1928
|
+
ChildWithoutType.class_eval do
|
1929
|
+
def foo(x); end
|
1930
|
+
end
|
1931
|
+
|
1932
|
+
assert_nil ChildWithoutType.new.foo(1)
|
1933
|
+
end
|
1934
|
+
|
1935
|
+
def test_object_sing_method
|
1936
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
1937
|
+
Object.class_eval do
|
1938
|
+
extend RDL::Annotate
|
1939
|
+
type '(Integer) -> String', typecheck: :now
|
1940
|
+
def self.add_one(x)
|
1941
|
+
x+1
|
1942
|
+
end
|
1943
|
+
end
|
1944
|
+
}
|
1945
|
+
end
|
1946
|
+
|
1947
|
+
def test_raise_typechecks
|
1948
|
+
self.class.class_eval "module RaiseTypechecks; end"
|
1949
|
+
RaiseTypechecks.class_eval do
|
1950
|
+
extend RDL::Annotate
|
1951
|
+
type '() -> nil', :typecheck => :call
|
1952
|
+
def self.foo
|
1953
|
+
raise "strings are good"
|
1954
|
+
end
|
1955
|
+
|
1956
|
+
type '() -> nil', :typecheck => :call
|
1957
|
+
def self.bar
|
1958
|
+
raise RuntimeError.new, "so are two-args"
|
1959
|
+
end
|
1960
|
+
|
1961
|
+
type '() -> nil', :typecheck => :call
|
1962
|
+
def self.baz
|
1963
|
+
raise RuntimeError, "and just class is ok"
|
1964
|
+
end
|
1965
|
+
end
|
1966
|
+
|
1967
|
+
assert_raises(RuntimeError) do
|
1968
|
+
RaiseTypechecks.foo
|
1969
|
+
end
|
1970
|
+
assert_raises(RuntimeError) do
|
1971
|
+
RaiseTypechecks.bar
|
1972
|
+
end
|
1973
|
+
assert_raises(RuntimeError) do
|
1974
|
+
RaiseTypechecks.baz
|
1975
|
+
end
|
1976
|
+
end
|
1977
|
+
|
1978
|
+
|
1979
|
+
def test_sing_method_inheritence
|
1980
|
+
RDL.type SingletonInheritA, 'self.foo', '(Integer) -> Integer'
|
1981
|
+
self.class.class_eval do
|
1982
|
+
type '(Integer) -> Integer', typecheck: :now
|
1983
|
+
def calls_inherited_sing_meth(x)
|
1984
|
+
SingletonInheritB.foo(x)
|
1985
|
+
end
|
1986
|
+
end
|
1987
|
+
end
|
1988
|
+
|
1989
|
+
|
1990
|
+
def test_comp_types
|
1991
|
+
self.class.class_eval "class CompTypes; end"
|
1992
|
+
CompTypes.class_eval do
|
1993
|
+
### Tests where return type is computed
|
1994
|
+
extend RDL::Annotate
|
1995
|
+
type :bar, '(Integer or String) -> ``gen_return_type(targs)``'
|
1996
|
+
def self.gen_return_type(targs)
|
1997
|
+
raise RDL::Typecheck::StaticTypeError, "Unexpected number of arguments to bar." unless targs.size == 1
|
1998
|
+
if targs[0] == RDL::Globals.types[:integer]
|
1999
|
+
return RDL::Globals.types[:string]
|
2000
|
+
elsif targs[0] == RDL::Globals.types[:string]
|
2001
|
+
return RDL::Globals.types[:integer]
|
2002
|
+
else
|
2003
|
+
raise RDL::Typecheck::StaticTypeError, "Unexpected input type."
|
2004
|
+
end
|
2005
|
+
end
|
2006
|
+
|
2007
|
+
type '(Integer) -> String', typecheck: :now
|
2008
|
+
def uses_bar1(x)
|
2009
|
+
bar(x)
|
2010
|
+
end
|
2011
|
+
|
2012
|
+
type '(String) -> Integer', typecheck: :now
|
2013
|
+
def uses_bar2(x)
|
2014
|
+
bar(x)
|
2015
|
+
end
|
2016
|
+
end
|
2017
|
+
|
2018
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
2019
|
+
CompTypes.class_eval do
|
2020
|
+
type '(String) -> String', typecheck: :now
|
2021
|
+
def uses_bar3(x)
|
2022
|
+
bar(x)
|
2023
|
+
end
|
2024
|
+
end
|
2025
|
+
}
|
2026
|
+
|
2027
|
+
CompTypes.class_eval do
|
2028
|
+
### Tests where input type is computed
|
2029
|
+
type :baz, '(Integer or String, ``gen_input_type(targs)``) -> Integer'
|
2030
|
+
|
2031
|
+
def self.gen_input_type(targs)
|
2032
|
+
raise RDL::Typecheck::StaticTypeError, "Unexpected number of arguments to bar." unless targs.size == 2
|
2033
|
+
if targs[0] == RDL::Globals.types[:integer]
|
2034
|
+
return RDL::Globals.types[:string]
|
2035
|
+
elsif targs[0] == RDL::Globals.types[:string]
|
2036
|
+
return RDL::Globals.types[:integer]
|
2037
|
+
else
|
2038
|
+
raise RDL::Typecheck::StaticTypeError, "Unexpected input type."
|
2039
|
+
end
|
2040
|
+
end
|
2041
|
+
|
2042
|
+
type '(Integer, String) -> Integer', typecheck: :now
|
2043
|
+
def uses_baz1(x, y)
|
2044
|
+
baz(x, y)
|
2045
|
+
end
|
2046
|
+
|
2047
|
+
type '(String, Integer) -> Integer', typecheck: :now
|
2048
|
+
def uses_baz2(x, y)
|
2049
|
+
baz(x, y)
|
2050
|
+
end
|
2051
|
+
end
|
2052
|
+
|
2053
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
2054
|
+
CompTypes.class_eval do
|
2055
|
+
type '(Integer, Integer) -> Integer', typecheck: :now
|
2056
|
+
def uses_baz3(x, y)
|
2057
|
+
baz(x, y)
|
2058
|
+
end
|
2059
|
+
end
|
2060
|
+
}
|
2061
|
+
|
2062
|
+
end
|
1658
2063
|
end
|