diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bootstrap/primitives.c | 103 |
1 files changed, 52 insertions, 51 deletions
diff --git a/src/bootstrap/primitives.c b/src/bootstrap/primitives.c index ab147d4..0c2a17d 100644 --- a/src/bootstrap/primitives.c +++ b/src/bootstrap/primitives.c | |||
@@ -3,7 +3,8 @@ static Object *proc_if; | |||
3 | 3 | ||
4 | Object * | 4 | Object * |
5 | eval(Environment *env, Object *root) { | 5 | eval(Environment *env, Object *root) { |
6 | Object* lambda; | 6 | Object* lambda = NULL; |
7 | Object* args = NULL; | ||
7 | Object* ret = NULL; | 8 | Object* ret = NULL; |
8 | bool recursion_active = false; | 9 | bool recursion_active = false; |
9 | eval_start: | 10 | eval_start: |
@@ -85,65 +86,65 @@ eval_start: | |||
85 | if (lambda == obj_err) { | 86 | if (lambda == obj_err) { |
86 | return obj_err; | 87 | return obj_err; |
87 | } | 88 | } |
88 | if (lambda->type == OBJ_TYPE_LAMBDA) { | 89 | if (lambda->type != OBJ_TYPE_LAMBDA) { |
89 | Object *args; | 90 | error_push((Error){ |
91 | .type = ERR_TYPE_RUNTIME, | ||
92 | .value = ERR_OBJ_NOT_CALLABLE, | ||
93 | }); | ||
94 | return obj_err; | ||
95 | } | ||
96 | |||
90 | eval_lambda: | 97 | eval_lambda: |
91 | args = root->cdr; | 98 | args = root->cdr; |
92 | Object *params = lambda->params; | 99 | Object *params = lambda->params; |
93 | if (!recursion_active) { | 100 | if (!recursion_active) { |
94 | recursion_active = true; | 101 | recursion_active = true; |
95 | // Protect current stack. | 102 | // Protect current stack. |
96 | Environment *tmp = env_create(lambda->env); | 103 | Environment *tmp = env_create(lambda->env); |
97 | push_active_env(tmp); | 104 | push_active_env(tmp); |
98 | // Extend environment. | 105 | // Extend environment. |
99 | env = env_extend(tmp, env); | 106 | env = env_extend(tmp, env); |
107 | } | ||
108 | while (params != obj_nil) { | ||
109 | if (args == obj_nil) { | ||
110 | error_push((Error){ | ||
111 | .type = ERR_TYPE_RUNTIME, | ||
112 | .value = ERR_NOT_ENOUGH_ARGS, | ||
113 | }); | ||
114 | return obj_err; | ||
100 | } | 115 | } |
101 | while (params != obj_nil) { | 116 | Object *symbol = params->car; |
102 | if (args == obj_nil) { | 117 | Object *value = eval(env, args->car); |
103 | error_push((Error){ | 118 | if (value == obj_err) { |
104 | .type = ERR_TYPE_RUNTIME, | 119 | return obj_err; |
105 | .value = ERR_NOT_ENOUGH_ARGS, | ||
106 | }); | ||
107 | return obj_err; | ||
108 | } | ||
109 | Object *symbol = params->car; | ||
110 | Object *value = eval(env, args->car); | ||
111 | if (value == obj_err) { | ||
112 | return obj_err; | ||
113 | } | ||
114 | if (value == obj_nil) { | ||
115 | error_push((Error){ | ||
116 | .type = ERR_TYPE_RUNTIME, | ||
117 | .value = ERR_NOT_ENOUGH_ARGS, | ||
118 | }); | ||
119 | return obj_err; | ||
120 | } | ||
121 | env_add_or_update_current(env, symbol, value); | ||
122 | args = args->cdr; | ||
123 | params = params->cdr; | ||
124 | } | 120 | } |
125 | if (args != obj_nil) { | 121 | if (value == obj_nil) { |
126 | error_push((Error){ | 122 | error_push((Error){ |
127 | .type = ERR_TYPE_RUNTIME, | 123 | .type = ERR_TYPE_RUNTIME, |
128 | .value = ERR_TOO_MANY_ARGS, | 124 | .value = ERR_NOT_ENOUGH_ARGS, |
129 | }); | 125 | }); |
130 | return obj_err; | 126 | return obj_err; |
131 | } | 127 | } |
132 | root = lambda->body; | 128 | env_add_or_update_current(env, symbol, value); |
133 | while (root->cdr != obj_nil) { | 129 | args = args->cdr; |
134 | if (eval(env, root->car) == obj_err) { | 130 | params = params->cdr; |
135 | return obj_err; | ||
136 | }; | ||
137 | root = root->cdr; | ||
138 | } | ||
139 | root = root->car; | ||
140 | goto eval_start; | ||
141 | } | 131 | } |
142 | error_push((Error){ | 132 | if (args != obj_nil) { |
143 | .type = ERR_TYPE_RUNTIME, | 133 | error_push((Error){ |
144 | .value = ERR_OBJ_NOT_CALLABLE, | 134 | .type = ERR_TYPE_RUNTIME, |
145 | }); | 135 | .value = ERR_TOO_MANY_ARGS, |
146 | return obj_err; | 136 | }); |
137 | return obj_err; | ||
138 | } | ||
139 | root = lambda->body; | ||
140 | while (root->cdr != obj_nil) { | ||
141 | if (eval(env, root->car) == obj_err) { | ||
142 | return obj_err; | ||
143 | }; | ||
144 | root = root->cdr; | ||
145 | } | ||
146 | root = root->car; | ||
147 | goto eval_start; | ||
147 | } break; | 148 | } break; |
148 | } | 149 | } |
149 | 150 | ||