Esempio n. 1
0
static action_t cont_list() {
  ref_t sym = check_symbol(car(expr));
  expr = cdr(expr);
  if (sym == sym_do)
    eval_do(expr);
  else if (sym == sym_fn)
    C(cont)->fn = cont_fn;
  else if (sym == sym_if)
    C(cont)->fn = cont_if;
  else if (sym == sym_quote)
    C(cont)->fn = cont_quote;
  else
    eval_apply(get_function(sym));
  return ACTION_APPLY_CONT;
}
Esempio n. 2
0
File: eval.c Progetto: Pilen/ubertex
Value eval_list(Value expression, Environment *environment) {
    w_assert(expression.type == CONS);

    Bool lambda_call = false;
    Value function_symbol = NEXT(expression);
    Value lambda;
    Function *function;

    if (function_symbol.type == CONS) {
        if (CAR(function_symbol).type == SYMBOL &&
            CAR(function_symbol).val.symbol_val == symbols_lambda.val.symbol_val) {
            lambda = eval(function_symbol, environment);
            lambda_call = true;
        } else {
            return VALUE_ERROR;
        }
    } else if (function_symbol.type == LAMBDA) {
        lambda = function_symbol;
        lambda_call = true;
    } else if (function_symbol.type == SYMBOL) {
        Value function_value;
        Bool found = hash_get(environment -> functions, function_symbol, &function_value);
        if (!found) {
            /* TODO: log error */
            /* TODO: "Did you mean?" */
            debug_value(function_symbol);
            log_error("Function XXX not found");
            return VALUE_ERROR;
        }
        w_assert(function_value.type == FUNCTION);
        function = function_value.val.function_val;
    } else {
        return VALUE_ERROR;
    }

    Value args;
    if (lambda_call || function -> eval) {
        args = VALUE_NIL;
        while (expression.type == CONS) {
            Value arg = NEXT(expression);
            args = CONS(eval(arg, environment), args);
        }
        args = list_reverse(args);
        w_assert(expression.type == NIL);

        /* TODO: benchmark, which approach is better, the above or below? */

        /* if (expression.type == CONS) { */
        /*     args = CONS1(VALUE_NIL); */
        /* } else { */
        /*     args = expression; */
        /* } */
        /* Cons *top = args.val.cons_val; */
        /* while (true) { */
        /*     Value arg = NEXT(expression); */
        /*     top -> car = eval(arg, environment); */
        /*     if (expression.type == CONS) { */
        /*         top -> cdr = CONS1(VALUE_NIL); */
        /*         top = top -> cdr.val.cons_val; */
        /*     } else { */
        /*         top -> cdr = expression; */
        /*         break; */
        /*     } */
        /* } */
    } else {
        /* To ensure we avoid mutation in altering code the list is copied
           If we guaranteed that no function with eval = false modifies the list we could give it directly
           This would be an obvious performance optimization. But needs tests.
           We can only guarantee this for c_code, not for userdefined macros.
           TODO: Do this */
        args = list_copy(expression);
    }

    Value result;
    if (lambda_call) {
        result = eval_lambda(lambda, args, environment);
    } else {
        result = eval_apply(function_symbol, function, args, environment);
    }
    list_destroy(args);
    return result;
}
Esempio n. 3
0
static pobject apply(pobject env, pobject params)
{
    /* XXX: apply needs more work */
    return eval_apply(env, eval(env, cons_car(params)), 
                      eval(env, cons_nth(params, 2)));
}
Esempio n. 4
0
static void fn_apply() {
  eval_apply(check_function(lookup(sym_fn)));
  cont = continuation(NULL, cont);
  expr = check_list(lookup(sym_args));
}