- Notifications
You must be signed in to change notification settings - Fork 135
/
Copy pathprecedence.t
306 lines (224 loc) · 8 KB
/
precedence.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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
useTest;
uselib$?FILE.IO.parent(2).add:'packages/Test-Helpers';
useTest::Util;
# L<S03/Operator precedence>
=beginpod
Tests that each level bind tighter than the next by sampling some ops.
In between each precedence level are some tests that demonstrate the
proper separation of the two levels.
=endpod
plan77;
# terms
# FIXME how do we test this?
# postfix method
{
my@a=1,2,3;
is(++@a[2], 4, "bare postfix binds tighter than ++");
is(++@a.[2], 5, "dotted postfix binds tighter than ++");
}
# autoincrement
{
my$i=2;
is(++$i**2, 9, "++ bind tighter than **");
is(--$i**2, 4, "-- does too");
}
# exponentiation
is(-2**2, -4, "** bind tighter than unary -");
isa-ok(~2**4, Str, "~2**4 is a string");
# symbolic unary
is(!0 *2, 2, "unary ! binds tighter than *");
ok(!(0*2), "beh");
is(?2*2, 2, "binary -> numify causes reinterpretation as, binds tighter than *");
is-2**2.abs, 4, "on left side . is looser than ** and left-to-right with unary -";
is-2**2.abs+1, 5, "on right side . is tighter than addition";
is-2**2.abs.Str.ord, "4".ord, "on right side . is tighter than methodcall";
is-1*-1.abs, -1, "on left side . is tighter than *";
# multiplicative
is(4+3*2, 10, "* binds tighter than binary +");
is(2-2div2, 1, "div binds tighter than binary -");
is(2-2/2, 1/1, "/ binds tighter than binary -");
# additive
is(1~2*3, 16, "~ binds looser than *");
ok(?((1~2 & 12) ==12), "but tighter than &");
ok(?((2+2|4-1) ==4), "and + binds tighter than |");
# replication
is(2x2+3, "22222", "x binds looser than binary +");
is((2x2) +3, 25, "doublecheck");
# concatenation
is(2x2~3, "223", "x binds tighter than binary ~");
ok(?((2~2|4~1) ==41), "and ~ binds tighter than |");
# junctive and
ok( ?( (1 & 2|3) ==3), '& binds tighter than |');
ok((!(1 & 2|3) <2), "ditto");
ok(?((1 & 2^3) <3), "and also ^");
ok(?(!(1 & 2^4) !=3), "blah blah blah");
# junctive or
{ # test that | and ^ are on the same level but parsefail
throws-like'my Mu $a = (1 | 2 ^ 3)',
X::Syntax::NonListAssociative,
'| and ^ may not associate';
throws-like'my Mu $a = (1 ^ 2 | 3)',
X::Syntax::NonListAssociative,
'^ and | may not associate';
};
{
myMu$b= ((abs-1) ^-1); # -> (1 ^ -1)
ok($b==1, "this is true because only one is == 1");
};
# named unary
ok(0<2 <=> 1<2, "0 < 2 <=> 1 < 2 means 0 < 1 < 2");
# structural infix
is-deeply-junction (1|3 <=> 2), any(Less, More), '<=> binds looser than |';
is-deeply (1==3 <=> 2), True, '<=> binds tighter than ==';
throws-like'1 .. 2 .. 3',
X::Syntax::NonAssociative,
'identical .. is not associative';
throws-like'1 <=> 2 leg 3',
X::Syntax::NonAssociative,
'<=> and leg are not associative';
# chaining
is((0!=1&&"foo"), "foo", "!= binds tighter than &&");
ok((0||1== (2-1) == (0+1) ||"foo") ne"foo", "== binds tighter than || also when chaning");
# tight and (&&)
# tight or (||, ^^, //)
is((1&&0??2!!3), 3, "&& binds tighter than ??");
### FIXME - need also ||, otherwise we don't prove || and ?? are diff
# conditional
{
my$a=0??"yes"!!"no";
is($a, "no", "??!! binds tighter than =");
throws-like { EVAL'$a ?? $a = 42 !! $a = 43' },
X::Syntax::ConditionalOperator::PrecedenceTooLoose,
"Can't use assignop inside ??!!";
throws-like { EVAL'$a ?? $a += 42 !! $a = 43' },
X::Syntax::ConditionalOperator::PrecedenceTooLoose,
"Can't use meta-assignop inside ??!!";
# (my $b = 1) ?? "true" !! "false";
# is($b, 1, "?? !! just thrown away with = in parens");
};
# item assignment
{
my$c=1, 2, 3;
is($c, 1, '$ = binds tighter than ,');
my$a= (1, 3) X (2, 4);
is($a, [1, 3], "= binds tighter than X");
}
# loose unary
my$x;
is((so$x=42), True, "item assignment is tighter than true");
# comma
is(((not1,42)[1]), 42, "not is tighter than comma");
# list infix
{
my@d;
ok (@d=1,3Z2,4), "list infix tighter than list assignment, looser t than comma";
is(@d, [1..4], "to complicate things further, it dwims");
}
{
my@b;
@b= ((1, 3) Z (2, 4));
is(@b, [1..4], "parens work around this");
};
# https://github.com/Raku/old-issue-tracker/issues/2164
{
throws-like'4 X+> 1...2',
X::Syntax::NonListAssociative,
'X+> must not associate with ...';
throws-likeq['08:12:23'.split(':') Z* 60 X** reverse ^3],
X::Syntax::NonListAssociative,
'Z* and X** are non associative';
}
# list prefix
{
my$c=anyflat1, 2Z3, 4;
ok($c==3, "any is less tight than comma and Z");
}
my@c=1, 2, 3;
is(@c, [1,2,3], "@ = binds looser than ,");
# loose and
{
my$run=1;
subisfive (*@args) {
is(@args[0], 5, "First arg is 5, run "~$run++);
1;
}
# these are two tests per line, actually
# we should have a better way that doesn't just result in
# a wrong plan if gone wrong.
isfive(5) and isfive(5);
isfive 5and isfive 5;
}
# loose or
# terminator
# superscript exponentiation
{
my$i=2;
# https://github.com/Raku/old-issue-tracker/issues/5917
#?rakudo 2 skip 'superscript exponent associativity'
is(++$i², 9, "++ bind tighter than superscript exponent");
is(--$i², 4, "-- does too");
# https://github.com/Raku/old-issue-tracker/issues/5917
#?rakudo todo 'superscript exponent associativity'
is(2²**3, 256, "mixed exponent does right associative");
is(-2², -4, "superscript exponent binds tighter than unary -");
isa-ok(~2⁴, Str, "~2⁴ is a string");
is-2² .abs, 4, "on left side . is looser than superscript exponent and left-to-right with unary -";
is-2² .abs+1, 5, "on right side . is tighter than addition";
is-2² .abs.Str.ord, "4".ord, "on right side . is tighter than methodcall";
}
# Contrary to Perl there are no prototypes, and since normal built-ins
# are not defined as prefix ops, 'uc $a eq $A' actually parses as
# uc($a eq $A), not uc($a) eq $A.
# http://irclog.perlgeek.de/perl6/2009-07-14#i_1316200
#
# so uc(False) stringifies False to 'FALSE', and uc('0') is false. Phew.
is (uc"a"eq"A"), uc(False.Str), "uc has the correct precedence in comparison to eq";
# L<S03/Named unary precedence/my $i = int $x; # ILLEGAL>
throws-like'int 4.5', X::Syntax::Confused, 'there is no more prefix:<int>';
# http://irclog.perlgeek.de/perl6/2009-07-14#i_1315249
ok ((1=>2=>3).key!~~Pair), '=> is right-assoc (1)';
ok ((1=>2=>3).value~~Pair), '=> is right-assoc (2)';
# L<S03/Operator precedence/only works between identical operators>
throws-like'1, 2 Z 3, 4 X 5, 6',
X::Syntax::NonListAssociative,
'list associativity only works between identical operators';
{
# Check a 3 != 3 vs 3 !=3 parsing issue that can cropped up in Rakudo.
# Needs careful following of STD to get it right. :-)
my$r;
subfoo($x) { $r=$x }
foo 3!=3;
is($r, False, 'sanity 3 != 3');
$r=True;
# https://github.com/Raku/old-issue-tracker/issues/3322
lives-ok { foo 3!=3 }, '3 !=3 does not die';
is($r, False, 'ensure 3 !=3 gives same result as 3 != 3');
}
# https://github.com/Raku/old-issue-tracker/issues/1571
{
try { EVAL'say and die 73266' };
ok~$!!~~'73266', 'and after say is not interpreted as infix:<and>';
}
# https://github.com/Raku/old-issue-tracker/issues/2998
{
my$s= set(); my$e=5; $s=$s(|)$e;
is$s, Set.new(5), '(|) has correct precedence.';
}
# https://github.com/Raku/old-issue-tracker/issues/2832
{
isnot(0) +1, 2,
'"not(0) + 1" is parsed as "(not 0) + 1"';
}
# https://github.com/Raku/old-issue-tracker/issues/4250
throws-like'my $lizmat = 42; ++$lizmat++',
X::Syntax::NonAssociative,
'prefix/postfix ++ are not associative';
# https://github.com/Raku/old-issue-tracker/issues/5284
{
moduleRT128042 {
multiinfix:<§>($,$) istighter(&[+]) isexport {0};
};
import RT128042;
is (1+2 § 3), 1, 'exported multi has correct precedence';
}
# vim: expandtab shiftwidth=4