summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lisp.c36
-rw-r--r--lisp.h4
-rw-r--r--main.c1
3 files changed, 27 insertions, 14 deletions
diff --git a/lisp.c b/lisp.c
index b880eb3..be71a30 100644
--- a/lisp.c
+++ b/lisp.c
@@ -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) {
diff --git a/lisp.h b/lisp.h
index 162da09..bb4d3ae 100644
--- a/lisp.h
+++ b/lisp.h
@@ -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);
diff --git a/main.c b/main.c
index 2d258af..5a7c893 100644
--- a/main.c
+++ b/main.c
@@ -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));