/
type.t
135 lines (110 loc) · 5.04 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
use v6;
use Test;
=begin description
Basic tests about variables having built-in types assigned
=end description
# L<S02/"Built-In Data Types"/"A variable's type is a constraint indicating what sorts">
plan 44;
{
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;
{
#?pugs 1 todo
dies_ok({$foo = 'xyz'}, 'Int restricts to integers');
is(($foo = 42), 42, 'Int is an integer');
#?pugs 1 todo
dies_ok({$bar = 42}, 'Str restricts to strings');
is(($bar = 'xyz'), 'xyz', 'Str is a strings');
}
my $baz of Int;
{
dies_ok({$baz = 'xyz'}, 'of Int restricts to integers');
is(($baz = 42), 42, 'of Int is an integer');
}
# L<S02/Built-In Data Types/Variables with native types do not support undefinedness>
#?rakudo skip 'native types (causes false positives if marked with todo)'
{
eval_lives_ok('my int $alpha = 1', 'Has native type int');
eval_dies_ok('my int $alpha = undef', 'native int type cannot be undef');
lives_ok({my Int $beta = undef}, 'object Int type can be undef');
eval_lives_ok('my num $alpha = 1', 'Has native type num');
eval_dies_ok('my num $alpha = undef', 'native num type cannot be undef');
lives_ok({my Num $beta = undef}, 'object Num type can be undef');
}
# 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');
eval_dies_ok('paramtype("foo")', '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 accepts Int too.
{
my Num $n;
$n = 42;
is $n, 42, 'Num accepts Int too';
}
# 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)');
dies_ok({ returntype1(Bool::False) }, 'bad return value dies (returns)');
is(returntype2(Bool::True), 42, 'good return value works (of)');
dies_ok({ returntype2(Bool::False) }, 'bad return value dies (of)');
is(returntype3(Bool::True), True, 'good return value works (my Type sub)');
dies_ok({ returntype3(Bool::False) }, 'bad return value dies (my Type sub)');
is(returntype4(Bool::True), 'ok', 'good return value works (-->)');
dies_ok({ returntype4(Bool::False) }, '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)');
dies_ok({ returntype1(Bool::False) }, 'bad implicit return value dies (returns)');
is(returntype2(Bool::True), 42, 'good implicit return value works (of)');
dies_ok({ returntype2(Bool::False) }, 'bad implicit return value dies (of)');
is(returntype3(Bool::True), True, 'good implicit return value works (my Type sub)');
dies_ok({ returntype3(Bool::False) }, 'bad implicit return value dies (my Type sub)');
is(returntype4(Bool::True), 'ok', 'good implicit return value works (-->)');
dies_ok({ returntype4(Bool::False) }, 'bad implicit return value dies (-->)');
}
#?rakudo skip 'Rat not implemented, as not implemented'
{
# the following two are the same type of behavior
# S02: "It is possible for the of type to disagree with the as type"
my Rat sub returntype4 ($pass) as Num {$pass ?? 11 div 10 !! 1}
my sub returntype5 ($pass --> Rat) as Num {$pass ?? 11 div 5 !! 2}
is(returntype4(True), 1.1, 'good return value works (my Type sub as OtherType)');
eval_dies_ok('returntype4(False)', 'bad return value dies (my Type sub as OtherType)');
is(returntype5(True), 2.2, 'good return value works (--> Type as OtherType)');
eval_dies_ok('returntype5(False)', 'bad return value dies (--> Type as OtherType)');
}
{
eval_dies_ok('my Int Str $x', 'multiple prefix constraints not allowed');
eval_dies_ok('sub foo(Int Str $x) { }', 'multiple prefix constraints not allowed');
eval_dies_ok('sub foo(--> Int Str) { }', 'multiple prefix constraints not allowed');
eval_dies_ok('our Int Str sub foo() { }', 'multiple prefix constraints not allowed');
}