diff options
Diffstat (limited to 'src/bootstrap/primitives.c')
-rw-r--r-- | src/bootstrap/primitives.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/src/bootstrap/primitives.c b/src/bootstrap/primitives.c index a814e40..0403e3a 100644 --- a/src/bootstrap/primitives.c +++ b/src/bootstrap/primitives.c | |||
@@ -5,6 +5,7 @@ Object * proc_if(Environment *env, Object *obj); | |||
5 | Object * | 5 | Object * |
6 | eval(Environment *env, Object *root) { | 6 | eval(Environment *env, Object *root) { |
7 | Object* lambda; | 7 | Object* lambda; |
8 | Object* ret = NULL; | ||
8 | bool recursion_active = false; | 9 | bool recursion_active = false; |
9 | eval_start: | 10 | eval_start: |
10 | switch (root->type) { | 11 | switch (root->type) { |
@@ -15,7 +16,8 @@ eval_start: | |||
15 | case OBJ_TYPE_BOOL: | 16 | case OBJ_TYPE_BOOL: |
16 | case OBJ_TYPE_NIL: | 17 | case OBJ_TYPE_NIL: |
17 | case OBJ_TYPE_STRING: { | 18 | case OBJ_TYPE_STRING: { |
18 | return root; | 19 | ret = root; |
20 | goto eval_success; | ||
19 | } break; | 21 | } break; |
20 | case OBJ_TYPE_SYMBOL: { | 22 | case OBJ_TYPE_SYMBOL: { |
21 | Object *val = env_lookup(env, root); | 23 | Object *val = env_lookup(env, root); |
@@ -26,7 +28,8 @@ eval_start: | |||
26 | }); | 28 | }); |
27 | return obj_err; | 29 | return obj_err; |
28 | } | 30 | } |
29 | return val; | 31 | ret = val; |
32 | goto eval_success; | ||
30 | } break; | 33 | } break; |
31 | case OBJ_TYPE_PAIR: { | 34 | case OBJ_TYPE_PAIR: { |
32 | if (root->car->type == OBJ_TYPE_SYMBOL) { | 35 | if (root->car->type == OBJ_TYPE_SYMBOL) { |
@@ -64,7 +67,8 @@ eval_start: | |||
64 | } | 67 | } |
65 | goto eval_start; | 68 | goto eval_start; |
66 | } | 69 | } |
67 | return val->proc(env, root->cdr); | 70 | ret = val->proc(env, root->cdr); |
71 | goto eval_success; | ||
68 | } | 72 | } |
69 | if (val->type == OBJ_TYPE_LAMBDA) { | 73 | if (val->type == OBJ_TYPE_LAMBDA) { |
70 | lambda = val; | 74 | lambda = val; |
@@ -86,8 +90,12 @@ eval_lambda: | |||
86 | args = root->cdr; | 90 | args = root->cdr; |
87 | Object *params = lambda->params; | 91 | Object *params = lambda->params; |
88 | if (!recursion_active) { | 92 | if (!recursion_active) { |
89 | env = env_extend(lambda->env, env); | ||
90 | recursion_active = true; | 93 | recursion_active = true; |
94 | // Protect current stack. | ||
95 | Environment *tmp = env_create(lambda->env); | ||
96 | push_active_env(tmp); | ||
97 | // Extend environment. | ||
98 | env = env_extend(tmp, env); | ||
91 | } | 99 | } |
92 | while (params != obj_nil) { | 100 | while (params != obj_nil) { |
93 | if (args == obj_nil) { | 101 | if (args == obj_nil) { |
@@ -138,6 +146,12 @@ eval_lambda: | |||
138 | .value = ERR_UNKNOWN_OBJ_TYPE, | 146 | .value = ERR_UNKNOWN_OBJ_TYPE, |
139 | }); | 147 | }); |
140 | return obj_err; | 148 | return obj_err; |
149 | eval_success: | ||
150 | if (recursion_active) { | ||
151 | // Remove stack protector. | ||
152 | pop_active_env(); | ||
153 | } | ||
154 | return ret; | ||
141 | } | 155 | } |
142 | 156 | ||
143 | Object * | 157 | Object * |