"Fossies" - the Fresh Open Source Software Archive

Member "mlr-5.6.2/c/dsl/mlr_dsl_cst_condish_statements.c" (25 Aug 2019, 21076 Bytes) of package /linux/misc/mlr-5.6.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "mlr_dsl_cst_condish_statements.c" see the Fossies "Dox" file reference documentation.

    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 // ----------------------------------------------------------------
   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 // ----------------------------------------------------------------
   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 // ----------------------------------------------------------------
   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 
  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 
  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 // ----------------------------------------------------------------
  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 
  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 // ----------------------------------------------------------------
  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 // ----------------------------------------------------------------
  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 // ----------------------------------------------------------------
  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 // ----------------------------------------------------------------
  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 // ----------------------------------------------------------------
  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 // ----------------------------------------------------------------
  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 // ----------------------------------------------------------------
  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 // ----------------------------------------------------------------
  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 // ----------------------------------------------------------------
  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 // ----------------------------------------------------------------
  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 // ----------------------------------------------------------------
  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 // ----------------------------------------------------------------
  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 // ----------------------------------------------------------------
  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 // ----------------------------------------------------------------
  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 // ----------------------------------------------------------------
  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 // ----------------------------------------------------------------
  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 }