From b8bad3bf5af3261f25780a8cd8b90a659fe29bab Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Wed, 13 Oct 2021 14:19:32 +0200 Subject: Add support for environments and recursive evaluation --- src/bootstrap/objects.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 2 deletions(-) (limited to 'src/bootstrap/objects.c') 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 { OBJ_TYPE_ERR, } ObjectType; +struct Environment; + typedef struct Object { ObjectType type; union { @@ -34,7 +36,7 @@ typedef struct Object { }; // OBJ_TYPE_PROCEDURE - struct Object *(*proc)(struct Object *args); + struct Object *(*proc)(struct Environment *env, struct Object *args); }; } Object; @@ -66,7 +68,7 @@ make_fixnum(ssize_t num) { } Object * -make_procedure(Object *(*proc)(struct Object *args)) { +make_procedure(Object *(*proc)(struct Environment *, struct Object *args)) { Object *obj = alloc_object(OBJ_TYPE_PROCEDURE); obj->proc = proc; return obj; @@ -195,3 +197,106 @@ display(Object *root) { } return; } + +#include "environment.c" + +Object * +eval(Environment* env, Object *root) { + switch (root->type) { + case OBJ_TYPE_FIXNUM: + case OBJ_TYPE_BOOL: + case OBJ_TYPE_NIL: + case OBJ_TYPE_STRING: { + return root; + } break; + case OBJ_TYPE_SYMBOL: { + Object *val = env_lookup(env, root); + if (val == obj_err) { + error_push((Error){ + .type = ERR_TYPE_RUNTIME, + .value = ERR_SYMBOL_NOT_FOUND, + }); + return obj_err; + } + return val; + } break; + case OBJ_TYPE_PAIR: { + if (root->car->type == OBJ_TYPE_SYMBOL) { + Object *val = env_lookup(env, root->car); + if (val == obj_err) { + error_push((Error){ + .type = ERR_TYPE_RUNTIME, + .value = ERR_SYMBOL_NOT_FOUND, + }); + return obj_err; + } + if (val->type == OBJ_TYPE_PROCEDURE) { + return val->proc(env, root->cdr); + } + error_push((Error){ + .type = ERR_TYPE_RUNTIME, + .value = ERR_OBJ_NOT_CALLABLE, + }); + return obj_err; + } + } break; + default: { + break; + } break; + } + + error_push((Error){ + .type = ERR_TYPE_RUNTIME, + .value = ERR_UNKNOWN_OBJ_TYPE, + }); + return obj_err; +} + +Object * +proc_quote(Environment *env, Object *obj) { + (void)env; + return obj->car; +} + +Object * +proc_sum(Environment *env, Object *obj) { + // First argument. + if (obj == obj_nil) { + error_push((Error){ + .type = ERR_TYPE_RUNTIME, + .value = ERR_NOT_ENOUGH_ARGS, + }); + return obj_err; + } + Object *car = eval(env, obj->car); + if (car == obj_err) { + return obj_err; + } + if (car->type != OBJ_TYPE_FIXNUM) { + error_push((Error){ + .type = ERR_TYPE_RUNTIME, + .value = ERR_WRONG_ARG_TYPE, + }); + return obj_err; + } + + // Traverse the list. + obj = obj->cdr; + ssize_t tot = car->fixnum; + while (obj->type == OBJ_TYPE_PAIR) { + Object *car = eval(env, obj->car); + if (car == obj_err) { + return obj_err; + } + if (car->type != OBJ_TYPE_FIXNUM) { + error_push((Error){ + .type = ERR_TYPE_RUNTIME, + .value = ERR_WRONG_ARG_TYPE, + }); + return obj_err; + } + tot += car->fixnum; + obj = obj->cdr; + } + return make_fixnum(tot); +} -- cgit v1.2.1