1 #include <stdlib.h>
2 #include "lib/mlr_globals.h"
3 #include "lib/mlrutil.h"
4 #include "keylist_evaluators.h"
5 #include "mlr_dsl_cst.h"
6 #include "context_flags.h"
7
8 // ================================================================
9 typedef struct _full_srec_assignment_state_t {
10 rxval_evaluator_t* prhs_xevaluator;
11 } full_srec_assignment_state_t;
12
13 static mlr_dsl_cst_statement_handler_t handle_full_srec_assignment_nop;
14 static mlr_dsl_cst_statement_handler_t handle_full_srec_assignment;
15 static mlr_dsl_cst_statement_freer_t free_full_srec_assignment;
16
17 // ----------------------------------------------------------------
alloc_full_srec_assignment(mlr_dsl_cst_t * pcst,mlr_dsl_ast_node_t * pnode,int type_inferencing,int context_flags)18 mlr_dsl_cst_statement_t* alloc_full_srec_assignment(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pnode,
19 int type_inferencing, int context_flags)
20 {
21 full_srec_assignment_state_t* pstate = mlr_malloc_or_die(sizeof(
22 full_srec_assignment_state_t));
23
24 mlr_dsl_ast_node_t* plhs_node = pnode->pchildren->phead->pvvalue;
25 mlr_dsl_ast_node_t* prhs_node = pnode->pchildren->phead->pnext->pvvalue;
26
27 MLR_INTERNAL_CODING_ERROR_IF(plhs_node->type != MD_AST_NODE_TYPE_FULL_SREC);
28
29 mlr_dsl_cst_statement_handler_t* phandler = handle_full_srec_assignment;
30 if (prhs_node->type == MD_AST_NODE_TYPE_FULL_SREC) {
31 // '$* = $*' is a syntactically acceptable no-op
32 pstate->prhs_xevaluator = NULL;
33 phandler = handle_full_srec_assignment_nop;
34 } else {
35 pstate->prhs_xevaluator = rxval_evaluator_alloc_from_ast(
36 prhs_node, pcst->pfmgr, type_inferencing, context_flags);
37 phandler = handle_full_srec_assignment;
38 }
39
40 return mlr_dsl_cst_statement_valloc(
41 pnode,
42 phandler,
43 free_full_srec_assignment,
44 pstate);
45 }
46
47 // ----------------------------------------------------------------
free_full_srec_assignment(mlr_dsl_cst_statement_t * pstatement,context_t * _)48 static void free_full_srec_assignment(mlr_dsl_cst_statement_t* pstatement, context_t* _) {
49 full_srec_assignment_state_t* pstate = pstatement->pvstate;
50
51 if (pstate->prhs_xevaluator != NULL) {
52 pstate->prhs_xevaluator->pfree_func(pstate->prhs_xevaluator);
53 }
54
55 free(pstate);
56 }
57
58 // ----------------------------------------------------------------
handle_full_srec_assignment_nop(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)59 static void handle_full_srec_assignment_nop(
60 mlr_dsl_cst_statement_t* pstatement,
61 variables_t* pvars,
62 cst_outputs_t* pcst_outputs)
63 {
64 }
65
66 // ----------------------------------------------------------------
handle_full_srec_assignment(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)67 static void handle_full_srec_assignment(
68 mlr_dsl_cst_statement_t* pstatement,
69 variables_t* pvars,
70 cst_outputs_t* pcst_outputs)
71 {
72 full_srec_assignment_state_t* pstate = pstatement->pvstate;
73
74 lrec_t* poutrec = lrec_unbacked_alloc(); // pinrec might be part of the RHS.
75 lhmsmv_t* pout_typed_overlay = lhmsmv_alloc();
76
77 rxval_evaluator_t* prhs_xevaluator = pstate->prhs_xevaluator;
78 boxed_xval_t boxed_xval = prhs_xevaluator->pprocess_func(prhs_xevaluator->pvstate, pvars);
79
80 if (!boxed_xval.xval.is_terminal) {
81 for (mlhmmv_level_entry_t* pe = boxed_xval.xval.pnext_level->phead; pe != NULL; pe = pe->pnext) {
82 mv_t* pkey = &pe->level_key;
83 mlhmmv_xvalue_t* pval = &pe->level_xvalue;
84
85 if (pval->is_terminal) { // xxx else collapse-down using json separator?
86 char* skey = mv_alloc_format_val(pkey);
87 // xxx if we're going to transfer here *and* free below, this needs a nullptr poke
88 // at the copy-from site
89 //mv_t val = boxed_xval.is_ephemeral ? pval->terminal_mlrval : mv_copy(&pval->terminal_mlrval);
90 mv_t val = mv_copy(&pval->terminal_mlrval);
91
92 // Write typed mlrval output to the typed overlay rather than into the lrec
93 // (which holds only string values).
94 //
95 // The rval_evaluator reads the overlay in preference to the lrec. E.g. if the
96 // input had "x"=>"abc","y"=>"def" but a previous statement had set "y"=>7.4 and
97 // "z"=>"ghi", then an expression right-hand side referring to $y would get the
98 // floating-point value 7.4. So we don't need to lrec_put the value here, and
99 // moreover should not for two reasons: (1) there is a performance hit of doing
100 // throwaway number-to-string formatting -- it's better to do it once at the
101 // end; (2) having the string values doubly owned by the typed overlay and the
102 // lrec would result in double frees, or awkward bookkeeping. However, the NR
103 // variable evaluator reads prec->field_count, so we need to put something here.
104 // And putting something statically allocated minimizes copying/freeing.
105 lhmsmv_put(pout_typed_overlay, mlr_strdup_or_die(skey), &val,
106 FREE_ENTRY_KEY | FREE_ENTRY_VALUE);
107 lrec_put(poutrec, skey, "bug", FREE_ENTRY_KEY);
108 }
109 }
110 if (boxed_xval.is_ephemeral) {
111 mlhmmv_xvalue_free(&boxed_xval.xval);
112 }
113 } else {
114 mlhmmv_xvalue_free(&boxed_xval.xval);
115 }
116 lrec_free(pvars->pinrec);
117 lhmsmv_free(pvars->ptyped_overlay);
118 pvars->pinrec = poutrec;
119 pvars->ptyped_overlay = pout_typed_overlay;
120 }
121
122 // ================================================================
123 typedef struct _local_variable_definition_state_t {
124 char* lhs_variable_name;
125 int lhs_frame_relative_index;
126 int lhs_type_mask;
127 rxval_evaluator_t* prhs_xevaluator;
128 } local_variable_definition_state_t;
129
130 static mlr_dsl_cst_statement_handler_t handle_local_variable_definition_from_xval;
131 static mlr_dsl_cst_statement_freer_t free_local_variable_definition;
132
133 // ----------------------------------------------------------------
alloc_local_variable_definition(mlr_dsl_cst_t * pcst,mlr_dsl_ast_node_t * pnode,int type_inferencing,int context_flags,int type_mask)134 mlr_dsl_cst_statement_t* alloc_local_variable_definition(
135 mlr_dsl_cst_t* pcst,
136 mlr_dsl_ast_node_t* pnode,
137 int type_inferencing,
138 int context_flags,
139 int type_mask)
140 {
141 local_variable_definition_state_t* pstate = mlr_malloc_or_die(
142 sizeof(local_variable_definition_state_t));
143
144 pstate->lhs_variable_name = NULL;
145 pstate->lhs_frame_relative_index = MD_UNUSED_INDEX;
146 pstate->lhs_type_mask = 0;
147 pstate->prhs_xevaluator = NULL;
148
149 mlr_dsl_ast_node_t* pname_node = pnode->pchildren->phead->pvvalue;
150 pstate->lhs_variable_name = pname_node->text;
151 MLR_INTERNAL_CODING_ERROR_IF(pname_node->vardef_frame_relative_index == MD_UNUSED_INDEX);
152 pstate->lhs_frame_relative_index = pname_node->vardef_frame_relative_index;
153 pstate->lhs_type_mask = type_mask;
154
155 mlr_dsl_cst_statement_handler_t* pstatement_handler = NULL;
156 mlr_dsl_ast_node_t* prhs_node = pnode->pchildren->phead->pnext->pvvalue;
157 pstate->prhs_xevaluator = rxval_evaluator_alloc_from_ast(
158 prhs_node, pcst->pfmgr, type_inferencing, context_flags);
159 pstatement_handler = handle_local_variable_definition_from_xval;
160
161 return mlr_dsl_cst_statement_valloc(
162 pnode,
163 pstatement_handler,
164 free_local_variable_definition,
165 pstate);
166 }
167
168 // ----------------------------------------------------------------
free_local_variable_definition(mlr_dsl_cst_statement_t * pstatement,context_t * _)169 static void free_local_variable_definition(mlr_dsl_cst_statement_t* pstatement, context_t* _) {
170 local_variable_definition_state_t* pstate = pstatement->pvstate;
171
172 pstate->prhs_xevaluator->pfree_func(pstate->prhs_xevaluator);
173
174 free(pstate);
175 }
176
177 // ----------------------------------------------------------------
handle_local_variable_definition_from_xval(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)178 static void handle_local_variable_definition_from_xval(
179 mlr_dsl_cst_statement_t* pstatement,
180 variables_t* pvars,
181 cst_outputs_t* pcst_outputs)
182 {
183 local_variable_definition_state_t* pstate = pstatement->pvstate;
184 rxval_evaluator_t* prhs_xevaluator = pstate->prhs_xevaluator;
185 boxed_xval_t boxed_xval = prhs_xevaluator->pprocess_func(prhs_xevaluator->pvstate, pvars);
186
187 local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
188 if (boxed_xval.is_ephemeral) {
189 local_stack_frame_define_extended(pframe,
190 pstate->lhs_variable_name, pstate->lhs_frame_relative_index, pstate->lhs_type_mask,
191 boxed_xval.xval);
192 } else {
193 local_stack_frame_define_extended(pframe,
194 pstate->lhs_variable_name, pstate->lhs_frame_relative_index, pstate->lhs_type_mask,
195 mlhmmv_xvalue_copy(&boxed_xval.xval));
196 }
197 }
198
199 // ================================================================
200 typedef struct _nonindexed_local_variable_assignment_state_t {
201 char* lhs_variable_name; // For error messages only: stack-index is computed by stack-allocator:
202 int lhs_frame_relative_index;
203 rxval_evaluator_t* prhs_xevaluator;
204 } nonindexed_local_variable_assignment_state_t;
205
206 static mlr_dsl_cst_statement_handler_t handle_nonindexed_local_variable_assignment_from_xval;
207 static mlr_dsl_cst_statement_freer_t free_nonindexed_local_variable_assignment;
208
209 // ----------------------------------------------------------------
alloc_nonindexed_local_variable_assignment(mlr_dsl_cst_t * pcst,mlr_dsl_ast_node_t * pnode,int type_inferencing,int context_flags)210 mlr_dsl_cst_statement_t* alloc_nonindexed_local_variable_assignment(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pnode,
211 int type_inferencing, int context_flags)
212 {
213 nonindexed_local_variable_assignment_state_t* pstate = mlr_malloc_or_die(sizeof(
214 nonindexed_local_variable_assignment_state_t));
215
216 pstate->lhs_variable_name = NULL;
217 pstate->lhs_frame_relative_index = MD_UNUSED_INDEX;
218 pstate->prhs_xevaluator = NULL;
219
220 MLR_INTERNAL_CODING_ERROR_IF((pnode->pchildren == NULL) || (pnode->pchildren->length != 2));
221
222 mlr_dsl_ast_node_t* plhs_node = pnode->pchildren->phead->pvvalue;
223 mlr_dsl_ast_node_t* prhs_node = pnode->pchildren->phead->pnext->pvvalue;
224
225 MLR_INTERNAL_CODING_ERROR_IF(plhs_node->type != MD_AST_NODE_TYPE_NONINDEXED_LOCAL_VARIABLE);
226 MLR_INTERNAL_CODING_ERROR_IF(plhs_node->pchildren != NULL);
227
228 pstate->lhs_variable_name = plhs_node->text;
229 MLR_INTERNAL_CODING_ERROR_IF(plhs_node->vardef_frame_relative_index == MD_UNUSED_INDEX);
230 pstate->lhs_frame_relative_index = plhs_node->vardef_frame_relative_index;
231
232 mlr_dsl_cst_statement_handler_t* pstatement_handler = NULL;
233
234 pstate->prhs_xevaluator = rxval_evaluator_alloc_from_ast(
235 prhs_node, pcst->pfmgr, type_inferencing, context_flags);
236 pstatement_handler = handle_nonindexed_local_variable_assignment_from_xval;
237
238 return mlr_dsl_cst_statement_valloc(
239 pnode,
240 pstatement_handler,
241 free_nonindexed_local_variable_assignment,
242 pstate);
243 }
244
245 // ----------------------------------------------------------------
free_nonindexed_local_variable_assignment(mlr_dsl_cst_statement_t * pstatement,context_t * _)246 static void free_nonindexed_local_variable_assignment(mlr_dsl_cst_statement_t* pstatement, context_t* _) {
247 nonindexed_local_variable_assignment_state_t* pstate = pstatement->pvstate;
248
249 if (pstate->prhs_xevaluator != NULL) {
250 pstate->prhs_xevaluator->pfree_func(pstate->prhs_xevaluator);
251 }
252
253 free(pstate);
254 }
255
256 // ----------------------------------------------------------------
handle_nonindexed_local_variable_assignment_from_xval(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)257 static void handle_nonindexed_local_variable_assignment_from_xval(
258 mlr_dsl_cst_statement_t* pstatement,
259 variables_t* pvars,
260 cst_outputs_t* pcst_outputs)
261 {
262 nonindexed_local_variable_assignment_state_t* pstate = pstatement->pvstate;
263
264 rxval_evaluator_t* prhs_xevaluator = pstate->prhs_xevaluator;
265 boxed_xval_t boxed_xval = prhs_xevaluator->pprocess_func(prhs_xevaluator->pvstate, pvars);
266
267 if (!boxed_xval.xval.is_terminal || mv_is_present(&boxed_xval.xval.terminal_mlrval)) {
268 local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
269 if (boxed_xval.is_ephemeral) {
270 local_stack_frame_assign_extended_nonindexed(pframe, pstate->lhs_frame_relative_index,
271 boxed_xval.xval);
272 } else {
273 local_stack_frame_assign_extended_nonindexed(pframe, pstate->lhs_frame_relative_index,
274 mlhmmv_xvalue_copy(&boxed_xval.xval));
275 }
276 }
277 }
278
279 // ================================================================
280 typedef struct _indexed_local_variable_assignment_state_t {
281 char* lhs_variable_name; // For error messages only: stack-index is computed by stack-allocator:
282 int lhs_frame_relative_index;
283 sllv_t* plhs_keylist_evaluators;
284 rxval_evaluator_t* prhs_xevaluator;
285 } indexed_local_variable_assignment_state_t;
286
287 static mlr_dsl_cst_statement_handler_t handle_indexed_local_variable_assignment_from_xval;
288 static mlr_dsl_cst_statement_freer_t free_indexed_local_variable_assignment;
289
290 // ----------------------------------------------------------------
alloc_indexed_local_variable_assignment(mlr_dsl_cst_t * pcst,mlr_dsl_ast_node_t * pnode,int type_inferencing,int context_flags)291 mlr_dsl_cst_statement_t* alloc_indexed_local_variable_assignment(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pnode,
292 int type_inferencing, int context_flags)
293 {
294 indexed_local_variable_assignment_state_t* pstate = mlr_malloc_or_die(sizeof(
295 indexed_local_variable_assignment_state_t));
296
297 pstate->lhs_variable_name = NULL;
298 pstate->lhs_frame_relative_index = MD_UNUSED_INDEX;
299 pstate->prhs_xevaluator = NULL;
300
301 mlr_dsl_ast_node_t* plhs_node = pnode->pchildren->phead->pvvalue;
302 mlr_dsl_ast_node_t* prhs_node = pnode->pchildren->phead->pnext->pvvalue;
303
304 MLR_INTERNAL_CODING_ERROR_IF(plhs_node->type != MD_AST_NODE_TYPE_INDEXED_LOCAL_VARIABLE);
305 MLR_INTERNAL_CODING_ERROR_IF(plhs_node->pchildren == NULL);
306
307 pstate->lhs_variable_name = plhs_node->text;
308 MLR_INTERNAL_CODING_ERROR_IF(plhs_node->vardef_frame_relative_index == MD_UNUSED_INDEX);
309 pstate->lhs_frame_relative_index = plhs_node->vardef_frame_relative_index;
310
311 pstate->plhs_keylist_evaluators = allocate_keylist_evaluators_from_ast_node(
312 plhs_node, pcst->pfmgr, type_inferencing, context_flags);
313
314 mlr_dsl_cst_statement_handler_t* pstatement_handler = NULL;
315
316 pstate->prhs_xevaluator = rxval_evaluator_alloc_from_ast(
317 prhs_node, pcst->pfmgr, type_inferencing, context_flags);
318 pstatement_handler = handle_indexed_local_variable_assignment_from_xval;
319
320 return mlr_dsl_cst_statement_valloc(
321 pnode,
322 pstatement_handler,
323 free_indexed_local_variable_assignment,
324 pstate);
325 }
326
327 // ----------------------------------------------------------------
free_indexed_local_variable_assignment(mlr_dsl_cst_statement_t * pstatement,context_t * _)328 static void free_indexed_local_variable_assignment(mlr_dsl_cst_statement_t* pstatement, context_t* _) {
329 indexed_local_variable_assignment_state_t* pstate = pstatement->pvstate;
330
331 for (sllve_t* pe = pstate->plhs_keylist_evaluators->phead; pe != NULL; pe = pe->pnext) {
332 rval_evaluator_t* pev = pe->pvvalue;
333 pev->pfree_func(pev);
334 }
335 sllv_free(pstate->plhs_keylist_evaluators);
336
337 pstate->prhs_xevaluator->pfree_func(pstate->prhs_xevaluator);
338
339 free(pstate);
340 }
341
342 // ----------------------------------------------------------------
handle_indexed_local_variable_assignment_from_xval(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)343 static void handle_indexed_local_variable_assignment_from_xval(
344 mlr_dsl_cst_statement_t* pstatement,
345 variables_t* pvars,
346 cst_outputs_t* pcst_outputs)
347 {
348 indexed_local_variable_assignment_state_t* pstate = pstatement->pvstate;
349
350 int lhs_keys_all_non_null_or_error;
351 sllmv_t* pmvkeys = evaluate_list(pstate->plhs_keylist_evaluators, pvars, &lhs_keys_all_non_null_or_error);
352 if (lhs_keys_all_non_null_or_error) {
353
354 rxval_evaluator_t* prhs_xevaluator = pstate->prhs_xevaluator;
355 boxed_xval_t boxed_xval = prhs_xevaluator->pprocess_func(prhs_xevaluator->pvstate, pvars);
356
357 if (!boxed_xval.xval.is_terminal || mv_is_present(&boxed_xval.xval.terminal_mlrval)) {
358 local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
359 if (boxed_xval.is_ephemeral) {
360 local_stack_frame_assign_extended_indexed(pframe, pstate->lhs_frame_relative_index,
361 pmvkeys, boxed_xval.xval);
362 } else {
363 local_stack_frame_assign_extended_indexed(pframe, pstate->lhs_frame_relative_index,
364 pmvkeys, mlhmmv_xvalue_copy(&boxed_xval.xval));
365 }
366 }
367
368 }
369 sllmv_free(pmvkeys);
370
371 }
372
373 // ================================================================
374 typedef struct _oosvar_assignment_state_t {
375 sllv_t* plhs_keylist_evaluators;
376 rxval_evaluator_t* prhs_xevaluator;
377 } oosvar_assignment_state_t;
378
379 static mlr_dsl_cst_statement_handler_t handle_oosvar_assignment_from_xval;
380 static mlr_dsl_cst_statement_freer_t free_oosvar_assignment;
381
382 // ----------------------------------------------------------------
alloc_oosvar_assignment(mlr_dsl_cst_t * pcst,mlr_dsl_ast_node_t * pnode,int type_inferencing,int context_flags)383 mlr_dsl_cst_statement_t* alloc_oosvar_assignment(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pnode,
384 int type_inferencing, int context_flags)
385 {
386 oosvar_assignment_state_t* pstate = mlr_malloc_or_die(sizeof(oosvar_assignment_state_t));
387
388 pstate->plhs_keylist_evaluators = NULL;
389 pstate->prhs_xevaluator = NULL;
390
391 mlr_dsl_ast_node_t* plhs_node = pnode->pchildren->phead->pvvalue;
392 mlr_dsl_ast_node_t* prhs_node = pnode->pchildren->phead->pnext->pvvalue;
393
394 MLR_INTERNAL_CODING_ERROR_IF(plhs_node->type != MD_AST_NODE_TYPE_OOSVAR_KEYLIST);
395
396 pstate->plhs_keylist_evaluators = allocate_keylist_evaluators_from_ast_node(
397 plhs_node, pcst->pfmgr, type_inferencing, context_flags);
398
399 mlr_dsl_cst_statement_handler_t* pstatement_handler = NULL;
400
401 pstate->prhs_xevaluator = rxval_evaluator_alloc_from_ast(
402 prhs_node, pcst->pfmgr, type_inferencing, context_flags);
403 pstatement_handler = handle_oosvar_assignment_from_xval;
404
405 return mlr_dsl_cst_statement_valloc(
406 pnode,
407 pstatement_handler,
408 free_oosvar_assignment,
409 pstate);
410 }
411
412 // ----------------------------------------------------------------
free_oosvar_assignment(mlr_dsl_cst_statement_t * pstatement,context_t * _)413 static void free_oosvar_assignment(mlr_dsl_cst_statement_t* pstatement, context_t* _) {
414 oosvar_assignment_state_t* pstate = pstatement->pvstate;
415
416 for (sllve_t* pe = pstate->plhs_keylist_evaluators->phead; pe != NULL; pe = pe->pnext) {
417 rval_evaluator_t* pev = pe->pvvalue;
418 pev->pfree_func(pev);
419 }
420 sllv_free(pstate->plhs_keylist_evaluators);
421 if (pstate->prhs_xevaluator != NULL) {
422 pstate->prhs_xevaluator->pfree_func(pstate->prhs_xevaluator);
423 }
424
425 free(pstate);
426 }
427
428 // ----------------------------------------------------------------
handle_oosvar_assignment_from_xval(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)429 static void handle_oosvar_assignment_from_xval(
430 mlr_dsl_cst_statement_t* pstatement,
431 variables_t* pvars,
432 cst_outputs_t* pcst_outputs)
433 {
434 oosvar_assignment_state_t* pstate = pstatement->pvstate;
435
436 int lhs_all_non_null_or_error = TRUE;
437 sllmv_t* plhskeys = evaluate_list(pstate->plhs_keylist_evaluators, pvars,
438 &lhs_all_non_null_or_error);
439
440 if (lhs_all_non_null_or_error) {
441 rxval_evaluator_t* prhs_xevaluator = pstate->prhs_xevaluator;
442 boxed_xval_t boxed_xval = prhs_xevaluator->pprocess_func(prhs_xevaluator->pvstate, pvars);
443
444 if (!boxed_xval.xval.is_terminal || mv_is_present(&boxed_xval.xval.terminal_mlrval)) {
445 if (boxed_xval.is_ephemeral) {
446 mlhmmv_level_put_xvalue(pvars->poosvars->root_xvalue.pnext_level, plhskeys->phead, &boxed_xval.xval);
447 } else {
448 mlhmmv_xvalue_t copy_xval = mlhmmv_xvalue_copy(&boxed_xval.xval);
449 mlhmmv_level_put_xvalue(pvars->poosvars->root_xvalue.pnext_level, plhskeys->phead, ©_xval);
450 }
451 }
452 }
453
454 sllmv_free(plhskeys);
455 }
456
457 // ================================================================
458 typedef struct _full_oosvar_assignment_state_t {
459 rxval_evaluator_t* prhs_xevaluator;
460 } full_oosvar_assignment_state_t;
461
462 static mlr_dsl_cst_statement_handler_t handle_full_oosvar_assignment_from_xval;
463 static mlr_dsl_cst_statement_handler_t handle_full_oosvar_assignment_nop;
464 static mlr_dsl_cst_statement_freer_t free_full_oosvar_assignment;
465
466 // ----------------------------------------------------------------
alloc_full_oosvar_assignment(mlr_dsl_cst_t * pcst,mlr_dsl_ast_node_t * pnode,int type_inferencing,int context_flags)467 mlr_dsl_cst_statement_t* alloc_full_oosvar_assignment(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pnode,
468 int type_inferencing, int context_flags)
469 {
470 full_oosvar_assignment_state_t* pstate = mlr_malloc_or_die(sizeof(full_oosvar_assignment_state_t));
471
472 pstate->prhs_xevaluator = NULL;
473
474 mlr_dsl_ast_node_t* plhs_node = pnode->pchildren->phead->pvvalue;
475 mlr_dsl_ast_node_t* prhs_node = pnode->pchildren->phead->pnext->pvvalue;
476 MLR_INTERNAL_CODING_ERROR_UNLESS(plhs_node->type == MD_AST_NODE_TYPE_FULL_OOSVAR);
477
478 mlr_dsl_cst_statement_handler_t* pstatement_handler = NULL;
479 if (prhs_node->type == MD_AST_NODE_TYPE_FULL_OOSVAR) {
480 pstatement_handler = handle_full_oosvar_assignment_nop;
481 } else {
482 pstate->prhs_xevaluator = rxval_evaluator_alloc_from_ast(
483 prhs_node, pcst->pfmgr, type_inferencing, context_flags);
484 pstatement_handler = handle_full_oosvar_assignment_from_xval;
485 }
486
487 return mlr_dsl_cst_statement_valloc(
488 pnode,
489 pstatement_handler,
490 free_full_oosvar_assignment,
491 pstate);
492 }
493
494 // ----------------------------------------------------------------
free_full_oosvar_assignment(mlr_dsl_cst_statement_t * pstatement,context_t * _)495 static void free_full_oosvar_assignment(mlr_dsl_cst_statement_t* pstatement, context_t* _) {
496 full_oosvar_assignment_state_t* pstate = pstatement->pvstate;
497
498 if (pstate->prhs_xevaluator != NULL) {
499 pstate->prhs_xevaluator->pfree_func(pstate->prhs_xevaluator);
500 }
501
502 free(pstate);
503 }
504
505 // ----------------------------------------------------------------
handle_full_oosvar_assignment_from_xval(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)506 static void handle_full_oosvar_assignment_from_xval(
507 mlr_dsl_cst_statement_t* pstatement,
508 variables_t* pvars,
509 cst_outputs_t* pcst_outputs)
510 {
511 full_oosvar_assignment_state_t* pstate = pstatement->pvstate;
512 rxval_evaluator_t* prhs_xevaluator = pstate->prhs_xevaluator;
513 boxed_xval_t boxed_xval = prhs_xevaluator->pprocess_func(prhs_xevaluator->pvstate, pvars);
514
515 if (boxed_xval.xval.is_terminal) {
516 mlhmmv_root_clear(pvars->poosvars);
517 mlhmmv_xvalue_free(&boxed_xval.xval);
518 } else {
519 if (boxed_xval.is_ephemeral) {
520 mlhmmv_level_free(pvars->poosvars->root_xvalue.pnext_level);
521 pvars->poosvars->root_xvalue.pnext_level = boxed_xval.xval.pnext_level;
522 } else {
523 mlhmmv_xvalue_t copy = mlhmmv_xvalue_copy(&boxed_xval.xval);
524 mlhmmv_root_clear(pvars->poosvars);
525 for (mlhmmv_level_entry_t* pe = copy.pnext_level->phead; pe != NULL; pe = pe->pnext) {
526 // xxx comment: value transfer not copy.
527 mlhmmv_level_put_xvalue_singly_keyed(pvars->poosvars->root_xvalue.pnext_level, &pe->level_key, &pe->level_xvalue);
528 pe->level_xvalue.terminal_mlrval = mv_absent();
529 pe->level_xvalue.pnext_level = NULL;
530 pe->level_xvalue.is_terminal = TRUE;
531 }
532 mlhmmv_xvalue_free(©);
533 }
534 }
535 }
536
537 // ----------------------------------------------------------------
538 // @* = @*
handle_full_oosvar_assignment_nop(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)539 static void handle_full_oosvar_assignment_nop(
540 mlr_dsl_cst_statement_t* pstatement,
541 variables_t* pvars,
542 cst_outputs_t* pcst_outputs)
543 {
544 }
545