#include "uclisp.h" #include "internal.h" #include "state.h" #include "utility.h" #include #include #include // Implements state as a giant alist // TODO: Consider generalizing the alist concept struct ucl_state { struct ucl_object *list; struct ucl_state *parent; }; #define NAME_POSITION 0 #define DATA_POSITION 1 static struct ucl_object *ucl_state_get_cell(struct ucl_state *state, const char *name) { FOREACH_LIST(state->list, iter, item) { assert(item->type == UCL_TYPE_CELL); const char *item_name = ucl_list_nth(item, NAME_POSITION)->string; if (!strcmp(name, item_name)) { return item; } } return NULL; } struct ucl_object *ucl_state_get(struct ucl_state *state, const char *name) { struct ucl_object *cell = ucl_state_get_cell(state, name); if (cell == NULL) { if (state->parent == NULL) { return ucl_error_create("Unknown error"); } else { return ucl_state_get(state->parent, name); } } return ucl_list_nth(cell, DATA_POSITION); } void ucl_state_put(struct ucl_state *state, const char *name, struct ucl_object *obj) { struct ucl_object *cell = ucl_state_get_cell(state, name); if (cell == NULL) { ucl_list_append(state->list, ucl_tuple_create( ucl_string_create(name), obj)); } else { // TODO: Refcounting / cleanup cell->cell.cdr->cell.car = obj; } } struct ucl_state *ucl_state_create() { struct ucl_state *state = malloc(sizeof(struct ucl_state)); state->list = ucl_nil_create(); state->parent = NULL; return state; } struct ucl_state *ucl_state_create_child(struct ucl_state *parent) { struct ucl_state *state = ucl_state_create(); state->parent = parent; return state; } void ucl_state_delete(struct ucl_state *state) { // TODO: Cleanup // ucl_object_delete(state->list); }