diff options
Diffstat (limited to 'src/bootstrap/objects.c')
-rw-r--r-- | src/bootstrap/objects.c | 109 |
1 files changed, 107 insertions, 2 deletions
diff --git a/src/bootstrap/objects.c b/src/bootstrap/objects.c index 9acbcd9..30827f1 100644 --- a/src/bootstrap/objects.c +++ b/src/bootstrap/objects.c | |||
@@ -9,6 +9,8 @@ typedef enum ObjectType { | |||
9 | OBJ_TYPE_ERR, | 9 | OBJ_TYPE_ERR, |
10 | } ObjectType; | 10 | } ObjectType; |
11 | 11 | ||
12 | struct Environment; | ||
13 | |||
12 | typedef struct Object { | 14 | typedef struct Object { |
13 | ObjectType type; | 15 | ObjectType type; |
14 | union { | 16 | union { |
@@ -34,7 +36,7 @@ typedef struct Object { | |||
34 | }; | 36 | }; |
35 | 37 | ||
36 | // OBJ_TYPE_PROCEDURE | 38 | // OBJ_TYPE_PROCEDURE |
37 | struct Object *(*proc)(struct Object *args); | 39 | struct Object *(*proc)(struct Environment *env, struct Object *args); |
38 | }; | 40 | }; |
39 | } Object; | 41 | } Object; |
40 | 42 | ||
@@ -66,7 +68,7 @@ make_fixnum(ssize_t num) { | |||
66 | } | 68 | } |
67 | 69 | ||
68 | Object * | 70 | Object * |
69 | make_procedure(Object *(*proc)(struct Object *args)) { | 71 | make_procedure(Object *(*proc)(struct Environment *, struct Object *args)) { |
70 | Object *obj = alloc_object(OBJ_TYPE_PROCEDURE); | 72 | Object *obj = alloc_object(OBJ_TYPE_PROCEDURE); |
71 | obj->proc = proc; | 73 | obj->proc = proc; |
72 | return obj; | 74 | return obj; |
@@ -195,3 +197,106 @@ display(Object *root) { | |||
195 | } | 197 | } |
196 | return; | 198 | return; |
197 | } | 199 | } |
200 | |||
201 | #include "environment.c" | ||
202 | |||
203 | Object * | ||
204 | eval(Environment* env, Object *root) { | ||
205 | switch (root->type) { | ||
206 | case OBJ_TYPE_FIXNUM: | ||
207 | case OBJ_TYPE_BOOL: | ||
208 | case OBJ_TYPE_NIL: | ||
209 | case OBJ_TYPE_STRING: { | ||
210 | return root; | ||
211 | } break; | ||
212 | case OBJ_TYPE_SYMBOL: { | ||
213 | Object *val = env_lookup(env, root); | ||
214 | if (val == obj_err) { | ||
215 | error_push((Error){ | ||
216 | .type = ERR_TYPE_RUNTIME, | ||
217 | .value = ERR_SYMBOL_NOT_FOUND, | ||
218 | }); | ||
219 | return obj_err; | ||
220 | } | ||
221 | return val; | ||
222 | } break; | ||
223 | case OBJ_TYPE_PAIR: { | ||
224 | if (root->car->type == OBJ_TYPE_SYMBOL) { | ||
225 | Object *val = env_lookup(env, root->car); | ||
226 | if (val == obj_err) { | ||
227 | error_push((Error){ | ||
228 | .type = ERR_TYPE_RUNTIME, | ||
229 | .value = ERR_SYMBOL_NOT_FOUND, | ||
230 | }); | ||
231 | return obj_err; | ||
232 | } | ||
233 | if (val->type == OBJ_TYPE_PROCEDURE) { | ||
234 | return val->proc(env, root->cdr); | ||
235 | } | ||
236 | error_push((Error){ | ||
237 | .type = ERR_TYPE_RUNTIME, | ||
238 | .value = ERR_OBJ_NOT_CALLABLE, | ||
239 | }); | ||
240 | return obj_err; | ||
241 | } | ||
242 | } break; | ||
243 | default: { | ||
244 | break; | ||
245 | } break; | ||
246 | } | ||
247 | |||
248 | error_push((Error){ | ||
249 | .type = ERR_TYPE_RUNTIME, | ||
250 | .value = ERR_UNKNOWN_OBJ_TYPE, | ||
251 | }); | ||
252 | return obj_err; | ||
253 | } | ||
254 | |||
255 | Object * | ||
256 | proc_quote(Environment *env, Object *obj) { | ||
257 | (void)env; | ||
258 | return obj->car; | ||
259 | } | ||
260 | |||
261 | Object * | ||
262 | proc_sum(Environment *env, Object *obj) { | ||
263 | // First argument. | ||
264 | if (obj == obj_nil) { | ||
265 | error_push((Error){ | ||
266 | .type = ERR_TYPE_RUNTIME, | ||
267 | .value = ERR_NOT_ENOUGH_ARGS, | ||
268 | }); | ||
269 | return obj_err; | ||
270 | } | ||
271 | Object *car = eval(env, obj->car); | ||
272 | if (car == obj_err) { | ||
273 | return obj_err; | ||
274 | } | ||
275 | if (car->type != OBJ_TYPE_FIXNUM) { | ||
276 | error_push((Error){ | ||
277 | .type = ERR_TYPE_RUNTIME, | ||
278 | .value = ERR_WRONG_ARG_TYPE, | ||
279 | }); | ||
280 | return obj_err; | ||
281 | } | ||
282 | |||
283 | // Traverse the list. | ||
284 | obj = obj->cdr; | ||
285 | ssize_t tot = car->fixnum; | ||
286 | while (obj->type == OBJ_TYPE_PAIR) { | ||
287 | Object *car = eval(env, obj->car); | ||
288 | if (car == obj_err) { | ||
289 | return obj_err; | ||
290 | } | ||
291 | if (car->type != OBJ_TYPE_FIXNUM) { | ||
292 | error_push((Error){ | ||
293 | .type = ERR_TYPE_RUNTIME, | ||
294 | .value = ERR_WRONG_ARG_TYPE, | ||
295 | }); | ||
296 | return obj_err; | ||
297 | } | ||
298 | tot += car->fixnum; | ||
299 | obj = obj->cdr; | ||
300 | } | ||
301 | return make_fixnum(tot); | ||
302 | } | ||