-
Notifications
You must be signed in to change notification settings - Fork 135
/
type.t
184 lines (152 loc) · 8.48 KB
/
type.t
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
use v6;
use Test;
=begin description
Basic tests about variables having built-in types assigned
=end description
# L<S02/"Types as Constraints"/"A variable's type is a constraint indicating what sorts">
plan 80;
{
ok(try {my Int $foo; 1}, 'compile my Int $foo');
ok(try {my Str $bar; 1}, 'compile my Str $bar');
}
ok(do {my Int $foo; $foo ~~ Int}, 'Int $foo isa Int');
ok(do {my Str $bar; $bar ~~ Str}, 'Str $bar isa Str');
my Int $foo;
my Str $bar;
{
throws-like q[$foo = 'xyz'], X::TypeCheck::Assignment, 'Int restricts to integers';
throws-like q[$foo = Mu], X::TypeCheck::Assignment, 'Int does not accept Mu';
is(($foo = 42), 42, 'Int is an integer');
throws-like q[$bar = 42], X::TypeCheck::Assignment, 'Str restricts to strings';
throws-like q[$bar = Mu], X::TypeCheck::Assignment, 'Str does not accept Mu';
is(($bar = 'xyz'), 'xyz', 'Str is a strings');
}
{
my $baz of Int;
throws-like q[$baz = 'xyz'], X::TypeCheck::Assignment, 'of Int restricts to integers';
is(($baz = 42), 42, 'of Int is an integer');
}
# L<S02/Variables Containing Undefined Values/Variables with native types do not support undefinedness>
{
eval-lives-ok('my int $alpha = 1', 'Has native type int');
throws-like 'my int $alpha = Nil', Exception, 'native int type cannot be undefined';
lives-ok({my Int $beta = Nil}, 'object Int type can be undefined');
eval-lives-ok('my num $alpha = 1e0', 'Has native type num');
# RT #121518
#?rakudo todo "nigh, RT #121518"
eval-lives-ok('my num $alpha = Nil', 'native num type can be undefined');
lives-ok({my Num $beta = Nil}, 'object Num type can be undefined');
# RT #93982
lives-ok({my Str ($a) = ()}, 'object Str type can be undefined, list context');
}
# L<S02/Parameter types/Parameters may be given types, just like any other variable>
{
sub paramtype (Int $i) {return $i+1}
is(paramtype(5), 6, 'sub parameters with matching type');
throws-like 'paramtype("foo")', X::TypeCheck::Argument,
'sub parameters with non-matching type dies';
}
{
# test contributed by Ovid++
sub fact (Int $n) {
if 0 == $n {
1;
}
else {
$n * fact($n - 1);
}
}
is fact(5), 120, 'recursive factorial with type contstraints work';
}
# Num does not accept Int
throws-like q[my Num $n; $n = 42], X::Syntax::Number::LiteralType, 'Num does not accept Int';
throws-like q[my Num $n; $n = $*PID], X::TypeCheck::Assignment, 'Num does not accept Int';
# Complex does not accept Int
throws-like q[my Complex $n; $n = 42], X::Syntax::Number::LiteralType, 'Complex does not accept Int';
throws-like q[my Complex $n; $n = $*PID], X::TypeCheck::Assignment, 'Complex does not accept Int';
# Rat does not accept Int
throws-like q[my Rat $n; $n = 42], X::Syntax::Number::LiteralType, 'Rat does not accept Int';
throws-like q[my Rat $n; $n = $*PID], X::TypeCheck::Assignment, 'Rat does not accept Int';
# Int does not accept Num
throws-like q[my Int $n; $n = 42e0], X::Syntax::Number::LiteralType, 'Int does not accept Num';
throws-like q[my Int $n; $n = $*PID.Num], X::TypeCheck::Assignment, 'Int does not accept Num';
# Complex does not accept Num
throws-like q[my Complex $n; $n = 42e0], X::Syntax::Number::LiteralType, 'Complex does not accept Num';
throws-like q[my Complex $n; $n = $*PID.Num], X::TypeCheck::Assignment, 'Complex does not accept Num';
# Rat does not accept Num
throws-like q[my Rat $n; $n = 42e0], X::Syntax::Number::LiteralType, 'Rat does not accept Num';
throws-like q[my Rat $n; $n = $*PID.Num], X::TypeCheck::Assignment, 'Rat does not accept Num';
# Int does not accept Rat
throws-like q[my Int $n; $n = 42.0], X::Syntax::Number::LiteralType, 'Int does not accept Rat';
throws-like q[my Int $n; $n = $*PID.Rat], X::TypeCheck::Assignment, 'Int does not accept Rat';
# Complex does not accept Rat
throws-like q[my Complex $n; $n = 42.0], X::Syntax::Number::LiteralType, 'Complex does not accept Rat';
throws-like q[my Complex $n; $n = $*PID.Rat], X::TypeCheck::Assignment, 'Complex does not accept Rat';
# Num does not accept Rat
throws-like q[my Num $n; $n = 42.0], X::Syntax::Number::LiteralType, 'Num does not accept Rat';
throws-like q[my Num $n; $n = $*PID.Rat], X::TypeCheck::Assignment, 'Num does not accept Rat';
# Int does not accept Complex
throws-like q[my Int $n; $n = <42+0i>], X::Syntax::Number::LiteralType, 'Int does not accept Complex';
throws-like q[my Int $n; $n = $*PID\i], X::TypeCheck::Assignment, 'Int does not accept Complex';
# Complex does not accept Complex
throws-like q[my Rat $n; $n = <42+0i>], X::Syntax::Number::LiteralType, 'Rat does not accept Complex';
throws-like q[my Rat $n; $n = $*PID\i], X::TypeCheck::Assignment, 'Rat does not accept Complex';
# Num does not accept Complex
throws-like q[my Num $n; $n = <42+0i>], X::Syntax::Number::LiteralType, 'Num does not accept Complex';
throws-like q[my Num $n; $n = $*PID\i], X::TypeCheck::Assignment, 'Num does not accept Complex';
throws-like q[my num $n; $n = 42], X::Syntax::Number::LiteralType, 'num does not accept Int';
throws-like q[my int $n; $n = 42e0], X::Syntax::Number::LiteralType, 'int does not accept Num';
throws-like q[my int $n; $n = 42.0], X::Syntax::Number::LiteralType, 'int does not accept Rat';
throws-like q[my num $n; $n = 42.0], X::Syntax::Number::LiteralType, 'num does not accept Rat';
throws-like q[my int $n; $n = <42+0i>], X::Syntax::Number::LiteralType, 'int does not accept Complex';
throws-like q[my num $n; $n = <42+0i>], X::Syntax::Number::LiteralType, 'num does not accept Complex';
# L<S02/Return types/a return type can be specified before or after the name>
{
# Check with explicit return.
my sub returntype1 (Bool $pass) returns Str { return $pass ?? 'ok' !! -1}
my sub returntype2 (Bool $pass) of Int { return $pass ?? 42 !! 'no'}
my Bool sub returntype3 (Bool $pass) { return $pass ?? Bool::True !! ':('}
my sub returntype4 (Bool $pass --> Str) { return $pass ?? 'ok' !! -1}
is(returntype1(Bool::True), 'ok', 'good return value works (returns)');
throws-like 'returntype1(Bool::False)', X::TypeCheck::Return, 'bad return value dies (returns)';
is(returntype2(Bool::True), 42, 'good return value works (of)');
throws-like 'returntype2(Bool::False)', X::TypeCheck::Return, 'bad return value dies (of)';
is(returntype3(Bool::True), True, 'good return value works (my Type sub)');
throws-like 'returntype3(Bool::False)', X::TypeCheck::Return, 'bad return value dies (my Type sub)';
is(returntype4(Bool::True), 'ok', 'good return value works (-->)');
throws-like 'returntype4(Bool::False)', X::TypeCheck::Return, 'bad return value dies (-->)';
}
{
# Check with implicit return.
my sub returntype1 (Bool $pass) returns Str { $pass ?? 'ok' !! -1}
my sub returntype2 (Bool $pass) of Int { $pass ?? 42 !! 'no'}
my Bool sub returntype3 (Bool $pass) { $pass ?? Bool::True !! ':('}
my sub returntype4 (Bool $pass --> Str) { $pass ?? 'ok' !! -1}
is(returntype1(Bool::True), 'ok', 'good implicit return value works (returns)');
throws-like 'returntype1(Bool::False)', X::TypeCheck::Return, 'bad implicit return value dies (returns)';
is(returntype2(Bool::True), 42, 'good implicit return value works (of)');
throws-like 'returntype2(Bool::False)', X::TypeCheck::Return, 'bad implicit return value dies (of)';
is(returntype3(Bool::True), True, 'good implicit return value works (my Type sub)');
throws-like 'returntype3(Bool::False)', X::TypeCheck::Return, 'bad implicit return value dies (my Type sub)';
is(returntype4(Bool::True), 'ok', 'good implicit return value works (-->)');
throws-like 'returntype4(Bool::False)', X::TypeCheck::Return, 'bad implicit return value dies (-->)';
}
{
throws-like 'my Int Str $x', X::Comp::NYI, 'multiple prefix constraints not allowed';
throws-like 'sub foo(Int Str $x) { }', X::Parameter::MultipleTypeConstraints,
'multiple prefix constraints not allowed';
throws-like 'sub foo(--> Int Str) { }', Exception, 'multiple prefix constraints not allowed';
throws-like 'our Int Str sub foo() { }', X::Comp::NYI, 'multiple prefix constraints not allowed';
}
{
# TODO: many more of these are possible
ok Any ~~ Mu, 'Any ~~ Mu';
ok Mu !~~ Any, 'Mu !~~ Any';
ok Mu !~~ Int, 'Mu !~~ Int';
ok Int ~~ Numeric, 'Int ~~ Numeric';
ok Numeric !~~ Int, 'Numeric !~~ Int';
ok Array ~~ List, 'Array is a kind of List';
ok List !~~ Array, 'A List is not an Array';
ok Array ~~ Positional, 'Array does Positional too';
}
# vim: ft=perl6