File Coverage

XSParseInfix.h
Criterion Covered Total %
statement 15 19 78.9
branch 8 16 50.0
condition n/a
subroutine n/a
pod n/a
total 23 35 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 1
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              
21             enum XSParseInfixSelection {
22             XPI_SELECT_ANY,
23             XPI_SELECT_PREDICATE, /* any predicate */
24             XPI_SELECT_RELATION, /* any relation */
25             XPI_SELECT_EQUALITY, /* any equality */
26             XPI_SELECT_ORDERING, /* any ordering */
27              
28             XPI_SELECT_MATCH_NOSMART, /* any equality or other match operator, including smartmatch */
29             XPI_SELECT_MATCH_SMART, /* any equality or other match operator, not including smartmatch */
30             };
31              
32             /* lhs_flags, rhs_flags */
33             enum {
34             /* other space reserved for other scalar types */
35             XPI_OPERAND_ARITH = 2,
36             XPI_OPERAND_TERM = 4,
37             XPI_OPERAND_TERM_LIST = 6, /* term in list context */
38             XPI_OPERAND_LIST = 7, /* list in list context */
39              
40             /* Other bitflags */
41             XPI_OPERAND_ONLY_LOOK = (1<<3),
42             XPI_OPERAND_CUSTOM = (1<<7), /* rhs_flags only */
43             };
44              
45             struct XSParseInfixHooks {
46             U16 flags;
47             U8 lhs_flags, rhs_flags;
48             enum XSParseInfixClassification cls;
49              
50             const char *wrapper_func_name;
51              
52             /* These two hooks are ANDed together; both must pass, if present */
53             const char *permit_hintkey;
54             bool (*permit) (pTHX_ void *hookdata);
55              
56             /* These hooks are alternatives; the first one defined is used */
57             OP *(*new_op)(pTHX_ U32 flags, OP *lhs, OP *rhs, void *hookdata);
58             OP *(*ppaddr)(pTHX); /* A pp func used directly in newBINOP_custom() */
59              
60             /* Used if rhs_flags & XPI_OPERAND_CUSTOM */
61             OP *(*parse_rhs)(pTHX_ void *hookdata);
62             };
63              
64             struct XSParseInfixInfo {
65             const char *opname;
66             OPCODE opcode;
67              
68             const struct XSParseInfixHooks *hooks;
69             void *hookdata;
70             };
71              
72             static OP *(*xs_parse_infix_new_op_func)(pTHX_ const struct XSParseInfixInfo *info, U32 flags, OP *lhs, OP *rhs);
73             #define xs_parse_infix_new_op(info, flags, lhs, rhs) S_xs_parse_infix_new_op(aTHX_ info, flags, lhs, rhs)
74             static OP *S_xs_parse_infix_new_op(pTHX_ const struct XSParseInfixInfo *info, U32 flags, OP *lhs, OP *rhs)
75             {
76             if(!xs_parse_infix_new_op_func)
77             croak("Must call boot_xs_parse_infix() first");
78              
79             return (*xs_parse_infix_new_op_func)(aTHX_ info, flags, lhs, rhs);
80             }
81              
82             static void (*register_xs_parse_infix_func)(pTHX_ const char *kw, const struct XSParseInfixHooks *hooks, void *hookdata);
83             #define register_xs_parse_infix(opname, hooks, hookdata) S_register_xs_parse_infix(aTHX_ opname, hooks, hookdata)
84             static void S_register_xs_parse_infix(pTHX_ const char *opname, const struct XSParseInfixHooks *hooks, void *hookdata)
85             {
86 8           if(!register_xs_parse_infix_func)
87 0           croak("Must call boot_xs_parse_infix() first");
88              
89 8           return (*register_xs_parse_infix_func)(aTHX_ opname, hooks, hookdata);
90             }
91              
92             #define boot_xs_parse_infix(ver) S_boot_xs_parse_infix(aTHX_ ver)
93 4           static void S_boot_xs_parse_infix(pTHX_ double ver) {
94             SV **svp;
95 4 50         SV *versv = ver ? newSVnv(ver) : NULL;
96              
97             /* XS::Parse::Infix is implemented in XS::Parse::Keyword's .so file */
98 4           load_module(PERL_LOADMOD_NOIMPORT, newSVpvs("XS::Parse::Keyword"), versv, NULL);
99              
100 4           svp = hv_fetchs(PL_modglobal, "XS::Parse::Infix/ABIVERSION_MIN", 0);
101 4 50         if(!svp)
102 0           croak("XS::Parse::Infix ABI minimum version missing");
103 4 50         int abi_ver = SvIV(*svp);
104 4 50         if(abi_ver > XSPARSEINFIX_ABI_VERSION)
105 0           croak("XS::Parse::Infix ABI version mismatch - library supports >= %d, compiled for %d",
106             abi_ver, XSPARSEINFIX_ABI_VERSION);
107              
108 4           svp = hv_fetchs(PL_modglobal, "XS::Parse::Infix/ABIVERSION_MAX", 0);
109 4 50         abi_ver = SvIV(*svp);
110 4 50         if(abi_ver < XSPARSEINFIX_ABI_VERSION)
111 0           croak("XS::Parse::Infix ABI version mismatch - library supports <= %d, compiled for %d",
112             abi_ver, XSPARSEINFIX_ABI_VERSION);
113              
114 4 50         xs_parse_infix_new_op_func = INT2PTR(OP *(*)(pTHX_ const struct XSParseInfixInfo *, U32, OP *, OP *),
115             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/new_op()@0", 0)));
116 4 50         register_xs_parse_infix_func = INT2PTR(void (*)(pTHX_ const char *, const struct XSParseInfixHooks *, void *),
117             SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/register()@1", 0)));
118 4           }
119              
120             #endif