aboutsummaryrefslogtreecommitdiffstats
path: root/src/bootstrap/objects.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootstrap/objects.c')
-rw-r--r--src/bootstrap/objects.c109
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
12struct Environment;
13
12typedef struct Object { 14typedef 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
68Object * 70Object *
69make_procedure(Object *(*proc)(struct Object *args)) { 71make_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
203Object *
204eval(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
255Object *
256proc_quote(Environment *env, Object *obj) {
257 (void)env;
258 return obj->car;
259}
260
261Object *
262proc_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}