File Coverage

/usr/local/lib/perl5/site_perl/5.42.0/x86_64-linux/auto/share/module/XS-Parse-Infix/include/XSParseInfix.h
Criterion Covered Total %
statement 18 22 81.8
branch 5 10 50.0
condition n/a
subroutine n/a
pod n/a
total 23 32 71.8


line stmt bran cond sub pod time code
1             #ifndef __XS_PARSE_INFIX_H__
2             #define __XS_PARSE_INFIX_H__
3              
4             #define XSPARSEINFIX_ABI_VERSION 2
5              
6             /* Infix operator classifications */
7             /* No built-in operators use the _MISC categories, but they are provided for
8             * custom infix operators to use so they are still found by selections */
9             enum XSParseInfixClassification {
10             XPI_CLS_NONE = 0,
11             XPI_CLS_PREDICATE, /* any boolean-returning operator */
12             XPI_CLS_RELATION, /* ... any predicate that is typewise symmetric */
13             XPI_CLS_EQUALITY, /* ... any relation that is true for (x == x) and false otherwise */
14             XPI_CLS_SMARTMATCH, /* ... the predicate smartmatch (~~) */
15             XPI_CLS_MATCHRE, /* ... the predicate regexp match (=~) */
16             XPI_CLS_ISA, /* ... the predicate instance of (isa) */
17             XPI_CLS_MATCH_MISC, /* ... any other match-like predicate */
18             XPI_CLS_ORDERING, /* cmp or <=> */
19              
20             /* Since the _MISC categories never turn up in selections, put them at high
21             * index so as to leave space for more */
22             XPI_CLS_LOW_MISC = 0x80, /* an operator at low precedence */
23             XPI_CLS_LOGICAL_OR_LOW_MISC,
24             XPI_CLS_LOGICAL_AND_LOW_MISC,
25             XPI_CLS_ASSIGN_MISC,
26             XPI_CLS_LOGICAL_OR_MISC,
27             XPI_CLS_LOGICAL_AND_MISC,
28             XPI_CLS_ADD_MISC, /* an operator at addition-like precedence */
29             XPI_CLS_MUL_MISC, /* an operator at multiplication-like precedence */
30             XPI_CLS_POW_MISC, /* an operator at power exponentiation-like precedence */
31             XPI_CLS_HIGH_MISC, /* an operator at high precedence */
32             };
33              
34             enum XSParseInfixSelection {
35             XPI_SELECT_ANY,
36             XPI_SELECT_PREDICATE, /* any predicate */
37             XPI_SELECT_RELATION, /* any relation */
38             XPI_SELECT_EQUALITY, /* any equality */
39             XPI_SELECT_ORDERING, /* any ordering */
40              
41             XPI_SELECT_MATCH_NOSMART, /* any equality or other match operator, including smartmatch */
42             XPI_SELECT_MATCH_SMART, /* any equality or other match operator, not including smartmatch */
43             };
44              
45             /* flags */
46             enum {
47             XPI_FLAG_LISTASSOC = (1<<0),
48             };
49              
50             /* lhs_flags, rhs_flags */
51             enum {
52             XPI_OPERAND_TERM_LIST = 6, /* term in list context */
53             XPI_OPERAND_LIST = 7, /* list in list context */
54              
55             /* Other bitflags */
56             XPI_OPERAND_ONLY_LOOK = (1<<3),
57             };
58              
59             struct XSParseInfixHooks {
60             U16 flags;
61             U8 lhs_flags, rhs_flags;
62             enum XSParseInfixClassification cls;
63              
64             const char *wrapper_func_name;
65              
66             /* These two hooks are ANDed together; both must pass, if present */
67             const char *permit_hintkey;
68             bool (*permit) (pTHX_ void *hookdata);
69              
70             /* These hooks are alternatives; the first one defined is used */
71             OP *(*new_op)(pTHX_ U32 flags, OP *lhs, OP *rhs, SV **parsedata, void *hookdata);
72             OP *(*ppaddr)(pTHX); /* A pp func used directly in newBINOP_custom() */
73              
74             /* optional */
75             void (*parse)(pTHX_ U32 flags, SV **parsedata, void *hookdata);
76             };
77              
78             struct XSParseInfixInfo {
79             const char *opname;
80             OPCODE opcode;
81              
82             const struct XSParseInfixHooks *hooks;
83             void *hookdata;
84              
85             enum XSParseInfixClassification cls;
86             };
87              
88             static bool (*parse_infix_func)(pTHX_ enum XSParseInfixSelection select, struct XSParseInfixInfo **infop);
89             #define parse_infix(select, infop) S_parse_infix(aTHX_ select, infop)
90             static bool S_parse_infix(pTHX_ enum XSParseInfixSelection select, struct XSParseInfixInfo **infop)
91             {
92             if(!parse_infix_func)
93             croak("Must call boot_xs_parse_infix() first");
94              
95             struct XSParseInfixInfo *infocopy;
96              
97             return (*parse_infix_func)(aTHX_ select, infop);
98             }
99              
100             static OP *(*xs_parse_infix_new_op_func)(pTHX_ const struct XSParseInfixInfo *info, U32 flags, OP *lhs, OP *rhs);
101             #define xs_parse_infix_new_op(info, flags, lhs, rhs) S_xs_parse_infix_new_op(aTHX_ info, flags, lhs, rhs)
102             static OP *S_xs_parse_infix_new_op(pTHX_ const struct XSParseInfixInfo *info, U32 flags, OP *lhs, OP *rhs)
103             {
104             if(!xs_parse_infix_new_op_func)
105             croak("Must call boot_xs_parse_infix() first");
106              
107             return (*xs_parse_infix_new_op_func)(aTHX_ info, flags, lhs, rhs);
108             }
109              
110             static void (*register_xs_parse_infix_func)(pTHX_ const char *kw, const struct XSParseInfixHooks *hooks, void *hookdata);
111             #define register_xs_parse_infix(opname, hooks, hookdata) S_register_xs_parse_infix(aTHX_ opname, hooks, hookdata)
112 21           static void S_register_xs_parse_infix(pTHX_ const char *opname, const struct XSParseInfixHooks *hooks, void *hookdata)
113             {
114 21 50         if(!register_xs_parse_infix_func)
115 0           croak("Must call boot_xs_parse_infix() first");
116              
117 21           (*register_xs_parse_infix_func)(aTHX_ opname, hooks, hookdata);
118 21           }
119              
120             #define boot_xs_parse_infix(ver) S_boot_xs_parse_infix(aTHX_ ver)
121 7           static void S_boot_xs_parse_infix(pTHX_ double ver) {
122             SV **svp;
123 7 50         SV *versv = ver ? newSVnv(ver) : NULL;
124              
125 7           load_module(PERL_LOADMOD_NOIMPORT, newSVpvs("XS::Parse::Infix"), versv, NULL);
126              
127 7           svp = hv_fetchs(PL_modglobal, "XS::Parse::Infix/ABIVERSION_MIN", 0);
128 7 50         if(!svp)
129 0           croak("XS::Parse::Infix ABI minimum version missing");
130 7           int abi_ver = SvIV(*svp);
131 7 50         if(abi_ver > XSPARSEINFIX_ABI_VERSION)
132 0           croak("XS::Parse::Infix ABI version mismatch - library supports >= %d, compiled for %d",
133             abi_ver, XSPARSEINFIX_ABI_VERSION);
134              
135 7           svp = hv_fetchs(PL_modglobal, "XS::Parse::Infix/ABIVERSION_MAX", 0);
136 7           abi_ver = SvIV(*svp);
137 7 50         if(abi_ver < XSPARSEINFIX_ABI_VERSION)
138 0           croak("XS::Parse::Infix ABI version mismatch - library supports <= %d, compiled for %d",
139             abi_ver, XSPARSEINFIX_ABI_VERSION);
140              
141 7           parse_infix_func = INT2PTR(bool (*)(pTHX_ enum XSParseInfixSelection, struct XSParseInfixInfo **),
142             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/parse()@2", 0)));
143 7           xs_parse_infix_new_op_func = INT2PTR(OP *(*)(pTHX_ const struct XSParseInfixInfo *, U32, OP *, OP *),
144             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/new_op()@0", 0)));
145 7           register_xs_parse_infix_func = INT2PTR(void (*)(pTHX_ const char *, const struct XSParseInfixHooks *, void *),
146             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/register()@2", 0)));
147 7           }
148              
149             #endif