File Coverage

XSParseInfix.h
Criterion Covered Total %
statement 16 20 80.0
branch 9 18 50.0
condition n/a
subroutine n/a
pod n/a
total 25 38 65.7


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             XPI_CLS_ADD_MISC, /* an operator at addition-like precedence */
21             XPI_CLS_MUL_MISC, /* an operator at multiplication-like precedence */
22             XPI_CLS_POW_MISC, /* an operator at power exponentiation-like precedence */
23             };
24              
25             enum XSParseInfixSelection {
26             XPI_SELECT_ANY,
27             XPI_SELECT_PREDICATE, /* any predicate */
28             XPI_SELECT_RELATION, /* any relation */
29             XPI_SELECT_EQUALITY, /* any equality */
30             XPI_SELECT_ORDERING, /* any ordering */
31              
32             XPI_SELECT_MATCH_NOSMART, /* any equality or other match operator, including smartmatch */
33             XPI_SELECT_MATCH_SMART, /* any equality or other match operator, not including smartmatch */
34             };
35              
36             /* lhs_flags, rhs_flags */
37             enum {
38             XPI_OPERAND_TERM_LIST = 6, /* term in list context */
39             XPI_OPERAND_LIST = 7, /* list in list context */
40              
41             /* Other bitflags */
42             XPI_OPERAND_ONLY_LOOK = (1<<3),
43             };
44             // No longer used
45             #define XPI_OPERAND_ARITH 0
46             #define XPI_OPERAND_TERM 0
47             #define XPI_OPERAND_CUSTOM (1<<7)
48              
49             struct XSParseInfixHooks {
50             U16 flags;
51             U8 lhs_flags, rhs_flags;
52             enum XSParseInfixClassification cls;
53              
54             const char *wrapper_func_name;
55              
56             /* These two hooks are ANDed together; both must pass, if present */
57             const char *permit_hintkey;
58             bool (*permit) (pTHX_ void *hookdata);
59              
60             /* These hooks are alternatives; the first one defined is used */
61             OP *(*new_op)(pTHX_ U32 flags, OP *lhs, OP *rhs, SV **parsedata, void *hookdata);
62             OP *(*ppaddr)(pTHX); /* A pp func used directly in newBINOP_custom() */
63              
64             /* optional */
65             void (*parse)(pTHX_ U32 flags, SV **parsedata, void *hookdata);
66             };
67              
68             struct XSParseInfixInfo {
69             const char *opname;
70             OPCODE opcode;
71              
72             const struct XSParseInfixHooks *hooks;
73             void *hookdata;
74              
75             enum XSParseInfixClassification cls;
76             };
77              
78             static bool (*parse_infix_func)(pTHX_ enum XSParseInfixSelection select, struct XSParseInfixInfo **infop);
79             #define parse_infix(select, infop) S_parse_infix(aTHX_ select, infop)
80             static bool S_parse_infix(pTHX_ enum XSParseInfixSelection select, struct XSParseInfixInfo **infop)
81             {
82             if(!parse_infix_func)
83             croak("Must call boot_xs_parse_infix() first");
84              
85             struct XSParseInfixInfo *infocopy;
86              
87             return (*parse_infix_func)(aTHX_ select, infop);
88             }
89              
90             static OP *(*xs_parse_infix_new_op_func)(pTHX_ const struct XSParseInfixInfo *info, U32 flags, OP *lhs, OP *rhs);
91             #define xs_parse_infix_new_op(info, flags, lhs, rhs) S_xs_parse_infix_new_op(aTHX_ info, flags, lhs, rhs)
92             static OP *S_xs_parse_infix_new_op(pTHX_ const struct XSParseInfixInfo *info, U32 flags, OP *lhs, OP *rhs)
93             {
94             if(!xs_parse_infix_new_op_func)
95             croak("Must call boot_xs_parse_infix() first");
96              
97             return (*xs_parse_infix_new_op_func)(aTHX_ info, flags, lhs, rhs);
98             }
99              
100             static void (*register_xs_parse_infix_func)(pTHX_ const char *kw, const struct XSParseInfixHooks *hooks, void *hookdata);
101             #define register_xs_parse_infix(opname, hooks, hookdata) S_register_xs_parse_infix(aTHX_ opname, hooks, hookdata)
102             static void S_register_xs_parse_infix(pTHX_ const char *opname, const struct XSParseInfixHooks *hooks, void *hookdata)
103             {
104 10           if(!register_xs_parse_infix_func)
105 0           croak("Must call boot_xs_parse_infix() first");
106              
107 10           return (*register_xs_parse_infix_func)(aTHX_ opname, hooks, hookdata);
108             }
109              
110             #define boot_xs_parse_infix(ver) S_boot_xs_parse_infix(aTHX_ ver)
111 2           static void S_boot_xs_parse_infix(pTHX_ double ver) {
112             SV **svp;
113 2 50         SV *versv = ver ? newSVnv(ver) : NULL;
114              
115             /* XS::Parse::Infix is implemented in XS::Parse::Keyword's .so file */
116 2           load_module(PERL_LOADMOD_NOIMPORT, newSVpvs("XS::Parse::Keyword"), versv, NULL);
117              
118 2           svp = hv_fetchs(PL_modglobal, "XS::Parse::Infix/ABIVERSION_MIN", 0);
119 2 50         if(!svp)
120 0           croak("XS::Parse::Infix ABI minimum version missing");
121 2 50         int abi_ver = SvIV(*svp);
122 2 50         if(abi_ver > XSPARSEINFIX_ABI_VERSION)
123 0           croak("XS::Parse::Infix ABI version mismatch - library supports >= %d, compiled for %d",
124             abi_ver, XSPARSEINFIX_ABI_VERSION);
125              
126 2           svp = hv_fetchs(PL_modglobal, "XS::Parse::Infix/ABIVERSION_MAX", 0);
127 2 50         abi_ver = SvIV(*svp);
128 2 50         if(abi_ver < XSPARSEINFIX_ABI_VERSION)
129 0           croak("XS::Parse::Infix ABI version mismatch - library supports <= %d, compiled for %d",
130             abi_ver, XSPARSEINFIX_ABI_VERSION);
131              
132 2 50         parse_infix_func = INT2PTR(bool (*)(pTHX_ enum XSParseInfixSelection, struct XSParseInfixInfo **),
133             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/parse()@2", 0)));
134 2 50         xs_parse_infix_new_op_func = INT2PTR(OP *(*)(pTHX_ const struct XSParseInfixInfo *, U32, OP *, OP *),
135             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/new_op()@0", 0)));
136 2 50         register_xs_parse_infix_func = INT2PTR(void (*)(pTHX_ const char *, const struct XSParseInfixHooks *, void *),
137             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/register()@2", 0)));
138 2           }
139              
140             #endif