diff --git a/c/mapping/mlr_dsl_cst.h b/c/mapping/mlr_dsl_cst.h index b916e3e3a..efd2dc59d 100644 --- a/c/mapping/mlr_dsl_cst.h +++ b/c/mapping/mlr_dsl_cst.h @@ -168,6 +168,7 @@ typedef struct _mlr_dsl_cst_statement_t { char* local_lhs_variable_name; int local_lhs_frame_relative_index; int local_lhs_type_mask; + sllv_t* plocal_map_lhs_keylist_evaluators; // Assignment to local map-variable // Assignment to srec char* srec_lhs_field_name; diff --git a/c/mapping/mlr_dsl_cst_statements.c b/c/mapping/mlr_dsl_cst_statements.c index 71d60a22b..371552b03 100644 --- a/c/mapping/mlr_dsl_cst_statements.c +++ b/c/mapping/mlr_dsl_cst_statements.c @@ -656,6 +656,7 @@ static mlr_dsl_cst_statement_t* alloc_blank() { pstatement->preturn_evaluator = NULL; pstatement->pblock_handler = NULL; pstatement->poosvar_lhs_keylist_evaluators = NULL; + pstatement->plocal_map_lhs_keylist_evaluators = NULL; pstatement->pemit_keylist_evaluators = NULL; pstatement->num_emit_keylist_evaluators = 0; pstatement->ppemit_keylist_evaluators = NULL; @@ -750,20 +751,33 @@ static mlr_dsl_cst_statement_t* alloc_local_map_variable_assignment(mlr_dsl_cst_ { mlr_dsl_cst_statement_t* pstatement = alloc_blank(); - // xxx keylist evaluators - - MLR_INTERNAL_CODING_ERROR_IF((pnode->pchildren == NULL) || (pnode->pchildren->length != 2)); - mlr_dsl_ast_node_t* pleft = pnode->pchildren->phead->pvvalue; mlr_dsl_ast_node_t* pright = pnode->pchildren->phead->pnext->pvvalue; - MLR_INTERNAL_CODING_ERROR_IF(pleft->type != MD_AST_NODE_TYPE_LOCAL_VARIABLE); - MLR_INTERNAL_CODING_ERROR_IF(pleft->pchildren != NULL); + MLR_INTERNAL_CODING_ERROR_IF(pleft->type != MD_AST_NODE_TYPE_LOCAL_MAP_VARIABLE); + MLR_INTERNAL_CODING_ERROR_IF(pleft->pchildren == NULL); pstatement->pnode_handler = handle_local_map_variable_assignment; pstatement->local_lhs_variable_name = mlr_strdup_or_die(pleft->text); MLR_INTERNAL_CODING_ERROR_IF(pleft->vardef_frame_relative_index == MD_UNUSED_INDEX); pstatement->local_lhs_frame_relative_index = pleft->vardef_frame_relative_index; + +// xxx to code up + +// sllv_t* plocal_map_lhs_keylist_evaluators = allocate_keylist_evaluators_from_oosvar_node(pcst, pleft, +// type_inferencing, context_flags); +// +// if (pleft->type == MD_AST_NODE_TYPE_OOSVAR_KEYLIST && pright->type == MD_AST_NODE_TYPE_OOSVAR_KEYLIST) { +// pstatement->pnode_handler = handle_oosvar_to_oosvar_assignment; +// pstatement->poosvar_rhs_keylist_evaluators = allocate_keylist_evaluators_from_oosvar_node(pcst, pright, +// type_inferencing, context_flags); +// } else { +// pstatement->pnode_handler = handle_oosvar_assignment; +// pstatement->poosvar_rhs_keylist_evaluators = NULL; +// } +// +// pstatement->plocal_map_lhs_keylist_evaluators = plocal_map_lhs_keylist_evaluators; + pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(pright, pcst->pfmgr, type_inferencing, context_flags); return pstatement; } diff --git a/c/mapping/rval_evaluators.h b/c/mapping/rval_evaluators.h index 804f7886e..5f9f2dd5c 100644 --- a/c/mapping/rval_evaluators.h +++ b/c/mapping/rval_evaluators.h @@ -43,6 +43,8 @@ rval_evaluator_t* rval_evaluator_alloc_from_indirect_field_name(mlr_dsl_ast_node int type_inferencing, int context_flags); rval_evaluator_t* rval_evaluator_alloc_from_oosvar_keylist(mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags); +rval_evaluator_t* rval_evaluator_alloc_from_local_map_keylist(mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, + int type_inferencing, int context_flags); // This is used for evaluating strings and numbers in literal expressions, e.g. '$x = "abc"' // or '$x = "left_\1". The values are subject to replacement with regex captures. See comments diff --git a/c/mapping/rval_expr_evaluators.c b/c/mapping/rval_expr_evaluators.c index e7004dc9b..bff583c7c 100644 --- a/c/mapping/rval_expr_evaluators.c +++ b/c/mapping/rval_expr_evaluators.c @@ -90,7 +90,7 @@ rval_evaluator_t* rval_evaluator_alloc_from_ast(mlr_dsl_ast_node_t* pnode, fmgr_ return rval_evaluator_alloc_from_oosvar_keylist(pnode, pfmgr, type_inferencing, context_flags); } else if (pnode->type == MD_AST_NODE_TYPE_LOCAL_MAP_VARIABLE) { - return NULL; // xxx map-local keylist + return rval_evaluator_alloc_from_local_map_keylist(pnode, pfmgr, type_inferencing, context_flags); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - } else if (pnode->type == MD_AST_NODE_TYPE_ENV) { @@ -337,6 +337,75 @@ rval_evaluator_t* rval_evaluator_alloc_from_oosvar_keylist(mlr_dsl_ast_node_t* p return pevaluator; } +// ================================================================ +typedef struct _rval_evaluator_local_map_keylist_state_t { + int vardef_frame_relative_index; + sllv_t* plocal_map_rhs_keylist_evaluators; +} rval_evaluator_local_map_keylist_state_t; + +mv_t rval_evaluator_local_map_keylist_func(void* pvstate, variables_t* pvars) { + rval_evaluator_local_map_keylist_state_t* pstate = pvstate; + + int all_non_null_or_error = TRUE; + sllmv_t* pmvkeys = evaluate_list(pstate->plocal_map_rhs_keylist_evaluators, pvars, &all_non_null_or_error); + + mv_t rv = mv_absent(); + if (all_non_null_or_error) { + int error = 0; + mv_t* pval = mlhmmv_get_terminal(pvars->poosvars, pmvkeys, &error); // xxx temp -- get from stack frame + if (pval != NULL) { + if (pval->type == MT_STRING && *pval->u.strv == 0) + rv = mv_empty(); + else + rv = mv_copy(pval); + } + } + + sllmv_free(pmvkeys); + return rv; +} + +static void rval_evaluator_local_map_keylist_free(rval_evaluator_t* pevaluator) { + rval_evaluator_local_map_keylist_state_t* pstate = pevaluator->pvstate; + for (sllve_t* pe = pstate->plocal_map_rhs_keylist_evaluators->phead; pe != NULL; pe = pe->pnext) { + rval_evaluator_t* pevaluator = pe->pvvalue; + pevaluator->pfree_func(pevaluator); + } + sllv_free(pstate->plocal_map_rhs_keylist_evaluators); + free(pstate); + free(pevaluator); +} + +rval_evaluator_t* rval_evaluator_alloc_from_local_map_keylist(mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, + int type_inferencing, int context_flags) +{ + rval_evaluator_local_map_keylist_state_t* pstate = mlr_malloc_or_die( + sizeof(rval_evaluator_local_map_keylist_state_t)); + + MLR_INTERNAL_CODING_ERROR_IF(pnode->vardef_frame_relative_index == MD_UNUSED_INDEX); + + sllv_t* pkeylist_evaluators = sllv_alloc(); + + for (sllve_t* pe = pnode->pchildren->phead; pe != NULL; pe = pe->pnext) { + mlr_dsl_ast_node_t* pkeynode = pe->pvvalue; + if (pkeynode->type == MD_AST_NODE_TYPE_STRING_LITERAL) { + sllv_append(pkeylist_evaluators, rval_evaluator_alloc_from_string(pkeynode->text)); + } else { + sllv_append(pkeylist_evaluators, rval_evaluator_alloc_from_ast(pkeynode, pfmgr, + type_inferencing, context_flags)); + } + } + pstate->plocal_map_rhs_keylist_evaluators = pkeylist_evaluators; + + rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t)); + pevaluator->pvstate = pstate; + pevaluator->pprocess_func = NULL; + pevaluator->pprocess_func = rval_evaluator_local_map_keylist_func; + pevaluator->pfree_func = rval_evaluator_local_map_keylist_free; + + return pevaluator; +} + // ================================================================ // This is used for evaluating strings and numbers in literal expressions, e.g. '$x = "abc"' // or '$x = "left_\1". The values are subject to replacement with regex captures. See comments