Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions lib/B/Deparse.pm
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# This is based on the module of the same name by Malcolm Beattie,
# but essentially none of his code remains.

package B::Deparse 1.84;
package B::Deparse 1.85;
use strict;
use Carp;
use B qw(class main_root main_start main_cv svref_2object opnumber perlstring
Expand Down Expand Up @@ -3318,9 +3318,16 @@ sub pp_and { logop(@_, "and", 3, "&&", 11, "if") }
sub pp_or { logop(@_, "or", 2, "||", 10, "unless") }
sub pp_dor { logop(@_, "//", 10) }

# xor is syntactically a logop, but it's really a binop (contrary to
# old versions of opcode.pl). Syntax is what matters here.
sub pp_xor { logop(@_, "xor", 2, "^^", 10, "") }
sub pp_xor {
my $self = shift;
my ($op, $cx) = @_;
if ($cx > 2 or $op->flags & OPf_STACKED) {
binop($self, @_, "^^", 10, ASSIGN);
}
else {
binop($self, @_, "xor", 2);
}
}

sub logassignop {
my $self = shift;
Expand Down
5 changes: 5 additions & 0 deletions lib/B/Deparse.t
Original file line number Diff line number Diff line change
Expand Up @@ -3450,3 +3450,8 @@ $_ = (!$p) isa 'Some::Class';
$_ = (!$p) =~ tr/1//;
$_ = (!$p) =~ /1/;
$_ = (!$p) =~ s/1//r;
####
# xor operator
my($x, $y, $z);
$z = 1 + ($x ^^ $y);
$z = ($x ^^= $y);
1 change: 1 addition & 0 deletions op.c
Original file line number Diff line number Diff line change
Expand Up @@ -3230,6 +3230,7 @@ Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags)
case OP_I_MODULO:
case OP_I_ADD:
case OP_I_SUBTRACT:
case OP_XOR:
if (!(o->op_flags & OPf_STACKED))
goto nomod;
PL_modcount++;
Expand Down
6 changes: 6 additions & 0 deletions pod/perldelta.pod
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ here, but most should go in the L</Performance Enhancements> section.

[ List each enhancement as a =head2 entry ]

=head2 Assigning logical xor C<^^=> operator

Perl 5.40.0 introduced the logical medium-precedence exclusive-or operator
C<^^>. It was not noticed at the time that the assigning variant C<^^=> was
also missing. This is now added.

=head1 Security

XXX Any security-related notices go here. In particular, any security
Expand Down
4 changes: 2 additions & 2 deletions pod/perlop.pod
Original file line number Diff line number Diff line change
Expand Up @@ -1341,7 +1341,7 @@ That should probably be written more simply as:
=head2 Assignment Operators
X<assignment> X<operator, assignment> X<=> X<**=> X<+=> X<*=> X<&=>
X<<< <<= >>> X<&&=> X<-=> X</=> X<|=> X<<< >>= >>> X<||=> X<//=> X<.=>
X<%=> X<^=> X<x=> X<&.=> X<|.=> X<^.=>
X<%=> X<^=> X<x=> X<&.=> X<|.=> X<^.=> X<^^=>

C<"="> is the ordinary assignment operator.

Expand All @@ -1360,7 +1360,7 @@ The following are recognized:
**= += *= &= &.= <<= &&=
-= /= |= |.= >>= ||=
.= %= ^= ^.= //=
x=
x= ^^=

Although these are grouped by family, they all have the precedence
of assignment. These combined assignment operators can only operate on
Expand Down
15 changes: 10 additions & 5 deletions pp_ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2172,11 +2172,16 @@ Perl_die_unwind(pTHX_ SV *msv)

PP(pp_xor)
{
SV *left = PL_stack_sp[0];
SV *right = PL_stack_sp[-1];
rpp_replace_2_IMM_NN(SvTRUE_NN(left) != SvTRUE_NN(right)
? &PL_sv_yes
: &PL_sv_no);
SV *left = PL_stack_sp[-1];
SV *right = PL_stack_sp[0];
bool ret = SvTRUE_NN(left) != SvTRUE_NN(right);
if (PL_op->op_flags & OPf_STACKED) {
sv_setbool(left, ret);
rpp_replace_2_1(left);
}
else {
rpp_replace_2_IMM_NN(boolSV(ret));
}
return NORMAL;
}

Expand Down
10 changes: 9 additions & 1 deletion t/op/lop.t
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ BEGIN {
set_up_inc('../lib');
}

plan tests => 47;
plan tests => 58;

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

my ($lhs, $rhs) = @$test;
$lhs ^^= $rhs;
is($lhs, $exp, "$a ^^= $b gives '$exp'");
}

my $var = 123;
($var ^^= 456) ^^= 456;
is($var, 1, '^^= yields mutable lvalue');

# 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");
Expand Down
4 changes: 4 additions & 0 deletions toke.c
Original file line number Diff line number Diff line change
Expand Up @@ -6097,6 +6097,10 @@ yyl_caret(pTHX_ char *s)
TOKEN(0);
}
pl_yylval.ival = OP_XOR;
if (*s == '=') {
s++;
OPERATOR(ASSIGNOP);
}
OPERATOR(OROR);
}
if (bof && s[1] == '.')
Expand Down
Loading