nested-retval fixup

This commit is contained in:
John Kerl 2016-09-16 17:21:27 -07:00
parent 3141ac9f8e
commit 573f26fbb8
6 changed files with 67 additions and 21 deletions

View file

@ -212,6 +212,10 @@ static sllv_t* mapper_filter_process(lrec_t* pinrec, context_t* pctx, void* pvst
.pctx = pctx,
.pbind_stack = NULL,
.ploop_stack = NULL,
.return_state = {
.returned = FALSE,
.retval = mv_absent(),
}
};
mv_t val = pstate->pevaluator->pprocess_func(pstate->pevaluator->pvstate, &variables);

View file

@ -350,6 +350,10 @@ static sllv_t* mapper_put_process(lrec_t* pinrec, context_t* pctx, void* pvstate
.pctx = pctx,
.pbind_stack = pstate->pbind_stack,
.ploop_stack = pstate->ploop_stack,
.return_state = {
.returned = FALSE,
.retval = mv_absent(),
}
};
cst_outputs_t cst_outputs = (cst_outputs_t) {
.pshould_emit_rec = &should_emit_rec,
@ -372,6 +376,10 @@ static sllv_t* mapper_put_process(lrec_t* pinrec, context_t* pctx, void* pvstate
.pctx = pctx,
.pbind_stack = pstate->pbind_stack,
.ploop_stack = pstate->ploop_stack,
.return_state = {
.returned = FALSE,
.retval = mv_absent(),
}
};
cst_outputs_t cst_outputs = (cst_outputs_t) {
.pshould_emit_rec = &should_emit_rec,
@ -400,6 +408,10 @@ static sllv_t* mapper_put_process(lrec_t* pinrec, context_t* pctx, void* pvstate
.pctx = pctx,
.pbind_stack = pstate->pbind_stack,
.ploop_stack = pstate->ploop_stack,
.return_state = {
.returned = FALSE,
.retval = mv_absent(),
}
};
cst_outputs_t cst_outputs = (cst_outputs_t) {
.pshould_emit_rec = &should_emit_rec,

View file

@ -116,6 +116,8 @@ static void handle_statement_list_with_break_continue(
cst_outputs_t* pcst_outputs);
static cst_statement_handler_t handle_subr_callsite;
static cst_statement_handler_t handle_return_void;
static cst_statement_handler_t handle_return_value;
static cst_statement_handler_t handle_local_variable_assignment;
static cst_statement_handler_t handle_srec_assignment;
@ -724,7 +726,6 @@ static mlr_dsl_cst_statement_t* alloc_blank() {
pstatement->psubr_defsite = NULL;
pstatement->local_variable_name = NULL;
pstatement->preturn_evaluator = NULL;
pstatement->is_return_void = FALSE;
pstatement->pblock_handler = NULL;
pstatement->poosvar_lhs_keylist_evaluators = NULL;
pstatement->pemit_keylist_evaluators = NULL;
@ -776,6 +777,7 @@ static mlr_dsl_cst_statement_t* alloc_return_value(mlr_dsl_cst_t* pcst, mlr_dsl_
mlr_dsl_ast_node_t* prhs_node = pnode->pchildren->phead->pvvalue;
pstatement->preturn_evaluator = rval_evaluator_alloc_from_ast(prhs_node, pcst->pfmgr,
type_inferencing, context_flags);
pstatement->pnode_handler = handle_return_value;
return pstatement;
}
@ -783,7 +785,7 @@ static mlr_dsl_cst_statement_t* alloc_return_void(mlr_dsl_cst_t* pcst, mlr_dsl_a
int type_inferencing, int context_flags)
{
mlr_dsl_cst_statement_t* pstatement = alloc_blank();
pstatement->is_return_void = TRUE;
pstatement->pnode_handler = handle_return_void;
return pstatement;
}
@ -1996,6 +1998,10 @@ void mlr_dsl_cst_handle_statement_list(
for (sllve_t* pe = pcst_statements->phead; pe != NULL; pe = pe->pnext) {
mlr_dsl_cst_statement_t* pstatement = pe->pvvalue;
pstatement->pnode_handler(pstatement, pvars, pcst_outputs);
// The UDF/subroutine executor will clear the flag, and consume the retval if there is one.
if (pvars->return_state.returned) {
break;
}
}
}
@ -2012,6 +2018,10 @@ static void handle_statement_list_with_break_continue(
if (loop_stack_get(pvars->ploop_stack) != 0) {
break;
}
// The UDF/subroutine executor will clear the flag, and consume the retval if there is one.
if (pvars->return_state.returned) {
break;
}
}
}
@ -2030,6 +2040,25 @@ static void handle_subr_callsite(
pstatement->subr_callsite_arguments);
}
// ----------------------------------------------------------------
static void handle_return_void(
mlr_dsl_cst_statement_t* pstatement,
variables_t* pvars,
cst_outputs_t* pcst_outputs)
{
pvars->return_state.returned = TRUE;
}
// ----------------------------------------------------------------
static void handle_return_value(
mlr_dsl_cst_statement_t* pstatement,
variables_t* pvars,
cst_outputs_t* pcst_outputs)
{
pvars->return_state.returned = TRUE;
pvars->return_state.retval = pstatement->preturn_evaluator->pprocess_func(pstatement->preturn_evaluator->pvstate, pvars);
}
// ----------------------------------------------------------------
static void handle_local_variable_assignment(
mlr_dsl_cst_statement_t* pstatement,

View file

@ -118,8 +118,6 @@ typedef struct _mlr_dsl_cst_statement_t {
// Return statement within user-defined function
rval_evaluator_t* preturn_evaluator;
// Return statement within user-defined subroutine
int is_return_void;
// There are two variants of statement-list handlers: one for inside loop bodies which has to check break/continue
// flags after each statement, and another for outside loop bodies which doesn't need to check those. (This is a

View file

@ -144,16 +144,15 @@ static mv_t cst_udf_process_callback(void* pvstate, int arity, mv_t* args, varia
for (sllve_t* pe = pstate->pblock_statements->phead; pe != NULL; pe = pe->pnext) {
mlr_dsl_cst_statement_t* pstatement = pe->pvvalue;
if (pstatement->preturn_evaluator != NULL) {
// return statement
retval = pstatement->preturn_evaluator->pprocess_func(pstatement->preturn_evaluator->pvstate, pvars);
pstatement->pnode_handler(pstatement, pvars, pcst_outputs);
if (loop_stack_get(pvars->ploop_stack) != 0) {
break;
}
if (pvars->return_state.returned) {
pvars->return_state.returned = FALSE;
retval = pvars->return_state.retval;
pvars->return_state.retval = mv_absent();
break;
} else {
// anything else
pstatement->pnode_handler(pstatement, pvars, pcst_outputs);
if (loop_stack_get(pvars->ploop_stack) != 0) {
break;
}
}
}
@ -270,15 +269,13 @@ void mlr_dsl_cst_execute_subroutine(subr_defsite_t* pstate, variables_t* pvars,
for (sllve_t* pe = pstate->pblock_statements->phead; pe != NULL; pe = pe->pnext) {
mlr_dsl_cst_statement_t* pstatement = pe->pvvalue;
if (pstatement->is_return_void) {
// return statement
pstatement->pnode_handler(pstatement, pvars, pcst_outputs);
if (loop_stack_get(pvars->ploop_stack) != 0) {
break;
}
if (pvars->return_state.returned) {
pvars->return_state.returned = FALSE;
break;
} else {
// anything else
pstatement->pnode_handler(pstatement, pvars, pcst_outputs);
if (loop_stack_get(pvars->ploop_stack) != 0) {
break;
}
}
}

View file

@ -39,6 +39,11 @@
struct _rval_evaluator_t; // forward reference for method declarations
typedef struct _return_state_t {
int returned;
mv_t retval;
} return_state_t;
typedef struct _variables_t {
lrec_t* pinrec;
lhmsmv_t* ptyped_overlay;
@ -47,6 +52,7 @@ typedef struct _variables_t {
context_t* pctx;
bind_stack_t* pbind_stack;
loop_stack_t* ploop_stack;
return_state_t return_state;
} variables_t;
typedef mv_t rval_evaluator_process_func_t(void* pvstate, variables_t* pvars);