mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-30 03:01:39 +00:00
589 lines
19 KiB
C
589 lines
19 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#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;
|
|
}
|