From b9a80d8bbc568ae8e995fde0ea1710359ab4ab1c Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Mon, 18 Oct 2021 16:32:39 +0200 Subject: Fix a bug with too early binding of parameters --- src/bootstrap/objects.h | 2 +- src/bootstrap/primitives.c | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) (limited to 'src/bootstrap') diff --git a/src/bootstrap/objects.h b/src/bootstrap/objects.h index 56821eb..cba6f10 100644 --- a/src/bootstrap/objects.h +++ b/src/bootstrap/objects.h @@ -56,7 +56,7 @@ typedef struct Object { // Object constructors. Object * make_fixnum(ssize_t num); -Object * make_procedure(Object *(*proc)(struct Environment *, struct Object *args)); +Object * make_procedure(Object *(*proc)(struct Environment *, Object *args)); Object * make_pair(Object *car, Object *cdr); Object * make_symbol(StringView sv); Object * make_string(void); diff --git a/src/bootstrap/primitives.c b/src/bootstrap/primitives.c index 0f1498d..7ac9bf7 100644 --- a/src/bootstrap/primitives.c +++ b/src/bootstrap/primitives.c @@ -104,6 +104,12 @@ eval_lambda: // Extend environment. env = env_extend(tmp, env); } + + // Create temporary environment to store bindings. + Environment *tmp = env_create(env); + push_active_env(tmp); + + // Evaluate arguments in temporary environment. while (params != obj_nil) { if (args == obj_nil) { error_push((Error){ @@ -124,7 +130,7 @@ eval_lambda: }); return obj_err; } - env_add_or_update_current(env, symbol, value); + env_add_or_update_current(tmp, symbol, value); args = args->cdr; params = params->cdr; } @@ -135,6 +141,22 @@ eval_lambda: }); return obj_err; } + + // Copy temporary environment values to closure environment. + args = root->cdr; + params = lambda->params; + while (params != obj_nil) { + Object *symbol = params->car; + Object *value = env_lookup(tmp, symbol); + env_add_or_update_current(env, symbol, value); + args = args->cdr; + params = params->cdr; + } + + // Release the temporary environment protection. + pop_active_env(); + + // Run the body of the function. root = lambda->body; while (root->cdr != obj_nil) { if (eval(env, root->car) == obj_err) { -- cgit v1.2.1