diff options
| author | Felix Perktold <Felix.Perktold@student.uibk.ac.at> | 2025-12-22 15:23:11 +0100 |
|---|---|---|
| committer | Felix Perktold <Felix.Perktold@student.uibk.ac.at> | 2025-12-22 15:23:11 +0100 |
| commit | 42169e527f74d1b7ad7cd75faf35db149076298e (patch) | |
| tree | b7f0c56cf14c5cca6b25a229c4fb3204a5930783 | |
| parent | 91d683a1b819a5b720b9eb11f8409dff9c7883e1 (diff) | |
refactor apply / eval, add reverse builtin
| -rw-r--r-- | lisp.c | 36 | ||||
| -rw-r--r-- | lisp.h | 4 | ||||
| -rw-r--r-- | main.c | 1 |
3 files changed, 27 insertions, 14 deletions
@@ -84,7 +84,15 @@ value *cdr(value *cons) { printf("cdr of non-pair: "); println_value(cons); return make_nil(); -} +} + +value *reverse(value *list) { + value *reversed = make_nil(); + for(value *a = list; a->type == VT_PAIR; a = cdr(a)) { + reversed = cons(car(a), reversed); + } + return reversed; +} void *println_value(value *val){ print_value(val); @@ -238,8 +246,8 @@ value *eval_pair(env *e, value *v) { } if (head->type == VT_SYMBOL && (!strcmp(head->as.sym, "lambda") || - !strcmp(head->as.sym, "\\") || - !strcmp(head->as.sym, "λ"))) { + !strcmp(head->as.sym, "\\") || + !strcmp(head->as.sym, "λ"))) { value *params = car(tail); value *body = car(cdr(tail)); @@ -268,26 +276,24 @@ value *eval_pair(env *e, value *v) { } if (head_eval->type == VT_LAMBDA) { - return apply(e, head_eval, tail); + //evaluate arguents first, then apply + value *args_eval = make_nil(); + for(value *a = tail; a->type == VT_PAIR; a = cdr(a)) { + args_eval = cons(eval(e, car(a)), args_eval); + } + return apply(head_eval, reverse(args_eval)); } return v; } -value *apply(env *e, value *lval, value *args) { +value *apply(value *lval, value *args) { env *sub_env = env_create(lval->as.lambda.env); value *params = lval->as.lambda.params; value *arg = args; while (params->type == VT_PAIR && arg->type == VT_PAIR) { - if (car(params)->type != VT_SYMBOL) { - printf("not a symbol: "); - println_value(car(params)); - return make_nil(); - } - - value *arg_eval = eval(e, car(arg)); - env_define(sub_env, car(params)->as.sym, arg_eval); + env_define(sub_env, car(params)->as.sym, car(arg)); params = cdr(params); arg = cdr(arg); } @@ -307,6 +313,10 @@ value *builtin_cdr(env *e, value *args) { return cdr(eval(e, car(args))); } +value *builtin_reverse(env *e, value *args) { + return reverse(eval(e, car(args))); +} + value *builtin_isnull(env *e, value *args) { value *v = eval(e, car(args)); if(v->type == VT_NIL) { @@ -47,6 +47,7 @@ value *make_builtin(value *(*fn) (env *, value *)); value *cons(value *car, value *cdr); value *car(value *cons); value *cdr(value *cons); +value *reverse(value *list); void *print_value(value *val); void *println_value(value *val); @@ -68,11 +69,12 @@ extern env *global_env; value *eval(env *e, value *val); value *eval_pair(env *e, value *val); -value *apply(env *e, value *lambda, value *args); +value *apply(value *lambda, value *args); value *builtin_cons(env *e, value *args); value *builtin_car(env *e, value *args); value *builtin_cdr(env *e, value *args); +value *builtin_reverse(env *e, value *args); value *builtin_isnull(env *e, value *args); value *builtin_eq(env *e, value *args); value *builtin_add(env *e, value *args); @@ -31,6 +31,7 @@ int main(int argc, char **argv) { env_define(global_env, "cons", make_builtin(builtin_cons)); env_define(global_env, "car", make_builtin(builtin_car)); env_define(global_env, "cdr", make_builtin(builtin_cdr)); + env_define(global_env, "reverse", make_builtin(builtin_reverse)); env_define(global_env, "null?", make_builtin(builtin_isnull)); env_define(global_env, "eq?", make_builtin(builtin_eq)); env_define(global_env, "+", make_builtin(builtin_add)); |
