1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <ctype.h> // for tolower(), toupper()
5 #include "lib/mlr_globals.h"
6 #include "lib/mlrutil.h"
7 #include "lib/mlrregex.h"
8 #include "lib/mtrand.h"
9 #include "dsl/context_flags.h"
10 #include "dsl/keylist_evaluators.h"
11 #include "dsl/rval_evaluators.h"
12 #include "dsl/rxval_evaluators.h"
13 #include "dsl/function_manager.h"
14 #include "mapping/mapper.h"
15
16 // ================================================================
17 // See comments in rval_evaluators.h
18 // ================================================================
19
20 // ----------------------------------------------------------------
rxval_evaluator_alloc_from_ast(mlr_dsl_ast_node_t * pnode,fmgr_t * pfmgr,int type_inferencing,int context_flags)21 rxval_evaluator_t* rxval_evaluator_alloc_from_ast(mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr,
22 int type_inferencing, int context_flags)
23 {
24 switch(pnode->type) {
25
26 case MD_AST_NODE_TYPE_MAP_LITERAL:
27 return rxval_evaluator_alloc_from_map_literal(
28 pnode, pfmgr, type_inferencing, context_flags);
29 return NULL;
30 break;
31
32 case MD_AST_NODE_TYPE_NONINDEXED_LOCAL_VARIABLE:
33 return rxval_evaluator_alloc_from_nonindexed_local_variable(
34 pnode, pfmgr, type_inferencing, context_flags);
35 return NULL;
36 break;
37
38 case MD_AST_NODE_TYPE_INDEXED_LOCAL_VARIABLE:
39 return rxval_evaluator_alloc_from_indexed_local_variable(
40 pnode, pfmgr, type_inferencing, context_flags);
41 break;
42
43 case MD_AST_NODE_TYPE_INDEXED_FUNCTION_CALLSITE:
44 return rxval_evaluator_alloc_from_indexed_function_call(
45 pnode, pfmgr, type_inferencing, context_flags);
46 break;
47
48 case MD_AST_NODE_TYPE_OOSVAR_KEYLIST:
49 return rxval_evaluator_alloc_from_oosvar_keylist(
50 pnode, pfmgr, type_inferencing, context_flags);
51 break;
52
53 case MD_AST_NODE_TYPE_FULL_OOSVAR:
54 return rxval_evaluator_alloc_from_full_oosvar(
55 pnode, pfmgr, type_inferencing, context_flags);
56 return NULL;
57 break;
58
59 case MD_AST_NODE_TYPE_FULL_SREC:
60 return rxval_evaluator_alloc_from_full_srec(
61 pnode, pfmgr, type_inferencing, context_flags);
62 return NULL;
63 break;
64
65 case MD_AST_NODE_TYPE_FUNCTION_CALLSITE:
66 return fmgr_xalloc_provisional_from_operator_or_function_call(pfmgr, pnode, type_inferencing, context_flags);
67 break;
68
69 default:
70 return rxval_evaluator_alloc_wrapping_rval(pnode, pfmgr, type_inferencing, context_flags);
71 break;
72 }
73 }
74
75 // ----------------------------------------------------------------
76 // Srec assignments have output that is rval not rxval (scalar, not map). But for
77 // indexed function calls we have a function which produces rxval, indexed down by a
78 // keylist, to produce an rval as a final result. This needs special handling.
79 // Here we invoke the rxval evaluator, then unbox it and return the resulting rval.
80
81 typedef struct _rval_evaluator_indexed_function_call_state_t {
82 rxval_evaluator_t* prxval_evaluator;
83 } rval_evaluator_indexed_function_call_state_t;
84
rval_evaluator_indexed_function_call_func(void * pvstate,variables_t * pvars)85 static mv_t rval_evaluator_indexed_function_call_func(void* pvstate, variables_t* pvars) {
86 rval_evaluator_indexed_function_call_state_t* pstate = pvstate;
87
88 rxval_evaluator_t* prxval_evaluator = pstate->prxval_evaluator;
89 boxed_xval_t boxed_xval = prxval_evaluator->pprocess_func(prxval_evaluator->pvstate, pvars);
90 if (boxed_xval.xval.is_terminal) {
91 return boxed_xval.xval.terminal_mlrval;
92 } else {
93 return mv_absent();
94 }
95
96 }
rval_evaluator_indexed_function_call_free(rval_evaluator_t * pevaluator)97 static void rval_evaluator_indexed_function_call_free(rval_evaluator_t* pevaluator) {
98 rval_evaluator_indexed_function_call_state_t* pstate = pevaluator->pvstate;
99 pstate->prxval_evaluator->pfree_func(pstate->prxval_evaluator);
100 free(pstate);
101 free(pevaluator);
102 }
rval_evaluator_alloc_from_indexed_function_call(mlr_dsl_ast_node_t * pnode,fmgr_t * pfmgr,int type_inferencing,int context_flags)103 rval_evaluator_t* rval_evaluator_alloc_from_indexed_function_call(
104 mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags)
105 {
106 rval_evaluator_indexed_function_call_state_t* pstate = mlr_malloc_or_die(
107 sizeof(rval_evaluator_indexed_function_call_state_t)
108 );
109 rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
110
111 pstate->prxval_evaluator = rxval_evaluator_alloc_from_indexed_function_call(
112 pnode, pfmgr, type_inferencing, context_flags);
113
114 pevaluator->pprocess_func = rval_evaluator_indexed_function_call_func;
115 pevaluator->pfree_func = rval_evaluator_indexed_function_call_free;
116
117 pevaluator->pvstate = pstate;
118 return pevaluator;
119 }
120
121 // ================================================================
122 // Map-literal input:
123 //
124 // {
125 // "a" : 1,
126 // "b" : {
127 // "x" : 7,
128 // "y" : 8,
129 // },
130 // "c" : 3,
131 // }
132 //
133 // Map-literal AST:
134 //
135 // $ mlr --from s put -v -q 'm={"a":NR,"b":{"x":999},"c":3};dump m'
136 // text="block", type=STATEMENT_BLOCK:
137 // text="=", type=NONINDEXED_LOCAL_ASSIGNMENT:
138 // text="m", type=NONINDEXED_LOCAL_VARIABLE.
139 // text="map_literal", type=MAP_LITERAL:
140 // text="mappair", type=MAP_LITERAL_PAIR:
141 // text="mapkey", type=MAP_LITERAL:
142 // text="a", type=STRING_LITERAL.
143 // text="mapval", type=MAP_LITERAL:
144 // text="NR", type=CONTEXT_VARIABLE.
145 // text="mappair", type=MAP_LITERAL_PAIR:
146 // text="mapkey", type=MAP_LITERAL:
147 // text="b", type=STRING_LITERAL.
148 // text="mapval", type=MAP_LITERAL:
149 // text="map_literal", type=MAP_LITERAL:
150 // text="mappair", type=MAP_LITERAL_PAIR:
151 // text="mapkey", type=MAP_LITERAL:
152 // text="x", type=STRING_LITERAL.
153 // text="mapval", type=MAP_LITERAL:
154 // text="999", type=NUMERIC_LITERAL.
155 // text="mappair", type=MAP_LITERAL_PAIR:
156 // text="mapkey", type=MAP_LITERAL:
157 // text="c", type=STRING_LITERAL.
158 // text="mapval", type=MAP_LITERAL:
159 // text="3", type=NUMERIC_LITERAL.
160 // text="dump", type=DUMP:
161 // text=">", type=FILE_WRITE:
162 // text="stdout", type=STDOUT:
163 // text="m", type=NONINDEXED_LOCAL_VARIABLE.
164
165 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
166 typedef struct _map_literal_list_evaluator_t {
167 sllv_t* pkvpair_evaluators;
168 } map_literal_list_evaluator_t;
169
170 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
171 typedef struct _map_literal_kvpair_evaluator_t {
172 rval_evaluator_t* pkey_evaluator;
173 int is_terminal;
174 rxval_evaluator_t* pxval_evaluator;
175 map_literal_list_evaluator_t* plist_evaluator;
176 } map_literal_kvpair_evaluator_t;
177
178 // ----------------------------------------------------------------
allocate_map_literal_evaluator_from_ast(mlr_dsl_ast_node_t * pnode,fmgr_t * pfmgr,int type_inferencing,int context_flags)179 static map_literal_list_evaluator_t* allocate_map_literal_evaluator_from_ast(
180 mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags)
181 {
182 map_literal_list_evaluator_t* plist_evaluator = mlr_malloc_or_die(
183 sizeof(map_literal_list_evaluator_t));
184 plist_evaluator->pkvpair_evaluators = sllv_alloc();
185 MLR_INTERNAL_CODING_ERROR_IF(pnode->type != MD_AST_NODE_TYPE_MAP_LITERAL);
186 for (sllve_t* pe = pnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
187
188 map_literal_kvpair_evaluator_t* pkvpair = mlr_malloc_or_die(
189 sizeof(map_literal_kvpair_evaluator_t));
190 *pkvpair = (map_literal_kvpair_evaluator_t) {
191 .pkey_evaluator = NULL,
192 .is_terminal = TRUE,
193 .pxval_evaluator = NULL,
194 .plist_evaluator = NULL,
195 };
196
197 mlr_dsl_ast_node_t* pchild = pe->pvvalue;
198 MLR_INTERNAL_CODING_ERROR_IF(pchild->type != MD_AST_NODE_TYPE_MAP_LITERAL_PAIR);
199
200 mlr_dsl_ast_node_t* pleft = pchild->pchildren->phead->pvvalue;
201 MLR_INTERNAL_CODING_ERROR_IF(pleft->type != MD_AST_NODE_TYPE_MAP_LITERAL_KEY);
202 mlr_dsl_ast_node_t* pkeynode = pleft->pchildren->phead->pvvalue;
203 pkvpair->pkey_evaluator = rval_evaluator_alloc_from_ast(pkeynode, pfmgr,
204 type_inferencing, context_flags);
205
206 mlr_dsl_ast_node_t* pright = pchild->pchildren->phead->pnext->pvvalue;
207 mlr_dsl_ast_node_t* pvalnode = pright->pchildren->phead->pvvalue;
208 if (pright->type == MD_AST_NODE_TYPE_MAP_LITERAL_VALUE) {
209 pkvpair->pxval_evaluator = rxval_evaluator_alloc_from_ast(pvalnode, pfmgr,
210 type_inferencing, context_flags);
211 } else if (pright->type == MD_AST_NODE_TYPE_MAP_LITERAL) {
212 pkvpair->is_terminal = FALSE;
213 pkvpair->plist_evaluator = allocate_map_literal_evaluator_from_ast(
214 pvalnode, pfmgr, type_inferencing, context_flags);
215 } else {
216 MLR_INTERNAL_CODING_ERROR();
217 }
218
219 sllv_append(plist_evaluator->pkvpair_evaluators, pkvpair);
220 }
221 return plist_evaluator;
222 }
223
224 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
225 typedef struct _rxval_evaluator_from_map_literal_state_t {
226 map_literal_list_evaluator_t* proot_list_evaluator;
227 } rxval_evaluator_from_map_literal_state_t;
228
rxval_evaluator_from_map_literal_aux(rxval_evaluator_from_map_literal_state_t * pstate,map_literal_list_evaluator_t * plist_evaluator,mlhmmv_level_t * plevel,variables_t * pvars)229 static void rxval_evaluator_from_map_literal_aux(
230 rxval_evaluator_from_map_literal_state_t* pstate,
231 map_literal_list_evaluator_t* plist_evaluator,
232 mlhmmv_level_t* plevel,
233 variables_t* pvars)
234 {
235 for (sllve_t* pe = plist_evaluator->pkvpair_evaluators->phead; pe != NULL; pe = pe->pnext) {
236 map_literal_kvpair_evaluator_t* pkvpair = pe->pvvalue;
237
238 // mlhmmv_level_put_terminal will copy keys and values
239 mv_t mvkey = pkvpair->pkey_evaluator->pprocess_func(pkvpair->pkey_evaluator->pvstate, pvars);
240 if (pkvpair->is_terminal) {
241 boxed_xval_t boxed_xval = pkvpair->pxval_evaluator->pprocess_func(
242 pkvpair->pxval_evaluator->pvstate, pvars);
243 if (boxed_xval.is_ephemeral) {
244 mlhmmv_level_put_xvalue_singly_keyed(plevel, &mvkey, &boxed_xval.xval);
245 } else {
246 mlhmmv_xvalue_t copy_xval = mlhmmv_xvalue_copy(&boxed_xval.xval);
247 mlhmmv_level_put_xvalue_singly_keyed(plevel, &mvkey, ©_xval);
248 }
249 } else {
250 mlhmmv_level_t* pnext_level = mlhmmv_level_put_empty_map(plevel, &mvkey);
251 rxval_evaluator_from_map_literal_aux(pstate, pkvpair->plist_evaluator, pnext_level, pvars);
252 }
253 mv_free(&mvkey);
254 }
255 }
256
rxval_evaluator_from_map_literal_func(void * pvstate,variables_t * pvars)257 static boxed_xval_t rxval_evaluator_from_map_literal_func(void* pvstate, variables_t* pvars) {
258 rxval_evaluator_from_map_literal_state_t* pstate = pvstate;
259
260 mlhmmv_xvalue_t xval = mlhmmv_xvalue_alloc_empty_map();
261
262 rxval_evaluator_from_map_literal_aux(pstate, pstate->proot_list_evaluator, xval.pnext_level, pvars);
263
264 return (boxed_xval_t) {
265 .xval = xval,
266 .is_ephemeral = TRUE,
267 };
268 }
269
rxval_evaluator_from_map_literal_free_aux(map_literal_list_evaluator_t * plist_evaluator)270 static void rxval_evaluator_from_map_literal_free_aux(map_literal_list_evaluator_t* plist_evaluator) {
271 for (sllve_t* pe = plist_evaluator->pkvpair_evaluators->phead; pe != NULL; pe = pe->pnext) {
272 map_literal_kvpair_evaluator_t* pkvpair_evaluator = pe->pvvalue;
273 if (pkvpair_evaluator->pkey_evaluator != NULL) {
274 pkvpair_evaluator->pkey_evaluator->pfree_func(pkvpair_evaluator->pkey_evaluator);
275 }
276 if (pkvpair_evaluator->pxval_evaluator != NULL) {
277 pkvpair_evaluator->pxval_evaluator->pfree_func(pkvpair_evaluator->pxval_evaluator);
278 }
279 if (pkvpair_evaluator->plist_evaluator != NULL) {
280 rxval_evaluator_from_map_literal_free_aux(pkvpair_evaluator->plist_evaluator);
281 }
282 free(pkvpair_evaluator);
283 }
284 sllv_free(plist_evaluator->pkvpair_evaluators);
285 free(plist_evaluator);
286 }
287
rxval_evaluator_from_map_literal_free(rxval_evaluator_t * prxval_evaluator)288 static void rxval_evaluator_from_map_literal_free(rxval_evaluator_t* prxval_evaluator) {
289 rxval_evaluator_from_map_literal_state_t* pstate = prxval_evaluator->pvstate;
290 rxval_evaluator_from_map_literal_free_aux(pstate->proot_list_evaluator);
291 free(pstate);
292 free(prxval_evaluator);
293 }
294
rxval_evaluator_alloc_from_map_literal(mlr_dsl_ast_node_t * pnode,fmgr_t * pfmgr,int type_inferencing,int context_flags)295 rxval_evaluator_t* rxval_evaluator_alloc_from_map_literal(mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr,
296 int type_inferencing, int context_flags)
297 {
298 rxval_evaluator_from_map_literal_state_t* pstate = mlr_malloc_or_die(
299 sizeof(rxval_evaluator_from_map_literal_state_t));
300 pstate->proot_list_evaluator = allocate_map_literal_evaluator_from_ast(
301 pnode, pfmgr, type_inferencing, context_flags);
302
303 rxval_evaluator_t* prxval_evaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t));
304 prxval_evaluator->pvstate = pstate;
305 prxval_evaluator->pprocess_func = rxval_evaluator_from_map_literal_func;
306 prxval_evaluator->pfree_func = rxval_evaluator_from_map_literal_free;
307
308 return prxval_evaluator;
309 }
310
311 // ================================================================
312 typedef struct _rxval_evaluator_from_nonindexed_local_variable_state_t {
313 int vardef_frame_relative_index;
314 } rxval_evaluator_from_nonindexed_local_variable_state_t;
315
rxval_evaluator_from_nonindexed_local_variable_func(void * pvstate,variables_t * pvars)316 static boxed_xval_t rxval_evaluator_from_nonindexed_local_variable_func(void* pvstate, variables_t* pvars) {
317 rxval_evaluator_from_nonindexed_local_variable_state_t* pstate = pvstate;
318 local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
319 mlhmmv_xvalue_t* pxval = local_stack_frame_ref_extended_from_nonindexed(
320 pframe, pstate->vardef_frame_relative_index);
321 if (pxval == NULL) {
322 return (boxed_xval_t) {
323 .xval = mlhmmv_xvalue_wrap_terminal(mv_absent()),
324 .is_ephemeral = FALSE,
325 };
326 } else {
327 return (boxed_xval_t) {
328 .xval = *pxval,
329 .is_ephemeral = FALSE,
330 };
331 }
332 }
333
rxval_evaluator_from_nonindexed_local_variable_free(rxval_evaluator_t * prxval_evaluator)334 static void rxval_evaluator_from_nonindexed_local_variable_free(rxval_evaluator_t* prxval_evaluator) {
335 rxval_evaluator_from_nonindexed_local_variable_state_t* pstate = prxval_evaluator->pvstate;
336 free(pstate);
337 free(prxval_evaluator);
338 }
339
rxval_evaluator_alloc_from_nonindexed_local_variable(mlr_dsl_ast_node_t * pnode,fmgr_t * pfmgr,int type_inferencing,int context_flags)340 rxval_evaluator_t* rxval_evaluator_alloc_from_nonindexed_local_variable(
341 mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags)
342 {
343 rxval_evaluator_from_nonindexed_local_variable_state_t* pstate = mlr_malloc_or_die(
344 sizeof(rxval_evaluator_from_nonindexed_local_variable_state_t));
345 MLR_INTERNAL_CODING_ERROR_IF(pnode->vardef_frame_relative_index == MD_UNUSED_INDEX);
346 pstate->vardef_frame_relative_index = pnode->vardef_frame_relative_index;
347
348 rxval_evaluator_t* prxval_evaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t));
349 prxval_evaluator->pvstate = pstate;
350 prxval_evaluator->pprocess_func = rxval_evaluator_from_nonindexed_local_variable_func;
351 prxval_evaluator->pfree_func = rxval_evaluator_from_nonindexed_local_variable_free;
352
353 return prxval_evaluator;
354 }
355
356 // ================================================================
357 typedef struct _rxval_evaluator_from_indexed_local_variable_state_t {
358 int vardef_frame_relative_index;
359 sllv_t* pkeylist_evaluators;
360 } rxval_evaluator_from_indexed_local_variable_state_t;
361
rxval_evaluator_from_indexed_local_variable_func(void * pvstate,variables_t * pvars)362 static boxed_xval_t rxval_evaluator_from_indexed_local_variable_func(void* pvstate, variables_t* pvars) {
363 rxval_evaluator_from_indexed_local_variable_state_t* pstate = pvstate;
364
365 int all_non_null_or_error = TRUE;
366 sllmv_t* pmvkeys = evaluate_list(pstate->pkeylist_evaluators, pvars, &all_non_null_or_error);
367
368 if (all_non_null_or_error) {
369 local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
370 mlhmmv_xvalue_t* pxval = local_stack_frame_ref_extended_from_indexed(
371 pframe, pstate->vardef_frame_relative_index, pmvkeys);
372 sllmv_free(pmvkeys);
373 if (pxval == NULL) {
374 return (boxed_xval_t) {
375 .xval = mlhmmv_xvalue_wrap_terminal(mv_absent()),
376 .is_ephemeral = FALSE,
377 };
378 } else {
379 return (boxed_xval_t) {
380 .xval = *pxval,
381 .is_ephemeral = FALSE,
382 };
383 }
384 } else {
385 sllmv_free(pmvkeys);
386 return (boxed_xval_t) {
387 .xval = mlhmmv_xvalue_wrap_terminal(mv_absent()),
388 .is_ephemeral = TRUE,
389 };
390 }
391 }
392
rxval_evaluator_from_indexed_local_variable_free(rxval_evaluator_t * prxval_evaluator)393 static void rxval_evaluator_from_indexed_local_variable_free(rxval_evaluator_t* prxval_evaluator) {
394 rxval_evaluator_from_indexed_local_variable_state_t* pstate = prxval_evaluator->pvstate;
395 for (sllve_t* pe = pstate->pkeylist_evaluators->phead; pe != NULL; pe = pe->pnext) {
396 rval_evaluator_t* prval_evaluator = pe->pvvalue;
397 prval_evaluator->pfree_func(prval_evaluator);
398 }
399 sllv_free(pstate->pkeylist_evaluators);
400 free(pstate);
401 free(prxval_evaluator);
402 }
403
rxval_evaluator_alloc_from_indexed_local_variable(mlr_dsl_ast_node_t * pnode,fmgr_t * pfmgr,int type_inferencing,int context_flags)404 rxval_evaluator_t* rxval_evaluator_alloc_from_indexed_local_variable(
405 mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags)
406 {
407 rxval_evaluator_from_indexed_local_variable_state_t* pstate = mlr_malloc_or_die(
408 sizeof(rxval_evaluator_from_indexed_local_variable_state_t));
409 MLR_INTERNAL_CODING_ERROR_IF(pnode->vardef_frame_relative_index == MD_UNUSED_INDEX);
410 pstate->vardef_frame_relative_index = pnode->vardef_frame_relative_index;
411 pstate->pkeylist_evaluators = allocate_keylist_evaluators_from_ast_node(
412 pnode, pfmgr, type_inferencing, context_flags);
413
414 rxval_evaluator_t* prxval_evaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t));
415 prxval_evaluator->pvstate = pstate;
416 prxval_evaluator->pprocess_func = rxval_evaluator_from_indexed_local_variable_func;
417 prxval_evaluator->pfree_func = rxval_evaluator_from_indexed_local_variable_free;
418
419 return prxval_evaluator;
420 }
421
422 // ================================================================
423 typedef struct _rxval_evaluator_from_indexed_function_call_state_t {
424 rxval_evaluator_t* pfunction_call_evaluator;
425 sllv_t* pkeylist_evaluators;
426 } rxval_evaluator_from_indexed_function_call_state_t;
427
rxval_evaluator_from_indexed_function_call_func(void * pvstate,variables_t * pvars)428 static boxed_xval_t rxval_evaluator_from_indexed_function_call_func(void* pvstate, variables_t* pvars) {
429 rxval_evaluator_from_indexed_function_call_state_t* pstate = pvstate;
430
431 // This is for things like $b = splitnvx($a, ":")[1].
432 // * First we evaluate the function call -- the splitnvx($a, ":") part.
433 // * Second we evaluate the index/indices -- [1] part.
434 // * Third we index function-call return value by the indices.
435
436 // Evaluate the function call:
437 rxval_evaluator_t* pfunction_call_evaluator = pstate->pfunction_call_evaluator;
438 boxed_xval_t function_call_output = pfunction_call_evaluator->pprocess_func(
439 pfunction_call_evaluator->pvstate, pvars);
440
441 // Non-indexable if not a map.
442 if (function_call_output.xval.is_terminal) {
443 mv_free(&function_call_output.xval.terminal_mlrval);
444 return (boxed_xval_t) {
445 .xval = mlhmmv_xvalue_wrap_terminal(mv_absent()),
446 .is_ephemeral = TRUE,
447 };
448 }
449
450 // Evaluate the indices:
451 int all_non_null_or_error = TRUE;
452 sllmv_t* pmvkeys = evaluate_list(pstate->pkeylist_evaluators, pvars, &all_non_null_or_error);
453
454 if (!all_non_null_or_error) {
455 mlhmmv_xvalue_free(&function_call_output.xval);
456 sllmv_free(pmvkeys);
457 return (boxed_xval_t) {
458 .xval = mlhmmv_xvalue_wrap_terminal(mv_absent()),
459 .is_ephemeral = TRUE,
460 };
461 }
462
463 // Index the function-call return value by the indices:
464 int lookup_error_reason_unused = FALSE;
465 mlhmmv_xvalue_t* pxval = mlhmmv_level_look_up_and_ref_xvalue(
466 function_call_output.xval.pnext_level, pmvkeys, &lookup_error_reason_unused);
467
468 if (pxval == NULL) {
469 mlhmmv_xvalue_free(&function_call_output.xval);
470 sllmv_free(pmvkeys);
471 return (boxed_xval_t) {
472 .xval = mlhmmv_xvalue_wrap_terminal(mv_absent()),
473 .is_ephemeral = FALSE,
474 };
475 } else {
476 // xxx copy out little bit, free full retval
477 // mlhmmv_xvalue_free(&function_call_output.xval);
478 sllmv_free(pmvkeys);
479 return (boxed_xval_t) {
480 .xval = *pxval,
481 .is_ephemeral = FALSE,
482 };
483 }
484 }
485
rxval_evaluator_from_indexed_function_call_free(rxval_evaluator_t * prxval_evaluator)486 static void rxval_evaluator_from_indexed_function_call_free(rxval_evaluator_t* prxval_evaluator) {
487 rxval_evaluator_from_indexed_function_call_state_t* pstate = prxval_evaluator->pvstate;
488 for (sllve_t* pe = pstate->pkeylist_evaluators->phead; pe != NULL; pe = pe->pnext) {
489 rval_evaluator_t* prval_evaluator = pe->pvvalue;
490 prval_evaluator->pfree_func(prval_evaluator);
491 }
492 sllv_free(pstate->pkeylist_evaluators);
493 free(pstate);
494 free(prxval_evaluator);
495 }
496
rxval_evaluator_alloc_from_indexed_function_call(mlr_dsl_ast_node_t * pnode,fmgr_t * pfmgr,int type_inferencing,int context_flags)497 rxval_evaluator_t* rxval_evaluator_alloc_from_indexed_function_call(
498 mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags)
499 {
500 rxval_evaluator_from_indexed_function_call_state_t* pstate = mlr_malloc_or_die(
501 sizeof(rxval_evaluator_from_indexed_function_call_state_t));
502
503 // Example: 'foo(1,2,3)[4][5]' parses to AST
504 // text="foo", type=INDEXED_FUNCTION_CALLSITE:
505 // text="foo", type=FUNCTION_CALLSITE:
506 // text="1", type=NUMERIC_LITERAL.
507 // text="2", type=NUMERIC_LITERAL.
508 // text="3", type=NUMERIC_LITERAL.
509 // text="indexing", type=MD_AST_NODE_TYPE_INDEXED_FUNCTION_INDEX_LIST:
510 // text="4", type=NUMERIC_LITERAL.
511 // text="5", type=NUMERIC_LITERAL.
512 pstate->pfunction_call_evaluator = fmgr_xalloc_provisional_from_operator_or_function_call(
513 pfmgr, pnode->pchildren->phead->pvvalue, type_inferencing, context_flags);
514 pstate->pkeylist_evaluators = allocate_keylist_evaluators_from_ast_node(
515 pnode->pchildren->phead->pnext->pvvalue, pfmgr, type_inferencing, context_flags);
516
517 rxval_evaluator_t* prxval_evaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t));
518 prxval_evaluator->pvstate = pstate;
519 prxval_evaluator->pprocess_func = rxval_evaluator_from_indexed_function_call_func;
520 prxval_evaluator->pfree_func = rxval_evaluator_from_indexed_function_call_free;
521
522 return prxval_evaluator;
523 }
524
525 // ================================================================
526 typedef struct _rxval_evaluator_from_oosvar_keylist_state_t {
527 sllv_t* pkeylist_evaluators;
528 } rxval_evaluator_from_oosvar_keylist_state_t;
529
rxval_evaluator_from_oosvar_keylist_func(void * pvstate,variables_t * pvars)530 static boxed_xval_t rxval_evaluator_from_oosvar_keylist_func(void* pvstate, variables_t* pvars) {
531 rxval_evaluator_from_oosvar_keylist_state_t* pstate = pvstate;
532
533 int all_non_null_or_error = TRUE;
534 sllmv_t* pmvkeys = evaluate_list(pstate->pkeylist_evaluators, pvars, &all_non_null_or_error);
535
536 if (all_non_null_or_error) {
537 int lookup_error = FALSE;
538 mlhmmv_xvalue_t* pxval = pmvkeys->phead == NULL
539 ? &pvars->poosvars->root_xvalue
540 : mlhmmv_level_look_up_and_ref_xvalue(pvars->poosvars->root_xvalue.pnext_level, pmvkeys, &lookup_error);
541 sllmv_free(pmvkeys);
542 if (pxval != NULL) {
543 return (boxed_xval_t) {
544 .xval = *pxval,
545 .is_ephemeral = FALSE,
546 };
547 } else {
548 return (boxed_xval_t) {
549 .xval = mlhmmv_xvalue_wrap_terminal(mv_absent()),
550 .is_ephemeral = TRUE,
551 };
552 }
553 } else {
554 sllmv_free(pmvkeys);
555 return (boxed_xval_t) {
556 .xval = mlhmmv_xvalue_wrap_terminal(mv_absent()),
557 .is_ephemeral = TRUE,
558 };
559 }
560 }
561
rxval_evaluator_from_oosvar_keylist_free(rxval_evaluator_t * prxval_evaluator)562 static void rxval_evaluator_from_oosvar_keylist_free(rxval_evaluator_t* prxval_evaluator) {
563 rxval_evaluator_from_oosvar_keylist_state_t* pstate = prxval_evaluator->pvstate;
564 for (sllve_t* pe = pstate->pkeylist_evaluators->phead; pe != NULL; pe = pe->pnext) {
565 rval_evaluator_t* prval_evaluator = pe->pvvalue;
566 prval_evaluator->pfree_func(prval_evaluator);
567 }
568 sllv_free(pstate->pkeylist_evaluators);
569 free(pstate);
570 free(prxval_evaluator);
571 }
572
rxval_evaluator_alloc_from_oosvar_keylist(mlr_dsl_ast_node_t * pnode,fmgr_t * pfmgr,int type_inferencing,int context_flags)573 rxval_evaluator_t* rxval_evaluator_alloc_from_oosvar_keylist(
574 mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags)
575 {
576 rxval_evaluator_from_oosvar_keylist_state_t* pstate = mlr_malloc_or_die(
577 sizeof(rxval_evaluator_from_oosvar_keylist_state_t));
578 pstate->pkeylist_evaluators = allocate_keylist_evaluators_from_ast_node(
579 pnode, pfmgr, type_inferencing, context_flags);
580
581 rxval_evaluator_t* prxval_evaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t));
582 prxval_evaluator->pvstate = pstate;
583 prxval_evaluator->pprocess_func = rxval_evaluator_from_oosvar_keylist_func;
584 prxval_evaluator->pfree_func = rxval_evaluator_from_oosvar_keylist_free;
585
586 return prxval_evaluator;
587 }
588
589 // ================================================================
rxval_evaluator_from_full_oosvar_func(void * pvstate,variables_t * pvars)590 static boxed_xval_t rxval_evaluator_from_full_oosvar_func(void* pvstate, variables_t* pvars) {
591 return (boxed_xval_t) {
592 .is_ephemeral = FALSE,
593 .xval = pvars->poosvars->root_xvalue,
594 };
595 }
596
rxval_evaluator_from_full_oosvar_free(rxval_evaluator_t * prxval_evaluator)597 static void rxval_evaluator_from_full_oosvar_free(rxval_evaluator_t* prxval_evaluator) {
598 free(prxval_evaluator);
599 }
600
rxval_evaluator_alloc_from_full_oosvar(mlr_dsl_ast_node_t * pnode,fmgr_t * pfmgr,int type_inferencing,int context_flags)601 rxval_evaluator_t* rxval_evaluator_alloc_from_full_oosvar(
602 mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags)
603 {
604 rxval_evaluator_t* prxval_evaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t));
605 prxval_evaluator->pprocess_func = rxval_evaluator_from_full_oosvar_func;
606 prxval_evaluator->pfree_func = rxval_evaluator_from_full_oosvar_free;
607
608 return prxval_evaluator;
609 }
610
611 // ================================================================
rxval_evaluator_from_full_srec_func(void * pvstate,variables_t * pvars)612 static boxed_xval_t rxval_evaluator_from_full_srec_func(void* pvstate, variables_t* pvars) {
613 boxed_xval_t boxed_xval = box_ephemeral_xval(mlhmmv_xvalue_alloc_empty_map());
614
615 for (lrece_t* pe = pvars->pinrec->phead; pe != NULL; pe = pe->pnext) {
616 // mlhmmv_level_put_terminal will copy mv keys and values so we needn't (and shouldn't)
617 // duplicate them here.
618 mv_t k = mv_from_string(pe->key, NO_FREE);
619 mv_t* pomv = lhmsmv_get(pvars->ptyped_overlay, pe->key);
620 if (pomv != NULL) {
621 mlhmmv_level_put_terminal_singly_keyed(boxed_xval.xval.pnext_level, &k, pomv);
622 } else {
623 mv_t v = mv_from_string(pe->value, NO_FREE); // mlhmmv_level_put_terminal will copy
624 mlhmmv_level_put_terminal_singly_keyed(boxed_xval.xval.pnext_level, &k, &v);
625 }
626 }
627
628 return boxed_xval;
629 }
630
rxval_evaluator_from_full_srec_free(rxval_evaluator_t * prxval_evaluator)631 static void rxval_evaluator_from_full_srec_free(rxval_evaluator_t* prxval_evaluator) {
632 free(prxval_evaluator);
633 }
634
rxval_evaluator_alloc_from_full_srec(mlr_dsl_ast_node_t * pnode,fmgr_t * pfmgr,int type_inferencing,int context_flags)635 rxval_evaluator_t* rxval_evaluator_alloc_from_full_srec(
636 mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags)
637 {
638 rxval_evaluator_t* prxval_evaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t));
639 prxval_evaluator->pprocess_func = rxval_evaluator_from_full_srec_func;
640 prxval_evaluator->pfree_func = rxval_evaluator_from_full_srec_free;
641
642 return prxval_evaluator;
643 }
644
645 // ================================================================
646 // xxx code dup w/ function_manager.c
647
648 // ================================================================
649 typedef struct _rxval_evaluator_from_function_callsite_state_t {
650 rval_evaluator_t* prval_evaluator;
651 } rxval_evaluator_from_function_callsite_state_t;
652
rxval_evaluator_from_function_callsite_func(void * pvstate,variables_t * pvars)653 static boxed_xval_t rxval_evaluator_from_function_callsite_func(void* pvstate, variables_t* pvars) {
654 rxval_evaluator_from_function_callsite_state_t* pstate = pvstate;
655
656 rval_evaluator_t* prval_evaluator = pstate->prval_evaluator;
657 mv_t val = prval_evaluator->pprocess_func(prval_evaluator->pvstate, pvars);
658 return (boxed_xval_t) {
659 .xval = mlhmmv_xvalue_wrap_terminal(val),
660 .is_ephemeral = FALSE, // verify reference semantics for RHS evaluators!
661 };
662 }
663
rxval_evaluator_from_function_callsite_free(rxval_evaluator_t * prxval_evaluator)664 static void rxval_evaluator_from_function_callsite_free(rxval_evaluator_t* prxval_evaluator) {
665 rxval_evaluator_from_function_callsite_state_t* pstate = prxval_evaluator->pvstate;
666 pstate->prval_evaluator->pfree_func(pstate->prval_evaluator);
667 free(pstate);
668 free(prxval_evaluator);
669 }
670
rxval_evaluator_alloc_from_function_callsite(mlr_dsl_ast_node_t * pnode,fmgr_t * pfmgr,int type_inferencing,int context_flags)671 rxval_evaluator_t* rxval_evaluator_alloc_from_function_callsite(
672 mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags)
673 {
674 rxval_evaluator_from_function_callsite_state_t* pstate = mlr_malloc_or_die(
675 sizeof(rxval_evaluator_from_function_callsite_state_t));
676
677 pstate->prval_evaluator = rval_evaluator_alloc_from_ast(pnode, pfmgr, type_inferencing, context_flags);
678
679 rxval_evaluator_t* prxval_evaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t));
680
681 prxval_evaluator->pvstate = pstate;
682 prxval_evaluator->pprocess_func = rxval_evaluator_from_function_callsite_func;
683 prxval_evaluator->pfree_func = rxval_evaluator_from_function_callsite_free;
684
685 return prxval_evaluator;
686 }
687
688 // ================================================================
689 typedef struct _rxval_evaluator_wrapping_rval_state_t {
690 rval_evaluator_t* prval_evaluator;
691 } rxval_evaluator_wrapping_rval_state_t;
692
rxval_evaluator_wrapping_rval_func(void * pvstate,variables_t * pvars)693 static boxed_xval_t rxval_evaluator_wrapping_rval_func(void* pvstate, variables_t* pvars) {
694 rxval_evaluator_wrapping_rval_state_t* pstate = pvstate;
695 rval_evaluator_t* prval_evaluator = pstate->prval_evaluator;
696 mv_t val = prval_evaluator->pprocess_func(prval_evaluator->pvstate, pvars);
697 return (boxed_xval_t) {
698 .xval = mlhmmv_xvalue_wrap_terminal(val),
699 .is_ephemeral = TRUE, // verify reference semantics for RHS evaluators!
700 };
701 }
702
rxval_evaluator_wrapping_rval_free(rxval_evaluator_t * prxval_evaluator)703 static void rxval_evaluator_wrapping_rval_free(rxval_evaluator_t* prxval_evaluator) {
704 rxval_evaluator_wrapping_rval_state_t* pstate = prxval_evaluator->pvstate;
705 pstate->prval_evaluator->pfree_func(pstate->prval_evaluator);
706 free(pstate);
707 free(prxval_evaluator);
708 }
709
rxval_evaluator_alloc_wrapping_rval(mlr_dsl_ast_node_t * pnode,fmgr_t * pfmgr,int type_inferencing,int context_flags)710 rxval_evaluator_t* rxval_evaluator_alloc_wrapping_rval(mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr,
711 int type_inferencing, int context_flags)
712 {
713 rxval_evaluator_wrapping_rval_state_t* pstate = mlr_malloc_or_die(
714 sizeof(rxval_evaluator_wrapping_rval_state_t));
715 pstate->prval_evaluator = rval_evaluator_alloc_from_ast(pnode, pfmgr, type_inferencing, context_flags);
716
717 rxval_evaluator_t* prxval_evaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t));
718 prxval_evaluator->pvstate = pstate;
719 prxval_evaluator->pprocess_func = rxval_evaluator_wrapping_rval_func;
720 prxval_evaluator->pfree_func = rxval_evaluator_wrapping_rval_free;
721
722 return prxval_evaluator;
723 }
724