forked from Raku/roast
-
Notifications
You must be signed in to change notification settings - Fork 0
/
syntax.t
133 lines (110 loc) · 4.68 KB
/
syntax.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
use v6;
use Test;
plan 37;
# L<S06/Routine modifiers/>
# L<S06/Parameters and arguments/>
# multi sub with signature
multi sub foo() { "empty" }
multi sub foo($a) { "one" } #OK not used
is(foo(), "empty", "multi sub with empty signature");
is(foo(42), "one", "multi sub with parameter list");
# multi sub without signature
multi sub bar { "empty" }
multi sub bar($a) { "one" } #OK not used
is(bar(), "empty", "multi sub with no signature");
is(bar(42), "one", "multi sub with parameter list");
# multi without a routine type
multi baz { "empty" }
multi baz($a) { "one" } #OK not used
is(baz(), "empty", "multi with no signature");
is(baz(42), "one", "multi with parameter list");
# multi with some parameters not counting in dispatch (;;) - note that if the
# second parameter is counted as part of the dispatch, then invoking with 2
# ints means they are tied candidates as one isn't narrower than the other.
# (Note Int is narrower than Num - any two types where one is narrower than
# the other will do it, though.)
multi foo(Int $a, Num $b) { 1 } #OK not used
multi foo(Num $a, Int $b) { 2 } #OK not used
multi bar(Int $a;; Num $b) { 1 } #OK not used
multi bar(Num $a;; Int $b) { 2 } #OK not used
my $lived = 0;
try { foo(1,1); $lived = 1 }
is($lived, 0, "dispatch tied as expected");
is(bar(1,1), 1, "not tied as only first type in the dispatch");
# not allowed to declare anonymous routines with only, multi or proto.
eval_dies_ok 'only sub {}', 'anonymous only sub is an error';
eval_dies_ok 'multi sub {}', 'anonymous multi sub is an error';
eval_dies_ok 'proto sub {}', 'anonymous proto sub is an error';
eval_dies_ok 'only {}', 'anonymous only is an error';
eval_dies_ok 'multi {}', 'anonymous multi is an error';
eval_dies_ok 'proto {}', 'anonymous proto is an error';
eval_dies_ok 'class A { only method {} }', 'anonymous only method is an error';
eval_dies_ok 'class B { multi method {} }', 'anonymous multi method is an error';
eval_dies_ok 'class C { proto method {} }', 'anonymous proto method is an error';
ok(&foo ~~ Multi, 'a multi does Multi');
ok(&foo ~~ Callable, 'a multi does Callable');
ok(~&foo ~~ /foo/, 'a multi stringifies sensibly');
# note - example in ticket [perl #58948] a bit more elaborate
{
multi sub max($a, $b, $c) {return 9} #OK not used
lives_ok { max(1, 2, 3) }, 'use multi method to override builtin lives';
is eval('max(1, 2, 3)'), 9, 'use multi method to override builtin';
}
# named and slurpy interaction - there have been bugs in the past on this front
{
multi nsi_1(Int $x, Bool :$flag, *@vals) { "nsi 1" }; #OK not used
is nsi_1(1), 'nsi 1', 'interaction between named and slurpy (1)';
is nsi_1(1, 2, 3, 4, 5), 'nsi 1', 'interaction between named and slurpy (2)';
multi nsi_2(Bool :$baz = Bool::False, *@vals) { "nsi 2" }; #OK not used
is nsi_2(:baz(Bool::True), 1, 2, 3), 'nsi 2', 'interaction between named and slurpy (3)';
is nsi_2(1, 2, 3), 'nsi 2', 'interaction between named and slurpy (4)';
}
# RT #68234
{
multi rt68234(:$key!) { 'with key' }; #OK not used
multi rt68234(*%_) { 'unknown' }; #OK not used
is rt68234(:key), 'with key', 'can find multi method with key';
#?rakudo skip 'RT #68234'
is rt68234(:unknown), 'unknown', 'can find multi method with slurpy';
}
# RT #68158
{
multi rt68158() { 1 }
multi rt68158(*@x) { 2 } #OK not used
is rt68158(), 1, 'non-slurpy wins over slurpy';
is rt68158(9), 2, 'slurpy called when non-slurpy can not bind';
}
# RT #64922
{
multi rt64922($x, %h?) { 1 } #OK not used
multi rt64922(@x) { 2 } #OK not used
is rt64922(1), 1, 'optional parameter does not break type-based candidate sorting';
is rt64922([1,2]), 2, 'optional parameter does not break type-based candidate sorting';
}
# RT #65672
{
multi rt65672() { 99 }
multi rt65672($x) { $x }
sub rt65672caller( &x ) { &x() }
is rt65672caller( &rt65672 ), 99, 'multi can be passed as callable';
}
# We had a bug where the multiness leaked into a sub, so we got errors
# about anonymous methods not being allowed to be multi.
{
multi sub kangaroo() { return method () { self * 2 } }
my $m = kangaroo();
is 21.$m(), 42, 'can write anonymous methods inside multi subs';
}
# RT #75136
# a multi declaration should only return the current candidate, not the whole
# set of candidates.
{
multi sub koala(Int $x) { 42 * $x };
my $x = multi sub koala(Str $x) { 42 ~ $x }
is $x.candidates.elems,
1, 'multi sub declaration returns just the current candidate';
is $x('moep'), '42moep', 'and that candidate works';
dies_ok { $x(23) }, '... and does not contain the full multiness';
}
done;
# vim: ft=perl6