I've no idea what you mean by "precedence is weaker than context", but if you look into the perl source code, you'll notice that there's a special case for the 'x' operator in list context where the LHS of the operator has parens.
PP(pp_repeat)
{
dVAR; dSP; dATARGET; tryAMAGICbin(repeat,opASSIGN);
{
register IV count;
dPOPss;
SvGETMAGIC(sv);
if (SvIOKp(sv)) {
if (SvUOK(sv)) {
const UV uv = SvUV(sv);
if (uv > IV_MAX)
count = IV_MAX; /* The best we can do? */
else
count = uv;
} else {
const IV iv = SvIV(sv);
if (iv < 0)
count = 0;
else
count = iv;
}
}
else if (SvNOKp(sv)) {
const NV nv = SvNV(sv);
if (nv < 0.0)
count = 0;
else
count = (IV)nv;
}
else
count = SvIV(sv);
if (GIMME == G_ARRAY && PL_op->op_private & OPpREPEAT_DOLIST) {
dMARK;
static const char oom_list_extend[] = "Out of memory during li
+st extend"
;
const I32 items = SP - MARK;
const I32 max = items * count;
MEM_WRAP_CHECK_1(max, SV*, oom_list_extend);
/* Did the max computation overflow? */
if (items > 0 && max > 0 && (max < items || max < count))
Perl_croak(aTHX_ oom_list_extend);
MEXTEND(MARK, max);
if (count > 1) {
while (SP > MARK) {
if (*SP)
SvTEMP_off((*SP));
SP--;
}
MARK++;
repeatcpy((char*)(MARK + items), (char*)MARK,
items * sizeof(const SV *), count - 1);
SP += max;
}
else if (count <= 0)
SP -= items;
}
else { /* Note: mark already snarfed by pp_list */
SV * const tmpstr = POPs;
STRLEN len;
bool isutf;
static const char oom_string_extend[] =
"Out of memory during string extend";
SvSetSV(TARG, tmpstr);
SvPV_force(TARG, len);
isutf = DO_UTF8(TARG);
if (count != 1) {
if (count < 1)
SvCUR_set(TARG, 0);
else {
const STRLEN max = (UV)count * len;
if (len > MEM_SIZE_MAX / count)
Perl_croak(aTHX_ oom_string_extend);
MEM_WRAP_CHECK_1(max, char, oom_string_extend);
SvGROW(TARG, max + 1);
repeatcpy(SvPVX(TARG) + len, SvPVX(TARG), len, count -
+ 1);
SvCUR_set(TARG, SvCUR(TARG) * count);
}
*SvEND(TARG) = '\0';
}
if (isutf)
(void)SvPOK_only_UTF8(TARG);
else
(void)SvPOK_only(TARG);
if (PL_op->op_private & OPpREPEAT_DOLIST) {
/* The parser saw this as a list repeat, and there
are probably several items on the stack. But we're
in scalar context, and there's no pp_list to save us
now. So drop the rest of the items -- robin@kitsite.com
*/
dMARK;
SP = MARK;
}
PUSHTARG;
}
RETURN;
}
}
The flag OPpREPEAT_DOLIST is set in op.c:
OP *
Perl_ck_repeat(pTHX_ OP *o)
{
PERL_ARGS_ASSERT_CK_REPEAT;
if (cBINOPo->op_first->op_flags & OPf_PARENS) {
o->op_private |= OPpREPEAT_DOLIST;
cBINOPo->op_first = force_list(cBINOPo->op_first);
}
else
scalar(o);
return o;
}
As you can see, it's here where list context is forced upon the LHS operand.
This is one of the few cases in Perl where parens do create lists. |