summaryrefslogtreecommitdiff
path: root/lisp.c
diff options
context:
space:
mode:
authorFelix Perktold <Felix.Perktold@student.uibk.ac.at>2025-12-23 15:23:13 +0100
committerFelix Perktold <Felix.Perktold@student.uibk.ac.at>2025-12-23 15:23:13 +0100
commit0a9372bbf272ffd402938b992ef30ce4241bfa13 (patch)
treeafab5c61794271a1bb8571d09fbb5e9fbf91a7db /lisp.c
parentc63cbd8db40fbdeccabd218229010cbfb8a93977 (diff)
support partial function application and over-application chaining
Diffstat (limited to 'lisp.c')
-rw-r--r--lisp.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/lisp.c b/lisp.c
index a797e8e..a559330 100644
--- a/lisp.c
+++ b/lisp.c
@@ -283,7 +283,7 @@ value *eval_pair(env *e, value *v) {
}
if (head_eval->type == VT_LAMBDA) {
- //evaluate arguents first, then apply
+ //evaluate arguments 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);
@@ -296,16 +296,36 @@ value *eval_pair(env *e, value *v) {
}
value *apply(value *lval, value *args) {
+
+ if (lval->type != VT_LAMBDA) {
+ //ERROR
+ return make_nil();
+ }
+
env *sub_env = env_create(lval->as.lambda.env);
value *params = lval->as.lambda.params;
value *arg = args;
+ // bind all available args in subenv
while (params->type == VT_PAIR && arg->type == VT_PAIR) {
env_define(sub_env, car(params)->as.sym, car(arg));
params = cdr(params);
arg = cdr(arg);
}
- return eval(sub_env, lval->as.lambda.body);
+
+ // all lambda parameters bound to respective args
+ if (params->type == VT_NIL) {
+ value *result = eval(sub_env, lval->as.lambda.body);
+
+ // if arguments left, try applying them to evaluated lambda
+ if (arg->type == VT_PAIR) {
+ return apply(result, arg);
+ }
+ return result;
+ }
+
+ // if not all parameters bound, return partially applied lambda
+ return make_lambda(sub_env, params, lval->as.lambda.body);
}
value *builtin_cons(env *e, value *args) {