コード例 #1
0
LValue *l_eval_var_node(LNode *node, LClosure *closure) {
  LValue *value = l_closure_get(closure, node->val);
  if(value != NULL) {
    return value;
  } else {
    value = l_value_new(L_ERR_TYPE, closure);
    value->core.str = make_stringbuf(node->val);
    buffer_concat(value->core.str, " not found");
    l_handle_error(value, node, closure);
    return value;
  }
}
コード例 #2
0
ファイル: funcs.c プロジェクト: seven1m/lidija
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;
}