aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-18 16:32:39 +0200
committerBad Diode <bd@badd10de.dev>2021-10-18 16:32:39 +0200
commitb9a80d8bbc568ae8e995fde0ea1710359ab4ab1c (patch)
tree86fbc06feef30a2673758bb6513ee44e619a7fd1
parent043a96a6b7cf55f7ef58fb5ebf8ad87b7d50b571 (diff)
downloadbdl-b9a80d8bbc568ae8e995fde0ea1710359ab4ab1c.tar.gz
bdl-b9a80d8bbc568ae8e995fde0ea1710359ab4ab1c.zip
Fix a bug with too early binding of parameters
-rw-r--r--src/bootstrap/objects.h2
-rw-r--r--src/bootstrap/primitives.c24
2 files changed, 24 insertions, 2 deletions
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 {
56 56
57// Object constructors. 57// Object constructors.
58Object * make_fixnum(ssize_t num); 58Object * make_fixnum(ssize_t num);
59Object * make_procedure(Object *(*proc)(struct Environment *, struct Object *args)); 59Object * make_procedure(Object *(*proc)(struct Environment *, Object *args));
60Object * make_pair(Object *car, Object *cdr); 60Object * make_pair(Object *car, Object *cdr);
61Object * make_symbol(StringView sv); 61Object * make_symbol(StringView sv);
62Object * make_string(void); 62Object * 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:
104 // Extend environment. 104 // Extend environment.
105 env = env_extend(tmp, env); 105 env = env_extend(tmp, env);
106 } 106 }
107
108 // Create temporary environment to store bindings.
109 Environment *tmp = env_create(env);
110 push_active_env(tmp);
111
112 // Evaluate arguments in temporary environment.
107 while (params != obj_nil) { 113 while (params != obj_nil) {
108 if (args == obj_nil) { 114 if (args == obj_nil) {
109 error_push((Error){ 115 error_push((Error){
@@ -124,7 +130,7 @@ eval_lambda:
124 }); 130 });
125 return obj_err; 131 return obj_err;
126 } 132 }
127 env_add_or_update_current(env, symbol, value); 133 env_add_or_update_current(tmp, symbol, value);
128 args = args->cdr; 134 args = args->cdr;
129 params = params->cdr; 135 params = params->cdr;
130 } 136 }
@@ -135,6 +141,22 @@ eval_lambda:
135 }); 141 });
136 return obj_err; 142 return obj_err;
137 } 143 }
144
145 // Copy temporary environment values to closure environment.
146 args = root->cdr;
147 params = lambda->params;
148 while (params != obj_nil) {
149 Object *symbol = params->car;
150 Object *value = env_lookup(tmp, symbol);
151 env_add_or_update_current(env, symbol, value);
152 args = args->cdr;
153 params = params->cdr;
154 }
155
156 // Release the temporary environment protection.
157 pop_active_env();
158
159 // Run the body of the function.
138 root = lambda->body; 160 root = lambda->body;
139 while (root->cdr != obj_nil) { 161 while (root->cdr != obj_nil) {
140 if (eval(env, root->car) == obj_err) { 162 if (eval(env, root->car) == obj_err) {