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/environment.c | 106 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 src/bootstrap/environment.c (limited to 'src/bootstrap/environment.c') diff --git a/src/bootstrap/environment.c b/src/bootstrap/environment.c new file mode 100644 index 0000000..1bbe844 --- /dev/null +++ b/src/bootstrap/environment.c @@ -0,0 +1,106 @@ +// +// Environment. +// + +typedef struct EnvEntry { + Object *symbol; + Object *value; +} EnvEntry; + +typedef struct Environment { + struct Environment *parent; + EnvEntry *buf; + size_t size; + size_t cap; +} Environment; + +static Environment *global_env; + +#define ENV_BUF_CAP 8 + +Environment * +env_create(Environment *parent) { + Environment *env = malloc(sizeof(Environment)); + env->parent = parent; + env->buf = NULL; + env->size = 0; + env->cap = ENV_BUF_CAP; + return env; +} + +void +env_add_symbol(Environment *env, Object *symbol, Object *value) { + if (symbol->type != OBJ_TYPE_SYMBOL) { + error_push((Error){ + .type = ERR_TYPE_RUNTIME, + .value = ERR_NOT_A_SYMBOL, + .line = 0, + .col = 0, + }); + return; + } + if (env->buf == NULL) { + env->size = 0; + env->cap = ENV_BUF_CAP; + env->buf = malloc(env->cap * sizeof(EnvEntry)); + } else if (env->size == env->cap) { + env->cap *= 2; + env->buf = realloc(env->buf, env->cap * sizeof(EnvEntry)); + } + env->buf[env->size++] = (EnvEntry){symbol, value}; +} + +bool +obj_eq(Object *a, Object* b) { + if (a->type != b->type) { + return false; + } + switch (a->type) { + case OBJ_TYPE_FIXNUM: { + return a->fixnum == b->fixnum; + } break; + case OBJ_TYPE_STRING: { + if (a->string_n != b->string_n) { + return false; + } + for (size_t i = 0; i < a->string_n; i++) { + if (a->string[i] != b->string[i]) { + return false; + } + } + } break; + case OBJ_TYPE_SYMBOL: { + if (a->symbol_n != b->symbol_n) { + return false; + } + for (size_t i = 0; i < a->symbol_n; i++) { + if (a->symbol[i] != b->symbol[i]) { + return false; + } + } + } break; + case OBJ_TYPE_PAIR: { + // TODO: needs evaluation of parameters... + } break; + default: { + return a == b; + } break; + } + return true; +} + +Object * +env_lookup(Environment *env, Object *symbol) { + while (env != NULL) { + for (size_t i = 0; i < env->size; i++) { + EnvEntry entry = env->buf[i]; + if (obj_eq(symbol, entry.symbol)) { + return entry.value; + } + } + env = env->parent; + } + return obj_err; +} + +// TODO: Free env function. -- cgit v1.2.1