~tim/lydia

3a7873f12805cfcebbc3b7f3cbe892519c0430d0 — Tim Morgan 8 years ago 1f37fc4
Refactor function call evaluation.
6 files changed, 71 insertions(+), 71 deletions(-)

M src/eval.c
M src/eval.h
M src/funcs.c
M src/funcs.h
M src/lib/logic.c
M src/lib/logic.h
M src/eval.c => src/eval.c +1 -16
@@ 23,7 23,7 @@ LValue *l_eval_node(LNode *node, LClosure *closure) {
      value = l_eval_func_node(node, closure);
      break;
    case L_CALL_TYPE:
      value = l_eval_call_node(node, closure);
      value = l_eval_call_node(node, NULL, closure);
      break;
    case L_ASSIGN_TYPE:
      value = l_eval_assign_node(node, closure);


@@ 126,21 126,6 @@ LValue *l_eval_func_node(LNode *node, LClosure *closure) {
  return value;
}

LValue *l_eval_call_node(LNode *node, LClosure *closure) {
  LValue *value;
  LValue *func = l_closure_get(closure, node->val);
  if(func != NULL && func->type == L_FUNC_TYPE) {
    value = l_call_func(node, func, closure);
  } else {
    value = l_value_new(L_ERR_TYPE, closure);
    value->core.str = make_stringbuf("function with name '");
    buffer_concat(value->core.str, node->val);
    buffer_concat(value->core.str, "' not found");
    l_handle_error(value, node, closure);
  }
  return value;
}

void l_eval(const char *source, const char *source_file, LClosure *closure) {
  LAst ast = l_parse(source, source_file);
  list_iter_p iter = list_iterator(ast, FRONT);

M src/eval.h => src/eval.h +0 -1
@@ 10,7 10,6 @@ LValue *l_eval_string_node(LNode *node, LClosure *closure);
LValue *l_eval_var_node(LNode *node, LClosure *closure);
LValue *l_eval_list_node(LNode *node, LClosure *closure);
LValue *l_eval_func_node(LNode *node, LClosure *closure);
LValue *l_eval_call_node(LNode *node, LClosure *closure);
LValue *l_eval_error_node(LNode *node, LClosure *closure);
LValue *l_eval_assign_node(LNode *node, LClosure *closure);


M src/funcs.c => src/funcs.c +65 -49
@@ 1,26 1,26 @@
#include "lidija.h"

LValue *l_call_func(LNode *node, LValue *func, LClosure *closure) {
  char *name;
  int argc;
  LNode **args;
LValue *l_eval_call_node(LNode *node, LValue *func, LClosure *closure) {

  if(node != NULL) {
    name = node->val;
    argc = node->exprc;
    args = node->exprs;
  } else {
    name = "";
    argc = 0;
    args = NULL;
  // get func from closure if not already specified
  if(func == NULL) {
    func = l_closure_get(closure, node->val);
    if(func == NULL || func->type != L_FUNC_TYPE) {
      func = l_value_new(L_ERR_TYPE, closure);
      func->core.str = make_stringbuf("function with name '");
      buffer_concat(func->core.str, node->val);
      buffer_concat(func->core.str, "' not found");
      l_handle_error(func, node, closure);
    }
  }

  l_debug(L_DEBUG_CALL) {
    printf(">>> entering %s\n", name);
  }
  char *name = (node != NULL) ? node->val : "";

  l_debug(L_DEBUG_CALL) printf(">>> entering %s\n", name);

  LValue *value;
  int i;
  LValue *v, *argsVal, **ref;
  LValue *argsVal;

  // create a running scope to hold arguments
  // and a reference to self (for recursion)


@@ 28,66 28,82 @@ LValue *l_call_func(LNode *node, LValue *func, LClosure *closure) {
  if(strcmp(name, "") != 0)
    l_closure_set(cl, name, func, true);

  argsVal = l_eval_call_args(node, func, closure, cl);

  if(func->core.func.ptr != NULL) {
    // native C code
    value = func->core.func.ptr(argsVal, cl);
  } else {
    // Lidija code
    int exprc = func->core.func.exprc;
    for(i=0; i<exprc; i++) {
      value = l_eval_node(func->core.func.exprs[i], cl);
    }
    if(exprc == 0) {
      value = l_value_new(L_NIL_TYPE, cl);
    }
  }

  l_closure_free(cl);

  l_debug(L_DEBUG_CALL) printf("<<< returning from %s\n", name);

  return value;
}

LValue *l_eval_call_args(LNode *node, LValue *func, LClosure *outer_closure, LClosure *inner_closure) {
  int i, argc;
  LValue *v, *argsVal, **ref;
  LNode **args;

  if(node != NULL) {
    argc = node->exprc;
    args = node->exprs;
  } else {
    argc = 0;
    args = NULL;
  }

  // initialize all args to nil
  for(i=0; i<func->core.func.argc; i++) {
    v = l_value_new(L_NIL_TYPE, cl);
    l_closure_set(cl, func->core.func.args[i]->val, v, true);
    v = l_value_new(L_NIL_TYPE, inner_closure);
    l_closure_set(inner_closure, func->core.func.args[i]->val, v, true);
  }

  // setup the arguments
  argsVal = l_value_new(L_LIST_TYPE, cl);
  argsVal = l_value_new(L_LIST_TYPE, inner_closure);
  argsVal->core.list = create_vector();
  l_closure_set(cl, "args", argsVal, true);
  l_closure_set(inner_closure, "args", argsVal, true);

  // 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 closure var
      ref = l_closure_get_ref(closure, args[i]->val);
      // 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(closure, args[i]->val);
        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(cl->locals, func->core.func.args[i]->val, ref);
          l_ref_put(inner_closure->locals, func->core.func.args[i]->val, ref);
        }
      } else {
        v = l_value_new(L_ERR_TYPE, closure);
        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, closure);
        l_handle_error(v, node, outer_closure);
      }
    } else {
      // eval as normal and set the value
      v = l_eval_node(args[i], closure); // use calling closure
      v = l_eval_node(args[i], outer_closure); // use outer closure
      if(i < func->core.func.argc) {
        l_closure_set(cl, func->core.func.args[i]->val, v, true);
        l_closure_set(inner_closure, func->core.func.args[i]->val, v, true);
      }
    }
    // append to 'args' variable
    vector_add(argsVal->core.list, v, sizeof(v));
  }

  if(func->core.func.ptr != NULL) {
    // native C code
    value = func->core.func.ptr(argsVal, cl);
  } else {
    // Lidija code
    int exprc = func->core.func.exprc;
    for(i=0; i<exprc; i++) {
      value = l_eval_node(func->core.func.exprs[i], cl);
    }
    if(exprc == 0) {
      value = l_value_new(L_NIL_TYPE, cl);
    }
  }

  l_closure_free(cl);

  l_debug(L_DEBUG_CALL) {
    printf("<<< returning from %s\n", name);
  }

  return value;
  return argsVal;
}

