From f17d9825ab9b50967fd3d8742cc1bbccec96c049 Mon Sep 17 00:00:00 2001 From: "Paul \"LeoNerd\" Evans" Date: Sat, 19 Nov 2022 11:48:19 +0000 Subject: Recognise `//=` and `||=` syntax in signature parameter defaults These create parameters where the default expression is assigned whenever the caller did not pass a defined (or true) value. I.e. both if it is missing, or is present but undef (or false). --- perly.y | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'perly.y') diff --git a/perly.y b/perly.y index 1cb83cc9e5..23c8dd6ee8 100644 --- a/perly.y +++ b/perly.y @@ -749,15 +749,15 @@ sigslurpsigil: /* @, %, @foo, %foo */ sigslurpelem: sigslurpsigil sigvarname sigdefault/* def only to catch errors */ { - I32 sigil = $sigslurpsigil; - OP *var = $sigvarname; - OP *defexpr = $sigdefault; + I32 sigil = $sigslurpsigil; + OP *var = $sigvarname; + OP *defop = $sigdefault; if (parser->sig_slurpy) yyerror("Multiple slurpy parameters not allowed"); parser->sig_slurpy = (char)sigil; - if (defexpr) + if (defop) yyerror("A slurpy parameter may not have " "a default value"); @@ -769,26 +769,35 @@ sigslurpelem: sigslurpsigil sigvarname sigdefault/* def only to catch errors */ sigdefault : empty | ASSIGNOP - { $$ = newOP(OP_NULL, 0); } + { $$ = newARGDEFELEMOP(0, newOP(OP_NULL, 0), parser->sig_elems); } | ASSIGNOP term - { $$ = $term; } + { + I32 flags = 0; + if ($ASSIGNOP == OP_DORASSIGN) + flags |= OPpARG_IF_UNDEF << 8; + if ($ASSIGNOP == OP_ORASSIGN) + flags |= OPpARG_IF_FALSE << 8; + $$ = newARGDEFELEMOP(flags, $term, parser->sig_elems); + } /* subroutine signature scalar element: e.g. '$x', '$=', '$x = $default' */ sigscalarelem: PERLY_DOLLAR sigvarname sigdefault { - OP *var = $sigvarname; - OP *defexpr = $sigdefault; + OP *var = $sigvarname; + OP *defop = $sigdefault; if (parser->sig_slurpy) yyerror("Slurpy parameter not last"); parser->sig_elems++; - if (defexpr) { + if (defop) { parser->sig_optelems++; + OP *defexpr = cLOGOPx(defop)->op_first; + if ( defexpr->op_type == OP_NULL && !(defexpr->op_flags & OPf_KIDS)) { @@ -796,17 +805,10 @@ sigscalarelem: if (var) yyerror("Optional parameter " "lacks default expression"); - op_free(defexpr); + op_free(defop); } else { /* a normal '=default' expression */ - OP *defop = (OP*)alloc_LOGOP(OP_ARGDEFELEM, - defexpr, - LINKLIST(defexpr)); - /* re-purpose op_targ to hold @_ index */ - defop->op_targ = - (PADOFFSET)(parser->sig_elems - 1); - if (var) { var->op_flags |= OPf_STACKED; (void)op_sibling_splice(var, -- cgit v1.2.1