Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package perl-XS-Parse-Keyword for openSUSE:Factory checked in at 2022-11-09 12:56:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/perl-XS-Parse-Keyword (Old) and /work/SRC/openSUSE:Factory/.perl-XS-Parse-Keyword.new.1597 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-XS-Parse-Keyword" Wed Nov 9 12:56:30 2022 rev:9 rq:1034531 version:0.27 Changes: -------- --- /work/SRC/openSUSE:Factory/perl-XS-Parse-Keyword/perl-XS-Parse-Keyword.changes 2022-08-17 18:23:04.175168450 +0200 +++ /work/SRC/openSUSE:Factory/.perl-XS-Parse-Keyword.new.1597/perl-XS-Parse-Keyword.changes 2022-11-09 12:56:40.200089005 +0100 @@ -1,0 +2,24 @@ +Tue Nov 1 03:08:08 UTC 2022 - Tina M??ller <timueller+p...@suse.de> + +- updated to 0.27 + see /usr/share/doc/packages/perl-XS-Parse-Keyword/Changes + + 0.27 2022-10-31 + [CHANGES] + * Updates to XS::Parse::Infix for latest `infix-plugin` perl5 branch + + parsedata field is now an SV **, not an ANY * + * Expose parse_infix() as a real ABI function, allowing infix + operators to be hyper-operators and parse other operator names + + 0.26 2022-10-24 + [CHANGES] + * Updates to XS::Parse::Infix for latest `infix-plugin` perl5 branch + + Requires classification to set the operator precedence + + No longer need XPI_OPERAND_ARITH or XPI_OPERAND_TERM; most of + .lhs_flags and .rhs_flags are redundant now + + No longer support XPI_OPERAND_CUSTOM + + Optional `parse` phase for parametric/hyper-operators + * Bump XS::Parse::Infix ABI version to 2 + * Declare XPI ABI v0 as deprecated, soon to be removed + +------------------------------------------------------------------- Old: ---- XS-Parse-Keyword-0.25.tar.gz New: ---- XS-Parse-Keyword-0.27.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ perl-XS-Parse-Keyword.spec ++++++ --- /var/tmp/diff_new_pack.S8cUwP/_old 2022-11-09 12:56:40.784092297 +0100 +++ /var/tmp/diff_new_pack.S8cUwP/_new 2022-11-09 12:56:40.788092320 +0100 @@ -18,7 +18,7 @@ %define cpan_name XS-Parse-Keyword Name: perl-XS-Parse-Keyword -Version: 0.25 +Version: 0.27 Release: 0 License: Artistic-1.0 OR GPL-1.0-or-later Summary: XS functions to assist in parsing keyword syntax ++++++ XS-Parse-Keyword-0.25.tar.gz -> XS-Parse-Keyword-0.27.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/Build.PL new/XS-Parse-Keyword-0.27/Build.PL --- old/XS-Parse-Keyword-0.25/Build.PL 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/Build.PL 2022-10-31 23:09:16.000000000 +0100 @@ -54,7 +54,12 @@ #include "perl.h" #include "XSUB.h" -int main(void) { struct Perl_custom_infix def; return 0; } +int main(void) { + struct Perl_custom_infix def; + def.prec = INFIX_PREC_LOW; + def.build_op = NULL; + return 0; +} EOF ) if $] >= 5.037000; # maybe I'll start this in 5.37... diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/Changes new/XS-Parse-Keyword-0.27/Changes --- old/XS-Parse-Keyword-0.25/Changes 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/Changes 2022-10-31 23:09:16.000000000 +0100 @@ -1,5 +1,23 @@ Revision history for XS-Parse-Keyword +0.27 2022-10-31 + [CHANGES] + * Updates to XS::Parse::Infix for latest `infix-plugin` perl5 branch + + parsedata field is now an SV **, not an ANY * + * Expose parse_infix() as a real ABI function, allowing infix + operators to be hyper-operators and parse other operator names + +0.26 2022-10-24 + [CHANGES] + * Updates to XS::Parse::Infix for latest `infix-plugin` perl5 branch + + Requires classification to set the operator precedence + + No longer need XPI_OPERAND_ARITH or XPI_OPERAND_TERM; most of + .lhs_flags and .rhs_flags are redundant now + + No longer support XPI_OPERAND_CUSTOM + + Optional `parse` phase for parametric/hyper-operators + * Bump XS::Parse::Infix ABI version to 2 + * Declare XPI ABI v0 as deprecated, soon to be removed + 0.25 2022-07-25 [CHANGES] * Permit infix operators to consume fewer than all the available diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/MANIFEST new/XS-Parse-Keyword-0.27/MANIFEST --- old/XS-Parse-Keyword-0.25/MANIFEST 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/MANIFEST 2022-10-31 23:09:16.000000000 +0100 @@ -6,6 +6,7 @@ hax/make_argcheck_ops.c.inc hax/newOP_CUSTOM.c.inc hax/op_sibling_splice.c.inc +hax/optree-additions.c.inc hax/perl-backcompat.c.inc hax/wrap_keyword_plugin.c.inc inc/Module/Build/with/XSTests.pm diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/META.json new/XS-Parse-Keyword-0.27/META.json --- old/XS-Parse-Keyword-0.25/META.json 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/META.json 2022-10-31 23:09:16.000000000 +0100 @@ -40,19 +40,19 @@ "provides" : { "XS::Parse::Infix" : { "file" : "lib/XS/Parse/Infix.pm", - "version" : "0.25" + "version" : "0.27" }, "XS::Parse::Infix::Builder" : { "file" : "lib/XS/Parse/Infix/Builder.pm", - "version" : "0.25" + "version" : "0.27" }, "XS::Parse::Keyword" : { "file" : "lib/XS/Parse/Keyword.pm", - "version" : "0.25" + "version" : "0.27" }, "XS::Parse::Keyword::Builder" : { "file" : "lib/XS/Parse/Keyword/Builder.pm", - "version" : "0.25" + "version" : "0.27" } }, "release_status" : "stable", @@ -61,6 +61,6 @@ "http://dev.perl.org/licenses/" ] }, - "version" : "0.25", + "version" : "0.27", "x_serialization_backend" : "JSON::PP version 4.06" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/META.yml new/XS-Parse-Keyword-0.27/META.yml --- old/XS-Parse-Keyword-0.25/META.yml 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/META.yml 2022-10-31 23:09:16.000000000 +0100 @@ -19,19 +19,19 @@ provides: XS::Parse::Infix: file: lib/XS/Parse/Infix.pm - version: '0.25' + version: '0.27' XS::Parse::Infix::Builder: file: lib/XS/Parse/Infix/Builder.pm - version: '0.25' + version: '0.27' XS::Parse::Keyword: file: lib/XS/Parse/Keyword.pm - version: '0.25' + version: '0.27' XS::Parse::Keyword::Builder: file: lib/XS/Parse/Keyword/Builder.pm - version: '0.25' + version: '0.27' requires: perl: '5.014' resources: license: http://dev.perl.org/licenses/ -version: '0.25' +version: '0.27' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/XSParseInfix.h new/XS-Parse-Keyword-0.27/XSParseInfix.h --- old/XS-Parse-Keyword-0.25/XSParseInfix.h 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/XSParseInfix.h 2022-10-31 23:09:16.000000000 +0100 @@ -1,7 +1,7 @@ #ifndef __XS_PARSE_INFIX_H__ #define __XS_PARSE_INFIX_H__ -#define XSPARSEINFIX_ABI_VERSION 1 +#define XSPARSEINFIX_ABI_VERSION 2 /* Infix operator classifications */ /* No built-in operators use the _MISC categories, but they are provided for @@ -16,6 +16,10 @@ XPI_CLS_ISA, /* ... the predicate instance of (isa) */ XPI_CLS_MATCH_MISC, /* ... any other match-like predicate */ XPI_CLS_ORDERING, /* cmp or <=> */ + + XPI_CLS_ADD_MISC, /* an operator at addition-like precedence */ + XPI_CLS_MUL_MISC, /* an operator at multiplication-like precedence */ + XPI_CLS_POW_MISC, /* an operator at power exponentiation-like precedence */ }; enum XSParseInfixSelection { @@ -31,16 +35,16 @@ /* lhs_flags, rhs_flags */ enum { - /* other space reserved for other scalar types */ - XPI_OPERAND_ARITH = 2, - XPI_OPERAND_TERM = 4, XPI_OPERAND_TERM_LIST = 6, /* term in list context */ XPI_OPERAND_LIST = 7, /* list in list context */ /* Other bitflags */ XPI_OPERAND_ONLY_LOOK = (1<<3), - XPI_OPERAND_CUSTOM = (1<<7), /* rhs_flags only */ }; +// No longer used +#define XPI_OPERAND_ARITH 0 +#define XPI_OPERAND_TERM 0 +#define XPI_OPERAND_CUSTOM (1<<7) struct XSParseInfixHooks { U16 flags; @@ -54,11 +58,11 @@ bool (*permit) (pTHX_ void *hookdata); /* These hooks are alternatives; the first one defined is used */ - OP *(*new_op)(pTHX_ U32 flags, OP *lhs, OP *rhs, void *hookdata); + OP *(*new_op)(pTHX_ U32 flags, OP *lhs, OP *rhs, SV **parsedata, void *hookdata); OP *(*ppaddr)(pTHX); /* A pp func used directly in newBINOP_custom() */ - /* Used if rhs_flags & XPI_OPERAND_CUSTOM */ - OP *(*parse_rhs)(pTHX_ void *hookdata); + /* optional */ + void (*parse)(pTHX_ U32 flags, SV **parsedata, void *hookdata); }; struct XSParseInfixInfo { @@ -69,6 +73,18 @@ void *hookdata; }; +static bool (*parse_infix_func)(pTHX_ enum XSParseInfixSelection select, struct XSParseInfixInfo **infop); +#define parse_infix(select, infop) S_parse_infix(aTHX_ select, infop) +static bool S_parse_infix(pTHX_ enum XSParseInfixSelection select, struct XSParseInfixInfo **infop) +{ + if(!parse_infix_func) + croak("Must call boot_xs_parse_infix() first"); + + struct XSParseInfixInfo *infocopy; + + return (*parse_infix_func)(aTHX_ select, infop); +} + static OP *(*xs_parse_infix_new_op_func)(pTHX_ const struct XSParseInfixInfo *info, U32 flags, OP *lhs, OP *rhs); #define xs_parse_infix_new_op(info, flags, lhs, rhs) S_xs_parse_infix_new_op(aTHX_ info, flags, lhs, rhs) static OP *S_xs_parse_infix_new_op(pTHX_ const struct XSParseInfixInfo *info, U32 flags, OP *lhs, OP *rhs) @@ -111,10 +127,12 @@ croak("XS::Parse::Infix ABI version mismatch - library supports <= %d, compiled for %d", abi_ver, XSPARSEINFIX_ABI_VERSION); + parse_infix_func = INT2PTR(bool (*)(pTHX_ enum XSParseInfixSelection, struct XSParseInfixInfo **), + SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/parse()@2", 0))); xs_parse_infix_new_op_func = INT2PTR(OP *(*)(pTHX_ const struct XSParseInfixInfo *, U32, OP *, OP *), SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/new_op()@0", 0))); register_xs_parse_infix_func = INT2PTR(void (*)(pTHX_ const char *, const struct XSParseInfixHooks *, void *), - SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/register()@1", 0))); + SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/register()@2", 0))); } #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/hax/optree-additions.c.inc new/XS-Parse-Keyword-0.27/hax/optree-additions.c.inc --- old/XS-Parse-Keyword-0.25/hax/optree-additions.c.inc 1970-01-01 01:00:00.000000000 +0100 +++ new/XS-Parse-Keyword-0.27/hax/optree-additions.c.inc 2022-10-31 23:09:16.000000000 +0100 @@ -0,0 +1,92 @@ +/* vi: set ft=c : */ + +#define newAELEMOP(flags, first, key) S_newAELEMOP(aTHX_ flags, first, key) +static OP *S_newAELEMOP(pTHX_ U32 flags, OP *first, I32 key) +{ +#if HAVE_PERL_VERSION(5, 16, 0) + if(key >= -128 && key < 128 && first->op_type == OP_PADAV) { + OP *o = newOP(OP_AELEMFAST_LEX, flags); + o->op_private = (I8)key; + o->op_targ = first->op_targ; + op_free(first); + return o; + } +#endif + + return newBINOP(OP_AELEM, flags, first, newSVOP(OP_CONST, 0, newSViv(key))); +} + +#define newPADxVOP(type, flags, padix) S_newPADxVOP(aTHX_ type, flags, padix) +static OP *S_newPADxVOP(pTHX_ I32 type, I32 flags, PADOFFSET padix) +{ + OP *op = newOP(type, flags); + op->op_targ = padix; + return op; +} + +#if HAVE_PERL_VERSION(5, 22, 0) +# define HAVE_UNOP_AUX +#endif + +#ifndef HAVE_UNOP_AUX +typedef struct UNOP_with_IV { + UNOP baseop; + IV iv; +} UNOP_with_IV; + +#define newUNOP_with_IV(type, flags, first, iv) S_newUNOP_with_IV(aTHX_ type, flags, first, iv) +static OP *S_newUNOP_with_IV(pTHX_ I32 type, I32 flags, OP *first, IV iv) +{ + /* Cargoculted from perl's op.c:Perl_newUNOP() + */ + UNOP_with_IV *op = PerlMemShared_malloc(sizeof(UNOP_with_IV) * 1); + NewOp(1101, op, 1, UNOP_with_IV); + + if(!first) + first = newOP(OP_STUB, 0); + UNOP *unop = (UNOP *)op; + unop->op_type = (OPCODE)type; + unop->op_first = first; + unop->op_ppaddr = NULL; + unop->op_flags = (U8)flags | OPf_KIDS; + unop->op_private = (U8)(1 | (flags >> 8)); + + op->iv = iv; + + return (OP *)op; +} +#endif + +#define newMETHOD_REDIR_OP(rclass, methname, flags) S_newMETHOD_REDIR_OP(aTHX_ rclass, methname, flags) +static OP *S_newMETHOD_REDIR_OP(pTHX_ SV *rclass, SV *methname, I32 flags) +{ +#if HAVE_PERL_VERSION(5, 22, 0) + OP *op = newMETHOP_named(OP_METHOD_REDIR, flags, methname); +# ifdef USE_ITHREADS + { + /* cargoculted from S_op_relocate_sv() */ + PADOFFSET ix = pad_alloc(OP_CONST, SVf_READONLY); + PAD_SETSV(ix, rclass); + cMETHOPx(op)->op_rclass_targ = ix; + } +# else + cMETHOPx(op)->op_rclass_sv = rclass; +# endif +#else + OP *op = newUNOP(OP_METHOD, flags, + newSVOP(OP_CONST, 0, newSVpvf("%" SVf "::%" SVf, rclass, methname))); +#endif + + return op; +} + +/* If `@_` is called "snail", then elements of it can be called "slugs"; i.e. + * snails without their container + */ +#define newSLUGOP(idx) S_newSLUGOP(aTHX_ idx) +static OP *S_newSLUGOP(pTHX_ int idx) +{ + OP *op = newGVOP(OP_AELEMFAST, 0, PL_defgv); + op->op_private = idx; + return op; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/hax/perl-backcompat.c.inc new/XS-Parse-Keyword-0.27/hax/perl-backcompat.c.inc --- old/XS-Parse-Keyword-0.25/hax/perl-backcompat.c.inc 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/hax/perl-backcompat.c.inc 2022-10-31 23:09:16.000000000 +0100 @@ -34,6 +34,16 @@ #if !HAVE_PERL_VERSION(5, 22, 0) # define CvPADLIST_set(cv, padlist) (CvPADLIST(cv) = padlist) +# define newPADNAMEpvn(p,n) S_newPADNAMEpvn(aTHX_ p,n) +static PADNAME *S_newPADNAMEpvn(pTHX_ const char *pv, STRLEN n) +{ + PADNAME *pn = newSVpvn(pv, n); + /* PADNAMEs need to be at least SVt_PVNV in order to store the COP_SEQ_* + * fields */ + sv_upgrade(pn, SVt_PVNV); + return pn; +} +# define PadnameREFCNT_dec(pn) SvREFCNT_dec(pn) #endif #ifndef av_count @@ -149,3 +159,32 @@ # define isIDFIRST_utf8_safe(s, e) (PERL_UNUSED_ARG(e), isIDFIRST_utf8(s)) # define isIDCONT_utf8_safe(s, e) (PERL_UNUSED_ARG(e), isIDCONT_utf8(s)) #endif + +#if !HAVE_PERL_VERSION(5, 26, 0) +# define sv_set_undef(sv) sv_setsv(sv, &PL_sv_undef) +#endif + +#ifndef newAVav +# define newAVav(av) S_newAVav(aTHX_ av) +static AV *S_newAVav(pTHX_ AV *av) +{ + AV *ret = newAV(); + U32 count = av_count(av); + U32 i; + for(i = 0; i < count; i++) + av_push(ret, newSVsv(AvARRAY(av)[i])); + return ret; +} +#endif + +#if !defined(sv_derived_from_hv) && HAVE_PERL_VERSION(5, 16, 0) +# define sv_derived_from_hv(sv, hv) MY_sv_derived_from_hv(aTHX_ sv, hv) +static bool MY_sv_derived_from_hv(pTHX_ SV *sv, HV *hv) +{ + char *hvname = HvNAME(hv); + if(!hvname) + return FALSE; + + return sv_derived_from_pvn(sv, hvname, HvNAMELEN(hv), HvNAMEUTF8(hv) ? SVf_UTF8 : 0); +} +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/lib/XS/Parse/Infix/Builder.pm new/XS-Parse-Keyword-0.27/lib/XS/Parse/Infix/Builder.pm --- old/XS-Parse-Keyword-0.25/lib/XS/Parse/Infix/Builder.pm 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/lib/XS/Parse/Infix/Builder.pm 2022-10-31 23:09:16.000000000 +0100 @@ -3,7 +3,7 @@ # # (C) Paul Evans, 2021 -- leon...@leonerd.org.uk -package XS::Parse::Infix::Builder 0.25; +package XS::Parse::Infix::Builder 0.27; use v5.14; use warnings; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/lib/XS/Parse/Infix/Builder_data.pm.PL new/XS-Parse-Keyword-0.27/lib/XS/Parse/Infix/Builder_data.pm.PL --- old/XS-Parse-Keyword-0.25/lib/XS/Parse/Infix/Builder_data.pm.PL 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/lib/XS/Parse/Infix/Builder_data.pm.PL 2022-10-31 23:09:16.000000000 +0100 @@ -28,7 +28,7 @@ <$in_h> } ); __DATA__ -package XS::Parse::Infix::Builder_data 0.25; +package XS::Parse::Infix::Builder_data 0.27; use v5.14; use warnings; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/lib/XS/Parse/Infix.pm new/XS-Parse-Keyword-0.27/lib/XS/Parse/Infix.pm --- old/XS-Parse-Keyword-0.25/lib/XS/Parse/Infix.pm 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/lib/XS/Parse/Infix.pm 2022-10-31 23:09:16.000000000 +0100 @@ -1,9 +1,9 @@ # You may distribute under the terms of either the GNU General Public License # or the Artistic License (the same terms as Perl itself) # -# (C) Paul Evans, 2021 -- leon...@leonerd.org.uk +# (C) Paul Evans, 2021-2022 -- leon...@leonerd.org.uk -package XS::Parse::Infix 0.25; +package XS::Parse::Infix 0.27; use v5.14; use warnings; @@ -68,6 +68,15 @@ boot_xs_parse_infix(0.14); +=head2 parse_infix + + bool parse_infix(enum XSParseInfixSelection select, struct XSParseInfixInfo **infop); + +This function attempts to parse syntax for an infix operator from the current +parser position. If it is successful, it fills in the variable pointed to by +I<infop> with a pointer to the actual information structure and returns +C<true>. If no suitable operator is found, returns C<false>. + =head2 xs_parse_infix_new_op OP *xs_parse_infix_new_op(const struct XSParseInfixInfo *info, U32 flags, @@ -79,7 +88,7 @@ The C<info> structure pointer would be obtained from the C<infix> field of the result of invoking the various C<XPK_INFIX_*> token types from -C<XS::Parse::Keyword>. +C<XS::Parse::Keyword>, or by calling L</parse_infix> directly. =head2 register_xs_parse_infix @@ -88,8 +97,8 @@ This function installs a set of parsing hooks to be associated with the given operator name. This new operator will then be available via -L<XS::Parse::Keyword> by the various C<XPK_INFIX_*> token types, or to core -perl's C<PL_infix_plugin> if availble. +L<XS::Parse::Keyword> by the various C<XPK_INFIX_*> token types, +L</parse_infix>, or to core perl's C<PL_infix_plugin> if available. These tokens will all yield an info structure, with the following fields: @@ -123,8 +132,11 @@ const char *permit_hintkey; bool (*permit)(pTHX_ void *hookdata); - OP *(*new_op)(pTHX_ U32 flags, OP *lhs, OP *rhs, void *hookdata); + OP *(*new_op)(pTHX_ U32 flags, OP *lhs, OP *rhs, ANY *parsedata, void *hookdata); OP *(*ppaddr)(pTHX); + + /* optional */ + void (*parse)(pTHX_ U32 flags, ANY *parsedata, void *hookdata); }; =head2 Flags @@ -132,32 +144,30 @@ The C<flags> field is currently ignored. It is defined simply to reserve the space in case used in a later version. It should be set to zero. -The C<rhs_flags> field gives details on how to parse and handle the right-hand -side of the operator syntax. It should be set to one of the following constants: +The C<lhs_flags> and C<rhs_flags> fields give details on how to handle the +left- and right-hand side operands, respectively. -=over 4 +It should be set to one of the following constants, or left as zero: -=item XPI_OPERAND_ARITH - -The operand is an arithmetic expression. - -=item XPI_OPERAND_TERM - -The operand is a term expression. +=over 4 =item XPI_OPERAND_TERM_LIST -The operand is a term expression. It will be foced into list context, -preserving the C<OP_PUSHMARK> at the beginning. This means that the ppfunc for -this infix operator will have to C<POPMARK> to find that. +The operand will be foced into list context, preserving the C<OP_PUSHMARK> at +the beginning. This means that the ppfunc for this infix operator will have to +C<POPMARK> to find that. =item XPI_OPERAND_LIST -The operand is a list expression. It will be forced into list context, the -same as above. +The same as above. =back +Older versions used to provide constants named C<XPI_OPERAND_ARITH> and +C<XPI_OPERAND_TERM> but they related to an older version of the core perl +branch. These names are now aliases for zero, and can be removed from new +code. + In addition the following extra bitflags are defined: =over 4 @@ -183,12 +193,6 @@ =back -The C<lhs_flags> field gives details on how to handle the left-hand side of -the operator syntax. It takes similar values to C<rhs_flags>, except that it -does not accept the C<XPI_OPERAND_LIST> value. Parsing always happens on just -a term expression, though it may be placed into list context (which therefore -still permits things like parenthesized lists, or array variables). - =head2 The Selection Stage The C<cls> field gives a "classification" of the operator, suggesting what @@ -214,6 +218,18 @@ If neither is present then the keyword is always permitted - which is likely not what you wanted to do. +=head2 The C<parse> Stage + +If the optional C<parse> hook function is present, it is called immediately +after the parser has recognised the presence of the named operator itself but +before it attempts to consume the right-hand side term. This hook function can +attempt further parsing, in order to implement more complex syntax such as +hyper-operators. + +When invoked, it is passed a pointer to an C<ANY>-typed storage variable. It +is free to use whichever field of this variable it desires to store a result, +which will then later be made available to the C<new_op> function. + =head2 The Op Generation Stage If the infix operator is going to be used, then one of the C<new_op> or the @@ -221,8 +237,14 @@ If C<new_op> is defined then it will be used, and is expected to return an optree fragment that consumes the LHS and RHS arguments to implement the -semantics of the operator. If this is not present, then the C<ppaddr> will be -used instead to construct a new BINOP of the C<OP_CUSTOM> type. +semantics of the operator. If the optional C<parse> stage had been present +earlier, the C<ANY> pointer passed here will point to the same storage that +C<parse> had previously had access to, so it can retrieve the results. + +If C<new_op> is not present, then the C<ppaddr> will be used instead to +construct a new BINOP of the C<OP_CUSTOM> type. If an earlier C<parse> stage +had stored additional results into the C<ANY> variable these will be lost +here. =head2 The Wrapper Function @@ -322,6 +344,11 @@ The first registration will create the wrapper function; the subsequent one will skip it because it would otherwise be identical. +Note that when generating an optree for a wrapper function call, the C<new_op> +hook function will be invoked with a C<NULL> pointer for the C<ANY>-typed +parse data storage, as there won't be an opporunity for the C<parse> hook to +run in this case. + =cut =head1 DEPARSE @@ -423,6 +450,12 @@ anon-array argument forms (C<WRAPPERFUNC( \@lhs, \@rhs )> or C<WRAPPERFUNC( [LHS], [RHS] )>). +=item * + +Further thoughts about how infix operators with C<parse> hooks will work with +automatic deparse, and also how to integrate them with L<XS::Parse::Keyword>'s +grammar piece. + =back =cut diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/lib/XS/Parse/Keyword/Builder.pm new/XS-Parse-Keyword-0.27/lib/XS/Parse/Keyword/Builder.pm --- old/XS-Parse-Keyword-0.25/lib/XS/Parse/Keyword/Builder.pm 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/lib/XS/Parse/Keyword/Builder.pm 2022-10-31 23:09:16.000000000 +0100 @@ -3,7 +3,7 @@ # # (C) Paul Evans, 2021 -- leon...@leonerd.org.uk -package XS::Parse::Keyword::Builder 0.25; +package XS::Parse::Keyword::Builder 0.27; use v5.14; use warnings; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/lib/XS/Parse/Keyword/Builder_data.pm.PL new/XS-Parse-Keyword-0.27/lib/XS/Parse/Keyword/Builder_data.pm.PL --- old/XS-Parse-Keyword-0.25/lib/XS/Parse/Keyword/Builder_data.pm.PL 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/lib/XS/Parse/Keyword/Builder_data.pm.PL 2022-10-31 23:09:16.000000000 +0100 @@ -28,7 +28,7 @@ <$in_h> } ); __DATA__ -package XS::Parse::Keyword::Builder_data 0.25; +package XS::Parse::Keyword::Builder_data 0.27; use v5.14; use warnings; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/lib/XS/Parse/Keyword.pm new/XS-Parse-Keyword-0.27/lib/XS/Parse/Keyword.pm --- old/XS-Parse-Keyword-0.25/lib/XS/Parse/Keyword.pm 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/lib/XS/Parse/Keyword.pm 2022-10-31 23:09:16.000000000 +0100 @@ -3,7 +3,7 @@ # # (C) Paul Evans, 2021-2022 -- leon...@leonerd.org.uk -package XS::Parse::Keyword 0.25; +package XS::Parse::Keyword 0.27; use v5.14; use warnings; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/lib/XS/Parse/Keyword.xs new/XS-Parse-Keyword-0.27/lib/XS/Parse/Keyword.xs --- old/XS-Parse-Keyword-0.25/lib/XS/Parse/Keyword.xs 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/lib/XS/Parse/Keyword.xs 2022-10-31 23:09:16.000000000 +0100 @@ -30,18 +30,64 @@ static void XSParseInfix_register_v0(pTHX_ const char *opname, const struct XSParseInfixHooks_v0 *hooks_v0, void *hookdata) { + warn("XSParseInfix ABI version 0 is deprecated and will soon be removed"); + struct XSParseInfixHooks *hooks; Newx(hooks, 1, struct XSParseInfixHooks); - hooks->flags = hooks_v0->flags; + hooks->flags = hooks_v0->flags | (1<<15); /* NO_PARSEDATA */ hooks->cls = hooks_v0->cls; hooks->wrapper_func_name = NULL; hooks->permit_hintkey = hooks_v0->permit_hintkey; hooks->permit = hooks_v0->permit; - hooks->new_op = hooks_v0->new_op; + hooks->new_op = (OP *(*)(pTHX_ U32, OP *, OP *, SV **, void *))hooks_v0->new_op; hooks->ppaddr = hooks_v0->ppaddr; + hooks->parse = NULL; + + XSParseInfix_register(aTHX_ opname, hooks, hookdata); +} + +/* v1 hooks.newop did not pass parsedata */ +struct XSParseInfixHooks_v1 { + U16 flags; + U8 lhs_flags, rhs_flags; + enum XSParseInfixClassification cls; + + const char *wrapper_func_name; + + const char *permit_hintkey; + bool (*permit) (pTHX_ void *hookdata); + + OP *(*new_op)(pTHX_ U32 flags, OP *lhs, OP *rhs, void *hookdata); + OP *(*ppaddr)(pTHX); + + OP *(*parse_rhs)(pTHX_ void *hookdata); +}; + +static void XSParseInfix_register_v1(pTHX_ const char *opname, const struct XSParseInfixHooks_v1 *hooks_v1, void *hookdata) +{ + if(hooks_v1->rhs_flags & XPI_OPERAND_CUSTOM) + croak("XPI_OPERAND_CUSTOM is no longer supported"); + if(hooks_v1->parse_rhs) + croak("XSParseInfixHooks.parse_rhs is no longer supported"); + + struct XSParseInfixHooks *hooks; + Newx(hooks, 1, struct XSParseInfixHooks); + + hooks->flags = hooks_v1->flags | (1<<15) /* NO_PARSEDATA */; + hooks->lhs_flags = hooks_v1->lhs_flags; + hooks->rhs_flags = hooks_v1->rhs_flags; + hooks->cls = hooks_v1->cls; + + hooks->wrapper_func_name = hooks_v1->wrapper_func_name; + + hooks->permit_hintkey = hooks_v1->permit_hintkey; + hooks->permit = hooks_v1->permit; + hooks->new_op = (OP *(*)(pTHX_ U32, OP *, OP *, SV **, void *))hooks_v1->new_op; + hooks->ppaddr = hooks_v1->ppaddr; + hooks->parse = NULL; XSParseInfix_register(aTHX_ opname, hooks, hookdata); } @@ -65,8 +111,10 @@ sv_setiv(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/ABIVERSION_MIN", 1), 0); sv_setiv(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/ABIVERSION_MAX", 1), XSPARSEINFIX_ABI_VERSION); + sv_setuv(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/parse()@2", 1), PTR2UV(&XSParseInfix_parse)); sv_setuv(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/new_op()@0", 1), PTR2UV(&XSParseInfix_new_op)); sv_setuv(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/register()@0", 1), PTR2UV(&XSParseInfix_register_v0)); - sv_setuv(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/register()@1", 1), PTR2UV(&XSParseInfix_register)); + sv_setuv(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/register()@1", 1), PTR2UV(&XSParseInfix_register_v1)); + sv_setuv(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/register()@2", 1), PTR2UV(&XSParseInfix_register)); XSParseInfix_boot(aTHX); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/src/infix.c new/XS-Parse-Keyword-0.27/src/infix.c --- old/XS-Parse-Keyword-0.25/src/infix.c 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/src/infix.c 2022-10-31 23:09:16.000000000 +0100 @@ -13,6 +13,7 @@ #include "infix.h" #include "perl-backcompat.c.inc" +#include "optree-additions.c.inc" #include "force_list_keeping_pushmark.c.inc" #include "make_argcheck_ops.c.inc" @@ -75,9 +76,7 @@ { U8 lhs_gimme; switch(hd->hooks->lhs_flags & 0x07) { - case 0: /* back-compat */ - case XPI_OPERAND_ARITH: - case XPI_OPERAND_TERM: + case 0: lhs_gimme = G_SCALAR; break; @@ -93,9 +92,7 @@ U8 rhs_gimme; switch(hd->hooks->rhs_flags & 0x07) { - case 0: /* back-compat */ - case XPI_OPERAND_ARITH: - case XPI_OPERAND_TERM: + case 0: rhs_gimme = G_SCALAR; break; @@ -150,10 +147,16 @@ static struct Registration *registrations; -static OP *new_op(pTHX_ const struct HooksAndData hd, U32 flags, OP *lhs, OP *rhs) +static OP *new_op(pTHX_ const struct HooksAndData hd, U32 flags, OP *lhs, OP *rhs, SV **parsedata) { - if(hd.hooks->new_op) - return (*hd.hooks->new_op)(aTHX_ flags, lhs, rhs, hd.data); + if(hd.hooks->new_op) { + if(hd.hooks->flags & (1<<15)) { + OP *(*new_op_v1)(pTHX_ U32, OP *, OP *, void *) = (OP *(*)(pTHX_ U32, OP *, OP *, void *))hd.hooks->new_op; + return (*new_op_v1)(aTHX_ flags, lhs, rhs, hd.data); /* no parsedata */ + } + + return (*hd.hooks->new_op)(aTHX_ flags, lhs, rhs, parsedata, hd.data); + } OP *ret = newBINOP_CUSTOM(hd.hooks->ppaddr, flags, lhs, rhs); @@ -231,51 +234,40 @@ #ifdef HAVE_PL_INFIX_PLUGIN -OP *parse(pTHX_ OP *lhs, struct Perl_custom_infix *def) +void parse(pTHX_ SV **parsedata, struct Perl_custom_infix *def) +{ + struct Registration *reg = (struct Registration *)def; + + (*reg->hd.hooks->parse)(aTHX_ 0, parsedata, reg->hd.data); +} + +OP *build_op(pTHX_ SV **parsedata, OP *lhs, OP *rhs, struct Perl_custom_infix *def) { struct Registration *reg = (struct Registration *)def; switch(reg->hd.hooks->lhs_flags & 0x07) { - case XPI_OPERAND_TERM: + case 0: break; case XPI_OPERAND_TERM_LIST: + case XPI_OPERAND_LIST: lhs = force_list_keeping_pushmark(lhs); break; } /* TODO: maybe operator has a 'parse' hook? */ - lex_read_space(0); - OP *rhs = NULL; - - switch(reg->hd.hooks->rhs_flags & 0x87) { - case XPI_OPERAND_ARITH: - rhs = parse_arithexpr(0); - break; - - case 0: /* back-compat */ - case XPI_OPERAND_TERM: - rhs = parse_termexpr(0); + switch(reg->hd.hooks->rhs_flags & 0x07) { + case 0: break; case XPI_OPERAND_TERM_LIST: - rhs = force_list_keeping_pushmark(parse_termexpr(0)); - break; - case XPI_OPERAND_LIST: - rhs = force_list_keeping_pushmark(parse_listexpr(0)); - break; - - case XPI_OPERAND_CUSTOM: - rhs = (*reg->hd.hooks->parse_rhs)(aTHX_ reg->hd.data); + rhs = force_list_keeping_pushmark(rhs); break; - - default: - croak("hooks->rhs_flags did not provide a valid RHS type"); } - return new_op(aTHX_ reg->hd, 0, lhs, rhs); + return new_op(aTHX_ reg->hd, 0, lhs, rhs, parsedata); } static STRLEN (*next_infix_plugin)(pTHX_ char *, STRLEN, struct Perl_custom_infix **); @@ -380,7 +372,7 @@ return new_op(aTHX_ (struct HooksAndData) { .hooks = info->hooks, .data = info->hookdata, - }, flags, lhs, rhs); + }, flags, lhs, rhs, NULL); return newBINOP(info->opcode, flags, lhs, rhs); } @@ -470,7 +462,7 @@ if(!extract_wrapper2_args(aTHX_ op, &left, &right)) return op; - return new_op(aTHX_ *hd, 0, left, right); + return new_op(aTHX_ *hd, 0, left, right, NULL); } static OP *ckcall_wrapper_func_listlist(pTHX_ OP *op, GV *namegv, SV *ckobj) @@ -483,21 +475,16 @@ return new_op(aTHX_ *hd, 0, unwrap_list(left, hd->hooks->lhs_flags & XPI_OPERAND_ONLY_LOOK), - unwrap_list(right, hd->hooks->rhs_flags & XPI_OPERAND_ONLY_LOOK)); -} - -#define newSLUGOP(idx) S_newSLUGOP(aTHX_ idx) -static OP *S_newSLUGOP(pTHX_ int idx) -{ - OP *op = newGVOP(OP_AELEMFAST, 0, PL_defgv); - op->op_private = idx; - return op; + unwrap_list(right, hd->hooks->rhs_flags & XPI_OPERAND_ONLY_LOOK), + NULL); } static void make_wrapper_func(pTHX_ const struct HooksAndData *hd) { SV *funcname = newSVpvn(hd->hooks->wrapper_func_name, strlen(hd->hooks->wrapper_func_name)); - if(gv_fetchsv(funcname, 0, 0)) { + + GV *gv; + if((gv = gv_fetchsv(funcname, 0, 0)) && GvCV(gv)) { /* The wrapper function already exists. We presume this is due to a duplicate * registration of identical hooks under a different name and just skip */ @@ -523,7 +510,7 @@ /* Body of the function is just $_[0] OP $_[1] */ body = op_append_list(OP_LINESEQ, body, - new_op(aTHX_ *hd, 0, newSLUGOP(0), newSLUGOP(1))); + new_op(aTHX_ *hd, 0, newSLUGOP(0), newSLUGOP(1), NULL)); ckcall = &ckcall_wrapper_func_scalarscalar; break; @@ -539,7 +526,8 @@ body = op_append_list(OP_LINESEQ, body, new_op(aTHX_ *hd, 0, newOP(OP_SHIFT, 0), - force_list_keeping_pushmark(newUNOP(OP_RV2AV, OPf_WANT_LIST, newGVOP(OP_GV, 0, PL_defgv))))); + force_list_keeping_pushmark(newUNOP(OP_RV2AV, OPf_WANT_LIST, newGVOP(OP_GV, 0, PL_defgv))), + NULL)); /* no ckcall */ break; @@ -555,7 +543,8 @@ body = op_append_list(OP_LINESEQ, body, new_op(aTHX_ *hd, 0, force_list_keeping_pushmark(newUNOP(OP_RV2AV, 0, newSLUGOP(0))), - force_list_keeping_pushmark(newUNOP(OP_RV2AV, 0, newSLUGOP(1))))); + force_list_keeping_pushmark(newUNOP(OP_RV2AV, 0, newSLUGOP(1))), + NULL)); ckcall = &ckcall_wrapper_func_listlist; break; @@ -665,6 +654,8 @@ void XSParseInfix_register(pTHX_ const char *opname, const struct XSParseInfixHooks *hooks, void *hookdata) { switch(hooks->flags) { + case (1<<15): + /* undocumented internal flag to indicate v1-compatible ->new_op hook function */ case 0: break; default: @@ -673,10 +664,8 @@ switch(hooks->lhs_flags & ~(XPI_OPERAND_ONLY_LOOK)) { case 0: - //warn("No .lhs_flags specified for XSParseInfixHooks; defaulting to XPI_OPERAND_TERM"); - /* FALLTHROUGH */ - case XPI_OPERAND_TERM: case XPI_OPERAND_TERM_LIST: + case XPI_OPERAND_LIST: break; default: croak("Unrecognised XSParseInfixHooks.lhs_flags value 0x%X", hooks->lhs_flags); @@ -684,23 +673,57 @@ switch(hooks->rhs_flags & ~(XPI_OPERAND_ONLY_LOOK)) { case 0: - //warn("No .rhs_flags specified for XSParseInfixHooks; defaulting to XPI_OPERAND_TERM"); - /* FALLTHROUGH */ - case XPI_OPERAND_ARITH: - case XPI_OPERAND_TERM: case XPI_OPERAND_TERM_LIST: case XPI_OPERAND_LIST: - case XPI_OPERAND_CUSTOM: break; default: croak("Unrecognised XSParseInfixHooks.rhs_flags value 0x%X", hooks->rhs_flags); + + case XPI_OPERAND_CUSTOM: + croak("TODO: Currently XPI_OPERAND_CUSTOM is not supported"); + } + +#ifdef HAVE_PL_INFIX_PLUGIN + enum Perl_custom_infix_precedence prec = 0; + + switch(hooks->cls) { + case 0: + warn("Unspecified operator classification for %s; treating it as RELATION for precedence", opname); + case XPI_CLS_RELATION: + case XPI_CLS_EQUALITY: + case XPI_CLS_MATCH_MISC: + prec = INFIX_PREC_REL; + break; + + case XPI_CLS_ADD_MISC: + prec = INFIX_PREC_ADD; + break; + + case XPI_CLS_MUL_MISC: + prec = INFIX_PREC_MUL; + break; + + case XPI_CLS_POW_MISC: + prec = INFIX_PREC_POW; + break; + + /* TODO: Add classifications for the HIGH and LOW also? */ + + default: + croak("TODO: need to write code for hooks->cls == %d\n", hooks->cls); } +#endif struct Registration *reg; Newx(reg, 1, struct Registration); #ifdef HAVE_PL_INFIX_PLUGIN - reg->def.parse = &parse; + reg->def.prec = prec; + if(hooks->parse) + reg->def.parse = &parse; + else + reg->def.parse = NULL; + reg->def.build_op = &build_op; #endif reg->info.opname = savepv(opname); @@ -815,11 +838,6 @@ )); #ifdef HAVE_PL_INFIX_PLUGIN - OP_CHECK_MUTEX_LOCK; - if(!next_infix_plugin) { - next_infix_plugin = PL_infix_plugin; - PL_infix_plugin = &my_infix_plugin; - } - OP_CHECK_MUTEX_UNLOCK; + wrap_infix_plugin(&my_infix_plugin, &next_infix_plugin); #endif } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/t/70infix.t new/XS-Parse-Keyword-0.27/t/70infix.t --- old/XS-Parse-Keyword-0.25/t/70infix.t 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/t/70infix.t 2022-10-31 23:09:16.000000000 +0100 @@ -87,9 +87,30 @@ "infix_add_0xXXX[aelemfast, aelemfast]", 'optree of call to infix operator'; + # Check precedence of operator parsing by observing the following precedence + # ordering: + # <--High Low--> + # ** * + && + is_optree sub { $_[0] * $_[1] add $_[2] * $_[3] }, "infix_add_0xXXX[multiply[aelemfast, aelemfast], multiply[aelemfast, aelemfast]]", - 'optree of call to infix operator at default precedence'; + 'optree binds add lower than *'; + is_optree sub { $_[0] + $_[1] add $_[2] + $_[3] }, + "add[infix_add_0xXXX[add[aelemfast, aelemfast], aelemfast], aelemfast]", + 'optree binds add equal to +'; + is_optree sub { $_[0] && $_[1] add $_[2] && $_[3] }, + "and[and[aelemfast, infix_add_0xXXX[aelemfast, aelemfast]], aelemfast]", + 'optree binds add higher than &&'; + + is_optree sub { $_[0] ** $_[1] mul $_[2] ** $_[3] }, + "infix_mul_0xXXX[pow[aelemfast, aelemfast], pow[aelemfast, aelemfast]]", + 'optree binds mul lower than **'; + is_optree sub { $_[0] * $_[1] mul $_[2] * $_[3] }, + "multiply[infix_mul_0xXXX[multiply[aelemfast, aelemfast], aelemfast], aelemfast]", + 'optree binds mul equal to *'; + is_optree sub { $_[0] + $_[1] mul $_[2] + $_[3] }, + "add[add[aelemfast, infix_mul_0xXXX[aelemfast, aelemfast]], aelemfast]", + 'optree binds mul higher than +'; is_optree sub { $_[0] * ($_[1] add $_[2]) * $_[3] }, "multiply[multiply[aelemfast, infix_add_0xXXX[aelemfast, aelemfast]], aelemfast]", @@ -116,11 +137,11 @@ { is_deparsed sub { $_[0] add $_[1] }, '$_[0] add $_[1];', - 'deparsed call to infix operator'; + 'deparsed call to infix add operator'; is_deparsed sub { $_[0] * $_[1] add $_[2] * $_[3] }, '($_[0] * $_[1]) add ($_[2] * $_[3]);', - 'deparsed call to infix operator at default precedence'; + 'deparsed call to infix add operator at default precedence'; is_deparsed sub { $_[0] ??? $_[1] }, '$_[0] ??? $_[1];', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.25/t/infix.xs new/XS-Parse-Keyword-0.27/t/infix.xs --- old/XS-Parse-Keyword-0.25/t/infix.xs 2022-07-26 00:36:23.000000000 +0200 +++ new/XS-Parse-Keyword-0.27/t/infix.xs 2022-10-31 23:09:16.000000000 +0100 @@ -26,16 +26,26 @@ } static const struct XSParseInfixHooks hooks_add = { - .lhs_flags = XPI_OPERAND_TERM, - .rhs_flags = XPI_OPERAND_TERM, + .cls = XPI_CLS_ADD_MISC, .permit_hintkey = hintkey, - .cls = 0, .wrapper_func_name = "t::infix::addfunc", .ppaddr = &pp_add, }; +OP *pp_mul(pTHX) +{ + croak("TODO"); /* We never actually call code with this so it doesn't matter */ +} + +static const struct XSParseInfixHooks hooks_mul = { + .cls = XPI_CLS_MUL_MISC, + .permit_hintkey = hintkey, + + .ppaddr = &pp_mul, +}; + OP *pp_xor(pTHX) { dSP; @@ -46,10 +56,8 @@ } static const struct XSParseInfixHooks hooks_xor = { - .lhs_flags = XPI_OPERAND_TERM, - .rhs_flags = XPI_OPERAND_TERM, + .cls = XPI_CLS_ADD_MISC, .permit_hintkey = hintkey, - .cls = 0, .ppaddr = &pp_xor, }; @@ -86,10 +94,9 @@ } static const struct XSParseInfixHooks hooks_intersperse = { - .lhs_flags = XPI_OPERAND_TERM, + .cls = XPI_CLS_ADD_MISC, .rhs_flags = XPI_OPERAND_LIST, .permit_hintkey = hintkey, - .cls = 0, .wrapper_func_name = "t::infix::interspersefunc", @@ -124,10 +131,10 @@ } static const struct XSParseInfixHooks hooks_addpairs = { - .lhs_flags = XPI_OPERAND_TERM_LIST, - .rhs_flags = XPI_OPERAND_TERM_LIST|XPI_OPERAND_ONLY_LOOK, /* only on RHS so we can test the logic */ + .cls = XPI_CLS_ADD_MISC, + .lhs_flags = XPI_OPERAND_LIST, + .rhs_flags = XPI_OPERAND_LIST|XPI_OPERAND_ONLY_LOOK, /* only on RHS so we can test the logic */ .permit_hintkey = hintkey, - .cls = 0, .wrapper_func_name = "t::infix::addpairsfunc", @@ -140,6 +147,7 @@ boot_xs_parse_infix(0); register_xs_parse_infix("add", &hooks_add, NULL); + register_xs_parse_infix("mul", &hooks_mul, NULL); register_xs_parse_infix("???", &hooks_xor, NULL);