Rename 'state' to 'scope'

This commit is contained in:
2022-11-14 22:49:02 -05:00
parent 706b4a586d
commit af88471b3a
21 changed files with 320 additions and 321 deletions

View File

@@ -17,7 +17,7 @@ lib_srcs = [
"src/evaluate.c",
"src/memory.c",
"src/special.c",
"src/state.c",
"src/scope.c",
"src/utility.c",
"src/parse.c",
]
@@ -28,7 +28,7 @@ test_srcs = [
"test/test_arena.c",
"test/test_e2e.c",
"test/test_parse.c",
"test/test_state.c",
"test/test_scope.c",
"test/test_utility.c",
]
test_lib_srcs = ["third-party/unity/src/unity.c"]

View File

@@ -2,7 +2,7 @@
#include "internal.h"
#include "utility.h"
#include "builtins.h"
#include "state.h"
#include "scope.h"
#include "lisp.h"
#include <assert.h>
@@ -11,7 +11,7 @@
#include <stdlib.h>
#include <stdio.h>
LISP_FUNC_1(ucl_builtin_type, state, arg) {
LISP_FUNC_1(ucl_builtin_type, scope, arg) {
switch (arg->type) {
case UCL_TYPE_CELL:
return ucl_symbol_create("list");
@@ -33,7 +33,7 @@ LISP_FUNC_1(ucl_builtin_type, state, arg) {
}
}
LISP_FUNC_1(ucl_builtin_error, state, arg) {
LISP_FUNC_1(ucl_builtin_error, scope, arg) {
if (arg->type != UCL_TYPE_STRING) {
return ucl_error_create("Expected type string passed to 'error'");
}
@@ -41,42 +41,42 @@ LISP_FUNC_1(ucl_builtin_error, state, arg) {
return ucl_error_create(arg->error);
}
LISP_FUNC_1(ucl_builtin_symbol_p, state, arg) {
LISP_FUNC_1(ucl_builtin_symbol_p, scope, arg) {
return ucl_predicate(arg->type == UCL_TYPE_SYMBOL);
}
LISP_FUNC_1(ucl_builtin_string_p, state, arg) {
LISP_FUNC_1(ucl_builtin_string_p, scope, arg) {
return ucl_predicate(arg->type == UCL_TYPE_STRING);
}
LISP_FUNC_1(ucl_builtin_int_p, state, arg) {
LISP_FUNC_1(ucl_builtin_int_p, scope, arg) {
return ucl_predicate(arg->type == UCL_TYPE_INT);
}
LISP_FUNC_1(ucl_builtin_list_p, state, arg) {
LISP_FUNC_1(ucl_builtin_list_p, scope, arg) {
return ucl_predicate(arg->type == UCL_TYPE_CELL);
}
LISP_FUNC_1(ucl_builtin_error_p, state, arg) {
LISP_FUNC_1(ucl_builtin_error_p, scope, arg) {
return ucl_predicate(arg->type == UCL_TYPE_ERROR);
}
LISP_FUNC_1(ucl_builtin_car, state, arg) {
LISP_FUNC_1(ucl_builtin_car, scope, arg) {
return ucl_car(arg);
}
LISP_FUNC_1(ucl_builtin_cdr, state, arg) {
LISP_FUNC_1(ucl_builtin_cdr, scope, arg) {
return ucl_cdr(arg);
}
LISP_FUNC_2(ucl_builtin_nth, state, n, list) {
LISP_FUNC_2(ucl_builtin_nth, scope, n, list) {
UCL_COND_OR_RET_ERROR(n->type == UCL_TYPE_INT, "First argument to nth must be an integer");
UCL_COND_OR_RET_ERROR(list->type == UCL_TYPE_CELL, "Second argument to nth must be a list");
return ucl_list_nth(list, n->integer);
}
LISP_FUNC_2(ucl_builtin_add, state, arg0, arg1) {
LISP_FUNC_2(ucl_builtin_add, scope, arg0, arg1) {
if (arg0->type != UCL_TYPE_INT) {
return ucl_error_create("Invalid type of argument 0 to 'add'");
}
@@ -88,7 +88,7 @@ LISP_FUNC_2(ucl_builtin_add, state, arg0, arg1) {
return ucl_int_create(arg0->integer + arg1->integer);
}
LISP_FUNC_2(ucl_builtin_sub, state, arg0, arg1) {
LISP_FUNC_2(ucl_builtin_sub, scope, arg0, arg1) {
if (arg0->type != UCL_TYPE_INT) {
return ucl_error_create("Invalid type of argument 0 to 'sub'");
}
@@ -100,7 +100,7 @@ LISP_FUNC_2(ucl_builtin_sub, state, arg0, arg1) {
return ucl_int_create(arg0->integer - arg1->integer);
}
LISP_FUNC_2(ucl_builtin_mul, state, arg0, arg1) {
LISP_FUNC_2(ucl_builtin_mul, scope, arg0, arg1) {
if (arg0->type != UCL_TYPE_INT) {
return ucl_error_create("Invalid type of argument 0 to 'mul'");
}
@@ -112,7 +112,7 @@ LISP_FUNC_2(ucl_builtin_mul, state, arg0, arg1) {
return ucl_int_create(arg0->integer * arg1->integer);
}
LISP_FUNC_2(ucl_builtin_div, state, arg0, arg1) {
LISP_FUNC_2(ucl_builtin_div, scope, arg0, arg1) {
if (arg0->type != UCL_TYPE_INT) {
return ucl_error_create("Invalid type of argument 0 to 'div'");
}
@@ -125,7 +125,7 @@ LISP_FUNC_2(ucl_builtin_div, state, arg0, arg1) {
return ucl_int_create(arg0->integer / arg1->integer);
}
LISP_FUNC_2(ucl_builtin_mod, state, arg0, arg1) {
LISP_FUNC_2(ucl_builtin_mod, scope, arg0, arg1) {
if (arg0->type != UCL_TYPE_INT) {
return ucl_error_create("Invalid type of argument 0 to 'mod'");
}
@@ -137,7 +137,7 @@ LISP_FUNC_2(ucl_builtin_mod, state, arg0, arg1) {
return ucl_int_create(arg0->integer % arg1->integer);
}
LISP_FUNC_2(ucl_builtin_concat, state, arg0, arg1) {
LISP_FUNC_2(ucl_builtin_concat, scope, arg0, arg1) {
if (arg0->type != UCL_TYPE_STRING) {
return ucl_error_create("Invalid type of argument 0 to 'concat'");
}
@@ -157,25 +157,25 @@ LISP_FUNC_2(ucl_builtin_concat, state, arg0, arg1) {
return result;
}
LISP_FUNC_0(ucl_builtin_now_millis_mono, state) {
LISP_FUNC_0(ucl_builtin_now_millis_mono, scope) {
// TODO: Implement and move to a 'platform' file
return NULL;
}
LISP_FUNC_1(ucl_builtin_print, state, arg0) {
LISP_FUNC_1(ucl_builtin_print, scope, arg0) {
ucl_print_obj(arg0);
return ucl_nil_create();
}
LISP_FUNC_1(ucl_builtin_printl, state, arg0) {
LISP_FUNC_1(ucl_builtin_printl, scope, arg0) {
ucl_print_obj(arg0);
printf("\n");
return ucl_nil_create();
}
struct ucl_object *ucl_builtin_list(struct ucl_state *state, struct ucl_object *args) {
struct ucl_object *ucl_builtin_list(struct ucl_scope *scope, struct ucl_object *args) {
struct ucl_object *head = ucl_nil_create();
FOREACH_LIST(args, iter, item) {
ucl_list_append(head, item);
@@ -184,57 +184,57 @@ struct ucl_object *ucl_builtin_list(struct ucl_state *state, struct ucl_object *
return head;
}
LISP_FUNC_2(ucl_builtin_mapcar, state, fun, elems) {
LISP_FUNC_2(ucl_builtin_mapcar, scope, fun, elems) {
// TODO: Support arbitrary number of 'elems' lists
struct ucl_object *result = ucl_nil_create();
FOREACH_LIST(elems, iter, elem) {
struct ucl_object *form = ucl_tuple_create(fun, elem);
struct ucl_object *value = ucl_evaluate(state, form);
struct ucl_object *value = ucl_evaluate(scope, form);
UCL_RET_IF_ERROR(value);
ucl_list_append(result, value);
}
return result;
}
LISP_FUNC_2(ucl_builtin_equal, state, arg0, arg1) {
LISP_FUNC_2(ucl_builtin_equal, scope, arg0, arg1) {
return ucl_equal(arg0, arg1);
}
LISP_FUNC_2(ucl_builtin_gt, state, arg0, arg1) {
LISP_FUNC_2(ucl_builtin_gt, scope, arg0, arg1) {
UCL_COND_OR_RET_ERROR(arg0->type == UCL_TYPE_INT, "First argument to > must be an integer");
UCL_COND_OR_RET_ERROR(arg0->type == UCL_TYPE_INT, "Second argument to > must be an integer");
return ucl_predicate(arg0->integer > arg1->integer);
}
LISP_FUNC_2(ucl_builtin_ge, state, arg0, arg1) {
LISP_FUNC_2(ucl_builtin_ge, scope, arg0, arg1) {
UCL_COND_OR_RET_ERROR(arg0->type == UCL_TYPE_INT, "First argument to >= must be an integer");
UCL_COND_OR_RET_ERROR(arg0->type == UCL_TYPE_INT, "Second argument to >= must be an integer");
return ucl_predicate(arg0->integer > arg1->integer);
}
LISP_FUNC_2(ucl_builtin_lt, state, arg0, arg1) {
LISP_FUNC_2(ucl_builtin_lt, scope, arg0, arg1) {
UCL_COND_OR_RET_ERROR(arg0->type == UCL_TYPE_INT, "First argument to < must be an integer");
UCL_COND_OR_RET_ERROR(arg0->type == UCL_TYPE_INT, "Second argument to < must be an integer");
return ucl_predicate(arg0->integer < arg1->integer);
}
LISP_FUNC_2(ucl_builtin_le, state, arg0, arg1) {
LISP_FUNC_2(ucl_builtin_le, scope, arg0, arg1) {
UCL_COND_OR_RET_ERROR(arg0->type == UCL_TYPE_INT, "First argument to <= must be an integer");
UCL_COND_OR_RET_ERROR(arg0->type == UCL_TYPE_INT, "Second argument to <= must be an integer");
return ucl_predicate(arg0->integer < arg1->integer);
}
LISP_FUNC_2(ucl_builtin_num_eq, state, arg0, arg1) {
LISP_FUNC_2(ucl_builtin_num_eq, scope, arg0, arg1) {
UCL_COND_OR_RET_ERROR(arg0->type == UCL_TYPE_INT, "First argument to = must be an integer");
UCL_COND_OR_RET_ERROR(arg0->type == UCL_TYPE_INT, "Second argument to = must be an integer");
return ucl_predicate(arg0->integer == arg1->integer);
}
LISP_FUNC_2(ucl_builtin_xor, state, arg0, arg1) {
LISP_FUNC_2(ucl_builtin_xor, scope, arg0, arg1) {
return ucl_predicate(ucl_truthy_bool(arg0) || ucl_truthy_bool(arg1));
}
LISP_FUNC_1(ucl_builtin_not, state, arg0) {
LISP_FUNC_1(ucl_builtin_not, scope, arg0) {
return ucl_predicate(!ucl_truthy_bool(arg0));
}

View File

@@ -3,37 +3,37 @@
#include "utility.h"
struct ucl_object *ucl_builtin_error(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_type(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_symbol_p(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_string_p(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_int_p(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_list_p(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_error(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_type(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_symbol_p(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_string_p(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_int_p(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_list_p(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_add(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_sub(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_mul(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_div(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_mod(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_gt(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_ge(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_lt(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_le(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_num_eq(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_concat(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_add(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_sub(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_mul(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_div(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_mod(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_gt(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_ge(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_lt(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_le(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_num_eq(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_concat(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_not(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_xor(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_not(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_xor(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_now_millis_mono(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_now_millis_mono(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_car(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_cdr(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_nth(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_list(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_mapcar(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_car(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_cdr(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_nth(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_list(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_mapcar(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_print(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_printl(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_builtin_print(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_printl(struct ucl_scope *scope, struct ucl_object *args);
#endif

View File

@@ -4,17 +4,17 @@
#include "uclisp.h"
#include "internal.h"
#include "utility.h"
#include "state.h"
#include "scope.h"
// TODO: remove string.h
#include <string.h>
struct ucl_object *ucl_evaluate_builtin_form(struct ucl_state *state, struct ucl_object *list) {
struct ucl_object *ucl_evaluate_builtin_form(struct ucl_scope *scope, struct ucl_object *list) {
// TODO: Reasonably split builtin and non-builtin evaluation
struct ucl_object *evaluated_list = ucl_nil_create();
FOREACH_LIST(list, iter, item) {
struct ucl_object *obj = ucl_evaluate(state, item);
struct ucl_object *obj = ucl_evaluate(scope, item);
UCL_RET_IF_ERROR(obj);
ucl_list_append(evaluated_list, obj);
};
@@ -24,18 +24,18 @@ struct ucl_object *ucl_evaluate_builtin_form(struct ucl_state *state, struct ucl
if (fun->type == UCL_TYPE_BUILTIN) {
struct ucl_object *args = ucl_cdr(evaluated_list);
result = fun->builtin(state, args);
result = fun->builtin(scope, args);
} else if (fun->type == UCL_TYPE_CELL) {
struct ucl_state *fun_state = ucl_state_create_child(state);
struct ucl_scope *fun_scope = ucl_scope_create_child(scope);
struct ucl_object *fun_arg_syms = ucl_car(fun);
struct ucl_object *fun_forms = ucl_cdr(fun);
int i = 0;
FOREACH_LIST(fun_arg_syms, iter, sym) {
ucl_state_put(fun_state, sym->symbol, ucl_list_nth(evaluated_list, i + 1));
ucl_scope_put(fun_scope, sym->symbol, ucl_list_nth(evaluated_list, i + 1));
i++;
}
result = ucl_progn(fun_state, fun_forms);
ucl_state_delete(fun_state);
result = ucl_progn(fun_scope, fun_forms);
ucl_scope_delete(fun_scope);
} else {
assert(0);
}
@@ -45,45 +45,45 @@ struct ucl_object *ucl_evaluate_builtin_form(struct ucl_state *state, struct ucl
return (result == NULL) ? ucl_nil_create() : result;
}
struct ucl_object *ucl_evaluate_special_form(struct ucl_state *state, struct ucl_object *list) {
struct ucl_object *ucl_evaluate_special_form(struct ucl_scope *scope, struct ucl_object *list) {
// TODO: Recursively eval args
const char *fun_sym = ucl_car(list)->symbol;
struct ucl_object *fun = ucl_state_get(state, fun_sym);
struct ucl_object *fun = ucl_scope_get(scope, fun_sym);
struct ucl_object *args = ucl_cdr(list);
struct ucl_object *result = NULL;
result = fun->special(state, args);
result = fun->special(scope, args);
return result;
}
struct ucl_object *ucl_evaluate_list(struct ucl_state *state, struct ucl_object *list) {
struct ucl_object *ucl_evaluate_list(struct ucl_scope *scope, struct ucl_object *list) {
if (list->cell.car == NULL) {
return list;
}
struct ucl_object *fun = ucl_evaluate(state, ucl_car(list));
struct ucl_object *fun = ucl_evaluate(scope, ucl_car(list));
UCL_RET_IF_ERROR(fun);
if (fun->type == UCL_TYPE_SPECIAL) {
return ucl_evaluate_special_form(state, list);
return ucl_evaluate_special_form(scope, list);
} else if (fun->type == UCL_TYPE_BUILTIN || fun->type == UCL_TYPE_CELL) {
return ucl_evaluate_builtin_form(state, list);
return ucl_evaluate_builtin_form(scope, list);
} else {
assert(0);
// TODO: Lisp functions and other errors
}
}
struct ucl_object *ucl_evaluate(struct ucl_state *state, struct ucl_object *obj) {
struct ucl_object *ucl_evaluate(struct ucl_scope *scope, struct ucl_object *obj) {
assert(obj != NULL);
switch (obj->type) {
case UCL_TYPE_CELL:
return ucl_evaluate_list(state, obj);
return ucl_evaluate_list(scope, obj);
case UCL_TYPE_SYMBOL:
return ucl_state_get(state, obj->symbol);
return ucl_scope_get(scope, obj->symbol);
case UCL_TYPE_INT:
case UCL_TYPE_STRING:
case UCL_TYPE_ERROR:

View File

@@ -14,13 +14,13 @@
iter_name = iter_name->cell.cdr, item_name = (iter_name == NULL) ? NULL : iter_name->cell.car)
// TODO: Refactor this struct's location
struct ucl_state {
struct ucl_scope {
// TODO: For garbage collection, we need references from the parent->child state
struct ucl_object *list;
struct ucl_state *parent;
struct ucl_scope *parent;
};
extern struct ucl_arena *state_arena;
extern struct ucl_arena *scope_arena;
struct ucl_object *ucl_cell_create(struct ucl_object *car, struct ucl_object *cdr);
struct ucl_object *ucl_int_create(int integer);

View File

@@ -4,19 +4,19 @@
#include "uclisp.h"
#include "utility.h"
#define LISP_FUNC_0(func_name, state_name) \
#define LISP_FUNC_0(func_name, scope_name) \
static struct ucl_object *func_name##_impl(); \
struct ucl_object *func_name(struct ucl_state *state, struct ucl_object *args) { \
struct ucl_object *func_name(struct ucl_scope *scope, struct ucl_object *args) { \
if (args->cell.car != NULL) { \
return NULL; \
} \
return func_name##_impl(state_name); \
return func_name##_impl(scope_name); \
} \
static struct ucl_object *func_name##_impl(struct ucl_state *state)
static struct ucl_object *func_name##_impl(struct ucl_scope *scope)
#define LISP_FUNC_1(func_name, state_name, arg0_name) \
static struct ucl_object *func_name##_impl(struct ucl_state *state, struct ucl_object *arg0_name); \
struct ucl_object *func_name(struct ucl_state *state, struct ucl_object *args) { \
#define LISP_FUNC_1(func_name, scope_name, arg0_name) \
static struct ucl_object *func_name##_impl(struct ucl_scope *scope, struct ucl_object *arg0_name); \
struct ucl_object *func_name(struct ucl_scope *scope, struct ucl_object *args) { \
struct ucl_object *len_obj = ucl_list_length(args); \
if (len_obj->type != UCL_TYPE_INT) { \
return NULL; \
@@ -25,14 +25,14 @@
return NULL; \
} \
struct ucl_object *arg0 = ucl_car(args); \
return func_name##_impl(state_name, arg0); \
return func_name##_impl(scope_name, arg0); \
} \
static struct ucl_object *func_name##_impl(struct ucl_state *state, struct ucl_object *arg0_name)
static struct ucl_object *func_name##_impl(struct ucl_scope *scope, struct ucl_object *arg0_name)
// TODO: Unroll the args more efficiently, this is O(n^2)
#define LISP_FUNC_2(func_name, state_name, arg0_name, arg1_name) \
static struct ucl_object *func_name##_impl(struct ucl_state *state, struct ucl_object *arg0_name, struct ucl_object *arg1_name); \
struct ucl_object *func_name(struct ucl_state *state, struct ucl_object *args) { \
#define LISP_FUNC_2(func_name, scope_name, arg0_name, arg1_name) \
static struct ucl_object *func_name##_impl(struct ucl_scope *scope, struct ucl_object *arg0_name, struct ucl_object *arg1_name); \
struct ucl_object *func_name(struct ucl_scope *scope, struct ucl_object *args) { \
struct ucl_object *len_obj = ucl_list_length(args); \
if (len_obj->type != UCL_TYPE_INT) { \
return NULL; \
@@ -42,8 +42,8 @@
} \
struct ucl_object *arg0 = ucl_list_nth(args, 0); \
struct ucl_object *arg1 = ucl_list_nth(args, 1); \
return func_name##_impl(state_name, arg0, arg1); \
return func_name##_impl(scope_name, arg0, arg1); \
} \
static struct ucl_object *func_name##_impl(struct ucl_state *state, struct ucl_object *arg0_name, struct ucl_object *arg1_name)
static struct ucl_object *func_name##_impl(struct ucl_scope *scope, struct ucl_object *arg0_name, struct ucl_object *arg1_name)
#endif

View File

@@ -8,62 +8,62 @@
#include "builtins.h"
#include "internal.h"
#include "special.h"
#include "state.h"
#include "scope.h"
#include "utility.h"
int main(int argc, const char **argv) {
(void) argc, (void) argv;
struct ucl_state *state = ucl_state_create();
struct ucl_scope *scope = ucl_scope_create();
ucl_state_put(state, "let", ucl_special_create(ucl_special_let));
ucl_state_put(state, "if", ucl_special_create(ucl_special_if));
ucl_state_put(state, "defun", ucl_special_create(ucl_special_defun));
ucl_state_put(state, "lambda", ucl_special_create(ucl_special_lambda));
ucl_state_put(state, "setq", ucl_special_create(ucl_special_setq));
ucl_state_put(state, "progn", ucl_special_create(ucl_special_progn));
ucl_state_put(state, "quote", ucl_special_create(ucl_special_quote));
ucl_state_put(state, "and", ucl_special_create(ucl_special_and));
ucl_state_put(state, "or", ucl_special_create(ucl_special_or));
ucl_scope_put(scope, "let", ucl_special_create(ucl_special_let));
ucl_scope_put(scope, "if", ucl_special_create(ucl_special_if));
ucl_scope_put(scope, "defun", ucl_special_create(ucl_special_defun));
ucl_scope_put(scope, "lambda", ucl_special_create(ucl_special_lambda));
ucl_scope_put(scope, "setq", ucl_special_create(ucl_special_setq));
ucl_scope_put(scope, "progn", ucl_special_create(ucl_special_progn));
ucl_scope_put(scope, "quote", ucl_special_create(ucl_special_quote));
ucl_scope_put(scope, "and", ucl_special_create(ucl_special_and));
ucl_scope_put(scope, "or", ucl_special_create(ucl_special_or));
// TODO:
// - iteration
ucl_state_put(state, "print", ucl_builtin_create(ucl_builtin_print));
ucl_state_put(state, "printl", ucl_builtin_create(ucl_builtin_printl));
ucl_scope_put(scope, "print", ucl_builtin_create(ucl_builtin_print));
ucl_scope_put(scope, "printl", ucl_builtin_create(ucl_builtin_printl));
// TODO:
// - object -> string
// - formatted printing?
ucl_state_put(state, "+", ucl_builtin_create(ucl_builtin_add));
ucl_state_put(state, "-", ucl_builtin_create(ucl_builtin_sub));
ucl_state_put(state, "*", ucl_builtin_create(ucl_builtin_mul));
ucl_state_put(state, "/", ucl_builtin_create(ucl_builtin_div));
ucl_state_put(state, "%", ucl_builtin_create(ucl_builtin_mod));
ucl_state_put(state, ">", ucl_builtin_create(ucl_builtin_gt));
ucl_state_put(state, ">=", ucl_builtin_create(ucl_builtin_ge));
ucl_state_put(state, "<", ucl_builtin_create(ucl_builtin_lt));
ucl_state_put(state, "<=", ucl_builtin_create(ucl_builtin_le));
ucl_state_put(state, "=", ucl_builtin_create(ucl_builtin_num_eq));
ucl_state_put(state, "not", ucl_builtin_create(ucl_builtin_not));
ucl_state_put(state, "xor", ucl_builtin_create(ucl_builtin_xor));
ucl_scope_put(scope, "+", ucl_builtin_create(ucl_builtin_add));
ucl_scope_put(scope, "-", ucl_builtin_create(ucl_builtin_sub));
ucl_scope_put(scope, "*", ucl_builtin_create(ucl_builtin_mul));
ucl_scope_put(scope, "/", ucl_builtin_create(ucl_builtin_div));
ucl_scope_put(scope, "%", ucl_builtin_create(ucl_builtin_mod));
ucl_scope_put(scope, ">", ucl_builtin_create(ucl_builtin_gt));
ucl_scope_put(scope, ">=", ucl_builtin_create(ucl_builtin_ge));
ucl_scope_put(scope, "<", ucl_builtin_create(ucl_builtin_lt));
ucl_scope_put(scope, "<=", ucl_builtin_create(ucl_builtin_le));
ucl_scope_put(scope, "=", ucl_builtin_create(ucl_builtin_num_eq));
ucl_scope_put(scope, "not", ucl_builtin_create(ucl_builtin_not));
ucl_scope_put(scope, "xor", ucl_builtin_create(ucl_builtin_xor));
// TODO:
// - Floats or nah?
ucl_state_put(state, "concat", ucl_builtin_create(ucl_builtin_concat));
ucl_scope_put(scope, "concat", ucl_builtin_create(ucl_builtin_concat));
ucl_state_put(state, "error", ucl_builtin_create(ucl_builtin_error));
ucl_state_put(state, "type", ucl_builtin_create(ucl_builtin_type));
ucl_state_put(state, "symbol-p", ucl_builtin_create(ucl_builtin_symbol_p));
ucl_state_put(state, "string-p", ucl_builtin_create(ucl_builtin_string_p));
ucl_state_put(state, "int-p", ucl_builtin_create(ucl_builtin_int_p));
ucl_state_put(state, "list-p", ucl_builtin_create(ucl_builtin_list_p));
ucl_scope_put(scope, "error", ucl_builtin_create(ucl_builtin_error));
ucl_scope_put(scope, "type", ucl_builtin_create(ucl_builtin_type));
ucl_scope_put(scope, "symbol-p", ucl_builtin_create(ucl_builtin_symbol_p));
ucl_scope_put(scope, "string-p", ucl_builtin_create(ucl_builtin_string_p));
ucl_scope_put(scope, "int-p", ucl_builtin_create(ucl_builtin_int_p));
ucl_scope_put(scope, "list-p", ucl_builtin_create(ucl_builtin_list_p));
ucl_state_put(state, "list", ucl_builtin_create(ucl_builtin_list));
ucl_state_put(state, "car", ucl_builtin_create(ucl_builtin_car));
ucl_state_put(state, "cdr", ucl_builtin_create(ucl_builtin_cdr));
ucl_state_put(state, "nth", ucl_builtin_create(ucl_builtin_nth));
ucl_state_put(state, "mapcar", ucl_builtin_create(ucl_builtin_mapcar));
ucl_state_put(state, "equal", ucl_builtin_create(ucl_builtin_mapcar));
ucl_scope_put(scope, "list", ucl_builtin_create(ucl_builtin_list));
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, "equal", ucl_builtin_create(ucl_builtin_mapcar));
// TODO:
// - reduce
@@ -80,7 +80,7 @@ int main(int argc, const char **argv) {
}
struct ucl_object *sexp = ucl_parse(line);
struct ucl_object *result = ucl_evaluate(state, ucl_car(sexp));
struct ucl_object *result = ucl_evaluate(scope, ucl_car(sexp));
ucl_print_obj(result);
printf("\n");
@@ -89,7 +89,7 @@ int main(int argc, const char **argv) {
}
} else {
struct ucl_object *sexp = ucl_parse(argv[1]);
struct ucl_object *result = ucl_evaluate(state, ucl_car(sexp));
struct ucl_object *result = ucl_evaluate(scope, ucl_car(sexp));
if (result->type == UCL_TYPE_ERROR) {
printf("%s", result->error);

View File

@@ -9,8 +9,8 @@
#include <limits.h>
#include <stdint.h>
#ifndef UCL_STATE_ARENA_SIZE
#define UCL_STATE_ARENA_SIZE 16
#ifndef UCL_SCOPE_ARENA_SIZE
#define UCL_SCOPE_ARENA_SIZE 16
#endif
#ifndef UCL_OBJECT_ARENA_SIZE
@@ -134,11 +134,11 @@ void ucl_object_mark(struct ucl_object *obj) {
}
}
void ucl_state_mark(struct ucl_arena * arena, void *obj) {
void ucl_scope_mark(struct ucl_arena * arena, void *obj) {
(void) arena;
struct ucl_state *state = (struct ucl_state *) obj;
struct ucl_scope *scope = (struct ucl_scope *) obj;
ucl_object_mark(state->list);
ucl_object_mark(scope->list);
}
void ucl_gc_unmark(struct ucl_arena * arena, void *obj) {
@@ -161,7 +161,7 @@ void ucl_gc_sweep(struct ucl_arena * arena, void *obj) {
void ucl_gc() {
ucl_arena_map(object_arena, ucl_gc_unmark);
ucl_arena_map(state_arena, ucl_state_mark);
ucl_arena_map(scope_arena, ucl_scope_mark);
ucl_arena_map(object_arena, ucl_gc_sweep);
}

87
src/scope.c Normal file
View File

@@ -0,0 +1,87 @@
#include "uclisp.h"
#include "internal.h"
#include "scope.h"
#include "utility.h"
#include "arena.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
// Implements state as a giant alist
// TODO: Consider generalizing the alist concept
#define NAME_POSITION 0
#define DATA_POSITION 1
#define SCOPE_ARENA_CAPACITY 32
struct ucl_arena *scope_arena;
static struct ucl_object *ucl_scope_get_cell(struct ucl_scope *scope, const char *name) {
FOREACH_LIST(scope->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_scope_get(struct ucl_scope *scope, const char *name) {
struct ucl_object *cell = ucl_scope_get_cell(scope, name);
if (cell == NULL) {
if (scope->parent == NULL) {
// TODO: Include the symbol name
return ucl_error_create("Unbound symbol");
} else {
return ucl_scope_get(scope->parent, name);
}
}
return ucl_list_nth(cell, DATA_POSITION);
}
void ucl_scope_put(struct ucl_scope *scope, const char *name, struct ucl_object *obj) {
struct ucl_object *cell = ucl_scope_get_cell(scope, name);
if (cell == NULL) {
ucl_list_append(scope->list,
ucl_tuple_create(
ucl_string_create(name),
obj));
} else {
// TODO: Refcounting / cleanup
cell->cell.cdr->cell.car = obj;
}
}
struct ucl_scope *ucl_scope_create() {
if (scope_arena == NULL) {
scope_arena = ucl_arena_create(sizeof(struct ucl_scope), SCOPE_ARENA_CAPACITY);
}
struct ucl_scope *scope = ucl_arena_get(scope_arena);
scope->list = ucl_nil_create();
scope->parent = NULL;
return scope;
}
struct ucl_scope *ucl_scope_create_child(struct ucl_scope *parent) {
struct ucl_scope *scope = ucl_scope_create();
scope->parent = parent;
return scope;
}
struct ucl_scope *ucl_scope_get_root(struct ucl_scope *scope) {
while (scope->parent != NULL) {
scope = scope->parent;
}
return scope;
}
void ucl_scope_delete(struct ucl_scope *scope) {
assert(scope_arena != NULL);
ucl_arena_put(scope_arena, scope);
// Garbage collection will handle the objects, they are shared
}

15
src/scope.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef _UCLISP_SCOPE_H_
#define _UCLISP_SCOPE_H_
struct ucl_scope;
struct ucl_scope *ucl_scope_create();
struct ucl_scope *ucl_scope_create_child(struct ucl_scope *parent);
void ucl_scope_delete(struct ucl_scope *scope);
struct ucl_object *ucl_scope_get(struct ucl_scope *scope, const char *name);
void ucl_scope_put(struct ucl_scope *scope, const char *name, struct ucl_object *obj);
struct ucl_scope *ucl_scope_get_root(struct ucl_scope *scope);
#endif

View File

@@ -1,55 +1,55 @@
#include "state.h"
#include "scope.h"
#include "lisp.h"
#include "utility.h"
#include "internal.h"
#include <assert.h>
struct ucl_object *ucl_special_let(struct ucl_state *state, struct ucl_object *args) {
struct ucl_object *ucl_special_let(struct ucl_scope *scope, struct ucl_object *args) {
// TODO: Check arguments
struct ucl_object *assignments = ucl_car(args);
struct ucl_object *expressions = ucl_cdr(args);
struct ucl_state *let_state = ucl_state_create_child(state);
struct ucl_scope *let_scope = ucl_scope_create_child(scope);
FOREACH_LIST(assignments, iter, item) {
// TODO: Check arguments
struct ucl_object *sym = ucl_car(item);
struct ucl_object *expr = ucl_car(ucl_cdr(item));
struct ucl_object *value = ucl_evaluate(let_state, expr);
struct ucl_object *value = ucl_evaluate(let_scope, expr);
assert(sym->type == UCL_TYPE_SYMBOL);
//assert(ucl_list_length(expr)->integer == 1);
if (value->type == UCL_TYPE_ERROR) {
// TODO cleanup
ucl_state_delete(let_state);
ucl_scope_delete(let_scope);
return value;
}
ucl_state_put(let_state, sym->symbol, value);
ucl_scope_put(let_scope, sym->symbol, value);
}
struct ucl_object *result = ucl_progn(let_state, expressions);
ucl_state_delete(let_state);
struct ucl_object *result = ucl_progn(let_scope, expressions);
ucl_scope_delete(let_scope);
return result;
}
struct ucl_object *ucl_special_if(struct ucl_state *state, struct ucl_object *args) {
struct ucl_object *ucl_special_if(struct ucl_scope *scope, struct ucl_object *args) {
// TODO: Check arguments
struct ucl_object *cond = ucl_car(args);
struct ucl_object *true_form = ucl_list_nth(args, 1);
struct ucl_object *false_forms = ucl_cdr(ucl_cdr(args));
struct ucl_object *cond_result = ucl_evaluate(state, cond);
struct ucl_object *cond_result = ucl_evaluate(scope, cond);
UCL_RET_IF_ERROR(cond_result);
if (ucl_truthy(cond_result)->type == UCL_TYPE_SYMBOL) {
return ucl_evaluate(state, true_form);
return ucl_evaluate(scope, true_form);
}
return ucl_progn(state, false_forms);
return ucl_progn(scope, false_forms);
}
struct ucl_object *ucl_special_defun(struct ucl_state *state, struct ucl_object *args) {
struct ucl_object *ucl_special_defun(struct ucl_scope *scope, struct ucl_object *args) {
// TODO: Check arguments
struct ucl_object *fun_sym = ucl_car(args);
if (fun_sym->type != UCL_TYPE_SYMBOL) {
@@ -66,13 +66,13 @@ struct ucl_object *ucl_special_defun(struct ucl_state *state, struct ucl_object
// there will be docstrings, maybe not!
// Functions are added to the root scope
ucl_state_put(ucl_state_get_root(state), fun_sym->symbol, ucl_cdr(args));
ucl_scope_put(ucl_scope_get_root(scope), fun_sym->symbol, ucl_cdr(args));
return fun_sym;
}
struct ucl_object *ucl_special_lambda(struct ucl_state *state, struct ucl_object *args) {
struct ucl_object *ucl_special_lambda(struct ucl_scope *scope, struct ucl_object *args) {
// TODO: Check arguments
struct ucl_object *fun_args = ucl_list_nth(args, 0);
if (fun_args->type != UCL_TYPE_CELL) {
@@ -84,33 +84,33 @@ struct ucl_object *ucl_special_lambda(struct ucl_state *state, struct ucl_object
}
struct ucl_object *ucl_special_setq(struct ucl_state *state, struct ucl_object *args) {
struct ucl_object *ucl_special_setq(struct ucl_scope *scope, struct ucl_object *args) {
// TODO: Check arguments
struct ucl_object *sym = ucl_car(args);
struct ucl_state *root_state = ucl_state_get_root(state);
struct ucl_scope *root_scope = ucl_scope_get_root(scope);
if (sym->type != UCL_TYPE_SYMBOL) {
return ucl_error_create("First argument to setq must be a symbol");
}
struct ucl_object *value = ucl_evaluate(state, ucl_list_nth(args, 1));
struct ucl_object *value = ucl_evaluate(scope, ucl_list_nth(args, 1));
ucl_state_put(root_state, sym->symbol, value);
ucl_scope_put(root_scope, sym->symbol, value);
return value;
}
struct ucl_object *ucl_special_progn(struct ucl_state *state, struct ucl_object *args) {
return ucl_progn(state, args);
struct ucl_object *ucl_special_progn(struct ucl_scope *scope, struct ucl_object *args) {
return ucl_progn(scope, args);
}
struct ucl_object *ucl_special_quote(struct ucl_state *state, struct ucl_object *args) {
struct ucl_object *ucl_special_quote(struct ucl_scope *scope, struct ucl_object *args) {
return ucl_car(args);
}
struct ucl_object *ucl_special_and(struct ucl_state *state, struct ucl_object *args) {
struct ucl_object *ucl_special_and(struct ucl_scope *scope, struct ucl_object *args) {
struct ucl_object *value = ucl_t_create();
FOREACH_LIST(args, iter, form) {
value = ucl_evaluate(state, form);
value = ucl_evaluate(scope, form);
if (!ucl_truthy_bool(value)) {
return value;
}
@@ -118,10 +118,10 @@ struct ucl_object *ucl_special_and(struct ucl_state *state, struct ucl_object *a
return value;
}
struct ucl_object *ucl_special_or(struct ucl_state *state, struct ucl_object *args) {
struct ucl_object *ucl_special_or(struct ucl_scope *scope, struct ucl_object *args) {
struct ucl_object *value = ucl_nil_create();
FOREACH_LIST(args, iter, form) {
value = ucl_evaluate(state, form);
value = ucl_evaluate(scope, form);
if (ucl_truthy_bool(value)) {
return value;
}

View File

@@ -3,14 +3,14 @@
#include "uclisp.h"
struct ucl_object *ucl_special_let(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_special_if(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_special_defun(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_special_lambda(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_special_setq(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_special_progn(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_special_quote(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_special_and(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_special_or(struct ucl_state *state, struct ucl_object *args);
struct ucl_object *ucl_special_let(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_special_if(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_special_defun(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_special_lambda(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_special_setq(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_special_progn(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_special_quote(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_special_and(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_special_or(struct ucl_scope *scope, struct ucl_object *args);
#endif

View File

@@ -1,88 +0,0 @@
#include "uclisp.h"
#include "internal.h"
#include "state.h"
#include "utility.h"
#include "arena.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
// Implements state as a giant alist
// TODO: Consider generalizing the alist concept
// TODO: Rename 'state' to 'scope'
#define NAME_POSITION 0
#define DATA_POSITION 1
#define STATE_ARENA_CAPACITY 32
struct ucl_arena *state_arena;
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) {
// TODO: Include the symbol name
return ucl_error_create("Unbound symbol");
} 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() {
if (state_arena == NULL) {
state_arena = ucl_arena_create(sizeof(struct ucl_state), STATE_ARENA_CAPACITY);
}
struct ucl_state *state = ucl_arena_get(state_arena);
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;
}
struct ucl_state *ucl_state_get_root(struct ucl_state *state) {
while (state->parent != NULL) {
state = state->parent;
}
return state;
}
void ucl_state_delete(struct ucl_state *state) {
assert(state_arena != NULL);
ucl_arena_put(state_arena, state);
// Garbage collection will handle the objects, they are shared
}

View File

@@ -1,15 +0,0 @@
#ifndef _UCLISP_STATE_H_
#define _UCLISP_STATE_H_
struct ucl_state;
struct ucl_state *ucl_state_create();
struct ucl_state *ucl_state_create_child(struct ucl_state *parent);
void ucl_state_delete(struct ucl_state *state);
struct ucl_object *ucl_state_get(struct ucl_state *state, const char *name);
void ucl_state_put(struct ucl_state *state, const char *name, struct ucl_object *obj);
struct ucl_state *ucl_state_get_root(struct ucl_state *state);
#endif

View File

@@ -17,8 +17,8 @@ struct ucl_cell {
struct ucl_object *cdr;
};
struct ucl_state;
typedef struct ucl_object *(*ucl_lisp)(struct ucl_state* state, struct ucl_object *args);
struct ucl_scope;
typedef struct ucl_object *(*ucl_lisp)(struct ucl_scope* state, struct ucl_object *args);
struct ucl_object {
union {
@@ -41,11 +41,11 @@ struct ucl_parse_result {
struct ucl_cell *statement;
};
struct ucl_state; // TODO
struct ucl_scope; // TODO
struct ucl_object *ucl_tokenize(const char *source);
struct ucl_object *ucl_parse(const char *sexp);
struct ucl_object *ucl_evaluate(struct ucl_state *state, struct ucl_object *sexp);
struct ucl_object *ucl_evaluate(struct ucl_scope *state, struct ucl_object *sexp);
// TODO: State encapsulation is all wonky here)
void ucl_gc();

View File

@@ -162,7 +162,7 @@ void ucl_print_obj(struct ucl_object *obj) {
}
}
struct ucl_object *ucl_progn(struct ucl_state *state, struct ucl_object *forms) {
struct ucl_object *ucl_progn(struct ucl_scope *state, struct ucl_object *forms) {
struct ucl_object *result = NULL;
FOREACH_LIST(forms, iter, form) {
result = ucl_evaluate(state, form);

View File

@@ -20,7 +20,7 @@ struct ucl_object* ucl_list_nth(struct ucl_object *list, int n);
struct ucl_object* ucl_list_append(struct ucl_object *list, struct ucl_object *obj);
struct ucl_object* ucl_tuple_create(struct ucl_object *obj0, struct ucl_object *obj1);
struct ucl_object *ucl_progn(struct ucl_state *state, struct ucl_object *forms);
struct ucl_object *ucl_progn(struct ucl_scope *scope, struct ucl_object *forms);
void ucl_print_obj(struct ucl_object *obj);

View File

@@ -6,51 +6,51 @@
#include "internal.h"
#include "utility.h"
#include "testing_helpers.h"
#include "state.h"
#include "scope.h"
#include "builtins.h"
#include "special.h"
static struct ucl_object *input;
static struct ucl_object *response;
static struct ucl_state *state;
static struct ucl_scope *scope;
void setUp(void) {
input = NULL;
response = NULL;
state = ucl_state_create();
ucl_state_put(state, "let", ucl_special_create(ucl_special_let));
ucl_state_put(state, "defun", ucl_special_create(ucl_special_defun));
ucl_state_put(state, "+", ucl_builtin_create(ucl_builtin_add));
ucl_state_put(state, "error", ucl_builtin_create(ucl_builtin_error));
ucl_state_put(state, "list", ucl_builtin_create(ucl_builtin_list));
ucl_state_put(state, "setq", ucl_special_create(ucl_special_setq));
ucl_state_put(state, "car", ucl_builtin_create(ucl_builtin_car));
ucl_state_put(state, "cdr", ucl_builtin_create(ucl_builtin_cdr));
ucl_state_put(state, "nth", ucl_builtin_create(ucl_builtin_nth));
ucl_state_put(state, "mapcar", ucl_builtin_create(ucl_builtin_mapcar));
ucl_state_put(state, "lambda", ucl_special_create(ucl_special_lambda));
ucl_state_put(state, "quote", ucl_special_create(ucl_special_quote));
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, "lambda", ucl_special_create(ucl_special_lambda));
ucl_scope_put(scope, "quote", ucl_special_create(ucl_special_quote));
}
void tearDown(void) {
// TODO: Implement GC so we can clean these both up
//ucl_object_delete(input);
input = NULL;
ucl_state_delete(state);
ucl_scope_delete(scope);
ucl_gc();
response = NULL;
state = NULL;
scope = NULL;
}
static struct ucl_object *eval (const char *code) {
struct ucl_object *sexp = ucl_parse(code);
return ucl_evaluate(state, ucl_car(sexp));
return ucl_evaluate(scope, ucl_car(sexp));
}
void test_simple_add(void) {
ucl_state_put(state, "+", ucl_builtin_create(ucl_builtin_add));
ucl_scope_put(scope, "+", ucl_builtin_create(ucl_builtin_add));
response = eval("(+ 2 3)");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 5);
@@ -103,7 +103,7 @@ void test_eval_string(void) {
}
void test_eval_sym_defined(void) {
ucl_state_put(state, "foo", ucl_int_create(2));
ucl_scope_put(scope, "foo", ucl_int_create(2));
response = eval("foo");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 2);

View File

@@ -162,7 +162,7 @@ static void test_tokenize_nil(void) {
TEST_ASSERT_NULL(token2->cell.cdr);
}
static void test_tokenize_statement(void) {
static void test_tokenize_scopement(void) {
response = ucl_tokenize("(foo)");
TEST_ASSERT_NOT_NULL(response);
@@ -344,7 +344,7 @@ int main(void) {
RUN_TEST(test_token_next_symbol_w_whitespace);
RUN_TEST(test_tokenize_empty_str);
RUN_TEST(test_tokenize_nil);
RUN_TEST(test_tokenize_statement);
RUN_TEST(test_tokenize_scopement);
RUN_TEST(test_parse_atom_symbol);
RUN_TEST(test_parse_atom_lparen);
RUN_TEST(test_parse_atom_rparen);

View File

@@ -4,38 +4,38 @@
#include "uclisp.h"
#include "internal.h"
#include "state.h"
#include "scope.h"
#include "utility.h"
#include "testing_helpers.h"
/* static struct ucl_parse_result *result; */
static struct ucl_state *state;
static struct ucl_scope *scope;
static struct ucl_object *response;
void setUp(void) {
state = ucl_state_create();
scope = ucl_scope_create();
}
void tearDown(void) {
ucl_state_delete(state);
state = NULL;
ucl_scope_delete(scope);
scope = NULL;
}
static void test_get_empty(void) {
response = ucl_state_get(state, "foo");
response = ucl_scope_get(scope, "foo");
TEST_ASSERT_OBJ_ERROR(response);
}
static void test_put_get(void) {
ucl_state_put(state, "foo", ucl_t_create());
response = ucl_state_get(state, "foo");
ucl_scope_put(scope, "foo", ucl_t_create());
response = ucl_scope_get(scope, "foo");
TEST_ASSERT_T(response);
}
static void test_put2_get(void) {
ucl_state_put(state, "foo1", ucl_t_create());
ucl_state_put(state, "foo2", ucl_nil_create());
response = ucl_state_get(state, "foo1");
ucl_scope_put(scope, "foo1", ucl_t_create());
ucl_scope_put(scope, "foo2", ucl_nil_create());
response = ucl_scope_get(scope, "foo1");
TEST_ASSERT_T(response);
}
@@ -44,9 +44,9 @@ static void test_put_modify_get(void) {
ucl_string_create("bar"),
ucl_string_create("baz"));
ucl_state_put(state, "foo", obj);
ucl_scope_put(scope, "foo", obj);
ucl_list_append(obj, ucl_string_create("quux"));
response = ucl_state_get(state, "foo");
response = ucl_scope_get(scope, "foo");
TEST_ASSERT_OBJ_STRING(ucl_list_nth(response, 2));
TEST_ASSERT_EQUAL_STRING(ucl_list_nth(response, 2)->string, "quux");

View File

@@ -5,7 +5,7 @@
#include "uclisp.h"
#include "internal.h"
#include "utility.h"
#include "state.h"
#include "scope.h"
#include "testing_helpers.h"
static struct ucl_object *input;