1 #ifndef XVFUNCS_H
2 #define XVFUNCS_H
3
4 // ================================================================
5 // Functions on extended values, namely, scalars and maps.
6 //
7 // NOTE ON EPHEMERALITY OF MAPS:
8 //
9 // Most functions here free their inputs. E.g. for string concatenation, the
10 // output which is returned is the concatenation of the two inputs which are
11 // freed. This is true for functions on scalars as well as functions on maps
12 // (the latter in this header file).
13 //
14 // However, maps are treated differently from scalars in that some maps are
15 // referenced, rather than copied, within the concrete syntax tree. E.g. in
16 // 'mapsum({3:4},@v)', the map literal {3:4} is ephemeral to the expression and
17 // must be freed during evaluation, but the @v part is referenced to the @v data
18 // structure and is only copied on write. The boxed_xval_t's is_ephemeral flag
19 // tracks the difference between the two cases.
20 // ================================================================
21
22 #include "../lib/mlrutil.h"
23 #include "../containers/mlhmmv.h"
24 #include "../containers/boxed_xval.h"
25
26 // ----------------------------------------------------------------
27 typedef boxed_xval_t xv_variadic_func_t(
28 boxed_xval_t* pbxvals,
29 int nxvals);
30
31 typedef boxed_xval_t xv_zary_func_t();
32
33 typedef boxed_xval_t xv_unary_func_t(
34 boxed_xval_t* pbxval1);
35
36 typedef boxed_xval_t xv_binary_func_t(
37 boxed_xval_t* pbxval1,
38 boxed_xval_t* pbxval2);
39
40 typedef boxed_xval_t xv_ternary_func_t(
41 boxed_xval_t* pbxval1,
42 boxed_xval_t* pbxval2,
43 boxed_xval_t* pbxval3);
44
45 // ----------------------------------------------------------------
46 // Most functions here free their inputs. E.g. for string concatenation, the
47 // output which is returned is the concatenation of the two inputs which are
48 // freed. For another example, is_string frees its input and returns the boolean
49 // value of the result. These functions, by contrast, only return a boolean for
50 // the outcome of the test but do not free the inputs. The intended usage is for
51 // type-assertion checks. E.g. in '$b = asserting_string($a)', if $a is a
52 // string it is assigned to $b, else an error is thrown.
53
b_x_is_present_no_free_xfunc(boxed_xval_t * pbxval1)54 static inline boxed_xval_t b_x_is_present_no_free_xfunc(boxed_xval_t* pbxval1) {
55 return box_ephemeral_val(
56 mv_from_bool(
57 !pbxval1->xval.is_terminal || mv_is_present(&pbxval1->xval.terminal_mlrval)
58 )
59 );
60 }
61
b_x_is_absent_no_free_xfunc(boxed_xval_t * pbxval1)62 static inline boxed_xval_t b_x_is_absent_no_free_xfunc(boxed_xval_t* pbxval1) {
63 return box_ephemeral_val(
64 mv_from_bool(
65 pbxval1->xval.is_terminal && mv_is_absent(&pbxval1->xval.terminal_mlrval)
66 )
67 );
68 }
69
b_x_is_map_no_free_xfunc(boxed_xval_t * pbxval1)70 static inline boxed_xval_t b_x_is_map_no_free_xfunc(boxed_xval_t* pbxval1) {
71 return box_ephemeral_val(
72 mv_from_bool(
73 !pbxval1->xval.is_terminal
74 )
75 );
76 }
77
b_x_is_not_map_no_free_xfunc(boxed_xval_t * pbxval1)78 static inline boxed_xval_t b_x_is_not_map_no_free_xfunc(boxed_xval_t* pbxval1) {
79 return box_ephemeral_val(
80 mv_from_bool(
81 pbxval1->xval.is_terminal
82 )
83 );
84 }
85
b_x_is_numeric_no_free_xfunc(boxed_xval_t * pbxval1)86 static inline boxed_xval_t b_x_is_numeric_no_free_xfunc(boxed_xval_t* pbxval1) {
87 return box_ephemeral_val(
88 mv_from_bool(
89 pbxval1->xval.is_terminal && mv_is_numeric(&pbxval1->xval.terminal_mlrval)
90 )
91 );
92 }
93
b_x_is_int_no_free_xfunc(boxed_xval_t * pbxval1)94 static inline boxed_xval_t b_x_is_int_no_free_xfunc(boxed_xval_t* pbxval1) {
95 return box_ephemeral_val(
96 mv_from_bool(
97 pbxval1->xval.is_terminal && mv_is_int(&pbxval1->xval.terminal_mlrval)
98 )
99 );
100 }
101
b_x_is_float_no_free_xfunc(boxed_xval_t * pbxval1)102 static inline boxed_xval_t b_x_is_float_no_free_xfunc(boxed_xval_t* pbxval1) {
103 return box_ephemeral_val(
104 mv_from_bool(
105 pbxval1->xval.is_terminal && mv_is_float(&pbxval1->xval.terminal_mlrval)
106 )
107 );
108 }
109
b_x_is_boolean_no_free_xfunc(boxed_xval_t * pbxval1)110 static inline boxed_xval_t b_x_is_boolean_no_free_xfunc(boxed_xval_t* pbxval1) {
111 return box_ephemeral_val(
112 mv_from_bool(
113 pbxval1->xval.is_terminal && mv_is_boolean(&pbxval1->xval.terminal_mlrval)
114 )
115 );
116 }
117
b_x_is_string_no_free_xfunc(boxed_xval_t * pbxval1)118 static inline boxed_xval_t b_x_is_string_no_free_xfunc(boxed_xval_t* pbxval1) {
119 return box_ephemeral_val(
120 mv_from_bool(
121 pbxval1->xval.is_terminal && mv_is_string(&pbxval1->xval.terminal_mlrval)
122 )
123 );
124 }
125
b_x_is_null_no_free_xfunc(boxed_xval_t * pbxval1)126 static inline boxed_xval_t b_x_is_null_no_free_xfunc(boxed_xval_t* pbxval1) {
127 return box_ephemeral_val(
128 mv_from_bool(
129 pbxval1->xval.is_terminal && mv_is_null(&pbxval1->xval.terminal_mlrval)
130 )
131 );
132 }
133
b_x_is_not_null_no_free_xfunc(boxed_xval_t * pbxval1)134 static inline boxed_xval_t b_x_is_not_null_no_free_xfunc(boxed_xval_t* pbxval1) {
135 return box_ephemeral_val(
136 mv_from_bool(
137 !(pbxval1->xval.is_terminal && mv_is_null(&pbxval1->xval.terminal_mlrval))
138 )
139 );
140 }
141
b_x_is_empty_no_free_xfunc(boxed_xval_t * pbxval1)142 static inline boxed_xval_t b_x_is_empty_no_free_xfunc(boxed_xval_t* pbxval1) {
143 return box_ephemeral_val(
144 mv_from_bool(
145 pbxval1->xval.is_terminal && mv_is_empty(&pbxval1->xval.terminal_mlrval)
146 )
147 );
148 }
149
b_x_is_not_empty_no_free_xfunc(boxed_xval_t * pbxval1)150 static inline boxed_xval_t b_x_is_not_empty_no_free_xfunc(boxed_xval_t* pbxval1) {
151 return box_ephemeral_val(
152 mv_from_bool(
153 !(pbxval1->xval.is_terminal && mv_is_empty(&pbxval1->xval.terminal_mlrval))
154 )
155 );
156 }
157
b_x_is_empty_map_no_free_xfunc(boxed_xval_t * pbxval1)158 static inline boxed_xval_t b_x_is_empty_map_no_free_xfunc(boxed_xval_t* pbxval1) {
159 return box_ephemeral_val(
160 mv_from_bool(
161 !pbxval1->xval.is_terminal && pbxval1->xval.pnext_level->num_occupied == 0
162 )
163 );
164 }
165
b_x_is_nonempty_map_no_free_xfunc(boxed_xval_t * pbxval1)166 static inline boxed_xval_t b_x_is_nonempty_map_no_free_xfunc(boxed_xval_t* pbxval1) {
167 return box_ephemeral_val(
168 mv_from_bool(
169 !pbxval1->xval.is_terminal && pbxval1->xval.pnext_level->num_occupied != 0
170 )
171 );
172 }
173
s_x_typeof_no_free_xfunc(boxed_xval_t * pbxval1)174 static inline boxed_xval_t s_x_typeof_no_free_xfunc(boxed_xval_t* pbxval1) {
175 return box_ephemeral_val(
176 mv_from_string(
177 mlhmmv_xvalue_describe_type_simple(&pbxval1->xval), NO_FREE
178 )
179 );
180 }
181
182 // ----------------------------------------------------------------
b_x_is_present_xfunc(boxed_xval_t * pbxval1)183 static inline boxed_xval_t b_x_is_present_xfunc(boxed_xval_t* pbxval1) {
184 boxed_xval_t rv = b_x_is_present_no_free_xfunc(pbxval1);
185 if (pbxval1->is_ephemeral)
186 mlhmmv_xvalue_free(&pbxval1->xval);
187 return rv;
188 }
189
b_x_is_absent_xfunc(boxed_xval_t * pbxval1)190 static inline boxed_xval_t b_x_is_absent_xfunc(boxed_xval_t* pbxval1) {
191 boxed_xval_t rv = b_x_is_absent_no_free_xfunc(pbxval1);
192 if (pbxval1->is_ephemeral)
193 mlhmmv_xvalue_free(&pbxval1->xval);
194 return rv;
195 }
196
b_x_is_map_xfunc(boxed_xval_t * pbxval1)197 static inline boxed_xval_t b_x_is_map_xfunc(boxed_xval_t* pbxval1) {
198 boxed_xval_t rv = b_x_is_map_no_free_xfunc(pbxval1);
199 if (pbxval1->is_ephemeral)
200 mlhmmv_xvalue_free(&pbxval1->xval);
201 return rv;
202 }
203
b_x_is_not_map_xfunc(boxed_xval_t * pbxval1)204 static inline boxed_xval_t b_x_is_not_map_xfunc(boxed_xval_t* pbxval1) {
205 boxed_xval_t rv = b_x_is_not_map_no_free_xfunc(pbxval1);
206 if (pbxval1->is_ephemeral)
207 mlhmmv_xvalue_free(&pbxval1->xval);
208 return rv;
209 }
210
b_x_is_numeric_xfunc(boxed_xval_t * pbxval1)211 static inline boxed_xval_t b_x_is_numeric_xfunc(boxed_xval_t* pbxval1) {
212 boxed_xval_t rv = b_x_is_numeric_no_free_xfunc(pbxval1);
213 if (pbxval1->is_ephemeral)
214 mlhmmv_xvalue_free(&pbxval1->xval);
215 return rv;
216 }
217
b_x_is_int_xfunc(boxed_xval_t * pbxval1)218 static inline boxed_xval_t b_x_is_int_xfunc(boxed_xval_t* pbxval1) {
219 boxed_xval_t rv = b_x_is_int_no_free_xfunc(pbxval1);
220 if (pbxval1->is_ephemeral)
221 mlhmmv_xvalue_free(&pbxval1->xval);
222 return rv;
223 }
224
b_x_is_float_xfunc(boxed_xval_t * pbxval1)225 static inline boxed_xval_t b_x_is_float_xfunc(boxed_xval_t* pbxval1) {
226 boxed_xval_t rv = b_x_is_float_no_free_xfunc(pbxval1);
227 if (pbxval1->is_ephemeral)
228 mlhmmv_xvalue_free(&pbxval1->xval);
229 return rv;
230 }
231
b_x_is_boolean_xfunc(boxed_xval_t * pbxval1)232 static inline boxed_xval_t b_x_is_boolean_xfunc(boxed_xval_t* pbxval1) {
233 boxed_xval_t rv = b_x_is_boolean_no_free_xfunc(pbxval1);
234 if (pbxval1->is_ephemeral)
235 mlhmmv_xvalue_free(&pbxval1->xval);
236 return rv;
237 }
238
b_x_is_string_xfunc(boxed_xval_t * pbxval1)239 static inline boxed_xval_t b_x_is_string_xfunc(boxed_xval_t* pbxval1) {
240 boxed_xval_t rv = b_x_is_string_no_free_xfunc(pbxval1);
241 if (pbxval1->is_ephemeral)
242 mlhmmv_xvalue_free(&pbxval1->xval);
243 return rv;
244 }
245
b_x_is_null_xfunc(boxed_xval_t * pbxval1)246 static inline boxed_xval_t b_x_is_null_xfunc(boxed_xval_t* pbxval1) {
247 boxed_xval_t rv = b_x_is_null_no_free_xfunc(pbxval1);
248 if (pbxval1->is_ephemeral)
249 mlhmmv_xvalue_free(&pbxval1->xval);
250 return rv;
251 }
252
b_x_is_not_null_xfunc(boxed_xval_t * pbxval1)253 static inline boxed_xval_t b_x_is_not_null_xfunc(boxed_xval_t* pbxval1) {
254 boxed_xval_t rv = b_x_is_not_null_no_free_xfunc(pbxval1);
255 if (pbxval1->is_ephemeral)
256 mlhmmv_xvalue_free(&pbxval1->xval);
257 return rv;
258 }
259
b_x_is_empty_xfunc(boxed_xval_t * pbxval1)260 static inline boxed_xval_t b_x_is_empty_xfunc(boxed_xval_t* pbxval1) {
261 boxed_xval_t rv = b_x_is_empty_no_free_xfunc(pbxval1);
262 if (pbxval1->is_ephemeral)
263 mlhmmv_xvalue_free(&pbxval1->xval);
264 return rv;
265 }
266
b_x_is_not_empty_xfunc(boxed_xval_t * pbxval1)267 static inline boxed_xval_t b_x_is_not_empty_xfunc(boxed_xval_t* pbxval1) {
268 boxed_xval_t rv = b_x_is_not_empty_no_free_xfunc(pbxval1);
269 if (pbxval1->is_ephemeral)
270 mlhmmv_xvalue_free(&pbxval1->xval);
271 return rv;
272 }
273
b_x_is_empty_map_xfunc(boxed_xval_t * pbxval1)274 static inline boxed_xval_t b_x_is_empty_map_xfunc(boxed_xval_t* pbxval1) {
275 boxed_xval_t rv = b_x_is_empty_map_no_free_xfunc(pbxval1);
276 if (pbxval1->is_ephemeral)
277 mlhmmv_xvalue_free(&pbxval1->xval);
278 return rv;
279 }
280
b_x_is_nonempty_map_xfunc(boxed_xval_t * pbxval1)281 static inline boxed_xval_t b_x_is_nonempty_map_xfunc(boxed_xval_t* pbxval1) {
282 boxed_xval_t rv = b_x_is_nonempty_map_no_free_xfunc(pbxval1);
283 if (pbxval1->is_ephemeral)
284 mlhmmv_xvalue_free(&pbxval1->xval);
285 return rv;
286 }
287
s_x_typeof_xfunc(boxed_xval_t * pbxval1)288 static inline boxed_xval_t s_x_typeof_xfunc(boxed_xval_t* pbxval1) {
289 boxed_xval_t rv = s_x_typeof_no_free_xfunc(pbxval1);
290 if (pbxval1->is_ephemeral)
291 mlhmmv_xvalue_free(&pbxval1->xval);
292 return rv;
293 }
294
295 // ----------------------------------------------------------------
296 boxed_xval_t b_xx_haskey_xfunc(
297 boxed_xval_t* pmapval,
298 boxed_xval_t* pkeyval);
299
300 boxed_xval_t i_x_length_xfunc(
301 boxed_xval_t* pbxval1);
302
303 boxed_xval_t i_x_depth_xfunc(
304 boxed_xval_t* pbxval1);
305
306 boxed_xval_t i_x_leafcount_xfunc(
307 boxed_xval_t* pbxval1);
308
309 boxed_xval_t variadic_mapsum_xfunc(
310 boxed_xval_t* pbxvals, int nxvals);
311
312 boxed_xval_t variadic_mapdiff_xfunc(
313 boxed_xval_t* pbxvals, int nxvals);
314
315 boxed_xval_t variadic_mapexcept_xfunc(
316 boxed_xval_t* pbxvals, int nxvals);
317
318 boxed_xval_t variadic_mapselect_xfunc(
319 boxed_xval_t* pbxvals, int nxvals);
320
321 boxed_xval_t m_ss_splitnv_xfunc(
322 boxed_xval_t* pstringval,
323 boxed_xval_t* psepval);
324
325 boxed_xval_t m_ss_splitnvx_xfunc(
326 boxed_xval_t* pstringval,
327 boxed_xval_t* psepval);
328
329 boxed_xval_t m_sss_splitkv_xfunc(
330 boxed_xval_t* pstringval,
331 boxed_xval_t* ppairsepval,
332 boxed_xval_t* plistsepval);
333
334 boxed_xval_t m_sss_splitkvx_xfunc(
335 boxed_xval_t* pstringval,
336 boxed_xval_t* ppairsepval,
337 boxed_xval_t* plistsepval);
338
339 boxed_xval_t s_ms_joink_xfunc(
340 boxed_xval_t* pmapval,
341 boxed_xval_t* psepval);
342
343 boxed_xval_t s_ms_joinv_xfunc(
344 boxed_xval_t* pmapval,
345 boxed_xval_t* psepval);
346
347 boxed_xval_t s_mss_joinkv_xfunc(
348 boxed_xval_t* pmapval,
349 boxed_xval_t* ppairsepval,
350 boxed_xval_t* plistsepval);
351
352 #endif // XVFUNCS_H
353