From 4f025b96cfe6bc121ea9b37eb26d8814dd838647 Mon Sep 17 00:00:00 2001 From: Felix Perktold Date: Sun, 21 Dec 2025 14:01:36 +0100 Subject: start implementing eval --- lisp.c | 94 +++++++++++++++++++++++++++++++++++++++++------------------------- lisp.h | 7 +++++ lisp.y | 10 +++++-- 3 files changed, 74 insertions(+), 37 deletions(-) diff --git a/lisp.c b/lisp.c index 95d8670..b195352 100644 --- a/lisp.c +++ b/lisp.c @@ -48,6 +48,17 @@ value *cons(value *car, value *cdr) { return val; } +value *car(value *cons) { + //TODO: more robust implementation with error catching + return cons->as.pair.car; +} + +value *cdr(value *cons) { + //TODO: more robust implementation with error catching + return cons->as.pair.cdr; +} + + void *print_value(value *val){ char *str; switch (val->type) { @@ -118,45 +129,58 @@ value *env_lookup(env *e, const char *sym) { return NULL; } -int main(void) { - /* TEST; DANKE CHATGPT - // create global environment - env *global = env_create(NULL); - // define some variables - env_define(global, "x", make_int(10)); - env_define(global, "y", make_int(42)); - - // lookup variables - value *vx = env_lookup(global, "x"); - value *vy = env_lookup(global, "y"); - value *vz = env_lookup(global, "z"); // undefined - // - if (vx) { - printf("x = "); - print_value(vx); - printf("\n"); +value *eval(env *e, value *v) { + value *found; + + if (v->type == VALTYPE_NIL) { + return v; } - if (vx) { - printf("y = "); - print_value(vy); - printf("\n"); + + if (v->type == VALTYPE_SYMBOL && + (found = env_lookup(e, v->as.sym))) { + return found; + } + + if (v->type == VALTYPE_SYMBOL) { + printf("symbol %s not found\n", v->as.sym); + return v; } - if (vz) { - printf("z = "); - print_value(vz); - printf("\n"); + + if (v->type == VALTYPE_PAIR) { + return eval_pair(e, v); } - // create nested environment - env *local = env_create(global); - env_define(local, "x", make_int(99)); // shadow global x - - value *lx = env_lookup(local, "x"); // should find local - value *ly = env_lookup(local, "y"); // should find global - - printf("local x = %d\n", lx ? lx->as.i : -1); - printf("local y = %d\n", ly ? ly->as.i : -1); - */ + return v; +} + +value *eval_pair(env *e, value *v) { + value *head = v->as.pair.car; + value *tail = v->as.pair.cdr; + + if (head->type == VALTYPE_SYMBOL && + tail->type == VALTYPE_PAIR) { + if(!strcmp(head->as.str, "define")) { + value *defargs = cdr(v); + value *defname = car(defargs); + value *defval = eval(e, car(cdr(defargs))); + + if (defname->type != VALTYPE_SYMBOL) { + printf("error, expected symbol, found: "); + print_value(defname); + printf("\n"); + return v; + } + env_define(e, defname->as.sym, defval); + } + } + return v; +} + +env *global_env = NULL; + +int main(void) { + // init global env + global_env = env_create(NULL); // START REPL char* line; while ((line = readline("λ > ")) != NULL) { diff --git a/lisp.h b/lisp.h index 4053bd5..6ebf9a2 100644 --- a/lisp.h +++ b/lisp.h @@ -31,6 +31,8 @@ value *make_symbol(const char *sym); value *make_string(const char *str); value *make_nil(); value *cons(value *car, value *cdr); +value *car(value *cons); +value *cdr(value *cons); void *print_value(value *val); // environments, TODO: make this use hashtable @@ -47,4 +49,9 @@ env *env_create(env *parent); env *env_define(env *e, const char *sym, value *val); value *env_lookup(env *e, const char *sym); +extern env *global_env; + +value *eval(env *e, value *val); +value *eval_pair(env *e, value *val); + #endif diff --git a/lisp.y b/lisp.y index 93dd877..8ed479d 100644 --- a/lisp.y +++ b/lisp.y @@ -28,8 +28,14 @@ static int is_integer(double x) { %start sexprs %% -sexprs: sexpr { print_value($1); printf("\n"); } - | sexprs sexpr { print_value($2); printf("\n"); }; +sexprs: sexpr + { + print_value(eval(global_env, $1)); printf("\n"); + } + | sexprs sexpr + { + print_value(eval(global_env, $2)); printf("\n"); + }; sexpr: atom | list -- cgit v1.2.3