Beispiel #1
0
void dump_config(struct config* cfg)
{
	printf("#include \"init.h\"\n\n");
	printf("#define NULL ((void*)0)\n");	/* eh */

	dump_tab("builtin_tab", cfg->inittab);
	dump_env("builtin_env", cfg->env);

	printf("static struct config builtin = {\n");
	printf("\t.inittab = builtin_tab + 1,\n");
	printf("\t.initnum = %i,\n", cfg->initnum);
	printf("\t.env = builtin_env,\n");
	printf("};\n\n");

	printf("struct config* cfg = &builtin;\n");
}
Beispiel #2
0
static lisp_obj *apply(lisp_expr_application *app, lisp_env *env, lisp_err *err)
{
    lisp_obj *callable = FORCE_VALUE(app->proc, env, err);
    if (! callable){
        return NULL;
    }

    lisp_obj *res = NIL;

    /* Internal procedure */
    if (callable->type == PROC){
        /* Eval args */
        lisp_obj **args = calloc(app->nparams, sizeof(lisp_obj*));
        for (size_t i=0; i<app->nparams; i++){
            lisp_obj *arg = FORCE_VALUE(app->params[i], env, err);
            if (! arg){
                for (size_t j=0; j<i; j++){
                    release(args[j]);
                }
                free(args);
                return NULL;
            }
            args[i] = arg;
        }

        /* Eval internal */
        res = callable->value.p(app->nparams, args);
        
        /* Free args */
        for (size_t i=0; i<app->nparams; i++){
            release(args[i]);
        }
        free(args);
    }

    /* Lisp func */
    else if (callable->type == LAMBDA){
        lisp_lambda *lambda = &(callable->value.l);
        lisp_expr_lambda *lambda_expr = &(lambda->declaration->value.mklambda);

        /* Check arity */
        if (app->nparams != lambda_expr->nparams){
            raise_error(err, WRONG_ARITY, "Arity error ! Expected %d params, got %d",
                lambda_expr->nparams, app->nparams);
            return NULL;
        }

        /* Extend env */
        lisp_env *locals = create_env(lambda->context);
        for (size_t i=0; i<lambda_expr->nparams; i++){
            lisp_obj *param = eval_expression(app->params[i], env, err);
            if (! param){
                release_env(locals);
                return NULL;
            }
            DEBUG("Extend env with %s", lambda_expr->param_names[i]);
            release(set_env(locals, lambda_expr->param_names[i], param));
        }

        if (enable_debug){
            printf("\033[1mCALL\033[0m ");
            dump_expr(lambda_expr->body);
            printf(" with env\n");
            dump_env(locals);
        }

        /* Wrap in thunk for trampoline */
        res = make_thunk(lambda_expr->body, locals);
        release_env(locals);
    }
    else {
        lisp_print(callable);
        raise_error(err, NOT_CALLABLE, "CANNOT CALL obj %p", callable);
        return NULL;
    }

    release(callable);
    return res;
}
Beispiel #3
0
struct value *eval(struct value *sexp, struct env *env)
{
    struct value *car = atom("car");
    struct value *cdr = atom("cdr");
    struct value *cond = atom("cond");
    struct value *cons_ = atom("cons");
    struct value *else_ = atom("else");
    struct value *equalp = atom("equal?");
    struct value *lambda_ = atom("lambda");
    struct value *let = atom("let*");
    struct value *listp = atom("list?");
    struct value *quote = atom("quote");
    struct value *truth = atom("#t");
    struct value *falsehood = atom("#f");

    int done = 0;
    while (!done) {
        done = 1;
        switch (sexp->type) {
            case V_ATOM:
            {
                struct atom *name = (struct atom *)sexp;
                struct value *value = lookup(env, name);
                if (value == NULL) {
                    printf("Atom ");
                    dump(sexp);
                    printf(" has no meaning\n");
                    exit(1);
                }
                return value;
            }
            case V_CONS:
            {
                struct value *h = head(sexp);
                struct value *t = tail(sexp);
                struct value *bound = lookup(env, (struct atom *)h);
                debug("V_CONS");
                if (bound != NULL) {
                    debug("*(bound)");
                    debug(((struct atom *)h)->string);
                    sexp = cons(bound, t); /* pair of a lambda and a list */
                    done = 0; /* "tail call" */
                } else if (h == car) {
                    struct value *k = eval(head(t), env);
                    debug("*car");
                    return head(k);
                } else if (h == cdr) {
                    struct value *k = eval(head(t), env);
                    debug("*cdr");
                    return tail(k);
                } else if (h == cond) {
                    struct value *branch = head(t);
                    debug("*cond");
                    /* this will error out with car(nil) if no 'else' in cond */
                    while (done) {
                        struct value *test = head(branch);
                        struct value *expr = head(tail(branch));
                        if (test == else_) {
                            sexp = expr;
                            done = 0; /* "tail call" */
                        } else {
                            test = eval(test, env);
                            if (test != falsehood) {
                                sexp = expr;
                                done = 0; /* "tail call" */
                            } else {
                                t = tail(t);
                                branch = head(t);
                            }
                        }
                    }
                } else if (h == cons_) {
                    struct value *j = eval(head(t), env);
                    struct value *k = eval(head(tail(t)), env);
                    debug("*cons");
                    return cons(j, k);
                } else if (h == equalp) {
                    struct value *j = eval(head(t), env);
                    struct value *k = eval(head(tail(t)), env);
                    debug("*equalp");
                    if (equal(j, k)) {
                        return truth;
                    } else {
                        return falsehood;
                    }
                } else if (h == lambda_) {
                    debug("*lambda");
                    return lambda(env, head(t), head(tail(t)));
                } else if (h == let) {
                    struct value *pairs = head(t);
                    struct value *body = head(tail(t));
                    debug("*let*");
                    while (pairs != nil) {
                        struct value *pair = head(pairs);
                        struct value *name = head(pair);
                        struct value *value = eval(head(tail(pair)), env);
                        /* TODO: check that head(pair) is an atom! */
                        debug("binding");
                        debug(((struct atom *)name)->string);
                        env = bind(env, (struct atom *)name, value);
                        pairs = tail(pairs);
                    }
#ifdef DEBUG
                    dump_env(env);
#endif
                    sexp = body;
                    done = 0; /* "tail call" */
                } else if (h == listp) {
                    struct value *k = eval(head(t), env);
                    debug("*list?");
                    while (k->type == V_CONS) {
                        k = tail(k);
                    }
                    if (k == nil) {
                        return truth;
                    } else {
                        return falsehood;
                    }
                } else if (h == quote) {
                    debug("*quote");
                    if (t == nil)
                        return t;
                    return head(t);
                } else if (h->type == V_LAMBDA) {
                    struct lambda *l = (struct lambda *)h;
                    struct value *formals = l->formals;
                    struct env *l_env = l->env;
                    debug("*(lambda)");
                    while (t->type == V_CONS) {
                        struct value *formal = head(formals);
                        struct value *value = eval(head(t), env);
                        l_env = bind(l_env, (struct atom *)formal, value);
                        formals = tail(formals);
                        t = tail(t);
                    }
                    env = l_env;
                    sexp = l->body;
                    done = 0; /* "tail call" */       
                } else {
                    struct value *k = eval(h, env);
                    struct value *m = cons(eval(k, env), t);
                    debug("*(inner sexp)*");
                    return eval(m, env);
                }
                break;
            }
            case V_LAMBDA:
            {
                debug("V_LAMBDA\n");
                return sexp;
            }
        }
    }
    return sexp;
}