mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-23 16:08:43 +00:00
local-stack iterate
This commit is contained in:
parent
75dce976bc
commit
d0c48eb02b
2 changed files with 216 additions and 238 deletions
|
|
@ -3,192 +3,183 @@
|
|||
#include "lib/mlr_globals.h"
|
||||
#include "containers/local_stack.h"
|
||||
|
||||
#define INITIAL_SIZE 32
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Private to .c file
|
||||
struct _local_stack_frame_t {
|
||||
lhmsmv_t* pbindings;
|
||||
char fenced;
|
||||
char ephemeral;
|
||||
char in_use;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
local_stack_t* local_stack_alloc() {
|
||||
local_stack_t* local_stack_alloc(int size) {
|
||||
local_stack_t* pstack = mlr_malloc_or_die(sizeof(local_stack_t));
|
||||
|
||||
pstack->num_used = 0;
|
||||
pstack->num_allocated = INITIAL_SIZE;
|
||||
|
||||
pstack->ppframes = mlr_malloc_or_die(pstack->num_allocated * sizeof(local_stack_frame_t*));
|
||||
memset(pstack->ppframes, 0, pstack->num_allocated * sizeof(local_stack_frame_t*));
|
||||
|
||||
pstack->pbase_frame = local_stack_frame_alloc_unfenced();
|
||||
local_stack_push(pstack, pstack->pbase_frame);
|
||||
pstack->in_use = FALSE;
|
||||
pstack->size = size;
|
||||
pstack->pvars = mlr_malloc_or_die(size * sizeof(mv_t));
|
||||
for (int i = 0; i < size; i++) {
|
||||
pstack->pvars[i] = mv_absent();
|
||||
}
|
||||
|
||||
return pstack;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_free(local_stack_t* pstack) {
|
||||
if (pstack == NULL)
|
||||
return;
|
||||
|
||||
local_stack_frame_free(pstack->pbase_frame);
|
||||
free(pstack->ppframes);
|
||||
free(pstack);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static inline local_stack_frame_t* local_stack_frame_alloc(int fenced, int ephemeral) {
|
||||
local_stack_frame_t* pframe = mlr_malloc_or_die(sizeof(local_stack_frame_t));
|
||||
pframe->pbindings = lhmsmv_alloc();
|
||||
pframe->fenced = fenced;
|
||||
pframe->ephemeral = ephemeral;
|
||||
pframe->in_use = FALSE;
|
||||
return pframe;
|
||||
}
|
||||
|
||||
local_stack_frame_t* local_stack_frame_alloc_unfenced() {
|
||||
return local_stack_frame_alloc(FALSE, FALSE);
|
||||
}
|
||||
|
||||
local_stack_frame_t* local_stack_frame_alloc_fenced() {
|
||||
return local_stack_frame_alloc(TRUE, FALSE);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_frame_free(local_stack_frame_t* pframe) {
|
||||
lhmsmv_free(pframe->pbindings);
|
||||
free(pframe);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// xxx cmt
|
||||
local_stack_frame_t* local_stack_frame_enter(local_stack_frame_t* pframe) {
|
||||
if (pframe->in_use) {
|
||||
local_stack_frame_t* pephemeral = local_stack_frame_alloc(pframe->fenced, TRUE);
|
||||
pephemeral->in_use = TRUE;
|
||||
return pephemeral;
|
||||
} else {
|
||||
pframe->in_use = TRUE;
|
||||
return pframe;
|
||||
}
|
||||
}
|
||||
|
||||
void local_stack_frame_exit(local_stack_frame_t* pframe) {
|
||||
if (pframe->ephemeral) {
|
||||
local_stack_frame_free(pframe);
|
||||
} else {
|
||||
lhmsmv_clear(pframe->pbindings);
|
||||
pframe->in_use = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_push(local_stack_t* pstack, local_stack_frame_t* pframe) {
|
||||
if (pstack->num_used >= pstack->num_allocated) {
|
||||
pstack->num_allocated += INITIAL_SIZE;
|
||||
pstack->ppframes = mlr_realloc_or_die(pstack->ppframes,
|
||||
pstack->num_allocated * sizeof(local_stack_frame_t*));
|
||||
}
|
||||
pstack->ppframes[pstack->num_used] = pframe;
|
||||
pstack->num_used++;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
local_stack_frame_t* local_stack_pop(local_stack_t* pstack) {
|
||||
if (pstack->num_used <= 0) {
|
||||
fprintf(stderr, "%s: internal coding error detected in file %s at line %d.\n",
|
||||
MLR_GLOBALS.bargv0, __FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
local_stack_frame_t* pframe = pstack->ppframes[pstack->num_used-1];
|
||||
pstack->num_used--;
|
||||
return pframe;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// xxx cmt
|
||||
mv_t* local_stack_resolve(local_stack_t* pstack, char* name) {
|
||||
for (int i = pstack->num_used - 1; i >= 0; i--) {
|
||||
mv_t* pval = lhmsmv_get(pstack->ppframes[i]->pbindings, name);
|
||||
if (pval != NULL) {
|
||||
return pval;
|
||||
}
|
||||
if (pstack->ppframes[i]->fenced) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// xxx
|
||||
//// ----------------------------------------------------------------
|
||||
//void local_stack_free(local_stack_t* pstack) {
|
||||
// if (pstack == NULL)
|
||||
// return;
|
||||
//
|
||||
// run_mlr --opprint --from $indir/abixy put '
|
||||
// func f(x) {
|
||||
// local a = 1;
|
||||
// if (NR > 5) {
|
||||
// a = 2;
|
||||
// }
|
||||
// return a;
|
||||
// }
|
||||
// local_stack_frame_free(pstack->pbase_frame);
|
||||
// free(pstack->ppframes);
|
||||
// free(pstack);
|
||||
//}
|
||||
|
||||
//// ----------------------------------------------------------------
|
||||
//static inline local_stack_frame_t* local_stack_frame_alloc(int fenced, int ephemeral) {
|
||||
// local_stack_frame_t* pframe = mlr_malloc_or_die(sizeof(local_stack_frame_t));
|
||||
// pframe->pbindings = lhmsmv_alloc();
|
||||
// pframe->fenced = fenced;
|
||||
// pframe->ephemeral = ephemeral;
|
||||
// pframe->in_use = FALSE;
|
||||
// return pframe;
|
||||
//}
|
||||
//
|
||||
//local_stack_frame_t* local_stack_frame_alloc_unfenced() {
|
||||
// return local_stack_frame_alloc(FALSE, FALSE);
|
||||
//}
|
||||
//
|
||||
//local_stack_frame_t* local_stack_frame_alloc_fenced() {
|
||||
// return local_stack_frame_alloc(TRUE, FALSE);
|
||||
//}
|
||||
//
|
||||
//// ----------------------------------------------------------------
|
||||
//void local_stack_frame_free(local_stack_frame_t* pframe) {
|
||||
// lhmsmv_free(pframe->pbindings);
|
||||
// free(pframe);
|
||||
//}
|
||||
//
|
||||
//// ----------------------------------------------------------------
|
||||
//// xxx cmt
|
||||
//local_stack_frame_t* local_stack_frame_enter(local_stack_frame_t* pframe) {
|
||||
// if (pframe->in_use) {
|
||||
// local_stack_frame_t* pephemeral = local_stack_frame_alloc(pframe->fenced, TRUE);
|
||||
// pephemeral->in_use = TRUE;
|
||||
// return pephemeral;
|
||||
// } else {
|
||||
// pframe->in_use = TRUE;
|
||||
// return pframe;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//void local_stack_frame_exit(local_stack_frame_t* pframe) {
|
||||
// if (pframe->ephemeral) {
|
||||
// local_stack_frame_free(pframe);
|
||||
// } else {
|
||||
// lhmsmv_clear(pframe->pbindings);
|
||||
// pframe->in_use = FALSE;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//// ----------------------------------------------------------------
|
||||
//void local_stack_push(local_stack_t* pstack, local_stack_frame_t* pframe) {
|
||||
// if (pstack->num_used >= pstack->num_allocated) {
|
||||
// pstack->num_allocated += INITIAL_SIZE;
|
||||
// pstack->ppframes = mlr_realloc_or_die(pstack->ppframes,
|
||||
// pstack->num_allocated * sizeof(local_stack_frame_t*));
|
||||
// }
|
||||
// pstack->ppframes[pstack->num_used] = pframe;
|
||||
// pstack->num_used++;
|
||||
//}
|
||||
//
|
||||
//// ----------------------------------------------------------------
|
||||
//local_stack_frame_t* local_stack_pop(local_stack_t* pstack) {
|
||||
// if (pstack->num_used <= 0) {
|
||||
// fprintf(stderr, "%s: internal coding error detected in file %s at line %d.\n",
|
||||
// MLR_GLOBALS.bargv0, __FILE__, __LINE__);
|
||||
// exit(1);
|
||||
// }
|
||||
//
|
||||
// local_stack_frame_t* pframe = pstack->ppframes[pstack->num_used-1];
|
||||
// pstack->num_used--;
|
||||
// return pframe;
|
||||
//}
|
||||
//
|
||||
//// ----------------------------------------------------------------
|
||||
//// xxx cmt
|
||||
//mv_t* local_stack_resolve(local_stack_t* pstack, char* name) {
|
||||
// for (int i = pstack->num_used - 1; i >= 0; i--) {
|
||||
// mv_t* pval = lhmsmv_get(pstack->ppframes[i]->pbindings, name);
|
||||
// if (pval != NULL) {
|
||||
// return pval;
|
||||
// }
|
||||
// if (pstack->ppframes[i]->fenced) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// return NULL;
|
||||
//}
|
||||
//
|
||||
//// ----------------------------------------------------------------
|
||||
//// xxx
|
||||
////
|
||||
//// run_mlr --opprint --from $indir/abixy put '
|
||||
//// func f(x) {
|
||||
//// local a = 1;
|
||||
//// if (NR > 5) {
|
||||
//// a = 2;
|
||||
//// }
|
||||
//// return a;
|
||||
//// }
|
||||
////
|
||||
//// func g(x) {
|
||||
//// local b = 1;
|
||||
//// if (NR > 5) {
|
||||
//// local b = 2;
|
||||
//// }
|
||||
//// return b;
|
||||
//// }
|
||||
//// $of = f(NR);
|
||||
//// $og = g(NR);
|
||||
//// '
|
||||
//
|
||||
//void local_stack_define(local_stack_t* pstack, char* name, mv_t* pmv, char free_flags) {
|
||||
// local_stack_frame_t* ptop_frame = pstack->ppframes[pstack->num_used - 1];
|
||||
// lhmsmv_put(ptop_frame->pbindings, name, pmv, free_flags);
|
||||
//}
|
||||
//
|
||||
//void local_stack_set(local_stack_t* pstack, char* name, mv_t* pmv, char free_flags) {
|
||||
//
|
||||
// // xxx comment
|
||||
// // xxx test thoroughly
|
||||
// for (int i = pstack->num_used - 1; i >= 0; i--) {
|
||||
// local_stack_frame_t* pframe = pstack->ppframes[i];
|
||||
// if (lhmsmv_get(pframe->pbindings, name)) {
|
||||
// lhmsmv_put(pframe->pbindings, name, pmv, free_flags);
|
||||
// return;
|
||||
// }
|
||||
// if (pstack->ppframes[i]->fenced) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// local_stack_frame_t* ptop_frame = pstack->ppframes[pstack->num_used - 1];
|
||||
// lhmsmv_put(ptop_frame->pbindings, name, pmv, free_flags);
|
||||
//}
|
||||
//
|
||||
//// ----------------------------------------------------------------
|
||||
//void local_stack_clear(local_stack_t* pstack) {
|
||||
// if (pstack->num_used <= 0) {
|
||||
// fprintf(stderr, "%s: internal coding error detected in file %s at line %d.\n",
|
||||
// MLR_GLOBALS.bargv0, __FILE__, __LINE__);
|
||||
// exit(1);
|
||||
// }
|
||||
// lhmsmv_clear(pstack->ppframes[pstack->num_used-1]->pbindings);
|
||||
//}
|
||||
//
|
||||
//// ----------------------------------------------------------------
|
||||
//void local_stack_print(local_stack_t* pstack) {
|
||||
// printf("BIND STACK BEGIN (#frames %d):\n", pstack->num_used);
|
||||
// for (int i = pstack->num_used - 1; i >= 0; i--) {
|
||||
// printf("-- FRAME %d (fenced:%d):\n", i, pstack->ppframes[i]->fenced);
|
||||
// lhmsmv_dump(pstack->ppframes[i]->pbindings);
|
||||
// }
|
||||
// printf("BIND STACK END\n");
|
||||
//}
|
||||
//
|
||||
// func g(x) {
|
||||
// local b = 1;
|
||||
// if (NR > 5) {
|
||||
// local b = 2;
|
||||
// }
|
||||
// return b;
|
||||
// }
|
||||
// $of = f(NR);
|
||||
// $og = g(NR);
|
||||
// '
|
||||
|
||||
void local_stack_define(local_stack_t* pstack, char* name, mv_t* pmv, char free_flags) {
|
||||
local_stack_frame_t* ptop_frame = pstack->ppframes[pstack->num_used - 1];
|
||||
lhmsmv_put(ptop_frame->pbindings, name, pmv, free_flags);
|
||||
}
|
||||
|
||||
void local_stack_set(local_stack_t* pstack, char* name, mv_t* pmv, char free_flags) {
|
||||
|
||||
// xxx comment
|
||||
// xxx test thoroughly
|
||||
for (int i = pstack->num_used - 1; i >= 0; i--) {
|
||||
local_stack_frame_t* pframe = pstack->ppframes[i];
|
||||
if (lhmsmv_get(pframe->pbindings, name)) {
|
||||
lhmsmv_put(pframe->pbindings, name, pmv, free_flags);
|
||||
return;
|
||||
}
|
||||
if (pstack->ppframes[i]->fenced) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
local_stack_frame_t* ptop_frame = pstack->ppframes[pstack->num_used - 1];
|
||||
lhmsmv_put(ptop_frame->pbindings, name, pmv, free_flags);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_clear(local_stack_t* pstack) {
|
||||
if (pstack->num_used <= 0) {
|
||||
fprintf(stderr, "%s: internal coding error detected in file %s at line %d.\n",
|
||||
MLR_GLOBALS.bargv0, __FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
lhmsmv_clear(pstack->ppframes[pstack->num_used-1]->pbindings);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
void local_stack_print(local_stack_t* pstack) {
|
||||
printf("BIND STACK BEGIN (#frames %d):\n", pstack->num_used);
|
||||
for (int i = pstack->num_used - 1; i >= 0; i--) {
|
||||
printf("-- FRAME %d (fenced:%d):\n", i, pstack->ppframes[i]->fenced);
|
||||
lhmsmv_dump(pstack->ppframes[i]->pbindings);
|
||||
}
|
||||
printf("BIND STACK END\n");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,80 +2,67 @@
|
|||
#define LOCAL_STACK_H
|
||||
|
||||
#include "containers/mlrval.h"
|
||||
#include "containers/lhmsmv.h"
|
||||
|
||||
// Bound & scoped variables for use in for-loops, function bodies, and
|
||||
// subroutine bodies. A frame is 'fenced' if it's at entry to a
|
||||
// function/subroutine body. Example:
|
||||
// subroutine bodies. Indices of local variables, and max-depth for top-level
|
||||
// statement blocks, are compted by the stack-allocator which marks up the AST
|
||||
// before the CST is built from it.
|
||||
//
|
||||
// mlr ... put -f '
|
||||
// func f(x) {
|
||||
// return k;
|
||||
// }
|
||||
// for (k,v in $*) {
|
||||
// $[k] = f(v)
|
||||
// }
|
||||
// '
|
||||
//
|
||||
// There is a bind-stack created on entering the put. A frame is pushed in the
|
||||
// for-loop. A second frame is pushed in the call to f(x). The former should
|
||||
// have access to k; the latter should not.
|
||||
// A convention shared between the stack-allocator and this data structure is
|
||||
// that slot 0 is an absent-null which is used for reads of undefined (or
|
||||
// as-yet-undefined) local variables.
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Data private to .c file
|
||||
typedef struct _local_stack_frame_t local_stack_frame_t;
|
||||
|
||||
typedef struct _local_stack_t {
|
||||
int num_used;
|
||||
int num_allocated;
|
||||
local_stack_frame_t** ppframes;
|
||||
local_stack_frame_t* pbase_frame;
|
||||
int in_use;
|
||||
int size;
|
||||
mv_t* pvars;
|
||||
} local_stack_t;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Constructors/destructors
|
||||
|
||||
local_stack_t* local_stack_alloc();
|
||||
local_stack_t* local_stack_alloc(int size);
|
||||
void local_stack_free(local_stack_t* pstack);
|
||||
|
||||
local_stack_frame_t* local_stack_frame_alloc_unfenced();
|
||||
local_stack_frame_t* local_stack_frame_alloc_fenced();
|
||||
void local_stack_frame_free(local_stack_frame_t* pframe);
|
||||
|
||||
// xxx comment
|
||||
local_stack_frame_t* local_stack_frame_enter(local_stack_frame_t* pframe);
|
||||
void local_stack_frame_exit(local_stack_frame_t* pframe);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Scope entry/exit
|
||||
|
||||
// To be called on entry to scoped block
|
||||
void local_stack_push(local_stack_t* pstack, local_stack_frame_t* pframe);
|
||||
|
||||
// To be called on exit from scoped block.
|
||||
local_stack_frame_t* local_stack_pop(local_stack_t* pstack);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Access within scope
|
||||
|
||||
// Use of local variables on expression right-hand sides
|
||||
mv_t* local_stack_resolve(local_stack_t* pstack, char* key);
|
||||
|
||||
// Use of local variables on expression left-hand sides
|
||||
// The pmv is not copied. You may wish to mv_copy the argument you pass in.
|
||||
// The pmv will be freed.
|
||||
|
||||
// xxx cmt
|
||||
void local_stack_define(local_stack_t* pstack, char* name, mv_t* pmv, char free_flags);
|
||||
void local_stack_set(local_stack_t* pstack, char* name, mv_t* pmv, char free_flags);
|
||||
|
||||
// Clears the binding from the top frame without popping it. Useful
|
||||
// for clearing the baseframe which is never popped.
|
||||
void local_stack_clear(local_stack_t* pstack);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Test/debug
|
||||
|
||||
void local_stack_print(local_stack_t* pstack);
|
||||
//local_stack_frame_t* local_stack_frame_alloc_unfenced();
|
||||
//local_stack_frame_t* local_stack_frame_alloc_fenced();
|
||||
//void local_stack_frame_free(local_stack_frame_t* pframe);
|
||||
//
|
||||
//// xxx comment
|
||||
//local_stack_frame_t* local_stack_frame_enter(local_stack_frame_t* pframe);
|
||||
//void local_stack_frame_exit(local_stack_frame_t* pframe);
|
||||
//
|
||||
//// ----------------------------------------------------------------
|
||||
//// Scope entry/exit
|
||||
//
|
||||
//// To be called on entry to scoped block
|
||||
//void local_stack_push(local_stack_t* pstack, local_stack_frame_t* pframe);
|
||||
//
|
||||
//// To be called on exit from scoped block.
|
||||
//local_stack_frame_t* local_stack_pop(local_stack_t* pstack);
|
||||
//
|
||||
//// ----------------------------------------------------------------
|
||||
//// Access within scope
|
||||
//
|
||||
//// Use of local variables on expression right-hand sides
|
||||
//mv_t* local_stack_resolve(local_stack_t* pstack, char* key);
|
||||
//
|
||||
//// Use of local variables on expression left-hand sides
|
||||
//// The pmv is not copied. You may wish to mv_copy the argument you pass in.
|
||||
//// The pmv will be freed.
|
||||
//
|
||||
//// xxx cmt
|
||||
//void local_stack_define(local_stack_t* pstack, char* name, mv_t* pmv, char free_flags);
|
||||
//void local_stack_set(local_stack_t* pstack, char* name, mv_t* pmv, char free_flags);
|
||||
//
|
||||
//// Clears the binding from the top frame without popping it. Useful
|
||||
//// for clearing the baseframe which is never popped.
|
||||
//void local_stack_clear(local_stack_t* pstack);
|
||||
//
|
||||
//// ----------------------------------------------------------------
|
||||
//// Test/debug
|
||||
//
|
||||
//void local_stack_print(local_stack_t* pstack);
|
||||
|
||||
#endif // LOCAL_STACK_H
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue