~tim/lydia

bbecd6ab1f6277a36fd140524218f86e5000ac26 — Tim Morgan 8 years ago 3a7873f
Refactor arg pass by ref.
3 files changed, 21 insertions(+), 18 deletions(-)

M src/closure.c
M src/closure.h
M src/funcs.c
M src/closure.c => src/closure.c +12 -0
@@ 110,6 110,18 @@ LValue **l_closure_get_ref(LClosure *closure, char *name) {
  }
}

LValue **l_closure_pass_by_ref(LNode *node, char *name, LClosure *outer_closure, LClosure *inner_closure) {
  LValue **ref = l_closure_get_ref(outer_closure, node->val);
  if(ref != NULL) {
    if(name != NULL) l_ref_put(inner_closure->locals, name, ref);
    return ref;
  } else {
    // handle error
    l_eval_var_node(node, outer_closure);
    return NULL;
  }
}

static void l_inspect_closure_iter(char *key, void *ref, void *opt) {
  char buf[255] = "";
  printf("  %s = %s\n", key, l_inspect_to_str(*(LValue**)ref, buf, 255));

M src/closure.h => src/closure.h +1 -0
@@ 20,6 20,7 @@ void l_closure_set(LClosure *closure, char *name, LValue *value, bool local);
void l_closure_set_funcs(LClosure *closure);
LValue *l_closure_get(LClosure *closure, char *name);
LValue **l_closure_get_ref(LClosure *closure, char *name);
LValue **l_closure_pass_by_ref(LNode *node, char *name, LClosure *outer_closure, LClosure *inner_closure);

void l_inspect_closure(LClosure* closure);
int l_closure_size(LClosure *closure);

M src/funcs.c => src/funcs.c +8 -18
@@ 75,26 75,16 @@ LValue *l_eval_call_args(LNode *node, LValue *func, LClosure *outer_closure, LCl
  argsVal->core.list = create_vector();
  l_closure_set(inner_closure, "args", argsVal, true);

  char *arg_name;

  // set all passed args
  for(i=0; i<argc; i++) {
    if(args[i]->type == L_VAR_TYPE) {
      // L_VAR_TYPE is special case, since we must link the local to the parent (outer) closure var
      ref = l_closure_get_ref(outer_closure, args[i]->val);
      if(ref != NULL) {
        v = l_closure_get(outer_closure, args[i]->val);
        if(i < func->core.func.argc) {
          // store as named arg (uses ref so that it points to the same var)
          l_ref_put(inner_closure->locals, func->core.func.args[i]->val, ref);
        }
      } else {
        v = l_value_new(L_ERR_TYPE, outer_closure);
        v->core.str = make_stringbuf(args[i]->val);
        buffer_concat(v->core.str, " not found");
        l_handle_error(v, node, outer_closure);
      }
    } else {
      // eval as normal and set the value
      v = l_eval_node(args[i], outer_closure); // use outer closure
    if(args[i]->type == L_VAR_TYPE) { // pass vars by reference
      arg_name = (i < func->core.func.argc) ? func->core.func.args[i]->val : NULL;
      ref = l_closure_pass_by_ref(args[i], arg_name, outer_closure, inner_closure);
      v = *ref;
    } else { // eval as normal and set the value
      v = l_eval_node(args[i], outer_closure);
      if(i < func->core.func.argc) {
        l_closure_set(inner_closure, func->core.func.args[i]->val, v, true);
      }