// inserts given function as given name in given closure

M src/funcs.h => src/funcs.h +2 -2
@@ 1,8 1,8 @@
#ifndef FUNCS_H
#define FUNCS_H

LValue *l_call_func(LNode *node, LValue *func, LClosure *closure);
LValue *l_eval_func_body(LValue *func, LValue *args, LClosure *closure);
LValue *l_eval_call_node(LNode *node, LValue *func, LClosure *closure);
LValue *l_eval_call_args(LNode *node, LValue *func, LClosure *closure, LClosure *cl);
void l_insert_func(char *name, struct LValue* (*ptr)(struct LValue*, LClosure*), LClosure *closure);
void l_create_funcs(LClosure *closure);
void l_create_globals(LClosure *closure);

M src/lib/logic.c => src/lib/logic.c +2 -2
@@ 47,8 47,8 @@ LValue *l_func_while(LValue *args, LClosure *closure) {
  l_assert_is(ef, L_FUNC_TYPE, L_ERR_MISSING_FUNC, closure);
  l_assert_is(wf, L_FUNC_TYPE, L_ERR_MISSING_FUNC, closure);
  LValue *value;
  while(l_to_bool(l_call_func(NULL, ef, closure))) {
    value = l_call_func(NULL, wf, closure);
  while(l_to_bool(l_eval_call_node(NULL, ef, closure))) {
    value = l_eval_call_node(NULL, wf, closure);
  }
  return value;
}

M src/lib/logic.h => src/lib/logic.h +1 -1
@@ 1,7 1,7 @@
#ifndef LOGIC_H
#define LOGIC_H

#define l_eval_if_expr(e) ((e)->type == L_FUNC_TYPE) ? l_call_func(NULL, e, closure) : e
#define l_eval_if_expr(e) ((e)->type == L_FUNC_TYPE) ? l_eval_call_node(NULL, e, closure) : e

bool l_to_bool(LValue *cond);
bool l_eq(LValue *v1, LValue *v2);