mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-23 16:08:43 +00:00
mapvar-for iterate; name neatens
This commit is contained in:
parent
96cc9a412c
commit
c89eeec00d
9 changed files with 493 additions and 412 deletions
|
|
@ -97,7 +97,7 @@ local_stack_frame_t* local_stack_pop(local_stack_t* pstack) {
|
|||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
mv_t local_stack_frame_get_map(local_stack_frame_t* pframe,
|
||||
mv_t local_stack_frame_get_map(local_stack_frame_t* pframe, // xxx rename
|
||||
int vardef_frame_relative_index, sllmv_t* pmvkeys)
|
||||
{
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p GET %d\n", pframe, vardef_frame_relative_index));
|
||||
|
|
@ -125,6 +125,34 @@ mv_t local_stack_frame_get_map(local_stack_frame_t* pframe,
|
|||
}
|
||||
}
|
||||
|
||||
// a[b][c] w/ [b]
|
||||
// a[b][c] w/ [b,c]
|
||||
// a[b][c] w/ [b,c,d]
|
||||
// ----------------------------------------------------------------
|
||||
mlhmmv_value_t* local_stack_frame_get_map_value(local_stack_frame_t* pframe, // xxx rename w/ 'reference' in name
|
||||
int vardef_frame_relative_index, sllmv_t* pmvkeys)
|
||||
{
|
||||
LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p GET %d\n", pframe, vardef_frame_relative_index));
|
||||
LOCAL_STACK_BOUNDS_CHECK(pframe, "GET", FALSE, vardef_frame_relative_index);
|
||||
|
||||
local_stack_frame_entry_t* pentry = &pframe->pvars[vardef_frame_relative_index];
|
||||
mlhmmv_value_t* pmvalue = &pentry->value;
|
||||
if (pmvalue->u.pnext_level == NULL) {
|
||||
LOCAL_STACK_TRACE(printf("VALUE IS EMPTY\n"));
|
||||
return NULL;
|
||||
} else {
|
||||
int error = 0;
|
||||
LOCAL_STACK_TRACE(printf("VALUE IS:\n"));
|
||||
LOCAL_STACK_TRACE(printf("PTR IS %p\n", pmvalue->u.pnext_level));
|
||||
LOCAL_STACK_TRACE(mlhmmv_level_print_stacked(pmvalue->u.pnext_level, 0, TRUE, TRUE, "", stdout));
|
||||
|
||||
// Maybe null
|
||||
mlhmmv_value_t* pmval = mlhmmv_get_value_from_level(pmvalue->u.pnext_level, pmvkeys, &error);
|
||||
|
||||
return pmval;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_frame_assign_map(local_stack_frame_t* pframe,
|
||||
int vardef_frame_relative_index, sllmv_t* pmvkeys,
|
||||
|
|
|
|||
|
|
@ -100,7 +100,10 @@ static inline mv_t local_stack_frame_get_non_map(local_stack_frame_t* pframe,
|
|||
}
|
||||
}
|
||||
|
||||
mv_t local_stack_frame_get_map(local_stack_frame_t* pframe,
|
||||
mv_t local_stack_frame_get_map(local_stack_frame_t* pframe, // xxx rename
|
||||
int vardef_frame_relative_index, sllmv_t* pmvkeys);
|
||||
|
||||
mlhmmv_value_t* local_stack_frame_get_map_value(local_stack_frame_t* pframe, // xxx rename
|
||||
int vardef_frame_relative_index, sllmv_t* pmvkeys);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -480,6 +480,32 @@ static mlhmmv_value_t* mlhmmv_get_next_level_entry_value(mlhmmv_level_t* pmap, m
|
|||
return &pentry->level_value;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
mlhmmv_value_t* mlhmmv_get_value_from_level(mlhmmv_level_t* pstart_level, sllmv_t* pmvkeys, int* perror) {
|
||||
*perror = MLHMMV_ERROR_NONE;
|
||||
sllmve_t* prest_keys = pmvkeys->phead;
|
||||
if (prest_keys == NULL) {
|
||||
*perror = MLHMMV_ERROR_KEYLIST_TOO_SHALLOW;
|
||||
}
|
||||
mlhmmv_level_t* plevel = pstart_level;
|
||||
mlhmmv_level_entry_t* plevel_entry = mlhmmv_get_next_level_entry(plevel, &prest_keys->value, NULL);
|
||||
while (prest_keys->pnext != NULL) {
|
||||
if (plevel_entry == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
plevel = plevel_entry->level_value.u.pnext_level;
|
||||
prest_keys = prest_keys->pnext;
|
||||
plevel_entry = mlhmmv_get_next_level_entry(plevel_entry->level_value.u.pnext_level,
|
||||
&prest_keys->value, NULL);
|
||||
}
|
||||
}
|
||||
if (plevel_entry == NULL) {
|
||||
*perror = MLHMMV_ERROR_KEYLIST_TOO_DEEP;
|
||||
return NULL;
|
||||
}
|
||||
return &plevel_entry->level_value;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Removes entries from a specified level downward, unsetting any maps which become empty as a result. For example, if
|
||||
// e.g. a=>b=>c=>4 and the c level is to be removed, then all up-nodes are emptied out & should be pruned.
|
||||
|
|
|
|||
|
|
@ -103,6 +103,8 @@ void mlhmmv_put_terminal_from_level(mlhmmv_level_t* plevel, sllmve_t* prest_keys
|
|||
// The CST logic can use this function to get the @records[$key1][$key2] level of the mlhmmv,
|
||||
// then copy values from there.
|
||||
mlhmmv_level_t* mlhmmv_get_level(mlhmmv_t* pmap, sllmv_t* pmvkeys, int* perror);
|
||||
// This is for getting submaps out of local variables.
|
||||
mlhmmv_value_t* mlhmmv_get_value_from_level(mlhmmv_level_t* plevel, sllmv_t* pmvkeys, int* perror);
|
||||
|
||||
// For oosvar-to-oosvar assignment.
|
||||
void mlhmmv_copy(mlhmmv_t* pmap, sllmv_t* ptokeys, sllmv_t* pfromkeys);
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ char* mlr_dsl_ast_node_describe_type(mlr_dsl_ast_node_type_t type) {
|
|||
case MD_AST_NODE_TYPE_FULL_OOSVAR: return "FULL_OOSVAR"; break;
|
||||
case MD_AST_NODE_TYPE_NON_SIGIL_NAME: return "NON_SIGIL_NAME"; break;
|
||||
case MD_AST_NODE_TYPE_OPERATOR: return "OPERATOR"; break;
|
||||
case MD_AST_NODE_TYPE_LOCAL_NON_MAP_ASSIGNMENT: return "LOCAL_ASSIGNMENT"; break;
|
||||
case MD_AST_NODE_TYPE_LOCAL_NON_MAP_ASSIGNMENT: return "LOCAL_NON_MAP_ASSIGNMENT"; break;
|
||||
case MD_AST_NODE_TYPE_LOCAL_MAP_ASSIGNMENT: return "LOCAL_MAP_ASSIGNMENT"; break;
|
||||
case MD_AST_NODE_TYPE_SREC_ASSIGNMENT: return "SREC_ASSIGNMENT"; break;
|
||||
case MD_AST_NODE_TYPE_INDIRECT_SREC_ASSIGNMENT: return "INDIRECT_SREC_ASSIGNMENT"; break;
|
||||
|
|
@ -308,7 +308,7 @@ char* mlr_dsl_ast_node_describe_type(mlr_dsl_ast_node_type_t type) {
|
|||
case MD_AST_NODE_TYPE_FOR_LOCAL_MAP_KEY_ONLY: return "FOR_LOCAL_MAP_KEY_ONLY"; break;
|
||||
case MD_AST_NODE_TYPE_FOR_VARIABLES: return "FOR_VARIABLES"; break;
|
||||
case MD_AST_NODE_TYPE_TRIPLE_FOR: return "TRIPLE_FOR"; break;
|
||||
case MD_AST_NODE_TYPE_LOCAL_NON_MAP_VARIABLE: return "LOCAL_VARIABLE"; break;
|
||||
case MD_AST_NODE_TYPE_LOCAL_NON_MAP_VARIABLE: return "LOCAL_NON_MAP_VARIABLE"; break;
|
||||
case MD_AST_NODE_TYPE_LOCAL_MAP_VARIABLE: return "LOCAL_MAP_VARIABLE"; break;
|
||||
case MD_AST_NODE_TYPE_IN: return "IN"; break;
|
||||
case MD_AST_NODE_TYPE_BREAK: return "BREAK"; break;
|
||||
|
|
|
|||
|
|
@ -230,6 +230,8 @@ typedef struct _mlr_dsl_cst_statement_t {
|
|||
int for_v_frame_relative_index;
|
||||
int for_v_type_mask;
|
||||
|
||||
int for_map_target_frame_relative_index;
|
||||
|
||||
type_inferenced_srec_field_getter_t* ptype_inferenced_srec_field_getter;
|
||||
|
||||
// triple-for:
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ static void handle_for_local_map_aux(
|
|||
mlr_dsl_cst_statement_t* pstatement,
|
||||
variables_t* pvars,
|
||||
cst_outputs_t* pcst_outputs,
|
||||
mlhmmv_value_t submap,
|
||||
mlhmmv_value_t* psubmap,
|
||||
char** prest_for_k_variable_names,
|
||||
int* prest_for_k_frame_relative_indices,
|
||||
int* prest_for_k_frame_type_masks,
|
||||
|
|
@ -715,6 +715,7 @@ static mlr_dsl_cst_statement_t* alloc_blank() {
|
|||
pstatement->for_v_variable_name = NULL;
|
||||
pstatement->for_v_frame_relative_index = 0;
|
||||
pstatement->for_v_type_mask = TYPE_MASK_ANY;
|
||||
pstatement->for_map_target_frame_relative_index = 0;
|
||||
pstatement->ptype_inferenced_srec_field_getter = NULL;
|
||||
pstatement->ptriple_for_start_statements = NULL;
|
||||
pstatement->ptriple_for_pre_continuation_statements = NULL;
|
||||
|
|
@ -1349,7 +1350,10 @@ static mlr_dsl_cst_statement_t* alloc_for_local_map(mlr_dsl_cst_t* pcst, mlr_dsl
|
|||
pstatement->for_v_frame_relative_index = psubright->vardef_frame_relative_index;
|
||||
pstatement->for_v_type_mask = mlr_dsl_ast_node_type_to_type_mask(psubright->type);
|
||||
|
||||
pstatement->poosvar_lhs_keylist_evaluators = allocate_keylist_evaluators_from_oosvar_node(
|
||||
// xxx comment liberally
|
||||
MLR_INTERNAL_CODING_ERROR_IF(pmiddle->vardef_frame_relative_index == MD_UNUSED_INDEX);
|
||||
pstatement->for_map_target_frame_relative_index = pmiddle->vardef_frame_relative_index;
|
||||
pstatement->poosvar_lhs_keylist_evaluators = allocate_keylist_evaluators_from_oosvar_node( // xxx rename x 2
|
||||
pcst, pmiddle, type_inferencing, context_flags);
|
||||
|
||||
MLR_INTERNAL_CODING_ERROR_IF(pnode->subframe_var_count == MD_UNUSED_INDEX);
|
||||
|
|
@ -3039,26 +3043,36 @@ static void handle_for_local_map( // xxx vardef_frame_relative_index
|
|||
// of the for-loop, while the k1/k2/v are bound within the for-loop.
|
||||
|
||||
int keys_all_non_null_or_error = FALSE;
|
||||
// xxx confusing 'oosvar' name ... clean up please.
|
||||
// xxx confusing 'keylist' name ... clean up please.
|
||||
sllmv_t* plhskeylist = evaluate_list(pstatement->poosvar_lhs_keylist_evaluators, pvars,
|
||||
&keys_all_non_null_or_error);
|
||||
if (keys_all_non_null_or_error) {
|
||||
|
||||
// In '(for a, b in c) { ... }' the 'c' is evaluated in the outer scope and
|
||||
// the a, b are bound within the inner scope.
|
||||
local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
|
||||
//xxx = local_stack_frame_get_map_value(pframe, pstatement->local_lhs_frame_relative_index, pmvkeys);
|
||||
|
||||
// Locate and copy the submap indexed by the keylist. E.g. in 'for ((k1, k2), v in a[3][$4])
|
||||
// { ... }', the submap is first indexed by the stack-frame slot for "a", then further
|
||||
// indexed by [3, $4]. Copy it for the very likely case that it is being updated inside the
|
||||
// for-loop.
|
||||
|
||||
mlhmmv_value_t *psubmap = local_stack_frame_get_map_value(pframe,
|
||||
pstatement->for_map_target_frame_relative_index, plhskeylist);
|
||||
// xxx copy !!!
|
||||
|
||||
local_stack_subframe_enter(pframe, pstatement->pstatement_block->subframe_var_count);
|
||||
loop_stack_push(pvars->ploop_stack);
|
||||
|
||||
// Locate and copy the submap indexed by the keylist. E.g. in 'for ((k1, k2), v in @a[3][$4]) { ... }', the
|
||||
// submap is indexed by ["a", 3, $4]. Copy it for the very likely case that it is being updated inside the
|
||||
// for-loop.
|
||||
mlhmmv_value_t submap = mlhmmv_copy_submap(pvars->poosvars, plhskeylist); // xxx local-map
|
||||
|
||||
if (!submap.is_terminal && submap.u.pnext_level != NULL) {
|
||||
if (!psubmap->is_terminal && psubmap->u.pnext_level != NULL) {
|
||||
// Recurse over the for-k-names, e.g. ["k1", "k2"], on each call descending one level
|
||||
// deeper into the submap. Note there must be at least one k-name so we are assuming
|
||||
// the for-loop within handle_for_local_map_aux was gone through once & thus
|
||||
// handle_statement_block_with_break_continue was called through there.
|
||||
|
||||
handle_for_local_map_aux(pstatement, pvars, pcst_outputs, submap,
|
||||
handle_for_local_map_aux(pstatement, pvars, pcst_outputs, psubmap,
|
||||
pstatement->for_map_k_variable_names, pstatement->for_map_k_frame_relative_indices,
|
||||
pstatement->for_map_k_type_masks, pstatement->for_map_k_count);
|
||||
|
||||
|
|
@ -3070,7 +3084,8 @@ static void handle_for_local_map( // xxx vardef_frame_relative_index
|
|||
}
|
||||
}
|
||||
|
||||
mlhmmv_free_submap(submap);
|
||||
// xxx only after impl copy !!!
|
||||
// mlhmmv_free_submap(submap);
|
||||
|
||||
loop_stack_pop(pvars->ploop_stack);
|
||||
local_stack_subframe_exit(pframe, pstatement->pstatement_block->subframe_var_count);
|
||||
|
|
@ -3082,7 +3097,7 @@ static void handle_for_local_map_aux( // xxx vardef_frame_relative_index
|
|||
mlr_dsl_cst_statement_t* pstatement,
|
||||
variables_t* pvars,
|
||||
cst_outputs_t* pcst_outputs,
|
||||
mlhmmv_value_t submap,
|
||||
mlhmmv_value_t* psubmap,
|
||||
char** prest_for_k_variable_names,
|
||||
int* prest_for_k_frame_relative_indices,
|
||||
int* prest_for_k_type_masks,
|
||||
|
|
@ -3090,17 +3105,17 @@ static void handle_for_local_map_aux( // xxx vardef_frame_relative_index
|
|||
{
|
||||
if (prest_for_k_count > 0) { // Keep recursing over remaining k-names
|
||||
|
||||
if (submap.is_terminal) {
|
||||
if (psubmap->is_terminal) {
|
||||
// The submap was too shallow for the user-specified k-names; there are no terminals here.
|
||||
} else {
|
||||
// Loop over keys at this submap level:
|
||||
for (mlhmmv_level_entry_t* pe = submap.u.pnext_level->phead; pe != NULL; pe = pe->pnext) {
|
||||
for (mlhmmv_level_entry_t* pe = psubmap->u.pnext_level->phead; pe != NULL; pe = pe->pnext) {
|
||||
// Bind the k-name to the entry-key mlrval:
|
||||
local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
|
||||
local_stack_frame_define(pframe, prest_for_k_variable_names[0], prest_for_k_frame_relative_indices[0],
|
||||
prest_for_k_type_masks[0], mv_copy(&pe->level_key));
|
||||
// Recurse into the next-level submap:
|
||||
handle_for_local_map_aux(pstatement, pvars, pcst_outputs, pe->level_value,
|
||||
handle_for_local_map_aux(pstatement, pvars, pcst_outputs, &pe->level_value,
|
||||
&prest_for_k_variable_names[1], &prest_for_k_frame_relative_indices[1], &prest_for_k_type_masks[1],
|
||||
prest_for_k_count - 1);
|
||||
|
||||
|
|
@ -3116,13 +3131,13 @@ static void handle_for_local_map_aux( // xxx vardef_frame_relative_index
|
|||
|
||||
} else { // End of recursion: k-names have all been used up
|
||||
|
||||
if (!submap.is_terminal) {
|
||||
if (!psubmap->is_terminal) {
|
||||
// The submap was too deep for the user-specified k-names; there are no terminals here.
|
||||
} else {
|
||||
// Bind the v-name to the terminal mlrval:
|
||||
local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
|
||||
local_stack_frame_define(pframe, pstatement->for_v_variable_name, pstatement->for_v_frame_relative_index,
|
||||
pstatement->for_v_type_mask, mv_copy(&submap.u.mlrval));
|
||||
pstatement->for_v_type_mask, mv_copy(&psubmap->u.mlrval));
|
||||
// Execute the loop-body statements:
|
||||
pstatement->pblock_handler(pstatement->pstatement_block, pvars, pcst_outputs);
|
||||
}
|
||||
|
|
@ -3148,12 +3163,12 @@ static void handle_for_local_map_key_only( // xxx vardef_frame_relative_index
|
|||
// submap is indexed by ["a", 3, $4]. Copy it for the very likely case that it is being updated inside the
|
||||
// for-loop.
|
||||
|
||||
sllv_t* pkeys = mlhmmv_copy_keys_from_submap(pvars->poosvars, plhskeylist); // xxx for-local-maQ
|
||||
|
||||
local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
|
||||
local_stack_subframe_enter(pframe, pstatement->pstatement_block->subframe_var_count);
|
||||
loop_stack_push(pvars->ploop_stack);
|
||||
|
||||
sllv_t* pkeys = mlhmmv_copy_keys_from_submap(pvars->poosvars, plhskeylist); // xxx for-local-maQ
|
||||
|
||||
for (sllve_t* pe = pkeys->phead; pe != NULL; pe = pe->pnext) {
|
||||
// Bind the v-name to the terminal mlrval:
|
||||
local_stack_frame_define(pframe,
|
||||
|
|
|
|||
|
|
@ -507,6 +507,11 @@ static void pass_1_for_map_key_only_for_loop(mlr_dsl_ast_node_t* pnode, stkalc_s
|
|||
//
|
||||
// Example: 'for(a in @b[c][d]) { var e = a}': the c and d
|
||||
// should be obtained from the enclosing scope.
|
||||
|
||||
if (pkeylistnode->type == MD_AST_NODE_TYPE_LOCAL_NON_MAP_VARIABLE) {
|
||||
// For-local-map: e.g. 'for(a in b[c][d])'.
|
||||
pass_1_for_node(pkeylistnode, pframe_group, pmax_subframe_depth, trace);
|
||||
}
|
||||
for (sllve_t* pe = pkeylistnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
|
||||
mlr_dsl_ast_node_t* pchild = pe->pvvalue;
|
||||
pass_1_for_node(pchild, pframe_group, pmax_subframe_depth, trace);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue