mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-23 07:59:37 +00:00
194 lines
5.4 KiB
C
194 lines
5.4 KiB
C
#include <stdlib.h>
|
|
#include "lib/mlrutil.h"
|
|
#include "lib/mlr_globals.h"
|
|
#include "containers/bind_stack.h"
|
|
|
|
#define INITIAL_SIZE 32
|
|
|
|
// ----------------------------------------------------------------
|
|
// Private to .c file
|
|
struct _bind_stack_frame_t {
|
|
lhmsmv_t* pbindings;
|
|
char fenced;
|
|
char ephemeral;
|
|
char in_use;
|
|
};
|
|
|
|
// ----------------------------------------------------------------
|
|
bind_stack_t* bind_stack_alloc() {
|
|
bind_stack_t* pstack = mlr_malloc_or_die(sizeof(bind_stack_t));
|
|
|
|
pstack->num_used = 0;
|
|
pstack->num_allocated = INITIAL_SIZE;
|
|
|
|
pstack->ppframes = mlr_malloc_or_die(pstack->num_allocated * sizeof(bind_stack_frame_t*));
|
|
memset(pstack->ppframes, 0, pstack->num_allocated * sizeof(bind_stack_frame_t*));
|
|
|
|
pstack->pbase_frame = bind_stack_frame_alloc_unfenced();
|
|
bind_stack_push(pstack, pstack->pbase_frame);
|
|
|
|
return pstack;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
void bind_stack_free(bind_stack_t* pstack) {
|
|
if (pstack == NULL)
|
|
return;
|
|
|
|
bind_stack_frame_free(pstack->pbase_frame);
|
|
free(pstack->ppframes);
|
|
free(pstack);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
static inline bind_stack_frame_t* bind_stack_frame_alloc(int fenced, int ephemeral) {
|
|
bind_stack_frame_t* pframe = mlr_malloc_or_die(sizeof(bind_stack_frame_t));
|
|
pframe->pbindings = lhmsmv_alloc();
|
|
pframe->fenced = fenced;
|
|
pframe->ephemeral = ephemeral;
|
|
pframe->in_use = FALSE;
|
|
return pframe;
|
|
}
|
|
|
|
bind_stack_frame_t* bind_stack_frame_alloc_unfenced() {
|
|
return bind_stack_frame_alloc(FALSE, FALSE);
|
|
}
|
|
|
|
bind_stack_frame_t* bind_stack_frame_alloc_fenced() {
|
|
return bind_stack_frame_alloc(TRUE, FALSE);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
void bind_stack_frame_free(bind_stack_frame_t* pframe) {
|
|
lhmsmv_free(pframe->pbindings);
|
|
free(pframe);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// xxx cmt
|
|
bind_stack_frame_t* bind_stack_frame_enter(bind_stack_frame_t* pframe) {
|
|
if (pframe->in_use) {
|
|
bind_stack_frame_t* pephemeral = bind_stack_frame_alloc(pframe->fenced, TRUE);
|
|
pephemeral->in_use = TRUE;
|
|
return pephemeral;
|
|
} else {
|
|
pframe->in_use = TRUE;
|
|
return pframe;
|
|
}
|
|
}
|
|
|
|
void bind_stack_frame_exit(bind_stack_frame_t* pframe) {
|
|
if (pframe->ephemeral) {
|
|
bind_stack_frame_free(pframe);
|
|
} else {
|
|
lhmsmv_clear(pframe->pbindings);
|
|
pframe->in_use = FALSE;
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
void bind_stack_push(bind_stack_t* pstack, bind_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(bind_stack_frame_t*));
|
|
}
|
|
pstack->ppframes[pstack->num_used] = pframe;
|
|
pstack->num_used++;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
bind_stack_frame_t* bind_stack_pop(bind_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);
|
|
}
|
|
|
|
bind_stack_frame_t* pframe = pstack->ppframes[pstack->num_used-1];
|
|
pstack->num_used--;
|
|
return pframe;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// xxx cmt
|
|
mv_t* bind_stack_resolve(bind_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 bind_stack_define(bind_stack_t* pstack, char* name, mv_t* pmv, char free_flags) {
|
|
bind_stack_frame_t* ptop_frame = pstack->ppframes[pstack->num_used - 1];
|
|
lhmsmv_put(ptop_frame->pbindings, name, pmv, free_flags);
|
|
}
|
|
|
|
void bind_stack_set(bind_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--) {
|
|
bind_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;
|
|
}
|
|
}
|
|
|
|
bind_stack_frame_t* ptop_frame = pstack->ppframes[pstack->num_used - 1];
|
|
lhmsmv_put(ptop_frame->pbindings, name, pmv, free_flags);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
void bind_stack_clear(bind_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 bind_stack_print(bind_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");
|
|
}
|
|
|