File Coverage

XSParseInfix.h
Criterion Covered Total %
statement 15 19 78.9
branch 9 18 50.0
condition n/a
subroutine n/a
pod n/a
total 24 37 64.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             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, ANY *parsedata, void *hookdata);
62             OP *(*ppaddr)(pTHX); /* A pp func used directly in newBINOP_custom() */
63              
64             /* optional */
65             void (*parse)(pTHX_ U32 flags, ANY *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              
76             static OP *(*xs_parse_infix_new_op_func)(pTHX_ const struct XSParseInfixInfo *info, U32 flags, OP *lhs, OP *rhs);
77             #define xs_parse_infix_new_op(info, flags, lhs, rhs) S_xs_parse_infix_new_op(aTHX_ info, flags, lhs, rhs)
78             static OP *S_xs_parse_infix_new_op(pTHX_ const struct XSParseInfixInfo *info, U32 flags, OP *lhs, OP *rhs)
79             {
80             if(!xs_parse_infix_new_op_func)
81             croak("Must call boot_xs_parse_infix() first");
82              
83             return (*xs_parse_infix_new_op_func)(aTHX_ info, flags, lhs, rhs);
84             }
85              
86             static void (*register_xs_parse_infix_func)(pTHX_ const char *kw, const struct XSParseInfixHooks *hooks, void *hookdata);
87             #define register_xs_parse_infix(opname, hooks, hookdata) S_register_xs_parse_infix(aTHX_ opname, hooks, hookdata)
88             static void S_register_xs_parse_infix(pTHX_ const char *opname, const struct XSParseInfixHooks *hooks, void *hookdata)
89             {
90 3 50         if(!register_xs_parse_infix_func)
91 0           croak("Must call boot_xs_parse_infix() first");
92              
93 3           return (*register_xs_parse_infix_func)(aTHX_ opname, hooks, hookdata);
94             }
95              
96             #define boot_xs_parse_infix(ver) S_boot_xs_parse_infix(aTHX_ ver)
97 3           static void S_boot_xs_parse_infix(pTHX_ double ver) {
98             SV **svp;
99 3 50         SV *versv = ver ? newSVnv(ver) : NULL;
100              
101             /* XS::Parse::Infix is implemented in XS::Parse::Keyword's .so file */
102 3           load_module(PERL_LOADMOD_NOIMPORT, newSVpvs("XS::Parse::Keyword"), versv, NULL);
103              
104 3           svp = hv_fetchs(PL_modglobal, "XS::Parse::Infix/ABIVERSION_MIN", 0);
105 3 50         if(!svp)
106 0           croak("XS::Parse::Infix ABI minimum version missing");
107 3 50         int abi_ver = SvIV(*svp);
108 3 50         if(abi_ver > XSPARSEINFIX_ABI_VERSION)
109 0           croak("XS::Parse::Infix ABI version mismatch - library supports >= %d, compiled for %d",
110             abi_ver, XSPARSEINFIX_ABI_VERSION);
111              
112 3           svp = hv_fetchs(PL_modglobal, "XS::Parse::Infix/ABIVERSION_MAX", 0);
113 3 50         abi_ver = SvIV(*svp);
114 3 50         if(abi_ver < XSPARSEINFIX_ABI_VERSION)
115 0           croak("XS::Parse::Infix ABI version mismatch - library supports <= %d, compiled for %d",
116             abi_ver, XSPARSEINFIX_ABI_VERSION);
117              
118 3 50         xs_parse_infix_new_op_func = INT2PTR(OP *(*)(pTHX_ const struct XSParseInfixInfo *, U32, OP *, OP *),
119             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/new_op()@0", 0)));
120 3 50         register_xs_parse_infix_func = INT2PTR(void (*)(pTHX_ const char *, const struct XSParseInfixHooks *, void *),
121             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/register()@2", 0)));
122 3           }
123              
124             #endif