~tim/lydia

ac491010406397ebf135aa7cc0de4489660823a3 — Tim Morgan 7 years ago 025d432
Backfill vars from function closure on tail calls.
3 files changed, 23 insertions(+), 2 deletions(-)

M src/closure.c
M src/closure.h
M src/funcs.c
M src/closure.c => src/closure.c +19 -0
@@ 28,6 28,15 @@ LClosure *l_closure_clone(LClosure *parent, LNode *node) {
  return closure;
}

// copies keys from the source that don't exist on the target
LClosure *l_closure_backfill(LClosure *source, LClosure *target, LNode *node) {
  l_debug(L_DEBUG_STACK) printf("+++ backfilling closure\n");
  target->node = node;
  l_clone_vars_if_missing(source->vars, target->vars);
  l_clone_vars_if_missing(source->locals, target->locals);
  return target;
}

static void l_clone_var_iter(char *key, void *ref, void *to) {
  l_ref_put((hashmap_p)to, key, (LValue**)ref);
}


@@ 37,6 46,16 @@ void l_clone_vars(hashmap_p from, hashmap_p to) {
  hashmap_each(from, l_clone_var_iter, to);
}

static void l_clone_var_if_missing_iter(char *key, void *ref, void *to) {
  if(!hashmap_get((hashmap_p)to, key)) {
    l_ref_put((hashmap_p)to, key, (LValue**)ref);
  }
}

void l_clone_vars_if_missing(hashmap_p from, hashmap_p to) {
  hashmap_each(from, l_clone_var_if_missing_iter, to);
}

void l_closure_free(LClosure *closure) {
  l_debug(L_DEBUG_STACK) printf("--- freeing closure\n");
  if(closure->parent == NULL) return;

M src/closure.h => src/closure.h +2 -0
@@ 12,7 12,9 @@ typedef struct LClosure {

LClosure *l_closure_new(LNode *node);
LClosure *l_closure_clone(LClosure *parent, LNode *node);
LClosure *l_closure_backfill(LClosure *source, LClosure *target, LNode *node);
void l_clone_vars(hashmap_p from, hashmap_p to);
void l_clone_vars_if_missing(hashmap_p from, hashmap_p to);
void l_closure_free(LClosure *closure);
LClosure *l_closure_root(LClosure *closure);
LValue **l_ref_get(hashmap_p hash, char *name);

M src/funcs.c => src/funcs.c +2 -2
@@ 37,7 37,7 @@ tail_loop:
      node = NULL;
      func = l_closure_get(cl, "--tail-call--");
      closure = cl;
      cl = func->core.func.closure;
      l_closure_backfill(func->core.func.closure, cl, node);
      name = "";
      goto tail_loop;
    }


@@ 56,7 56,7 @@ tail_loop:
        node = expr;
        func = l_eval_var_node(node, cl);
        closure = cl;
        cl = func->core.func.closure;
        l_closure_backfill(func->core.func.closure, cl, node);
        name = node->val;
        goto tail_loop;
      } else {