Пример #1
0
LValue *l_eval_func_node(LNode *node, LClosure *closure) {
  LValue *value = l_value_new(L_FUNC_TYPE, closure);
  value->core.func.ptr = NULL;
  // pass node=NULL to l_closure_clone, so this lexical frame is not printed in a stack trace
  value->core.func.closure = l_closure_clone(closure, NULL);
  if(node->exprs[0]) {
    value->core.func.argc = node->exprs[0]->exprc;
    value->core.func.args = node->exprs[0]->exprs;
  } else {
    value->core.func.argc = 0;
  }
  value->core.func.exprc = node->exprs[1]->exprc;
  value->core.func.exprs = node->exprs[1]->exprs;
  return value;
}
Пример #2
0
LValue *l_eval_call_node(LNode *node, LValue *func, LClosure *closure) {

  if(func == NULL) func = l_eval_var_node(node, closure);

  char *name = (node != NULL) ? node->val : "";

  LValue *value, *args_val;
  LNode *expr;
  int i;

  // create a running scope to hold arguments
  // and a reference to self (for recursion)
  // TODO this may not be necessary (can't we just do `cl=func->core.func.closure`?)
  LClosure *cl = l_closure_clone(func->core.func.closure, node);

tail_loop:

  l_debug(L_DEBUG_CALL) {
    if(node) printf(">>> entering %s on line %d in %s\n", name, node->line_no, node->source_file);
    else printf(">>> entering %s\n", name);
  }

  if(strcmp(name, "") != 0)
    l_closure_set(cl, name, func, true);

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

  if(func->core.func.ptr != NULL) {
    // native C code
    if(!setjmp(cl->jmp)) {
      value = func->core.func.ptr(args_val, cl);
    } else {
      // function called longjmp to initiate a tail call
      l_debug(L_DEBUG_CALL) printf("^^^ reached end of %s (longjmp tail call)\n", name);
      node = NULL;
      func = l_closure_get(cl, "--tail-call--");
      closure = cl;
      l_closure_backfill(func->core.func.closure, cl, node);
      name = "";
      goto tail_loop;
    }
  } else {
    // Lydia code
    int exprc = func->core.func.exprc;
    if(exprc > 0) {
      // eval all but the last expression
      for(i=0; i<exprc-1; i++) {
        expr = func->core.func.exprs[i];
        value = l_eval_node(expr, cl);
      }
      expr = func->core.func.exprs[exprc-1];
      if(expr->type == L_CALL_TYPE) { // tail call
        l_debug(L_DEBUG_CALL) printf("^^^ reached end of %s (tail call)\n", name);
        node = expr;
        func = l_eval_var_node(node, cl);
        closure = cl;
        l_closure_backfill(func->core.func.closure, cl, node);
        name = node->val;
        goto tail_loop;
      } else {
        value = l_eval_node(expr, cl);
      }
    } else {
      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;
}