mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-21 10:29:02 +00:00
530 lines
20 KiB
C
530 lines
20 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <ctype.h> // for tolower(), toupper()
|
|
#include "lib/mlr_globals.h"
|
|
#include "lib/mlrutil.h"
|
|
#include "lib/mlrregex.h"
|
|
#include "lib/mtrand.h"
|
|
#include "mapping/mapper.h"
|
|
#include "mapping/rval_evaluators.h"
|
|
#include "mapping/function_manager.h"
|
|
#include "mapping/mlr_dsl_cst.h" // xxx only for allocate_keylist_evaluators_from_ast_node -- xxx move
|
|
#include "mapping/context_flags.h"
|
|
|
|
// ================================================================
|
|
// See comments in rval_evaluators.h
|
|
// ================================================================
|
|
|
|
// ----------------------------------------------------------------
|
|
rxval_evaluator_t* rxval_evaluator_alloc_from_ast(mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr,
|
|
int type_inferencing, int context_flags)
|
|
{
|
|
switch(pnode->type) {
|
|
|
|
case MD_AST_NODE_TYPE_NONINDEXED_LOCAL_VARIABLE:
|
|
return rxval_evaluator_alloc_from_nonindexed_local_variable(
|
|
pnode, pfmgr, type_inferencing, context_flags);
|
|
return NULL;
|
|
break;
|
|
|
|
case MD_AST_NODE_TYPE_INDEXED_LOCAL_VARIABLE:
|
|
return rxval_evaluator_alloc_from_indexed_local_variable(
|
|
pnode, pfmgr, type_inferencing, context_flags);
|
|
break;
|
|
|
|
case MD_AST_NODE_TYPE_OOSVAR_KEYLIST:
|
|
return rxval_evaluator_alloc_from_oosvar_keylist(
|
|
pnode, pfmgr, type_inferencing, context_flags);
|
|
break;
|
|
|
|
case MD_AST_NODE_TYPE_FULL_OOSVAR:
|
|
return rxval_evaluator_alloc_from_full_oosvar(
|
|
pnode, pfmgr, type_inferencing, context_flags);
|
|
return NULL;
|
|
break;
|
|
|
|
case MD_AST_NODE_TYPE_FULL_SREC:
|
|
return rxval_evaluator_alloc_from_full_srec(
|
|
pnode, pfmgr, type_inferencing, context_flags);
|
|
return NULL;
|
|
break;
|
|
|
|
case MD_AST_NODE_TYPE_FUNCTION_CALLSITE:
|
|
// xxx XXX to do
|
|
//return rxval_evaluator_alloc_from_function_callsite(
|
|
//pnode, pfmgr, type_inferencing, context_flags);
|
|
return rxval_evaluator_alloc_wrapping_rval(pnode, pfmgr, type_inferencing, context_flags);
|
|
break;
|
|
|
|
case MD_AST_NODE_TYPE_MAP_LITERAL:
|
|
return rxval_evaluator_alloc_from_map_literal(
|
|
pnode, pfmgr, type_inferencing, context_flags);
|
|
return NULL;
|
|
break;
|
|
|
|
default:
|
|
return rxval_evaluator_alloc_wrapping_rval(pnode, pfmgr, type_inferencing, context_flags);
|
|
return NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// ================================================================
|
|
// Map-literal input:
|
|
//
|
|
// {
|
|
// "a" : 1,
|
|
// "b" : {
|
|
// "x" : 7,
|
|
// "y" : 8,
|
|
// },
|
|
// "c" : 3,
|
|
// }
|
|
//
|
|
// Map-literal AST:
|
|
//
|
|
// $ mlr --from s put -v -q 'm={"a":NR,"b":{"x":999},"c":3};dump m'
|
|
// text="block", type=STATEMENT_BLOCK:
|
|
// text="=", type=NONINDEXED_LOCAL_ASSIGNMENT:
|
|
// text="m", type=NONINDEXED_LOCAL_VARIABLE.
|
|
// text="map_literal", type=MAP_LITERAL:
|
|
// text="mappair", type=MAP_LITERAL_PAIR:
|
|
// text="mapkey", type=MAP_LITERAL:
|
|
// text="a", type=STRING_LITERAL.
|
|
// text="mapval", type=MAP_LITERAL:
|
|
// text="NR", type=CONTEXT_VARIABLE.
|
|
// text="mappair", type=MAP_LITERAL_PAIR:
|
|
// text="mapkey", type=MAP_LITERAL:
|
|
// text="b", type=STRING_LITERAL.
|
|
// text="mapval", type=MAP_LITERAL:
|
|
// text="map_literal", type=MAP_LITERAL:
|
|
// text="mappair", type=MAP_LITERAL_PAIR:
|
|
// text="mapkey", type=MAP_LITERAL:
|
|
// text="x", type=STRING_LITERAL.
|
|
// text="mapval", type=MAP_LITERAL:
|
|
// text="999", type=NUMERIC_LITERAL.
|
|
// text="mappair", type=MAP_LITERAL_PAIR:
|
|
// text="mapkey", type=MAP_LITERAL:
|
|
// text="c", type=STRING_LITERAL.
|
|
// text="mapval", type=MAP_LITERAL:
|
|
// text="3", type=NUMERIC_LITERAL.
|
|
// text="dump", type=DUMP:
|
|
// text=">", type=FILE_WRITE:
|
|
// text="stdout", type=STDOUT:
|
|
// text="m", type=NONINDEXED_LOCAL_VARIABLE.
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
typedef struct _map_literal_list_evaluator_t {
|
|
sllv_t* pkvpair_evaluators;
|
|
} map_literal_list_evaluator_t;
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
typedef struct _map_literal_kvpair_evaluator_t {
|
|
rval_evaluator_t* pkey_evaluator;
|
|
int is_terminal;
|
|
rxval_evaluator_t* pxval_evaluator;
|
|
map_literal_list_evaluator_t* plist_evaluator;
|
|
} map_literal_kvpair_evaluator_t;
|
|
|
|
// ----------------------------------------------------------------
|
|
static map_literal_list_evaluator_t* allocate_map_literal_evaluator_from_ast(
|
|
mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags)
|
|
{
|
|
map_literal_list_evaluator_t* plist_evaluator = mlr_malloc_or_die(sizeof(map_literal_list_evaluator_t));
|
|
plist_evaluator->pkvpair_evaluators = sllv_alloc();
|
|
MLR_INTERNAL_CODING_ERROR_IF(pnode->type != MD_AST_NODE_TYPE_MAP_LITERAL);
|
|
for (sllve_t* pe = pnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
|
|
|
|
map_literal_kvpair_evaluator_t* pkvpair = mlr_malloc_or_die(sizeof(map_literal_kvpair_evaluator_t));
|
|
*pkvpair = (map_literal_kvpair_evaluator_t) {
|
|
.pkey_evaluator = NULL,
|
|
.is_terminal = TRUE,
|
|
.pxval_evaluator = NULL,
|
|
.plist_evaluator = NULL,
|
|
};
|
|
|
|
mlr_dsl_ast_node_t* pchild = pe->pvvalue;
|
|
MLR_INTERNAL_CODING_ERROR_IF(pchild->type != MD_AST_NODE_TYPE_MAP_LITERAL_PAIR);
|
|
|
|
mlr_dsl_ast_node_t* pleft = pchild->pchildren->phead->pvvalue;
|
|
MLR_INTERNAL_CODING_ERROR_IF(pleft->type != MD_AST_NODE_TYPE_MAP_LITERAL_KEY);
|
|
mlr_dsl_ast_node_t* pkeynode = pleft->pchildren->phead->pvvalue;
|
|
pkvpair->pkey_evaluator = rval_evaluator_alloc_from_ast(pkeynode, pfmgr, type_inferencing, context_flags);
|
|
|
|
mlr_dsl_ast_node_t* pright = pchild->pchildren->phead->pnext->pvvalue;
|
|
mlr_dsl_ast_node_t* pvalnode = pright->pchildren->phead->pvvalue;
|
|
if (pright->type == MD_AST_NODE_TYPE_MAP_LITERAL_VALUE) {
|
|
pkvpair->pxval_evaluator = rxval_evaluator_alloc_from_ast(pvalnode, pfmgr, type_inferencing, context_flags);
|
|
} else if (pright->type == MD_AST_NODE_TYPE_MAP_LITERAL) {
|
|
pkvpair->is_terminal = FALSE;
|
|
pkvpair->plist_evaluator = allocate_map_literal_evaluator_from_ast(
|
|
pvalnode, pfmgr, type_inferencing, context_flags);
|
|
} else {
|
|
MLR_INTERNAL_CODING_ERROR();
|
|
}
|
|
|
|
sllv_append(plist_evaluator->pkvpair_evaluators, pkvpair);
|
|
}
|
|
return plist_evaluator;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
typedef struct _rxval_evaluator_from_map_literal_state_t {
|
|
map_literal_list_evaluator_t* proot_list_evaluator;
|
|
} rxval_evaluator_from_map_literal_state_t;
|
|
|
|
static void rxval_evaluator_from_map_literal_aux(
|
|
rxval_evaluator_from_map_literal_state_t* pstate,
|
|
map_literal_list_evaluator_t* plist_evaluator,
|
|
mlhmmv_level_t* plevel,
|
|
variables_t* pvars)
|
|
{
|
|
for (sllve_t* pe = plist_evaluator->pkvpair_evaluators->phead; pe != NULL; pe = pe->pnext) {
|
|
map_literal_kvpair_evaluator_t* pkvpair = pe->pvvalue;
|
|
|
|
// mlhmmv_level_put_terminal will copy keys and values
|
|
mv_t mvkey = pkvpair->pkey_evaluator->pprocess_func(pkvpair->pkey_evaluator->pvstate, pvars);
|
|
if (pkvpair->is_terminal) {
|
|
sllmve_t e = { .value = mvkey, .free_flags = 0, .pnext = NULL };
|
|
boxed_xval_t boxed_xval = pkvpair->pxval_evaluator->pprocess_func(pkvpair->pxval_evaluator->pvstate, pvars);
|
|
if (!boxed_xval.xval.is_terminal && !boxed_xval.is_ephemeral) {
|
|
mlhmmv_xvalue_t copy_xval = mlhmmv_xvalue_copy(&boxed_xval.xval);
|
|
mlhmmv_level_put_xvalue(plevel, &e, ©_xval);
|
|
} else {
|
|
mlhmmv_level_put_xvalue(plevel, &e, &boxed_xval.xval);
|
|
}
|
|
} else {
|
|
sllmve_t e = { .value = mvkey, .free_flags = 0, .pnext = NULL };
|
|
mlhmmv_level_t* pnext_level = mlhmmv_level_put_empty_map(plevel, &e);
|
|
rxval_evaluator_from_map_literal_aux(pstate, pkvpair->plist_evaluator, pnext_level, pvars);
|
|
}
|
|
}
|
|
}
|
|
|
|
static boxed_xval_t rxval_evaluator_from_map_literal_func(void* pvstate, variables_t* pvars) {
|
|
rxval_evaluator_from_map_literal_state_t* pstate = pvstate;
|
|
|
|
mlhmmv_xvalue_t xval = mlhmmv_xvalue_alloc_empty_map();
|
|
|
|
rxval_evaluator_from_map_literal_aux(pstate, pstate->proot_list_evaluator, xval.pnext_level, pvars);
|
|
|
|
return (boxed_xval_t) {
|
|
.xval = xval,
|
|
.is_ephemeral = TRUE,
|
|
};
|
|
}
|
|
|
|
static void rxval_evaluator_from_map_literal_free_aux(map_literal_list_evaluator_t* plist_evaluator) {
|
|
for (sllve_t* pe = plist_evaluator->pkvpair_evaluators->phead; pe != NULL; pe = pe->pnext) {
|
|
map_literal_kvpair_evaluator_t* pkvpair_evaluator = pe->pvvalue;
|
|
if (pkvpair_evaluator->pkey_evaluator != NULL) {
|
|
pkvpair_evaluator->pkey_evaluator->pfree_func(pkvpair_evaluator->pkey_evaluator);
|
|
}
|
|
if (pkvpair_evaluator->pxval_evaluator != NULL) {
|
|
pkvpair_evaluator->pxval_evaluator->pfree_func(pkvpair_evaluator->pxval_evaluator);
|
|
}
|
|
if (pkvpair_evaluator->plist_evaluator != NULL) {
|
|
rxval_evaluator_from_map_literal_free_aux(pkvpair_evaluator->plist_evaluator);
|
|
}
|
|
free(pkvpair_evaluator);
|
|
}
|
|
sllv_free(plist_evaluator->pkvpair_evaluators);
|
|
free(plist_evaluator);
|
|
}
|
|
|
|
static void rxval_evaluator_from_map_literal_free(rxval_evaluator_t* prxval_evaluator) {
|
|
rxval_evaluator_from_map_literal_state_t* pstate = prxval_evaluator->pvstate;
|
|
rxval_evaluator_from_map_literal_free_aux(pstate->proot_list_evaluator);
|
|
free(pstate);
|
|
free(prxval_evaluator);
|
|
}
|
|
|
|
rxval_evaluator_t* rxval_evaluator_alloc_from_map_literal(mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr,
|
|
int type_inferencing, int context_flags)
|
|
{
|
|
rxval_evaluator_from_map_literal_state_t* pstate = mlr_malloc_or_die(
|
|
sizeof(rxval_evaluator_from_map_literal_state_t));
|
|
pstate->proot_list_evaluator = allocate_map_literal_evaluator_from_ast(
|
|
pnode, pfmgr, type_inferencing, context_flags);
|
|
|
|
rxval_evaluator_t* prxval_evaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t));
|
|
prxval_evaluator->pvstate = pstate;
|
|
prxval_evaluator->pprocess_func = rxval_evaluator_from_map_literal_func;
|
|
prxval_evaluator->pfree_func = rxval_evaluator_from_map_literal_free;
|
|
|
|
return prxval_evaluator;
|
|
}
|
|
|
|
// ================================================================
|
|
typedef struct _rxval_evaluator_from_nonindexed_local_variable_state_t {
|
|
int vardef_frame_relative_index;
|
|
} rxval_evaluator_from_nonindexed_local_variable_state_t;
|
|
|
|
static boxed_xval_t rxval_evaluator_from_nonindexed_local_variable_func(void* pvstate, variables_t* pvars) {
|
|
rxval_evaluator_from_nonindexed_local_variable_state_t* pstate = pvstate;
|
|
local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
|
|
mlhmmv_xvalue_t* pxval = local_stack_frame_ref_extended_from_indexed(
|
|
pframe, pstate->vardef_frame_relative_index, NULL);
|
|
if (pxval == NULL) {
|
|
return (boxed_xval_t) {
|
|
.xval = mlhmmv_xvalue_wrap_terminal(mv_absent()),
|
|
.is_ephemeral = FALSE,
|
|
};
|
|
} else {
|
|
return (boxed_xval_t) {
|
|
.xval = *pxval,
|
|
.is_ephemeral = FALSE,
|
|
};
|
|
}
|
|
}
|
|
|
|
static void rxval_evaluator_from_nonindexed_local_variable_free(rxval_evaluator_t* prxval_evaluator) {
|
|
rxval_evaluator_from_nonindexed_local_variable_state_t* pstate = prxval_evaluator->pvstate;
|
|
free(pstate);
|
|
free(prxval_evaluator);
|
|
}
|
|
|
|
rxval_evaluator_t* rxval_evaluator_alloc_from_nonindexed_local_variable(
|
|
mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags)
|
|
{
|
|
rxval_evaluator_from_nonindexed_local_variable_state_t* pstate = mlr_malloc_or_die(
|
|
sizeof(rxval_evaluator_from_nonindexed_local_variable_state_t));
|
|
MLR_INTERNAL_CODING_ERROR_IF(pnode->vardef_frame_relative_index == MD_UNUSED_INDEX);
|
|
pstate->vardef_frame_relative_index = pnode->vardef_frame_relative_index;
|
|
|
|
rxval_evaluator_t* prxval_evaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t));
|
|
prxval_evaluator->pvstate = pstate;
|
|
prxval_evaluator->pprocess_func = rxval_evaluator_from_nonindexed_local_variable_func;
|
|
prxval_evaluator->pfree_func = rxval_evaluator_from_nonindexed_local_variable_free;
|
|
|
|
return prxval_evaluator;
|
|
}
|
|
|
|
// ================================================================
|
|
typedef struct _rxval_evaluator_from_indexed_local_variable_state_t {
|
|
int vardef_frame_relative_index;
|
|
sllv_t* pkeylist_evaluators;
|
|
} rxval_evaluator_from_indexed_local_variable_state_t;
|
|
|
|
static boxed_xval_t rxval_evaluator_from_indexed_local_variable_func(void* pvstate, variables_t* pvars) {
|
|
rxval_evaluator_from_indexed_local_variable_state_t* pstate = pvstate;
|
|
|
|
int all_non_null_or_error = TRUE;
|
|
sllmv_t* pmvkeys = evaluate_list(pstate->pkeylist_evaluators, pvars, &all_non_null_or_error);
|
|
|
|
if (all_non_null_or_error) {
|
|
local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
|
|
mlhmmv_xvalue_t* pxval = local_stack_frame_ref_extended_from_indexed(pframe, pstate->vardef_frame_relative_index,
|
|
pmvkeys);
|
|
sllmv_free(pmvkeys);
|
|
if (pxval == NULL) {
|
|
return (boxed_xval_t) {
|
|
.xval = mlhmmv_xvalue_wrap_terminal(mv_absent()),
|
|
.is_ephemeral = FALSE,
|
|
};
|
|
} else {
|
|
return (boxed_xval_t) {
|
|
.xval = *pxval,
|
|
.is_ephemeral = FALSE,
|
|
};
|
|
}
|
|
} else {
|
|
sllmv_free(pmvkeys);
|
|
return (boxed_xval_t) {
|
|
.xval = mlhmmv_xvalue_wrap_terminal(mv_absent()),
|
|
.is_ephemeral = TRUE,
|
|
};
|
|
}
|
|
}
|
|
|
|
static void rxval_evaluator_from_indexed_local_variable_free(rxval_evaluator_t* prxval_evaluator) {
|
|
rxval_evaluator_from_indexed_local_variable_state_t* pstate = prxval_evaluator->pvstate;
|
|
for (sllve_t* pe = pstate->pkeylist_evaluators->phead; pe != NULL; pe = pe->pnext) {
|
|
rval_evaluator_t* prval_evaluator = pe->pvvalue;
|
|
prval_evaluator->pfree_func(prval_evaluator);
|
|
}
|
|
sllv_free(pstate->pkeylist_evaluators);
|
|
free(pstate);
|
|
free(prxval_evaluator);
|
|
}
|
|
|
|
rxval_evaluator_t* rxval_evaluator_alloc_from_indexed_local_variable(
|
|
mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags)
|
|
{
|
|
rxval_evaluator_from_indexed_local_variable_state_t* pstate = mlr_malloc_or_die(
|
|
sizeof(rxval_evaluator_from_indexed_local_variable_state_t));
|
|
MLR_INTERNAL_CODING_ERROR_IF(pnode->vardef_frame_relative_index == MD_UNUSED_INDEX);
|
|
pstate->vardef_frame_relative_index = pnode->vardef_frame_relative_index;
|
|
pstate->pkeylist_evaluators = allocate_keylist_evaluators_from_ast_node(
|
|
pnode, pfmgr, type_inferencing, context_flags);
|
|
|
|
rxval_evaluator_t* prxval_evaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t));
|
|
prxval_evaluator->pvstate = pstate;
|
|
prxval_evaluator->pprocess_func = rxval_evaluator_from_indexed_local_variable_func;
|
|
prxval_evaluator->pfree_func = rxval_evaluator_from_indexed_local_variable_free;
|
|
|
|
return prxval_evaluator;
|
|
}
|
|
|
|
// ================================================================
|
|
typedef struct _rxval_evaluator_from_oosvar_keylist_state_t {
|
|
sllv_t* pkeylist_evaluators;
|
|
} rxval_evaluator_from_oosvar_keylist_state_t;
|
|
|
|
static boxed_xval_t rxval_evaluator_from_oosvar_keylist_func(void* pvstate, variables_t* pvars) {
|
|
rxval_evaluator_from_oosvar_keylist_state_t* pstate = pvstate;
|
|
|
|
int all_non_null_or_error = TRUE;
|
|
sllmv_t* pmvkeys = evaluate_list(pstate->pkeylist_evaluators, pvars, &all_non_null_or_error);
|
|
|
|
if (all_non_null_or_error) {
|
|
int lookup_error = FALSE;
|
|
mlhmmv_xvalue_t* pxval = mlhmmv_level_look_up_and_ref_xvalue(pvars->poosvars->proot_level,
|
|
pmvkeys, &lookup_error);
|
|
sllmv_free(pmvkeys);
|
|
if (pxval != NULL) {
|
|
return (boxed_xval_t) {
|
|
.xval = *pxval,
|
|
.is_ephemeral = FALSE,
|
|
};
|
|
} else {
|
|
return (boxed_xval_t) {
|
|
.xval = mlhmmv_xvalue_wrap_terminal(mv_absent()),
|
|
.is_ephemeral = TRUE,
|
|
};
|
|
}
|
|
} else {
|
|
sllmv_free(pmvkeys);
|
|
return (boxed_xval_t) {
|
|
.xval = mlhmmv_xvalue_wrap_terminal(mv_absent()),
|
|
.is_ephemeral = TRUE,
|
|
};
|
|
}
|
|
}
|
|
|
|
static void rxval_evaluator_from_oosvar_keylist_free(rxval_evaluator_t* prxval_evaluator) {
|
|
rxval_evaluator_from_oosvar_keylist_state_t* pstate = prxval_evaluator->pvstate;
|
|
for (sllve_t* pe = pstate->pkeylist_evaluators->phead; pe != NULL; pe = pe->pnext) {
|
|
rval_evaluator_t* prval_evaluator = pe->pvvalue;
|
|
prval_evaluator->pfree_func(prval_evaluator);
|
|
}
|
|
sllv_free(pstate->pkeylist_evaluators);
|
|
free(pstate);
|
|
free(prxval_evaluator);
|
|
}
|
|
|
|
rxval_evaluator_t* rxval_evaluator_alloc_from_oosvar_keylist(
|
|
mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags)
|
|
{
|
|
rxval_evaluator_from_oosvar_keylist_state_t* pstate = mlr_malloc_or_die(
|
|
sizeof(rxval_evaluator_from_oosvar_keylist_state_t));
|
|
pstate->pkeylist_evaluators = allocate_keylist_evaluators_from_ast_node(
|
|
pnode, pfmgr, type_inferencing, context_flags);
|
|
|
|
rxval_evaluator_t* prxval_evaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t));
|
|
prxval_evaluator->pvstate = pstate;
|
|
prxval_evaluator->pprocess_func = rxval_evaluator_from_oosvar_keylist_func;
|
|
prxval_evaluator->pfree_func = rxval_evaluator_from_oosvar_keylist_free;
|
|
|
|
return prxval_evaluator;
|
|
}
|
|
|
|
// ================================================================
|
|
static boxed_xval_t rxval_evaluator_from_full_oosvar_func(void* pvstate, variables_t* pvars) {
|
|
return (boxed_xval_t) {
|
|
.is_ephemeral = FALSE,
|
|
.xval = (mlhmmv_xvalue_t) {
|
|
.is_terminal = FALSE,
|
|
.pnext_level = pvars->poosvars->proot_level,
|
|
},
|
|
};
|
|
}
|
|
|
|
static void rxval_evaluator_from_full_oosvar_free(rxval_evaluator_t* prxval_evaluator) {
|
|
free(prxval_evaluator);
|
|
}
|
|
|
|
rxval_evaluator_t* rxval_evaluator_alloc_from_full_oosvar(
|
|
mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags)
|
|
{
|
|
rxval_evaluator_t* prxval_evaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t));
|
|
prxval_evaluator->pprocess_func = rxval_evaluator_from_full_oosvar_func;
|
|
prxval_evaluator->pfree_func = rxval_evaluator_from_full_oosvar_free;
|
|
|
|
return prxval_evaluator;
|
|
}
|
|
|
|
// ================================================================
|
|
static boxed_xval_t rxval_evaluator_from_full_srec_func(void* pvstate, variables_t* pvars) {
|
|
boxed_xval_t boxed_xval;
|
|
boxed_xval.is_ephemeral = TRUE;
|
|
boxed_xval.xval = mlhmmv_xvalue_alloc_empty_map();
|
|
|
|
for (lrece_t* pe = pvars->pinrec->phead; pe != NULL; pe = pe->pnext) {
|
|
// mlhmmv_level_put_terminal will copy mv keys and values so we needn't (and shouldn't)
|
|
// duplicate them here.
|
|
mv_t k = mv_from_string(pe->key, NO_FREE);
|
|
sllmve_t e = { .value = k, .free_flags = 0, .pnext = NULL };
|
|
mv_t* pomv = lhmsmv_get(pvars->ptyped_overlay, pe->key);
|
|
if (pomv != NULL) {
|
|
mlhmmv_level_put_terminal(boxed_xval.xval.pnext_level, &e, pomv); // xxx make a simpler 1-level API call
|
|
} else {
|
|
mv_t v = mv_from_string(pe->value, NO_FREE); // mlhmmv_level_put_terminal will copy
|
|
mlhmmv_level_put_terminal(boxed_xval.xval.pnext_level, &e, &v);
|
|
}
|
|
}
|
|
|
|
return boxed_xval;
|
|
}
|
|
|
|
static void rxval_evaluator_from_full_srec_free(rxval_evaluator_t* prxval_evaluator) {
|
|
free(prxval_evaluator);
|
|
}
|
|
|
|
rxval_evaluator_t* rxval_evaluator_alloc_from_full_srec(
|
|
mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags)
|
|
{
|
|
rxval_evaluator_t* prxval_evaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t));
|
|
prxval_evaluator->pprocess_func = rxval_evaluator_from_full_srec_func;
|
|
prxval_evaluator->pfree_func = rxval_evaluator_from_full_srec_free;
|
|
|
|
return prxval_evaluator;
|
|
}
|
|
|
|
// ================================================================
|
|
typedef struct _rxval_evaluator_wrapping_rval_state_t {
|
|
rval_evaluator_t* prval_evaluator;
|
|
} rxval_evaluator_wrapping_rval_state_t;
|
|
|
|
static boxed_xval_t rxval_evaluator_wrapping_rval_func(void* pvstate, variables_t* pvars) {
|
|
rxval_evaluator_wrapping_rval_state_t* pstate = pvstate;
|
|
rval_evaluator_t* prval_evaluator = pstate->prval_evaluator;
|
|
mv_t val = prval_evaluator->pprocess_func(prval_evaluator->pvstate, pvars);
|
|
return (boxed_xval_t) {
|
|
.xval = mlhmmv_xvalue_wrap_terminal(val),
|
|
.is_ephemeral = FALSE, // verify reference semantics for RHS evaluators!
|
|
};
|
|
}
|
|
|
|
static void rxval_evaluator_wrapping_rval_free(rxval_evaluator_t* prxval_evaluator) {
|
|
rxval_evaluator_wrapping_rval_state_t* pstate = prxval_evaluator->pvstate;
|
|
pstate->prval_evaluator->pfree_func(pstate->prval_evaluator);
|
|
free(pstate);
|
|
free(prxval_evaluator);
|
|
}
|
|
|
|
rxval_evaluator_t* rxval_evaluator_alloc_wrapping_rval(mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr,
|
|
int type_inferencing, int context_flags)
|
|
{
|
|
rxval_evaluator_wrapping_rval_state_t* pstate = mlr_malloc_or_die(
|
|
sizeof(rxval_evaluator_wrapping_rval_state_t));
|
|
pstate->prval_evaluator = rval_evaluator_alloc_from_ast(pnode, pfmgr, type_inferencing, context_flags);
|
|
|
|
rxval_evaluator_t* prxval_evaluator = mlr_malloc_or_die(sizeof(rxval_evaluator_t));
|
|
prxval_evaluator->pvstate = pstate;
|
|
prxval_evaluator->pprocess_func = rxval_evaluator_wrapping_rval_func;
|
|
prxval_evaluator->pfree_func = rxval_evaluator_wrapping_rval_free;
|
|
|
|
return prxval_evaluator;
|
|
}
|