Refactor to encapsulate all state in a 'ucl'

This commit is contained in:
2022-11-22 15:50:46 -05:00
parent 13062a5b86
commit 5320c70dea
23 changed files with 641 additions and 663 deletions

View File

@@ -10,44 +10,26 @@
#include "builtins.h"
#include "special.h"
static struct ucl *state;
static struct ucl_object *input;
static struct ucl_object *response;
static struct ucl_scope *scope;
void setUp(void) {
input = NULL;
response = NULL;
scope = ucl_scope_create();
ucl_scope_put(scope, "let", ucl_special_create(ucl_special_let));
ucl_scope_put(scope, "defun", ucl_special_create(ucl_special_defun));
ucl_scope_put(scope, "+", ucl_builtin_create(ucl_builtin_add));
ucl_scope_put(scope, "error", ucl_builtin_create(ucl_builtin_error));
ucl_scope_put(scope, "list", ucl_builtin_create(ucl_builtin_list));
ucl_scope_put(scope, "setq", ucl_special_create(ucl_special_setq));
ucl_scope_put(scope, "car", ucl_builtin_create(ucl_builtin_car));
ucl_scope_put(scope, "cdr", ucl_builtin_create(ucl_builtin_cdr));
ucl_scope_put(scope, "nth", ucl_builtin_create(ucl_builtin_nth));
ucl_scope_put(scope, "mapcar", ucl_builtin_create(ucl_builtin_mapcar));
ucl_scope_put(scope, "filter", ucl_builtin_create(ucl_builtin_filter));
ucl_scope_put(scope, "reduce", ucl_builtin_create(ucl_builtin_reduce));
ucl_scope_put(scope, "lambda", ucl_special_create(ucl_special_lambda));
ucl_scope_put(scope, "quote", ucl_special_create(ucl_special_quote));
ucl_scope_put(scope, "%", ucl_builtin_create(ucl_builtin_mod));
state = ucl_create();
}
void tearDown(void) {
ucl_scope_delete(scope);
ucl_gc();
// TODO: Actually release resources
state = NULL;
input = NULL;
response = NULL;
scope = NULL;
}
static struct ucl_object *eval (const char *code) {
struct ucl_object *sexp = ucl_parse(code);
return ucl_evaluate(scope, ucl_car(sexp));
struct ucl_object *sexp = ucl_parse(state, code);
return ucl_evaluate(state, ucl_car(state, sexp));
}
void test_simple_add(void) {
@@ -96,7 +78,7 @@ void test_eval_string(void) {
}
void test_eval_sym_defined(void) {
ucl_scope_put(scope, "foo", ucl_int_create(2));
ucl_scope_put(state, state->global_scope, "foo", ucl_int_create(state, 2));
response = eval("foo");
TEST_ASSERT_OBJ_INT_V(response, 2);
}
@@ -114,7 +96,7 @@ void test_eval_nested_error(void) {
void test_eval_list(void) {
response = eval("(list 1 2 3)");
TEST_ASSERT_OBJ_LIST(response);
TEST_ASSERT_EQUAL(ucl_list_length(response)->integer, 3);
TEST_ASSERT_EQUAL(ucl_list_length(state, response)->integer, 3);
int i = 1;
FOREACH_LIST(response, iter, item) {
@@ -227,7 +209,7 @@ void test_eval_defun_gc(void) {
TEST_ASSERT_OBJ_SYMBOL_V(response, "foo");
ucl_gc();
ucl_gc(state);
response = eval("(foo 10 15)");
TEST_ASSERT_OBJ_INT_V(response, 25);

View File

@@ -9,14 +9,17 @@
#include "parse.h"
/* static struct ucl_parse_result *result; */
static struct ucl *state;
static struct ucl_object *response;
void setUp(void) {
state = ucl_create();
response = NULL;
}
void tearDown(void) {
ucl_gc();
// TODO: Release state
state = NULL;
response = NULL;
}
@@ -24,7 +27,7 @@ static void test_token_next_empty_str(void) {
const char *input = "";
const char *curr = input;
response = ucl_token_next(&curr);
response = ucl_token_next(state, &curr);
TEST_ASSERT_NULL(response);
TEST_ASSERT_EQUAL('\0', *curr);
@@ -34,7 +37,7 @@ static void test_token_next_only_whitespace(void) {
const char *input = " \n";
const char *curr = input;
response = ucl_token_next(&curr);
response = ucl_token_next(state, &curr);
TEST_ASSERT_NULL(response);
TEST_ASSERT_EQUAL('\0', *curr);
@@ -44,7 +47,7 @@ static void test_token_next_lparen(void) {
const char *input = "(";
const char *curr = input;
response = ucl_token_next(&curr);
response = ucl_token_next(state, &curr);
TEST_ASSERT_OBJ_SYMBOL_V(response, "(");
TEST_ASSERT_EQUAL('\0', *curr);
}
@@ -53,7 +56,7 @@ static void test_token_next_rparen(void) {
const char *input = ")";
const char *curr = input;
response = ucl_token_next(&curr);
response = ucl_token_next(state, &curr);
TEST_ASSERT_OBJ_SYMBOL_V(response, ")");
TEST_ASSERT_EQUAL('\0', *curr);
@@ -63,12 +66,12 @@ static void test_token_next_lrparen(void) {
const char *input = "()";
const char *curr = input;
response = ucl_token_next(&curr);
response = ucl_token_next(state, &curr);
TEST_ASSERT_OBJ_SYMBOL_V(response, "(");
ucl_object_delete(response);
response = ucl_token_next(&curr);
ucl_object_delete(state, response);
response = ucl_token_next(state, &curr);
TEST_ASSERT_OBJ_SYMBOL_V(response, ")");
TEST_ASSERT_EQUAL('\0', *curr);
@@ -78,7 +81,7 @@ static void test_token_next_string(void) {
const char *input = "\"foo\"";
const char *curr = input;
response = ucl_token_next(&curr);
response = ucl_token_next(state, &curr);
TEST_ASSERT_OBJ_STRING_V(response, "foo");
TEST_ASSERT_EQUAL('\0', *curr);
@@ -88,7 +91,7 @@ static void test_token_next_string_w_whitespace(void) {
const char *input = " \"foo\" ";
const char *curr = input;
response = ucl_token_next(&curr);
response = ucl_token_next(state, &curr);
TEST_ASSERT_OBJ_STRING_V(response, "foo");
TEST_ASSERT_EQUAL_STRING(" ", curr);
@@ -98,7 +101,7 @@ static void test_token_next_symbol(void) {
const char *input = "foo";
const char *curr = input;
response = ucl_token_next(&curr);
response = ucl_token_next(state, &curr);
TEST_ASSERT_OBJ_SYMBOL_V(response, "foo");
TEST_ASSERT_EQUAL_STRING("", curr);
@@ -108,20 +111,20 @@ static void test_token_next_symbol_w_whitespace(void) {
const char *input = " foo ";
const char *curr = input;
response = ucl_token_next(&curr);
response = ucl_token_next(state, &curr);
TEST_ASSERT_OBJ_SYMBOL_V(response, "foo");
TEST_ASSERT_EQUAL_STRING(" ", curr);
}
static void test_tokenize_empty_str(void) {
response = ucl_tokenize("");
response = ucl_tokenize(state, "");
TEST_ASSERT_NIL(response);
}
static void test_tokenize_nil(void) {
response = ucl_tokenize("()");
response = ucl_tokenize(state, "()");
TEST_ASSERT_NOT_NULL(response);
TEST_ASSERT_EQUAL(UCL_TYPE_CELL, response->type);
@@ -141,7 +144,7 @@ static void test_tokenize_nil(void) {
}
static void test_tokenize_scopement(void) {
response = ucl_tokenize("(foo)");
response = ucl_tokenize(state, "(foo)");
TEST_ASSERT_NOT_NULL(response);
TEST_ASSERT_EQUAL(UCL_TYPE_CELL, response->type);
@@ -166,27 +169,27 @@ static void test_tokenize_scopement(void) {
}
static void test_parse_atom_symbol(void) {
response = ucl_parse_token_atom(ucl_symbol_create("foo"));
response = ucl_parse_token_atom(state, ucl_symbol_create(state, "foo"));
TEST_ASSERT_EQUAL(response->type, UCL_TYPE_SYMBOL);
TEST_ASSERT_EQUAL_STRING(response->symbol, "foo");
}
static void test_parse_atom_lparen(void) {
response = ucl_parse_token_atom(ucl_symbol_create("("));
response = ucl_parse_token_atom(state, ucl_symbol_create(state, "("));
TEST_ASSERT_NULL(response);
}
static void test_parse_atom_rparen(void) {
response = ucl_parse_token_atom(ucl_symbol_create(")"));
response = ucl_parse_token_atom(state, ucl_symbol_create(state, ")"));
TEST_ASSERT_NULL(response);
}
static void test_parse_empty_str(void) {
response = ucl_parse("");
response = ucl_parse(state, "");
TEST_ASSERT_NOT_NULL(response);
TEST_ASSERT_EQUAL(UCL_TYPE_CELL, response->type);
@@ -195,7 +198,7 @@ static void test_parse_empty_str(void) {
}
static void test_parse_symbol(void) {
response = ucl_parse("foo");
response = ucl_parse(state, "foo");
TEST_ASSERT_NOT_NULL(response);
TEST_ASSERT_EQUAL(UCL_TYPE_CELL, response->type);
@@ -206,7 +209,7 @@ static void test_parse_symbol(void) {
}
static void test_parse_nil(void) {
response = ucl_parse("()");
response = ucl_parse(state, "()");
TEST_ASSERT_NOT_NULL(response);
TEST_ASSERT_EQUAL(UCL_TYPE_CELL, response->type);
@@ -219,7 +222,7 @@ static void test_parse_nil(void) {
}
static void test_parse_list_1elem(void) {
response = ucl_parse("(foo)");
response = ucl_parse(state, "(foo)");
TEST_ASSERT_NOT_NULL(response);
TEST_ASSERT_EQUAL(UCL_TYPE_CELL, response->type);
@@ -235,7 +238,7 @@ static void test_parse_list_1elem(void) {
}
static void test_parse_list_2elem(void) {
response = ucl_parse("(foo bar)");
response = ucl_parse(state, "(foo bar)");
TEST_ASSERT_NOT_NULL(response);
TEST_ASSERT_EQUAL(UCL_TYPE_CELL, response->type);
@@ -256,7 +259,7 @@ static void test_parse_list_2elem(void) {
}
static void test_parse_2elem(void) {
response = ucl_parse("foo bar");
response = ucl_parse(state, "foo bar");
TEST_ASSERT_NOT_NULL(response);
TEST_ASSERT_EQUAL(UCL_TYPE_CELL, response->type);
@@ -273,7 +276,7 @@ static void test_parse_2elem(void) {
}
static void test_parse_2elem_str(void) {
response = ucl_parse("\"foo\" \"bar\"");
response = ucl_parse(state, "\"foo\" \"bar\"");
TEST_ASSERT_NOT_NULL(response);
TEST_ASSERT_EQUAL(UCL_TYPE_CELL, response->type);
@@ -290,7 +293,7 @@ static void test_parse_2elem_str(void) {
}
static void test_parse_nested(void) {
response = ucl_parse("((foo))");
response = ucl_parse(state, "((foo))");
TEST_ASSERT_NOT_NULL(response);
TEST_ASSERT_EQUAL(UCL_TYPE_CELL, response->type);
@@ -309,45 +312,45 @@ static void test_parse_nested(void) {
}
static void test_parse_mismatched_open(void) {
response = ucl_parse("(");
response = ucl_parse(state, "(");
TEST_ASSERT_NOT_NULL(response);
TEST_ASSERT_OBJ_ERROR(response);
}
static void test_parse_mismatched_closed(void) {
response = ucl_parse(")");
response = ucl_parse(state, ")");
TEST_ASSERT_NOT_NULL(response);
TEST_ASSERT_OBJ_ERROR(response);
}
static void test_parse_int(void) {
response = ucl_parse("123");
response = ucl_parse(state, "123");
TEST_ASSERT_OBJ_INT_V(response->cell.car, 123);
}
static void test_parse_int_hex(void) {
response = ucl_parse("0xa");
response = ucl_parse(state, "0xa");
TEST_ASSERT_OBJ_INT_V(response->cell.car, 0xa);
}
static void test_parse_int_neg(void) {
response = ucl_parse("-7");
response = ucl_parse(state, "-7");
TEST_ASSERT_OBJ_INT_V(response->cell.car, -7);
}
static void test_parse_int_plus(void) {
response = ucl_parse("+7");
response = ucl_parse(state, "+7");
TEST_ASSERT_OBJ_INT_V(response->cell.car, 7);
}
static void test_parse_int_garbled(void) {
response = ucl_parse("+1234g7");
response = ucl_parse(state, "+1234g7");
TEST_ASSERT_OBJ_ERROR(response);
}

View File

@@ -9,51 +9,52 @@
#include "scope.h"
/* static struct ucl_parse_result *result; */
static struct ucl *state;
static struct ucl_scope *scope;
static struct ucl_object *response;
void setUp(void) {
scope = ucl_scope_create();
state = ucl_create();
scope = ucl_scope_create(state);
}
void tearDown(void) {
ucl_scope_delete(scope);
ucl_gc();
state = NULL;
scope = NULL;
}
static void test_get_empty(void) {
response = ucl_scope_get(scope, "foo");
response = ucl_scope_get(state, scope, "foo");
TEST_ASSERT_OBJ_ERROR(response);
}
static void test_put_get(void) {
ucl_scope_put(scope, "foo", ucl_t_create());
response = ucl_scope_get(scope, "foo");
ucl_scope_put(state, scope, "foo", ucl_t_create(state));
response = ucl_scope_get(state, scope, "foo");
TEST_ASSERT_T(response);
}
static void test_put2_get(void) {
ucl_scope_put(scope, "foo1", ucl_t_create());
ucl_scope_put(scope, "foo2", ucl_nil_create());
response = ucl_scope_get(scope, "foo1");
ucl_scope_put(state, scope, "foo1", ucl_t_create(state));
ucl_scope_put(state, scope, "foo2", ucl_nil_create(state));
response = ucl_scope_get(state, scope, "foo1");
TEST_ASSERT_T(response);
}
static void test_put_modify_get(void) {
struct ucl_object *obj = ucl_tuple_create(
ucl_string_create("bar"),
ucl_string_create("baz"));
struct ucl_object *obj = ucl_tuple_create(state,
ucl_string_create(state, "bar"),
ucl_string_create(state, "baz"));
ucl_scope_put(scope, "foo", obj);
ucl_list_append(obj, ucl_string_create("quux"));
response = ucl_scope_get(scope, "foo");
ucl_scope_put(state, scope, "foo", obj);
ucl_list_append(state, obj, ucl_string_create(state, "quux"));
response = ucl_scope_get(state, scope, "foo");
TEST_ASSERT_OBJ_STRING(ucl_list_nth(response, 2));
TEST_ASSERT_EQUAL_STRING(ucl_list_nth(response, 2)->string, "quux");
TEST_ASSERT_OBJ_STRING(ucl_list_nth(state, response, 2));
TEST_ASSERT_EQUAL_STRING(ucl_list_nth(state, response, 2)->string, "quux");
TEST_ASSERT_OBJ_STRING(ucl_list_nth(obj, 2));
TEST_ASSERT_EQUAL_STRING(ucl_list_nth(obj, 2)->string, "quux");
TEST_ASSERT_OBJ_STRING(ucl_list_nth(state, obj, 2));
TEST_ASSERT_EQUAL_STRING(ucl_list_nth(state, obj, 2)->string, "quux");
}

View File

@@ -7,89 +7,91 @@
#include "uclisp.h"
#include "common.h"
static struct ucl *state;
static struct ucl_object *input;
static struct ucl_object *response;
void setUp(void) {
state = ucl_create();
input = NULL;
response = NULL;
}
void tearDown(void) {
ucl_gc();
// TODO: Release memory
state = NULL;
input = NULL;
response = NULL;
}
static void test_nil_create(void) {
response = ucl_nil_create();
response = ucl_nil_create(state);
TEST_ASSERT_NIL(response);
}
static void test_t_create(void) {
response = ucl_t_create();
response = ucl_t_create(state);
TEST_ASSERT_T(response);
}
static void test_predicate_true(void) {
response = ucl_predicate(true);
response = ucl_predicate(state, true);
TEST_ASSERT_T(response);
}
static void test_predicate_false(void) {
response = ucl_predicate(false);
response = ucl_predicate(state, false);
TEST_ASSERT_NIL(response);
}
static void test_car_nil(void) {
response = ucl_car(ucl_nil_create());
response = ucl_car(state, ucl_nil_create(state));
TEST_ASSERT_NIL(response);
}
static void test_cdr_nil(void) {
response = ucl_cdr(ucl_nil_create());
response = ucl_cdr(state, ucl_nil_create(state));
TEST_ASSERT_NIL(response);
}
static void test_car_t(void) {
response = ucl_car(ucl_t_create());
response = ucl_car(state, ucl_t_create(state));
TEST_ASSERT_OBJ_ERROR(response);
}
static void test_cdr_t(void) {
response = ucl_car(ucl_t_create());
response = ucl_car(state, ucl_t_create(state));
TEST_ASSERT_OBJ_ERROR(response);
}
static void test_car_list(void) {
input = ucl_tuple_create(
ucl_string_create("foo"),
ucl_t_create());
response = ucl_car(input);
input = ucl_tuple_create(state,
ucl_string_create(state, "foo"),
ucl_t_create(state));
response = ucl_car(state, input);
TEST_ASSERT_OBJ_STRING(response);
}
static void test_cdr_list(void) {
input = ucl_tuple_create(
ucl_t_create(),
ucl_string_create("foo"));
response = ucl_cdr(input);
input = ucl_tuple_create(state,
ucl_t_create(state),
ucl_string_create(state, "foo"));
response = ucl_cdr(state, input);
TEST_ASSERT_OBJ_STRING(ucl_car(response));
TEST_ASSERT_OBJ_STRING(ucl_car(state, response));
}
static void test_list_length_nil() {
response = ucl_list_length(ucl_nil_create());
response = ucl_list_length(state, ucl_nil_create(state));
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 0);
@@ -97,8 +99,9 @@ static void test_list_length_nil() {
static void test_list_length_1() {
response = ucl_list_length(
ucl_cell_create(
ucl_t_create(), NULL));
state,
ucl_cell_create(state,
ucl_t_create(state), NULL));
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 1);
@@ -106,9 +109,10 @@ static void test_list_length_1() {
static void test_list_length_2() {
response = ucl_list_length(
ucl_tuple_create(
ucl_t_create(),
ucl_t_create()));
state,
ucl_tuple_create(state,
ucl_t_create(state),
ucl_t_create(state)));
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 2);
@@ -116,36 +120,37 @@ static void test_list_length_2() {
static void test_list_append_nil() {
input = ucl_nil_create();
ucl_list_append(input, ucl_t_create());
input = ucl_nil_create(state);
ucl_list_append(state, input, ucl_t_create(state));
TEST_ASSERT_EQUAL(ucl_list_length(input)->integer, 1);
TEST_ASSERT_EQUAL(ucl_list_length(state, input)->integer, 1);
}
static void test_list_append_list() {
input = ucl_tuple_create(ucl_t_create(), ucl_t_create());
ucl_list_append(input, ucl_t_create());
input = ucl_tuple_create(state, ucl_t_create(state), ucl_t_create(state));
ucl_list_append(state, input, ucl_t_create(state));
TEST_ASSERT_EQUAL(ucl_list_length(input)->integer, 3);
TEST_ASSERT_EQUAL(ucl_list_length(state, input)->integer, 3);
}
static void test_list_nth_nil_0() {
response = ucl_list_nth(ucl_nil_create(), 0);
response = ucl_list_nth(state, ucl_nil_create(state), 0);
TEST_ASSERT_OBJ_ERROR(response);
}
static void test_list_nth_nil_1() {
response = ucl_list_nth(ucl_nil_create(), 1);
response = ucl_list_nth(state, ucl_nil_create(state), 1);
TEST_ASSERT_OBJ_ERROR(response);
}
static void test_list_nth_list_0() {
response = ucl_list_nth(
ucl_tuple_create(
ucl_t_create(),
ucl_string_create("foo")),
state,
ucl_tuple_create(state,
ucl_t_create(state),
ucl_string_create(state, "foo")),
0);
TEST_ASSERT_T(response);
@@ -153,30 +158,32 @@ static void test_list_nth_list_0() {
static void test_list_nth_list_1() {
response = ucl_list_nth(
ucl_tuple_create(
ucl_t_create(),
ucl_string_create("foo")),
state,
ucl_tuple_create(state,
ucl_t_create(state),
ucl_string_create(state, "foo")),
1);
TEST_ASSERT_OBJ_STRING(response);
}
static void test_list_nth_t_0() {
response = ucl_list_nth(ucl_t_create(), 1);
response = ucl_list_nth(state, ucl_t_create(state), 1);
TEST_ASSERT_OBJ_ERROR(response);
}
static void test_list_nth_bounds_0() {
response = ucl_list_nth(ucl_nil_create(), 0);
response = ucl_list_nth(state, ucl_nil_create(state), 0);
TEST_ASSERT_OBJ_ERROR(response);
}
static void test_list_nth_bounds_1() {
response = ucl_list_nth(
ucl_cell_create(
ucl_nil_create(),
state,
ucl_cell_create(state,
ucl_nil_create(state),
NULL),
1);
@@ -185,42 +192,43 @@ static void test_list_nth_bounds_1() {
static void test_list_nth_bounds_2() {
response = ucl_list_nth(
ucl_tuple_create(
ucl_nil_create(),
ucl_nil_create()),
state,
ucl_tuple_create(state,
ucl_nil_create(state),
ucl_nil_create(state)),
2);
TEST_ASSERT_OBJ_ERROR(response);
}
static void test_truthy_0() {
response = ucl_truthy(ucl_int_create(0));
response = ucl_truthy(state, ucl_int_create(state, 0));
TEST_ASSERT_NIL(response);
}
static void test_truthy_1() {
response = ucl_truthy(ucl_int_create(1));
response = ucl_truthy(state, ucl_int_create(state, 1));
TEST_ASSERT_T(response);
}
static void test_truthy_nil() {
response = ucl_truthy(ucl_nil_create());
response = ucl_truthy(state, ucl_nil_create(state));
TEST_ASSERT_NIL(response);
}
static void test_truthy_list_w_elem() {
struct ucl_object *list = ucl_nil_create();
ucl_list_append(list, ucl_int_create(0));
response = ucl_truthy(list);
struct ucl_object *list = ucl_nil_create(state);
ucl_list_append(state, list, ucl_int_create(state, 0));
response = ucl_truthy(state, list);
TEST_ASSERT_T(response);
}
static void test_truthy_sym() {
response = ucl_truthy(ucl_symbol_create("t"));
response = ucl_truthy(state, ucl_symbol_create(state, "t"));
TEST_ASSERT_T(response);
}

View File

@@ -45,7 +45,7 @@
#define TEST_ASSERT_LIST_LEN(list, len) \
do { \
TEST_ASSERT_OBJ_LIST(list); \
TEST_ASSERT_EQUAL(len, ucl_list_length(list)->integer); \
TEST_ASSERT_EQUAL(len, ucl_list_length(state, list)->integer); \
} while(0)
#define TEST_ASSERT_NIL(obj) \