| 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
|
|
|
|
|
|
|
/* lhs_flags, rhs_flags */ |
|
46
|
|
|
|
|
|
|
enum { |
|
47
|
|
|
|
|
|
|
XPI_OPERAND_TERM_LIST = 6, /* term in list context */ |
|
48
|
|
|
|
|
|
|
XPI_OPERAND_LIST = 7, /* list in list context */ |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
/* Other bitflags */ |
|
51
|
|
|
|
|
|
|
XPI_OPERAND_ONLY_LOOK = (1<<3), |
|
52
|
|
|
|
|
|
|
}; |
|
53
|
|
|
|
|
|
|
// No longer used |
|
54
|
|
|
|
|
|
|
#define XPI_OPERAND_ARITH 0 |
|
55
|
|
|
|
|
|
|
#define XPI_OPERAND_TERM 0 |
|
56
|
|
|
|
|
|
|
#define XPI_OPERAND_CUSTOM (1<<7) |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
struct XSParseInfixHooks { |
|
59
|
|
|
|
|
|
|
U16 flags; |
|
60
|
|
|
|
|
|
|
U8 lhs_flags, rhs_flags; |
|
61
|
|
|
|
|
|
|
enum XSParseInfixClassification cls; |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
const char *wrapper_func_name; |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
/* These two hooks are ANDed together; both must pass, if present */ |
|
66
|
|
|
|
|
|
|
const char *permit_hintkey; |
|
67
|
|
|
|
|
|
|
bool (*permit) (pTHX_ void *hookdata); |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
/* These hooks are alternatives; the first one defined is used */ |
|
70
|
|
|
|
|
|
|
OP *(*new_op)(pTHX_ U32 flags, OP *lhs, OP *rhs, SV **parsedata, void *hookdata); |
|
71
|
|
|
|
|
|
|
OP *(*ppaddr)(pTHX); /* A pp func used directly in newBINOP_custom() */ |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
/* optional */ |
|
74
|
|
|
|
|
|
|
void (*parse)(pTHX_ U32 flags, SV **parsedata, void *hookdata); |
|
75
|
|
|
|
|
|
|
}; |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
struct XSParseInfixInfo { |
|
78
|
|
|
|
|
|
|
const char *opname; |
|
79
|
|
|
|
|
|
|
OPCODE opcode; |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
const struct XSParseInfixHooks *hooks; |
|
82
|
|
|
|
|
|
|
void *hookdata; |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
enum XSParseInfixClassification cls; |
|
85
|
|
|
|
|
|
|
}; |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
static bool (*parse_infix_func)(pTHX_ enum XSParseInfixSelection select, struct XSParseInfixInfo **infop); |
|
88
|
|
|
|
|
|
|
#define parse_infix(select, infop) S_parse_infix(aTHX_ select, infop) |
|
89
|
|
|
|
|
|
|
static bool S_parse_infix(pTHX_ enum XSParseInfixSelection select, struct XSParseInfixInfo **infop) |
|
90
|
|
|
|
|
|
|
{ |
|
91
|
|
|
|
|
|
|
if(!parse_infix_func) |
|
92
|
|
|
|
|
|
|
croak("Must call boot_xs_parse_infix() first"); |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
struct XSParseInfixInfo *infocopy; |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
return (*parse_infix_func)(aTHX_ select, infop); |
|
97
|
|
|
|
|
|
|
} |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
static OP *(*xs_parse_infix_new_op_func)(pTHX_ const struct XSParseInfixInfo *info, U32 flags, OP *lhs, OP *rhs); |
|
100
|
|
|
|
|
|
|
#define xs_parse_infix_new_op(info, flags, lhs, rhs) S_xs_parse_infix_new_op(aTHX_ info, flags, lhs, rhs) |
|
101
|
|
|
|
|
|
|
static OP *S_xs_parse_infix_new_op(pTHX_ const struct XSParseInfixInfo *info, U32 flags, OP *lhs, OP *rhs) |
|
102
|
|
|
|
|
|
|
{ |
|
103
|
|
|
|
|
|
|
if(!xs_parse_infix_new_op_func) |
|
104
|
|
|
|
|
|
|
croak("Must call boot_xs_parse_infix() first"); |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
return (*xs_parse_infix_new_op_func)(aTHX_ info, flags, lhs, rhs); |
|
107
|
|
|
|
|
|
|
} |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
static void (*register_xs_parse_infix_func)(pTHX_ const char *kw, const struct XSParseInfixHooks *hooks, void *hookdata); |
|
110
|
|
|
|
|
|
|
#define register_xs_parse_infix(opname, hooks, hookdata) S_register_xs_parse_infix(aTHX_ opname, hooks, hookdata) |
|
111
|
|
|
|
|
|
|
static void S_register_xs_parse_infix(pTHX_ const char *opname, const struct XSParseInfixHooks *hooks, void *hookdata) |
|
112
|
|
|
|
|
|
|
{ |
|
113
|
0
|
0
|
|
|
|
|
if(!register_xs_parse_infix_func) |
|
114
|
0
|
|
|
|
|
|
croak("Must call boot_xs_parse_infix() first"); |
|
115
|
|
|
|
|
|
|
|
|
116
|
0
|
|
|
|
|
|
return (*register_xs_parse_infix_func)(aTHX_ opname, hooks, hookdata); |
|
117
|
|
|
|
|
|
|
} |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
#define boot_xs_parse_infix(ver) S_boot_xs_parse_infix(aTHX_ ver) |
|
120
|
3
|
|
|
|
|
|
static void S_boot_xs_parse_infix(pTHX_ double ver) { |
|
121
|
|
|
|
|
|
|
SV **svp; |
|
122
|
3
|
50
|
|
|
|
|
SV *versv = ver ? newSVnv(ver) : NULL; |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
/* XS::Parse::Infix is implemented in XS::Parse::Keyword's .so file */ |
|
125
|
3
|
|
|
|
|
|
load_module(PERL_LOADMOD_NOIMPORT, newSVpvs("XS::Parse::Keyword"), versv, NULL); |
|
126
|
|
|
|
|
|
|
|
|
127
|
3
|
|
|
|
|
|
svp = hv_fetchs(PL_modglobal, "XS::Parse::Infix/ABIVERSION_MIN", 0); |
|
128
|
3
|
50
|
|
|
|
|
if(!svp) |
|
129
|
0
|
|
|
|
|
|
croak("XS::Parse::Infix ABI minimum version missing"); |
|
130
|
3
|
50
|
|
|
|
|
int abi_ver = SvIV(*svp); |
|
131
|
3
|
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
|
3
|
|
|
|
|
|
svp = hv_fetchs(PL_modglobal, "XS::Parse::Infix/ABIVERSION_MAX", 0); |
|
136
|
3
|
50
|
|
|
|
|
abi_ver = SvIV(*svp); |
|
137
|
3
|
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
|
3
|
50
|
|
|
|
|
parse_infix_func = INT2PTR(bool (*)(pTHX_ enum XSParseInfixSelection, struct XSParseInfixInfo **), |
|
142
|
|
|
|
|
|
|
SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/parse()@2", 0))); |
|
143
|
3
|
50
|
|
|
|
|
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
|
3
|
50
|
|
|
|
|
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
|
3
|
|
|
|
|
|
} |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
#endif |