1 #include <stdlib.h>
2 #include "lib/mlr_globals.h"
3 #include "lib/mlrutil.h"
4 #include "mlr_dsl_cst.h"
5 #include "context_flags.h"
6 
7 // ================================================================
8 typedef struct _conditional_block_state_t {
9 	rval_evaluator_t* pexpression_evaluator;
10 } conditional_block_state_t;
11 
12 static mlr_dsl_cst_statement_freer_t free_conditional_block;
13 static mlr_dsl_cst_statement_handler_t handle_conditional_block;
14 
15 // ----------------------------------------------------------------
alloc_conditional_block(mlr_dsl_cst_t * pcst,mlr_dsl_ast_node_t * pnode,int type_inferencing,int context_flags)16 mlr_dsl_cst_statement_t* alloc_conditional_block(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pnode,
17 	int type_inferencing, int context_flags)
18 {
19 	conditional_block_state_t* pstate = mlr_malloc_or_die(sizeof(conditional_block_state_t));
20 
21 	pstate->pexpression_evaluator = NULL;
22 
23 	// Right node is a list of statements to be executed if the left evaluates to true.
24 	mlr_dsl_ast_node_t* pleft  = pnode->pchildren->phead->pvvalue;
25 	mlr_dsl_ast_node_t* pright = pnode->pchildren->phead->pnext->pvvalue;
26 
27 	pstate->pexpression_evaluator = rval_evaluator_alloc_from_ast(
28 		pleft, pcst->pfmgr, type_inferencing, context_flags);
29 
30 	MLR_INTERNAL_CODING_ERROR_IF(pright->subframe_var_count == MD_UNUSED_INDEX);
31 	cst_statement_block_t* pblock = cst_statement_block_alloc(pright->subframe_var_count);
32 
33 	for (sllve_t* pe = pright->pchildren->phead; pe != NULL; pe = pe->pnext) {
34 		mlr_dsl_ast_node_t* pbody_ast_node = pe->pvvalue;
35 		mlr_dsl_cst_statement_t *pchild_statement = mlr_dsl_cst_alloc_statement(pcst, pbody_ast_node,
36 			type_inferencing, context_flags);
37 		sllv_append(pblock->pstatements, pchild_statement);
38 	}
39 
40 	mlr_dsl_cst_block_handler_t* pblock_handler = (context_flags & IN_BREAKABLE)
41 		? mlr_dsl_cst_handle_statement_block_with_break_continue
42 		: mlr_dsl_cst_handle_statement_block;
43 
44 	return mlr_dsl_cst_statement_valloc_with_block(
45 		pnode,
46 		handle_conditional_block,
47 		pblock,
48 		pblock_handler,
49 		free_conditional_block,
50 		pstate);
51 }
52 
53 // ----------------------------------------------------------------
free_conditional_block(mlr_dsl_cst_statement_t * pstatement,context_t * _)54 static void free_conditional_block(mlr_dsl_cst_statement_t* pstatement, context_t* _) {
55 	conditional_block_state_t* pstate = pstatement->pvstate;
56 
57 	pstate->pexpression_evaluator->pfree_func(pstate->pexpression_evaluator);
58 
59 	free(pstate);
60 }
61 
62 // ----------------------------------------------------------------
handle_conditional_block(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)63 static void handle_conditional_block(
64 	mlr_dsl_cst_statement_t* pstatement,
65 	variables_t*             pvars,
66 	cst_outputs_t*           pcst_outputs)
67 {
68 	conditional_block_state_t* pstate = pstatement->pvstate;
69 
70 	local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
71 	local_stack_subframe_enter(pframe, pstatement->pblock->subframe_var_count);
72 
73 	rval_evaluator_t* pexpression_evaluator = pstate->pexpression_evaluator;
74 
75 	mv_t val = pexpression_evaluator->pprocess_func(pexpression_evaluator->pvstate, pvars);
76 	if (mv_is_non_null(&val)) {
77 		mv_set_boolean_strict(&val);
78 		if (val.u.boolv) {
79 			pstatement->pblock_handler(pstatement->pblock, pvars, pcst_outputs);
80 		}
81 	}
82 
83 	local_stack_subframe_exit(pframe, pstatement->pblock->subframe_var_count);
84 }
85 
86 // ================================================================
87 typedef struct _if_head_state_t {
88 	sllv_t* pif_chain_statements;
89 } if_head_state_t;
90 
91 typedef struct _if_item_state_t {
92 	rval_evaluator_t* pexpression_evaluator;
93 } if_item_state_t;
94 
95 static mlr_dsl_cst_statement_handler_t handle_if_head;
96 static mlr_dsl_cst_statement_freer_t free_if_head;
97 static mlr_dsl_cst_statement_freer_t free_if_item;
98 
99 static mlr_dsl_cst_statement_t* alloc_if_item(
100 	mlr_dsl_cst_t*      pcst,
101 	mlr_dsl_ast_node_t* pitemnode,
102 	mlr_dsl_ast_node_t* pexprnode,
103 	mlr_dsl_ast_node_t* plistnode,
104 	int                 type_inferencing,
105 	int                 context_flags);
106 
107 // ----------------------------------------------------------------
108 // Example parser-input:
109 //
110 //   if (NR == 9) {
111 //       $x = 10;
112 //       $x = 11
113 //   } elif (NR == 12) {
114 //       $x = 13;
115 //       $x = 14
116 //   } else {
117 //       $x = 15;
118 //       $x = 16
119 //   };
120 //
121 // Corresponding parser-output AST:
122 //   if_head (if_head):
123 //       if (if_item):
124 //           == (operator):
125 //               NR (context_variable).
126 //               9 (numeric_literal).
127 //           list (statement_list):
128 //               = (srec_assignment):
129 //                   x (field_name).
130 //                   10 (numeric_literal).
131 //               = (srec_assignment):
132 //                   x (field_name).
133 //                   11 (numeric_literal).
134 //       elif (if_item):
135 //           == (operator):
136 //               NR (context_variable).
137 //               12 (numeric_literal).
138 //           list (statement_list):
139 //               = (srec_assignment):
140 //                   x (field_name).
141 //                   13 (numeric_literal).
142 //               = (srec_assignment):
143 //                   x (field_name).
144 //                   14 (numeric_literal).
145 //       else (if_item):
146 //           list (statement_list):
147 //               = (srec_assignment):
148 //                   x (field_name).
149 //                   15 (numeric_literal).
150 //               = (srec_assignment):
151 //                   x (field_name).
152 //                   16 (numeric_literal).
153 
alloc_if_head(mlr_dsl_cst_t * pcst,mlr_dsl_ast_node_t * pnode,int type_inferencing,int context_flags)154 mlr_dsl_cst_statement_t* alloc_if_head(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pnode,
155 	int type_inferencing, int context_flags)
156 {
157 	if_head_state_t* pstate = mlr_malloc_or_die(sizeof(if_head_state_t));
158 
159 	pstate->pif_chain_statements = sllv_alloc();
160 
161 	for (sllve_t* pe = pnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
162 		// For if and elif:
163 		// * Left subnode is the AST for the boolean expression.
164 		// * Right subnode is a list of statements to be executed if the left evaluates to true.
165 		// For else:
166 		// * Sole subnode is a list of statements to be executed.
167 		mlr_dsl_ast_node_t* pitemnode = pe->pvvalue;
168 		mlr_dsl_ast_node_t* pexprnode = NULL;
169 		mlr_dsl_ast_node_t* plistnode = NULL;
170 		if (pitemnode->pchildren->length == 2) {
171 			pexprnode = pitemnode->pchildren->phead->pvvalue;
172 			plistnode = pitemnode->pchildren->phead->pnext->pvvalue;
173 		} else {
174 			pexprnode = NULL;
175 			plistnode = pitemnode->pchildren->phead->pvvalue;
176 		}
177 
178 		sllv_append(pstate->pif_chain_statements,
179 			alloc_if_item(pcst, pitemnode, pexprnode, plistnode, type_inferencing, context_flags)
180 		);
181 	}
182 
183 	mlr_dsl_cst_block_handler_t* pblock_handler = (context_flags & IN_BREAKABLE)
184 		?  mlr_dsl_cst_handle_statement_block_with_break_continue
185 		: mlr_dsl_cst_handle_statement_block;
186 
187 	return mlr_dsl_cst_statement_valloc_with_block(
188 		pnode,
189 		handle_if_head,
190 		NULL,
191 		pblock_handler,
192 		free_if_head,
193 		pstate);
194 }
195 
alloc_if_item(mlr_dsl_cst_t * pcst,mlr_dsl_ast_node_t * pitemnode,mlr_dsl_ast_node_t * pexprnode,mlr_dsl_ast_node_t * plistnode,int type_inferencing,int context_flags)196 static mlr_dsl_cst_statement_t* alloc_if_item(mlr_dsl_cst_t* pcst,
197 	mlr_dsl_ast_node_t* pitemnode, mlr_dsl_ast_node_t* pexprnode, mlr_dsl_ast_node_t* plistnode,
198 	int type_inferencing, int context_flags)
199 {
200 	if_item_state_t* pstate = mlr_malloc_or_die(sizeof(if_item_state_t));
201 
202 	MLR_INTERNAL_CODING_ERROR_IF(plistnode->subframe_var_count == MD_UNUSED_INDEX);
203 	cst_statement_block_t* pblock = cst_statement_block_alloc(plistnode->subframe_var_count);
204 
205 	for (sllve_t* pe = plistnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
206 		mlr_dsl_ast_node_t* pbody_ast_node = pe->pvvalue;
207 		mlr_dsl_cst_statement_t *pchild_statement = mlr_dsl_cst_alloc_statement(pcst, pbody_ast_node,
208 			type_inferencing, context_flags);
209 		sllv_append(pblock->pstatements, pchild_statement);
210 	}
211 
212 	pstate->pexpression_evaluator = pexprnode != NULL
213 		? rval_evaluator_alloc_from_ast(pexprnode, pcst->pfmgr,
214 			type_inferencing, context_flags) // if-statement or elif-statement
215 		: rval_evaluator_alloc_from_boolean(TRUE); // else-statement
216 
217 	return mlr_dsl_cst_statement_valloc_with_block(
218 		pitemnode,
219 		NULL, // handled by the containing if-head evaluator
220 		pblock,
221 		NULL, // handled by the containing if-head evaluator
222 		free_if_item,
223 		pstate);
224 }
225 
226 // ----------------------------------------------------------------
free_if_head(mlr_dsl_cst_statement_t * pstatement,context_t * pctx)227 static void free_if_head(mlr_dsl_cst_statement_t* pstatement, context_t* pctx) {
228 	if_head_state_t* pstate = pstatement->pvstate;
229 
230 	if (pstate->pif_chain_statements != NULL) {
231 		for (sllve_t* pe = pstate->pif_chain_statements->phead; pe != NULL; pe = pe->pnext)
232 			mlr_dsl_cst_statement_free(pe->pvvalue, pctx);
233 		sllv_free(pstate->pif_chain_statements);
234 	}
235 
236 	free(pstate);
237 }
238 
free_if_item(mlr_dsl_cst_statement_t * pstatement,context_t * _)239 static void free_if_item(mlr_dsl_cst_statement_t* pstatement, context_t* _) {
240 	if_item_state_t* pstate = pstatement->pvstate;
241 
242 	pstate->pexpression_evaluator->pfree_func(pstate->pexpression_evaluator);
243 
244 	free(pstate);
245 }
246 
247 // ----------------------------------------------------------------
handle_if_head(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)248 static void handle_if_head(
249 	mlr_dsl_cst_statement_t* pstatement,
250 	variables_t*             pvars,
251 	cst_outputs_t*           pcst_outputs)
252 {
253 	if_head_state_t* pstate = pstatement->pvstate;
254 
255 	for (sllve_t* pe = pstate->pif_chain_statements->phead; pe != NULL; pe = pe->pnext) {
256 		mlr_dsl_cst_statement_t* pitem_statement = pe->pvvalue;
257 		if_item_state_t* pitem_state = pitem_statement->pvstate;
258 		rval_evaluator_t* pexpression_evaluator = pitem_state->pexpression_evaluator;
259 
260 		mv_t val = pexpression_evaluator->pprocess_func(pexpression_evaluator->pvstate, pvars);
261 		if (mv_is_non_null(&val)) {
262 			mv_set_boolean_strict(&val);
263 			if (val.u.boolv) {
264 				local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
265 				local_stack_subframe_enter(pframe, pitem_statement->pblock->subframe_var_count);
266 
267 				pstatement->pblock_handler(pitem_statement->pblock, pvars, pcst_outputs);
268 
269 				local_stack_subframe_exit(pframe, pitem_statement->pblock->subframe_var_count);
270 				break;
271 			}
272 		}
273 	}
274 }
275 
276 // ================================================================
277 typedef struct _while_state_t {
278 	rval_evaluator_t* pexpression_evaluator;
279 } while_state_t;
280 
281 static mlr_dsl_cst_statement_handler_t handle_while;
282 static mlr_dsl_cst_statement_freer_t free_while;
283 
284 // ----------------------------------------------------------------
alloc_while(mlr_dsl_cst_t * pcst,mlr_dsl_ast_node_t * pnode,int type_inferencing,int context_flags)285 mlr_dsl_cst_statement_t* alloc_while(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pnode,
286 	int type_inferencing, int context_flags)
287 {
288 	while_state_t* pstate = mlr_malloc_or_die(sizeof(while_state_t));
289 
290 	pstate->pexpression_evaluator = NULL;
291 
292 	// Left child node is the AST for the boolean expression.
293 	// Right child node is the list of statements in the body.
294 	mlr_dsl_ast_node_t* pleft  = pnode->pchildren->phead->pvvalue;
295 	mlr_dsl_ast_node_t* pright = pnode->pchildren->phead->pnext->pvvalue;
296 
297 	MLR_INTERNAL_CODING_ERROR_IF(pright->subframe_var_count == MD_UNUSED_INDEX);
298 	cst_statement_block_t* pblock = cst_statement_block_alloc(pright->subframe_var_count);
299 
300 	for (sllve_t* pe = pright->pchildren->phead; pe != NULL; pe = pe->pnext) {
301 		mlr_dsl_ast_node_t* pbody_ast_node = pe->pvvalue;
302 		mlr_dsl_cst_statement_t *pchild_statement = mlr_dsl_cst_alloc_statement(pcst, pbody_ast_node,
303 			type_inferencing, context_flags);
304 		sllv_append(pblock->pstatements, pchild_statement);
305 	}
306 
307 	pstate->pexpression_evaluator = rval_evaluator_alloc_from_ast(
308 		pleft, pcst->pfmgr, type_inferencing, context_flags);
309 
310 	return mlr_dsl_cst_statement_valloc_with_block(
311 		pnode,
312 		handle_while,
313 		pblock,
314 		mlr_dsl_cst_handle_statement_block_with_break_continue,
315 		free_while,
316 		pstate);
317 }
318 
319 // ----------------------------------------------------------------
free_while(mlr_dsl_cst_statement_t * pstatement,context_t * _)320 static void free_while(mlr_dsl_cst_statement_t* pstatement, context_t* _) {
321 	while_state_t* pstate = pstatement->pvstate;
322 
323 	pstate->pexpression_evaluator->pfree_func(pstate->pexpression_evaluator);
324 
325 	free(pstate);
326 }
327 
328 // ----------------------------------------------------------------
handle_while(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)329 static void handle_while(
330 	mlr_dsl_cst_statement_t* pstatement,
331 	variables_t*             pvars,
332 	cst_outputs_t*           pcst_outputs)
333 {
334 	while_state_t* pstate = pstatement->pvstate;
335 
336 	local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
337 	local_stack_subframe_enter(pframe, pstatement->pblock->subframe_var_count);
338 	loop_stack_push(pvars->ploop_stack);
339 
340 	rval_evaluator_t* pexpression_evaluator = pstate->pexpression_evaluator;
341 
342 	while (TRUE) {
343 		mv_t val = pexpression_evaluator->pprocess_func(pexpression_evaluator->pvstate, pvars);
344 		if (mv_is_non_null(&val)) {
345 			mv_set_boolean_strict(&val);
346 			if (val.u.boolv) {
347 				pstatement->pblock_handler(pstatement->pblock, pvars, pcst_outputs);
348 				if (loop_stack_get(pvars->ploop_stack) & LOOP_BROKEN) {
349 					loop_stack_clear(pvars->ploop_stack, LOOP_BROKEN);
350 					break;
351 				} else if (loop_stack_get(pvars->ploop_stack) & LOOP_CONTINUED) {
352 					loop_stack_clear(pvars->ploop_stack, LOOP_CONTINUED);
353 				}
354 			} else {
355 				break;
356 			}
357 		} else {
358 			break;
359 		}
360 	}
361 
362 	loop_stack_pop(pvars->ploop_stack);
363 	local_stack_subframe_exit(pframe, pstatement->pblock->subframe_var_count);
364 }
365 
366 
367 // ================================================================
368 typedef struct _do_while_state_t {
369 	rval_evaluator_t* pexpression_evaluator;
370 } do_while_state_t;
371 
372 static mlr_dsl_cst_statement_handler_t handle_do_while;
373 static mlr_dsl_cst_statement_freer_t free_do_while;
374 
375 // ----------------------------------------------------------------
alloc_do_while(mlr_dsl_cst_t * pcst,mlr_dsl_ast_node_t * pnode,int type_inferencing,int context_flags)376 mlr_dsl_cst_statement_t* alloc_do_while(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pnode,
377 	int type_inferencing, int context_flags)
378 {
379 	do_while_state_t* pstate = mlr_malloc_or_die(sizeof(do_while_state_t));
380 
381 	pstate->pexpression_evaluator = NULL;
382 
383 	// Left child node is the list of statements in the body.
384 	// Right child node is the AST for the boolean expression.
385 	mlr_dsl_ast_node_t* pleft  = pnode->pchildren->phead->pvvalue;
386 	mlr_dsl_ast_node_t* pright = pnode->pchildren->phead->pnext->pvvalue;
387 
388 	MLR_INTERNAL_CODING_ERROR_IF(pleft->subframe_var_count == MD_UNUSED_INDEX);
389 	cst_statement_block_t* pblock = cst_statement_block_alloc(pright->subframe_var_count);
390 
391 	for (sllve_t* pe = pleft->pchildren->phead; pe != NULL; pe = pe->pnext) {
392 		mlr_dsl_ast_node_t* pbody_ast_node = pe->pvvalue;
393 		mlr_dsl_cst_statement_t *pchild_statement = mlr_dsl_cst_alloc_statement(pcst, pbody_ast_node,
394 			type_inferencing, context_flags);
395 		sllv_append(pblock->pstatements, pchild_statement);
396 	}
397 
398 	pstate->pexpression_evaluator = rval_evaluator_alloc_from_ast(
399 		pright, pcst->pfmgr, type_inferencing, context_flags);
400 
401 	return mlr_dsl_cst_statement_valloc_with_block(
402 		pnode,
403 		handle_do_while,
404 		pblock,
405 		mlr_dsl_cst_handle_statement_block_with_break_continue,
406 		free_do_while,
407 		pstate);
408 }
409 
410 // ----------------------------------------------------------------
free_do_while(mlr_dsl_cst_statement_t * pstatement,context_t * _)411 static void free_do_while(mlr_dsl_cst_statement_t* pstatement, context_t* _) {
412 	do_while_state_t* pstate = pstatement->pvstate;
413 
414 	pstate->pexpression_evaluator->pfree_func(pstate->pexpression_evaluator);
415 
416 	free(pstate);
417 }
418 
419 // ----------------------------------------------------------------
handle_do_while(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)420 static void handle_do_while(
421 	mlr_dsl_cst_statement_t* pstatement,
422 	variables_t*             pvars,
423 	cst_outputs_t*           pcst_outputs)
424 {
425 	do_while_state_t* pstate = pstatement->pvstate;
426 
427 	local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
428 	local_stack_subframe_enter(pframe, pstatement->pblock->subframe_var_count);
429 	loop_stack_push(pvars->ploop_stack);
430 
431 	rval_evaluator_t* pexpression_evaluator = pstate->pexpression_evaluator;
432 
433 	while (TRUE) {
434 		pstatement->pblock_handler(pstatement->pblock, pvars, pcst_outputs);
435 		if (loop_stack_get(pvars->ploop_stack) & LOOP_BROKEN) {
436 			loop_stack_clear(pvars->ploop_stack, LOOP_BROKEN);
437 			break;
438 		} else if (loop_stack_get(pvars->ploop_stack) & LOOP_CONTINUED) {
439 			loop_stack_clear(pvars->ploop_stack, LOOP_CONTINUED);
440 			// don't skip the boolean test
441 		}
442 
443 		mv_t val = pexpression_evaluator->pprocess_func(pexpression_evaluator->pvstate, pvars);
444 		if (mv_is_non_null(&val)) {
445 			mv_set_boolean_strict(&val);
446 			if (!val.u.boolv) {
447 				break;
448 			}
449 		} else {
450 			break;
451 		}
452 	}
453 
454 	loop_stack_pop(pvars->ploop_stack);
455 	local_stack_subframe_exit(pframe, pstatement->pblock->subframe_var_count);
456 }
457 
458 // ================================================================
459 typedef struct _bare_boolean_state_t {
460 	rval_evaluator_t* pexpression_evaluator;
461 } bare_boolean_state_t;
462 
463 static mlr_dsl_cst_statement_handler_t handle_bare_boolean;
464 static mlr_dsl_cst_statement_freer_t free_bare_boolean;
465 
466 // ----------------------------------------------------------------
alloc_bare_boolean(mlr_dsl_cst_t * pcst,mlr_dsl_ast_node_t * pnode,int type_inferencing,int context_flags)467 mlr_dsl_cst_statement_t* alloc_bare_boolean(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pnode,
468 	int type_inferencing, int context_flags)
469 {
470 	bare_boolean_state_t* pstate = mlr_malloc_or_die(sizeof(bare_boolean_state_t));
471 
472 	pstate->pexpression_evaluator = NULL;
473 
474 	pstate->pexpression_evaluator = rval_evaluator_alloc_from_ast(
475 		pnode, pcst->pfmgr, type_inferencing, context_flags);
476 
477 	return mlr_dsl_cst_statement_valloc(
478 		pnode,
479 		handle_bare_boolean,
480 		free_bare_boolean,
481 		pstate);
482 }
483 
484 // ----------------------------------------------------------------
free_bare_boolean(mlr_dsl_cst_statement_t * pstatement,context_t * _)485 static void free_bare_boolean(mlr_dsl_cst_statement_t* pstatement, context_t* _) {
486 	bare_boolean_state_t* pstate = pstatement->pvstate;
487 
488 	pstate->pexpression_evaluator->pfree_func(pstate->pexpression_evaluator);
489 
490 	free(pstate);
491 }
492 
493 // ----------------------------------------------------------------
handle_bare_boolean(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)494 static void handle_bare_boolean(
495 	mlr_dsl_cst_statement_t* pstatement,
496 	variables_t*             pvars,
497 	cst_outputs_t*           pcst_outputs)
498 {
499 	bare_boolean_state_t* pstate = pstatement->pvstate;
500 	rval_evaluator_t* pexpression_evaluator = pstate->pexpression_evaluator;
501 
502 	mv_t val = pexpression_evaluator->pprocess_func(pexpression_evaluator->pvstate, pvars);
503 	if (mv_is_non_null(&val))
504 		mv_set_boolean_strict(&val);
505 }
506 
507 // ================================================================
508 typedef struct _filter_state_t {
509 	rval_evaluator_t* pexpression_evaluator;
510 } filter_state_t;
511 
512 static mlr_dsl_cst_statement_handler_t handle_filter;
513 static mlr_dsl_cst_statement_freer_t free_filter;
514 
515 // ----------------------------------------------------------------
alloc_filter(mlr_dsl_cst_t * pcst,mlr_dsl_ast_node_t * pnode,int type_inferencing,int context_flags)516 mlr_dsl_cst_statement_t* alloc_filter(
517 	mlr_dsl_cst_t*      pcst,
518 	mlr_dsl_ast_node_t* pnode,
519 	int                 type_inferencing,
520 	int                 context_flags)
521 {
522 	filter_state_t* pstate = mlr_malloc_or_die(sizeof(filter_state_t));
523 
524 	mlr_dsl_ast_node_t* pchild = pnode->pchildren->phead->pvvalue;
525 
526 	pstate->pexpression_evaluator = rval_evaluator_alloc_from_ast(
527 		pchild, pcst->pfmgr, type_inferencing, context_flags);
528 
529 	return mlr_dsl_cst_statement_valloc(
530 		pnode,
531 		handle_filter,
532 		free_filter,
533 		pstate);
534 }
535 
536 // ----------------------------------------------------------------
free_filter(mlr_dsl_cst_statement_t * pstatement,context_t * _)537 static void free_filter(mlr_dsl_cst_statement_t* pstatement, context_t* _) {
538 	filter_state_t* pstate = pstatement->pvstate;
539 
540 	pstate->pexpression_evaluator->pfree_func(pstate->pexpression_evaluator);
541 
542 	free(pstate);
543 }
544 
545 // ----------------------------------------------------------------
handle_filter(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)546 static void handle_filter(
547 	mlr_dsl_cst_statement_t* pstatement,
548 	variables_t*             pvars,
549 	cst_outputs_t*           pcst_outputs)
550 {
551 	filter_state_t* pstate = pstatement->pvstate;
552 	rval_evaluator_t* pexpression_evaluator = pstate->pexpression_evaluator;
553 
554 	mv_t val = pexpression_evaluator->pprocess_func(pexpression_evaluator->pvstate, pvars);
555 
556 	if (mv_is_non_null(&val)) {
557 		mv_set_boolean_strict(&val);
558 		*pcst_outputs->pshould_emit_rec = val.u.boolv;
559 	} else {
560 		*pcst_outputs->pshould_emit_rec = FALSE;
561 	}
562 }
563 
564 // ================================================================
565 typedef struct _final_filter_state_t {
566 	rval_evaluator_t* pexpression_evaluator;
567 	int               negate_final_filter;
568 } final_filter_state_t;
569 
570 static mlr_dsl_cst_statement_handler_t handle_final_filter;
571 static mlr_dsl_cst_statement_freer_t free_final_filter;
572 
573 // ----------------------------------------------------------------
alloc_final_filter(mlr_dsl_cst_t * pcst,mlr_dsl_ast_node_t * pnode,int negate_final_filter,int type_inferencing,int context_flags)574 mlr_dsl_cst_statement_t* alloc_final_filter(
575 	mlr_dsl_cst_t*      pcst,
576 	mlr_dsl_ast_node_t* pnode,
577 	int                 negate_final_filter,
578 	int                 type_inferencing,
579 	int                 context_flags)
580 {
581 	final_filter_state_t* pstate = mlr_malloc_or_die(sizeof(final_filter_state_t));
582 
583 	pstate->pexpression_evaluator = rval_evaluator_alloc_from_ast(
584 		pnode, pcst->pfmgr, type_inferencing, context_flags);
585 
586 	pstate->negate_final_filter = negate_final_filter;
587 
588 	return mlr_dsl_cst_statement_valloc(
589 		pnode,
590 		handle_final_filter,
591 		free_final_filter,
592 		pstate);
593 }
594 
595 // ----------------------------------------------------------------
free_final_filter(mlr_dsl_cst_statement_t * pstatement,context_t * _)596 static void free_final_filter(mlr_dsl_cst_statement_t* pstatement, context_t* _) {
597 	final_filter_state_t* pstate = pstatement->pvstate;
598 
599 	pstate->pexpression_evaluator->pfree_func(pstate->pexpression_evaluator);
600 
601 	free(pstate);
602 }
603 
604 // ----------------------------------------------------------------
handle_final_filter(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)605 static void handle_final_filter(
606 	mlr_dsl_cst_statement_t* pstatement,
607 	variables_t*             pvars,
608 	cst_outputs_t*           pcst_outputs)
609 {
610 	final_filter_state_t* pstate = pstatement->pvstate;
611 	rval_evaluator_t* pexpression_evaluator = pstate->pexpression_evaluator;
612 
613 	mv_t val = pexpression_evaluator->pprocess_func(pexpression_evaluator->pvstate, pvars);
614 
615 	if (mv_is_non_null(&val)) {
616 		mv_set_boolean_strict(&val);
617 		*pcst_outputs->pshould_emit_rec = val.u.boolv ^ pstate->negate_final_filter;
618 	} else {
619 		*pcst_outputs->pshould_emit_rec = FALSE;
620 	}
621 }
622