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, &copy_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