#include #include #include #include "lib/mlr_globals.h" #include "lib/mlrutil.h" #include "lib/mlrregex.h" #include "lib/mtrand.h" #include "mapping/mapper.h" #include "dsl/context_flags.h" #include "dsl/rxval_evaluators.h" // ---------------------------------------------------------------- typedef struct _rxval_evaluator_variadic_state_t { xv_variadic_func_t* pfunc; rxval_evaluator_t** pargs; boxed_xval_t* pbxvals; int nargs; } rxval_evaluator_variadic_state_t; static boxed_xval_t rxval_evaluator_variadic_func(void* pvstate, variables_t* pvars) { rxval_evaluator_variadic_state_t* pstate = pvstate; int nargs = pstate->nargs; for (int i = 0; i < nargs; i++) { rxval_evaluator_t* parg = pstate->pargs[i]; boxed_xval_t* pbxval = &pstate->pbxvals[i]; *pbxval = parg->pprocess_func(parg->pvstate, pvars); } boxed_xval_t bxrv = pstate->pfunc(pstate->pbxvals, nargs); for (int i = 0; i < nargs; i++) { boxed_xval_t* pbxval = &pstate->pbxvals[i]; if (pbxval->is_ephemeral) { mlhmmv_xvalue_free(&pbxval->xval); } } return bxrv; } static void rxval_evaluator_variadic_free(rxval_evaluator_t* pxevaluator) { rxval_evaluator_variadic_state_t* pstate = pxevaluator->pvstate; for (int i = 0; i < pstate->nargs; i++) pstate->pargs[i]->pfree_func(pstate->pargs[i]); free(pstate->pargs); for (int i = 0; i < pstate->nargs; i++) { if (pstate->pbxvals[i].is_ephemeral) { mlhmmv_xvalue_free(&pstate->pbxvals[i].xval); } } free(pstate->pbxvals); free(pstate); free(pxevaluator); } rxval_evaluator_t* rxval_evaluator_alloc_from_variadic_func( xv_variadic_func_t* pfunc, sllv_t* parg_nodes, fmgr_t* pfmgr, int type_inferencing, int context_flags) { rxval_evaluator_variadic_state_t* pstate = mlr_malloc_or_die(sizeof(rxval_evaluator_variadic_state_t)); pstate->pfunc = pfunc; int nargs = parg_nodes->length; rxval_evaluator_t** pargs = mlr_malloc_or_die(nargs * sizeof(rxval_evaluator_t*)); int i = 0; for (sllve_t* pe = parg_nodes->phead; pe != NULL; pe = pe->pnext, i++) { mlr_dsl_ast_node_t* pnode = pe->pvvalue; pargs[i] = rxval_evaluator_alloc_from_ast(pnode, pfmgr, type_inferencing, context_flags); } pstate->pargs = pargs; pstate->nargs = nargs; pstate->pbxvals = mlr_malloc_or_die(nargs * sizeof(boxed_xval_t)); rxval_evaluator_t* pxevaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t)); pxevaluator->pvstate = pstate; pxevaluator->pprocess_func = rxval_evaluator_variadic_func; pxevaluator->pfree_func = rxval_evaluator_variadic_free; return pxevaluator; } // ---------------------------------------------------------------- typedef struct _rxval_evaluator_x_x_state_t { xv_unary_func_t* pfunc; rxval_evaluator_t* parg1; } rxval_evaluator_x_x_state_t; static boxed_xval_t rxval_evaluator_x_x_func(void* pvstate, variables_t* pvars) { rxval_evaluator_x_x_state_t* pstate = pvstate; boxed_xval_t bxval1 = pstate->parg1->pprocess_func(pstate->parg1->pvstate, pvars); boxed_xval_t bxrv = pstate->pfunc(&bxval1); if (bxval1.is_ephemeral) { mlhmmv_xvalue_free(&bxval1.xval); } return bxrv; } static void rxval_evaluator_x_x_free(rxval_evaluator_t* pxevaluator) { rxval_evaluator_x_x_state_t* pstate = pxevaluator->pvstate; pstate->parg1->pfree_func(pstate->parg1); free(pstate); free(pxevaluator); } rxval_evaluator_t* rxval_evaluator_alloc_from_x_x_func( xv_unary_func_t* pfunc, mlr_dsl_ast_node_t* parg1_node, fmgr_t* pfmgr, int type_inferencing, int context_flags) { rxval_evaluator_x_x_state_t* pstate = mlr_malloc_or_die(sizeof(rxval_evaluator_x_x_state_t)); pstate->pfunc = pfunc; pstate->parg1 = rxval_evaluator_alloc_from_ast(parg1_node, pfmgr, type_inferencing, context_flags); rxval_evaluator_t* pxevaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t)); pxevaluator->pvstate = pstate; pxevaluator->pprocess_func = rxval_evaluator_x_x_func; pxevaluator->pfree_func = rxval_evaluator_x_x_free; return pxevaluator; } // ---------------------------------------------------------------- typedef struct _rxval_evaluator_x_m_state_t { xv_unary_func_t* pfunc; rxval_evaluator_t* parg1; } rxval_evaluator_x_m_state_t; static boxed_xval_t rxval_evaluator_x_m_func(void* pvstate, variables_t* pvars) { rxval_evaluator_x_m_state_t* pstate = pvstate; boxed_xval_t bxval1 = pstate->parg1->pprocess_func(pstate->parg1->pvstate, pvars); if (bxval1.xval.is_terminal) { return box_ephemeral_val(mv_error()); } boxed_xval_t bxrv = pstate->pfunc(&bxval1); if (bxval1.is_ephemeral) { mlhmmv_xvalue_free(&bxval1.xval); } return bxrv; } static void rxval_evaluator_x_m_free(rxval_evaluator_t* pxevaluator) { rxval_evaluator_x_m_state_t* pstate = pxevaluator->pvstate; pstate->parg1->pfree_func(pstate->parg1); free(pstate); free(pxevaluator); } rxval_evaluator_t* rxval_evaluator_alloc_from_x_m_func( xv_unary_func_t* pfunc, mlr_dsl_ast_node_t* parg1_node, fmgr_t* pfmgr, int type_inferencing, int context_flags) { rxval_evaluator_x_m_state_t* pstate = mlr_malloc_or_die(sizeof(rxval_evaluator_x_m_state_t)); pstate->pfunc = pfunc; pstate->parg1 = rxval_evaluator_alloc_from_ast(parg1_node, pfmgr, type_inferencing, context_flags); rxval_evaluator_t* pxevaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t)); pxevaluator->pvstate = pstate; pxevaluator->pprocess_func = rxval_evaluator_x_m_func; pxevaluator->pfree_func = rxval_evaluator_x_m_free; return pxevaluator; } // ---------------------------------------------------------------- typedef struct _rxval_evaluator_x_mx_state_t { xv_binary_func_t* pfunc; rxval_evaluator_t* parg1; rxval_evaluator_t* parg2; } rxval_evaluator_x_mx_state_t; static boxed_xval_t rxval_evaluator_x_mx_func(void* pvstate, variables_t* pvars) { rxval_evaluator_x_mx_state_t* pstate = pvstate; boxed_xval_t bxval1 = pstate->parg1->pprocess_func(pstate->parg1->pvstate, pvars); boxed_xval_t bxval2 = pstate->parg2->pprocess_func(pstate->parg2->pvstate, pvars); if (bxval1.xval.is_terminal) { return box_ephemeral_val(mv_error()); } if (!bxval2.xval.is_terminal) { return box_ephemeral_val(mv_error()); } boxed_xval_t bxrv = pstate->pfunc(&bxval1, &bxval2); if (bxval1.is_ephemeral) { mlhmmv_xvalue_free(&bxval1.xval); } if (bxval2.is_ephemeral) { mlhmmv_xvalue_free(&bxval2.xval); } return bxrv; } static void rxval_evaluator_x_mx_free(rxval_evaluator_t* pxevaluator) { rxval_evaluator_x_mx_state_t* pstate = pxevaluator->pvstate; pstate->parg1->pfree_func(pstate->parg1); pstate->parg2->pfree_func(pstate->parg2); free(pstate); free(pxevaluator); } rxval_evaluator_t* rxval_evaluator_alloc_from_x_mx_func( xv_binary_func_t* pfunc, mlr_dsl_ast_node_t* parg1_node, mlr_dsl_ast_node_t* parg2_node, fmgr_t* pfmgr, int type_inferencing, int context_flags) { rxval_evaluator_x_mx_state_t* pstate = mlr_malloc_or_die(sizeof(rxval_evaluator_x_mx_state_t)); pstate->pfunc = pfunc; pstate->parg1 = rxval_evaluator_alloc_from_ast(parg1_node, pfmgr, type_inferencing, context_flags); pstate->parg2 = rxval_evaluator_alloc_from_ast(parg2_node, pfmgr, type_inferencing, context_flags); rxval_evaluator_t* pxevaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t)); pxevaluator->pvstate = pstate; pxevaluator->pprocess_func = rxval_evaluator_x_mx_func; pxevaluator->pfree_func = rxval_evaluator_x_mx_free; return pxevaluator; } // ---------------------------------------------------------------- typedef struct _rxval_evaluator_x_ms_state_t { xv_binary_func_t* pfunc; rxval_evaluator_t* parg1; rxval_evaluator_t* parg2; } rxval_evaluator_x_ms_state_t; static boxed_xval_t rxval_evaluator_x_ms_func(void* pvstate, variables_t* pvars) { rxval_evaluator_x_ms_state_t* pstate = pvstate; boxed_xval_t bxval1 = pstate->parg1->pprocess_func(pstate->parg1->pvstate, pvars); boxed_xval_t bxval2 = pstate->parg2->pprocess_func(pstate->parg2->pvstate, pvars); if (bxval1.xval.is_terminal) { return box_ephemeral_val(mv_error()); } if (!bxval2.xval.is_terminal) { return box_ephemeral_val(mv_error()); } if (!mv_is_string_or_empty(&bxval2.xval.terminal_mlrval)) { mv_free(&bxval2.xval.terminal_mlrval); return box_ephemeral_val(mv_error()); } boxed_xval_t bxrv = pstate->pfunc(&bxval1, &bxval2); if (bxval1.is_ephemeral) { mlhmmv_xvalue_free(&bxval1.xval); } if (bxval2.is_ephemeral) { mlhmmv_xvalue_free(&bxval2.xval); } return bxrv; } static void rxval_evaluator_x_ms_free(rxval_evaluator_t* pxevaluator) { rxval_evaluator_x_ms_state_t* pstate = pxevaluator->pvstate; pstate->parg1->pfree_func(pstate->parg1); pstate->parg2->pfree_func(pstate->parg2); free(pstate); free(pxevaluator); } rxval_evaluator_t* rxval_evaluator_alloc_from_x_ms_func( xv_binary_func_t* pfunc, mlr_dsl_ast_node_t* parg1_node, mlr_dsl_ast_node_t* parg2_node, fmgr_t* pfmgr, int type_inferencing, int context_flags) { rxval_evaluator_x_ms_state_t* pstate = mlr_malloc_or_die(sizeof(rxval_evaluator_x_ms_state_t)); pstate->pfunc = pfunc; pstate->parg1 = rxval_evaluator_alloc_from_ast(parg1_node, pfmgr, type_inferencing, context_flags); pstate->parg2 = rxval_evaluator_alloc_from_ast(parg2_node, pfmgr, type_inferencing, context_flags); rxval_evaluator_t* pxevaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t)); pxevaluator->pvstate = pstate; pxevaluator->pprocess_func = rxval_evaluator_x_ms_func; pxevaluator->pfree_func = rxval_evaluator_x_ms_free; return pxevaluator; } // ---------------------------------------------------------------- typedef struct _rxval_evaluator_x_ss_state_t { xv_binary_func_t* pfunc; rxval_evaluator_t* parg1; rxval_evaluator_t* parg2; } rxval_evaluator_x_ss_state_t; static boxed_xval_t rxval_evaluator_x_ss_func(void* pvstate, variables_t* pvars) { rxval_evaluator_x_ss_state_t* pstate = pvstate; boxed_xval_t bxval1 = pstate->parg1->pprocess_func(pstate->parg1->pvstate, pvars); boxed_xval_t bxval2 = pstate->parg2->pprocess_func(pstate->parg2->pvstate, pvars); if (!bxval1.xval.is_terminal) { mv_free(&bxval1.xval.terminal_mlrval); return box_ephemeral_val(mv_error()); } if (!mv_is_string_or_empty(&bxval1.xval.terminal_mlrval)) { mv_free(&bxval1.xval.terminal_mlrval); return box_ephemeral_val(mv_error()); } if (!bxval2.xval.is_terminal) { mv_free(&bxval2.xval.terminal_mlrval); return box_ephemeral_val(mv_error()); } if (!mv_is_string_or_empty(&bxval2.xval.terminal_mlrval)) { mv_free(&bxval2.xval.terminal_mlrval); return box_ephemeral_val(mv_error()); } boxed_xval_t bxrv = pstate->pfunc(&bxval1, &bxval2); if (bxval1.is_ephemeral) { mlhmmv_xvalue_free(&bxval1.xval); } if (bxval2.is_ephemeral) { mlhmmv_xvalue_free(&bxval2.xval); } return bxrv; } static void rxval_evaluator_x_ss_free(rxval_evaluator_t* pxevaluator) { rxval_evaluator_x_ss_state_t* pstate = pxevaluator->pvstate; pstate->parg1->pfree_func(pstate->parg1); pstate->parg2->pfree_func(pstate->parg2); free(pstate); free(pxevaluator); } rxval_evaluator_t* rxval_evaluator_alloc_from_x_ss_func( xv_binary_func_t* pfunc, mlr_dsl_ast_node_t* parg1_node, mlr_dsl_ast_node_t* parg2_node, fmgr_t* pfmgr, int type_inferencing, int context_flags) { rxval_evaluator_x_ss_state_t* pstate = mlr_malloc_or_die(sizeof(rxval_evaluator_x_ss_state_t)); pstate->pfunc = pfunc; pstate->parg1 = rxval_evaluator_alloc_from_ast(parg1_node, pfmgr, type_inferencing, context_flags); pstate->parg2 = rxval_evaluator_alloc_from_ast(parg2_node, pfmgr, type_inferencing, context_flags); rxval_evaluator_t* pxevaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t)); pxevaluator->pvstate = pstate; pxevaluator->pprocess_func = rxval_evaluator_x_ss_func; pxevaluator->pfree_func = rxval_evaluator_x_ss_free; return pxevaluator; } // ---------------------------------------------------------------- typedef struct _rxval_evaluator_x_mss_state_t { xv_ternary_func_t* pfunc; rxval_evaluator_t* parg1; rxval_evaluator_t* parg2; rxval_evaluator_t* parg3; } rxval_evaluator_x_mss_state_t; static boxed_xval_t rxval_evaluator_x_mss_func(void* pvstate, variables_t* pvars) { rxval_evaluator_x_mss_state_t* pstate = pvstate; boxed_xval_t bxval1 = pstate->parg1->pprocess_func(pstate->parg1->pvstate, pvars); boxed_xval_t bxval2 = pstate->parg2->pprocess_func(pstate->parg2->pvstate, pvars); boxed_xval_t bxval3 = pstate->parg3->pprocess_func(pstate->parg3->pvstate, pvars); if (bxval1.xval.is_terminal) { return box_ephemeral_val(mv_error()); } if (!bxval2.xval.is_terminal) { return box_ephemeral_val(mv_error()); } if (!mv_is_string_or_empty(&bxval2.xval.terminal_mlrval)) { mv_free(&bxval2.xval.terminal_mlrval); return box_ephemeral_val(mv_error()); } if (!bxval3.xval.is_terminal) { return box_ephemeral_val(mv_error()); } if (!mv_is_string_or_empty(&bxval3.xval.terminal_mlrval)) { mv_free(&bxval3.xval.terminal_mlrval); return box_ephemeral_val(mv_error()); } boxed_xval_t bxrv = pstate->pfunc(&bxval1, &bxval2, &bxval3); if (bxval1.is_ephemeral) { mlhmmv_xvalue_free(&bxval1.xval); } if (bxval2.is_ephemeral) { mlhmmv_xvalue_free(&bxval2.xval); } return bxrv; } static void rxval_evaluator_x_mss_free(rxval_evaluator_t* pxevaluator) { rxval_evaluator_x_mss_state_t* pstate = pxevaluator->pvstate; pstate->parg1->pfree_func(pstate->parg1); pstate->parg2->pfree_func(pstate->parg2); pstate->parg3->pfree_func(pstate->parg3); free(pstate); free(pxevaluator); } rxval_evaluator_t* rxval_evaluator_alloc_from_x_mss_func( xv_ternary_func_t* pfunc, mlr_dsl_ast_node_t* parg1_node, mlr_dsl_ast_node_t* parg2_node, mlr_dsl_ast_node_t* parg3_node, fmgr_t* pfmgr, int type_inferencing, int context_flags) { rxval_evaluator_x_mss_state_t* pstate = mlr_malloc_or_die(sizeof(rxval_evaluator_x_mss_state_t)); pstate->pfunc = pfunc; pstate->parg1 = rxval_evaluator_alloc_from_ast(parg1_node, pfmgr, type_inferencing, context_flags); pstate->parg2 = rxval_evaluator_alloc_from_ast(parg2_node, pfmgr, type_inferencing, context_flags); pstate->parg3 = rxval_evaluator_alloc_from_ast(parg3_node, pfmgr, type_inferencing, context_flags); rxval_evaluator_t* pxevaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t)); pxevaluator->pvstate = pstate; pxevaluator->pprocess_func = rxval_evaluator_x_mss_func; pxevaluator->pfree_func = rxval_evaluator_x_mss_free; return pxevaluator; } // ---------------------------------------------------------------- typedef struct _rxval_evaluator_x_sss_state_t { xv_ternary_func_t* pfunc; rxval_evaluator_t* parg1; rxval_evaluator_t* parg2; rxval_evaluator_t* parg3; } rxval_evaluator_x_sss_state_t; static boxed_xval_t rxval_evaluator_x_sss_func(void* pvstate, variables_t* pvars) { rxval_evaluator_x_sss_state_t* pstate = pvstate; boxed_xval_t bxval1 = pstate->parg1->pprocess_func(pstate->parg1->pvstate, pvars); boxed_xval_t bxval2 = pstate->parg2->pprocess_func(pstate->parg2->pvstate, pvars); boxed_xval_t bxval3 = pstate->parg3->pprocess_func(pstate->parg3->pvstate, pvars); if (!bxval1.xval.is_terminal) { return box_ephemeral_val(mv_error()); } if (!mv_is_string_or_empty(&bxval1.xval.terminal_mlrval)) { mv_free(&bxval1.xval.terminal_mlrval); return box_ephemeral_val(mv_error()); } if (!bxval2.xval.is_terminal) { return box_ephemeral_val(mv_error()); } if (!mv_is_string_or_empty(&bxval2.xval.terminal_mlrval)) { mv_free(&bxval2.xval.terminal_mlrval); return box_ephemeral_val(mv_error()); } if (!bxval3.xval.is_terminal) { return box_ephemeral_val(mv_error()); } if (!mv_is_string_or_empty(&bxval3.xval.terminal_mlrval)) { mv_free(&bxval3.xval.terminal_mlrval); return box_ephemeral_val(mv_error()); } boxed_xval_t bxrv = pstate->pfunc(&bxval1, &bxval2, &bxval3); if (bxval1.is_ephemeral) { mlhmmv_xvalue_free(&bxval1.xval); } if (bxval2.is_ephemeral) { mlhmmv_xvalue_free(&bxval2.xval); } if (bxval3.is_ephemeral) { mlhmmv_xvalue_free(&bxval3.xval); } return bxrv; } static void rxval_evaluator_x_sss_free(rxval_evaluator_t* pxevaluator) { rxval_evaluator_x_sss_state_t* pstate = pxevaluator->pvstate; pstate->parg1->pfree_func(pstate->parg1); pstate->parg2->pfree_func(pstate->parg2); pstate->parg3->pfree_func(pstate->parg3); free(pstate); free(pxevaluator); } rxval_evaluator_t* rxval_evaluator_alloc_from_x_sss_func( xv_ternary_func_t* pfunc, mlr_dsl_ast_node_t* parg1_node, mlr_dsl_ast_node_t* parg2_node, mlr_dsl_ast_node_t* parg3_node, fmgr_t* pfmgr, int type_inferencing, int context_flags) { rxval_evaluator_x_sss_state_t* pstate = mlr_malloc_or_die(sizeof(rxval_evaluator_x_sss_state_t)); pstate->pfunc = pfunc; pstate->parg1 = rxval_evaluator_alloc_from_ast(parg1_node, pfmgr, type_inferencing, context_flags); pstate->parg2 = rxval_evaluator_alloc_from_ast(parg2_node, pfmgr, type_inferencing, context_flags); pstate->parg3 = rxval_evaluator_alloc_from_ast(parg3_node, pfmgr, type_inferencing, context_flags); rxval_evaluator_t* pxevaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t)); pxevaluator->pvstate = pstate; pxevaluator->pprocess_func = rxval_evaluator_x_sss_func; pxevaluator->pfree_func = rxval_evaluator_x_sss_free; return pxevaluator; } // ---------------------------------------------------------------- // Does type-check assertion on the argument and returns it unmodified if the // test passes. Else throws an error. typedef struct _rxval_evaluator_A_x_state_t { xv_unary_func_t* pfunc; rxval_evaluator_t* parg1; char* desc; } rxval_evaluator_A_x_state_t; static boxed_xval_t rxval_evaluator_A_x_func(void* pvstate, variables_t* pvars) { rxval_evaluator_A_x_state_t* pstate = pvstate; boxed_xval_t val1 = pstate->parg1->pprocess_func(pstate->parg1->pvstate, pvars); boxed_xval_t ok = pstate->pfunc(&val1); if (!ok.xval.terminal_mlrval.u.boolv) { fprintf(stderr, "%s: %s type-assertion failed at NR=%lld FNR=%lld FILENAME=%s\n", MLR_GLOBALS.bargv0, pstate->desc, pvars->pctx->nr, pvars->pctx->fnr, pvars->pctx->filename); exit(1); } return val1; } static void rxval_evaluator_A_x_free(rxval_evaluator_t* pevaluator) { rxval_evaluator_A_x_state_t* pstate = pevaluator->pvstate; pstate->parg1->pfree_func(pstate->parg1); free(pstate->desc); free(pstate); free(pevaluator); } rxval_evaluator_t* rxval_evaluator_alloc_from_A_x_func( xv_unary_func_t* pfunc, mlr_dsl_ast_node_t* parg1_node, fmgr_t* pfmgr, int type_inferencing, int context_flags, char* desc) { rxval_evaluator_A_x_state_t* pstate = mlr_malloc_or_die(sizeof(rxval_evaluator_A_x_state_t)); pstate->pfunc = pfunc; pstate->parg1 = rxval_evaluator_alloc_from_ast(parg1_node, pfmgr, type_inferencing, context_flags); pstate->desc = mlr_strdup_or_die(desc); rxval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t)); pevaluator->pvstate = pstate; pevaluator->pprocess_func = rxval_evaluator_A_x_func; pevaluator->pfree_func = rxval_evaluator_A_x_free; return pevaluator; }