Skip to content

Commit

Permalink
Create a new logical xor operator, spelled ^^
Browse files Browse the repository at this point in the history
Previously, the low-precedence `xor` operator did not have a
higher-precedence logical variant, as compared `or` vs `||` and
`and` vs `&&`. This PR adds such an operator syntax, completing the
set.
  • Loading branch information
Martijn Lievaart authored and leonerd committed Feb 18, 2024
1 parent 5fdf6e9 commit 0975291
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 8 deletions.
4 changes: 2 additions & 2 deletions perly.act

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion perly.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion perly.tab

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion perly.y
Original file line number Diff line number Diff line change
Expand Up @@ -1247,7 +1247,7 @@ termbinop: term[lhs] PLUGIN_HIGH_OP[op] term[rhs]
| term[lhs] PLUGIN_LOGICAL_AND_OP[op] term[rhs]
{ $$ = build_infix_plugin($lhs, $rhs, $op); }
| term[lhs] OROR term[rhs] /* $x || $y */
{ $$ = newLOGOP(OP_OR, 0, $lhs, $rhs); }
{ $$ = newLOGOP($OROR, 0, $lhs, $rhs); }
| term[lhs] PLUGIN_LOGICAL_OR_OP[op] term[rhs]
{ $$ = build_infix_plugin($lhs, $rhs, $op); }
| term[lhs] DORDOR term[rhs] /* $x // $y */
Expand Down
9 changes: 8 additions & 1 deletion pod/perlop.pod
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ values only, not array values.
left & &.
left | |. ^ ^.
left &&
left || //
left || ^^ //
nonassoc .. ...
right ?:
right = += -= *= etc. goto last next redo dump
Expand Down Expand Up @@ -1019,6 +1019,13 @@ if the left operand is true, the right operand is not even evaluated.
Scalar or list context propagates down to the right operand if it
is evaluated.

=head2 C-style Logical Xor
X<^^> X<operator, logical, xor>

Binary C<"^^"> performs a logical XOR operation. Both operands are
evaluated and the result is true only if exactly one of the operands is true.
Scalar or list context propagates down to the right operand.

=head2 Logical Defined-Or
X<//> X<operator, logical, defined-or>

Expand Down
11 changes: 9 additions & 2 deletions t/op/lop.t
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!./perl

#
# test the logical operators '&&', '||', '!', 'and', 'or', , 'xor', 'not'
# test the logical operators '&&', '||', '^^', '!', 'and', 'or', , 'xor', 'not'
#

BEGIN {
Expand All @@ -10,7 +10,7 @@ BEGIN {
set_up_inc('../lib');
}

plan tests => 33;
plan tests => 47;

for my $i (undef, 0 .. 2, "", "0 but true") {
my $true = 1;
Expand Down Expand Up @@ -104,4 +104,11 @@ for my $test (
) {
my ($a,$b, $exp) = @$test;
is(($a xor $b), $exp, "($a xor $b) == '$exp'");
is(($a ^^ $b), $exp, "($a ^^ $b) == '$exp'");
}

# precedence
is((1 xor 1 and 0), 1, '(1 xor 1 and 0) == 1');
is((1 xor 0 or 1), 1, "(1 xor 0 or 1) == 1");
is((1 ^^ 1 && 0), 1, '(1 ^^ 1 && 0) == 1');
is((1 ^^ 0 || 1), 1, "(1 ^^ 0 || 1) == 1");
11 changes: 11 additions & 0 deletions toke.c
Original file line number Diff line number Diff line change
Expand Up @@ -6099,6 +6099,16 @@ yyl_caret(pTHX_ char *s)
{
char *d = s;
const bool bof = cBOOL(FEATURE_BITWISE_IS_ENABLED);
if (s[1] == '^') {
s += 2;
if (!PL_lex_allbrackets && PL_lex_fakeeof >=
(*s == '=' ? LEX_FAKEEOF_ASSIGN : LEX_FAKEEOF_LOGIC)) {
s -= 2;
TOKEN(0);
}
pl_yylval.ival = OP_XOR;
OPERATOR(OROR);
}
if (bof && s[1] == '.')
s++;
if (!PL_lex_allbrackets && PL_lex_fakeeof >=
Expand Down Expand Up @@ -6618,6 +6628,7 @@ yyl_verticalbar(pTHX_ char *s)
s -= 2;
TOKEN(0);
}
pl_yylval.ival = OP_OR;
AOPERATOR(OROR);
}

Expand Down

0 comments on commit 0975291

Please sign in to comment.