75 lines
2.0 KiB
C
75 lines
2.0 KiB
C
#include "uclisp.h"
|
|
#include "internal.h"
|
|
#include "state.h"
|
|
#include "utility.h"
|
|
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
// 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(strdup("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(strdup(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);
|
|
}
|