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

View File

@@ -2,7 +2,7 @@
#include "internal.h" #include "internal.h"
#include "utility.h" #include "utility.h"
#include "builtins.h" #include "builtins.h"
#include "state.h" #include "scope.h"
#include "lisp.h" #include "lisp.h"
#include <assert.h> #include <assert.h>
@@ -11,7 +11,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
LISP_FUNC_1(ucl_builtin_type, state, arg) { LISP_FUNC_1(ucl_builtin_type, scope, arg) {
switch (arg->type) { switch (arg->type) {
case UCL_TYPE_CELL: case UCL_TYPE_CELL:
return ucl_symbol_create("list"); 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) { if (arg->type != UCL_TYPE_STRING) {
return ucl_error_create("Expected type string passed to 'error'"); 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); 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); 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); 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); 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); 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); 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); return ucl_car(arg);
} }
LISP_FUNC_1(ucl_builtin_cdr, state, arg) { LISP_FUNC_1(ucl_builtin_cdr, scope, arg) {
return ucl_cdr(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(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"); 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); 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) { if (arg0->type != UCL_TYPE_INT) {
return ucl_error_create("Invalid type of argument 0 to 'add'"); 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); 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) { if (arg0->type != UCL_TYPE_INT) {
return ucl_error_create("Invalid type of argument 0 to 'sub'"); 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); 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) { if (arg0->type != UCL_TYPE_INT) {
return ucl_error_create("Invalid type of argument 0 to 'mul'"); 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); 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) { if (arg0->type != UCL_TYPE_INT) {
return ucl_error_create("Invalid type of argument 0 to 'div'"); 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); 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) { if (arg0->type != UCL_TYPE_INT) {
return ucl_error_create("Invalid type of argument 0 to 'mod'"); 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); 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) { if (arg0->type != UCL_TYPE_STRING) {
return ucl_error_create("Invalid type of argument 0 to 'concat'"); 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; 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 // TODO: Implement and move to a 'platform' file
return NULL; return NULL;
} }
LISP_FUNC_1(ucl_builtin_print, state, arg0) { LISP_FUNC_1(ucl_builtin_print, scope, arg0) {
ucl_print_obj(arg0); ucl_print_obj(arg0);
return ucl_nil_create(); return ucl_nil_create();
} }
LISP_FUNC_1(ucl_builtin_printl, state, arg0) { LISP_FUNC_1(ucl_builtin_printl, scope, arg0) {
ucl_print_obj(arg0); ucl_print_obj(arg0);
printf("\n"); printf("\n");
return ucl_nil_create(); 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(); struct ucl_object *head = ucl_nil_create();
FOREACH_LIST(args, iter, item) { FOREACH_LIST(args, iter, item) {
ucl_list_append(head, 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; 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 // TODO: Support arbitrary number of 'elems' lists
struct ucl_object *result = ucl_nil_create(); struct ucl_object *result = ucl_nil_create();
FOREACH_LIST(elems, iter, elem) { FOREACH_LIST(elems, iter, elem) {
struct ucl_object *form = ucl_tuple_create(fun, 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_RET_IF_ERROR(value);
ucl_list_append(result, value); ucl_list_append(result, value);
} }
return result; 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); 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, "First argument to > must be an integer");
UCL_COND_OR_RET_ERROR(arg0->type == UCL_TYPE_INT, "Second 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); 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, "First argument to >= must be an integer");
UCL_COND_OR_RET_ERROR(arg0->type == UCL_TYPE_INT, "Second 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); 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, "First argument to < must be an integer");
UCL_COND_OR_RET_ERROR(arg0->type == UCL_TYPE_INT, "Second 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); 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, "First argument to <= must be an integer");
UCL_COND_OR_RET_ERROR(arg0->type == UCL_TYPE_INT, "Second 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); 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, "First argument to = must be an integer");
UCL_COND_OR_RET_ERROR(arg0->type == UCL_TYPE_INT, "Second 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); 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)); 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)); return ucl_predicate(!ucl_truthy_bool(arg0));
} }

View File

@@ -3,37 +3,37 @@
#include "utility.h" #include "utility.h"
struct ucl_object *ucl_builtin_error(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_state *state, 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_state *state, 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_state *state, 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_state *state, 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_state *state, 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_add(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_sub(struct ucl_state *state, 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_state *state, 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_state *state, 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_state *state, 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_state *state, 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_state *state, 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_state *state, 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_state *state, 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_state *state, 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_state *state, 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_not(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_xor(struct ucl_state *state, 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_car(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_cdr(struct ucl_state *state, 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_state *state, 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_state *state, 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_state *state, 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_print(struct ucl_scope *scope, struct ucl_object *args);
struct ucl_object *ucl_builtin_printl(struct ucl_state *state, struct ucl_object *args); struct ucl_object *ucl_builtin_printl(struct ucl_scope *scope, struct ucl_object *args);
#endif #endif

View File

@@ -4,17 +4,17 @@
#include "uclisp.h" #include "uclisp.h"
#include "internal.h" #include "internal.h"
#include "utility.h" #include "utility.h"
#include "state.h" #include "scope.h"
// TODO: remove string.h // TODO: remove string.h
#include <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 // TODO: Reasonably split builtin and non-builtin evaluation
struct ucl_object *evaluated_list = ucl_nil_create(); struct ucl_object *evaluated_list = ucl_nil_create();
FOREACH_LIST(list, iter, item) { 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_RET_IF_ERROR(obj);
ucl_list_append(evaluated_list, 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) { if (fun->type == UCL_TYPE_BUILTIN) {
struct ucl_object *args = ucl_cdr(evaluated_list); 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) { } 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_arg_syms = ucl_car(fun);
struct ucl_object *fun_forms = ucl_cdr(fun); struct ucl_object *fun_forms = ucl_cdr(fun);
int i = 0; int i = 0;
FOREACH_LIST(fun_arg_syms, iter, sym) { 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++; i++;
} }
result = ucl_progn(fun_state, fun_forms); result = ucl_progn(fun_scope, fun_forms);
ucl_state_delete(fun_state); ucl_scope_delete(fun_scope);
} else { } else {
assert(0); 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; 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 // TODO: Recursively eval args
const char *fun_sym = ucl_car(list)->symbol; 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 *args = ucl_cdr(list);
struct ucl_object *result = NULL; struct ucl_object *result = NULL;
result = fun->special(state, args); result = fun->special(scope, args);
return result; 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) { if (list->cell.car == NULL) {
return list; 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); UCL_RET_IF_ERROR(fun);
if (fun->type == UCL_TYPE_SPECIAL) { 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) { } 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 { } else {
assert(0); assert(0);
// TODO: Lisp functions and other errors // 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); assert(obj != NULL);
switch (obj->type) { switch (obj->type) {
case UCL_TYPE_CELL: case UCL_TYPE_CELL:
return ucl_evaluate_list(state, obj); return ucl_evaluate_list(scope, obj);
case UCL_TYPE_SYMBOL: 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_INT:
case UCL_TYPE_STRING: case UCL_TYPE_STRING:
case UCL_TYPE_ERROR: 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) iter_name = iter_name->cell.cdr, item_name = (iter_name == NULL) ? NULL : iter_name->cell.car)
// TODO: Refactor this struct's location // TODO: Refactor this struct's location
struct ucl_state { struct ucl_scope {
// TODO: For garbage collection, we need references from the parent->child state // TODO: For garbage collection, we need references from the parent->child state
struct ucl_object *list; 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_cell_create(struct ucl_object *car, struct ucl_object *cdr);
struct ucl_object *ucl_int_create(int integer); struct ucl_object *ucl_int_create(int integer);

View File

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

View File

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

View File

@@ -9,8 +9,8 @@
#include <limits.h> #include <limits.h>
#include <stdint.h> #include <stdint.h>
#ifndef UCL_STATE_ARENA_SIZE #ifndef UCL_SCOPE_ARENA_SIZE
#define UCL_STATE_ARENA_SIZE 16 #define UCL_SCOPE_ARENA_SIZE 16
#endif #endif
#ifndef UCL_OBJECT_ARENA_SIZE #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; (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) { 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() { void ucl_gc() {
ucl_arena_map(object_arena, ucl_gc_unmark); 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); 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 "lisp.h"
#include "utility.h" #include "utility.h"
#include "internal.h" #include "internal.h"
#include <assert.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 // TODO: Check arguments
struct ucl_object *assignments = ucl_car(args); struct ucl_object *assignments = ucl_car(args);
struct ucl_object *expressions = ucl_cdr(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) { FOREACH_LIST(assignments, iter, item) {
// TODO: Check arguments // TODO: Check arguments
struct ucl_object *sym = ucl_car(item); struct ucl_object *sym = ucl_car(item);
struct ucl_object *expr = ucl_car(ucl_cdr(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(sym->type == UCL_TYPE_SYMBOL);
//assert(ucl_list_length(expr)->integer == 1); //assert(ucl_list_length(expr)->integer == 1);
if (value->type == UCL_TYPE_ERROR) { if (value->type == UCL_TYPE_ERROR) {
// TODO cleanup // TODO cleanup
ucl_state_delete(let_state); ucl_scope_delete(let_scope);
return value; 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); struct ucl_object *result = ucl_progn(let_scope, expressions);
ucl_state_delete(let_state); ucl_scope_delete(let_scope);
return result; 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 // TODO: Check arguments
struct ucl_object *cond = ucl_car(args); struct ucl_object *cond = ucl_car(args);
struct ucl_object *true_form = ucl_list_nth(args, 1); struct ucl_object *true_form = ucl_list_nth(args, 1);
struct ucl_object *false_forms = ucl_cdr(ucl_cdr(args)); 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); UCL_RET_IF_ERROR(cond_result);
if (ucl_truthy(cond_result)->type == UCL_TYPE_SYMBOL) { 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 // TODO: Check arguments
struct ucl_object *fun_sym = ucl_car(args); struct ucl_object *fun_sym = ucl_car(args);
if (fun_sym->type != UCL_TYPE_SYMBOL) { 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! // there will be docstrings, maybe not!
// Functions are added to the root scope // 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; 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 // TODO: Check arguments
struct ucl_object *fun_args = ucl_list_nth(args, 0); struct ucl_object *fun_args = ucl_list_nth(args, 0);
if (fun_args->type != UCL_TYPE_CELL) { 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 // TODO: Check arguments
struct ucl_object *sym = ucl_car(args); 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) { if (sym->type != UCL_TYPE_SYMBOL) {
return ucl_error_create("First argument to setq must be a 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; return value;
} }
struct ucl_object *ucl_special_progn(struct ucl_state *state, struct ucl_object *args) { struct ucl_object *ucl_special_progn(struct ucl_scope *scope, struct ucl_object *args) {
return ucl_progn(state, 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); 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(); struct ucl_object *value = ucl_t_create();
FOREACH_LIST(args, iter, form) { FOREACH_LIST(args, iter, form) {
value = ucl_evaluate(state, form); value = ucl_evaluate(scope, form);
if (!ucl_truthy_bool(value)) { if (!ucl_truthy_bool(value)) {
return value; return value;
} }
@@ -118,10 +118,10 @@ struct ucl_object *ucl_special_and(struct ucl_state *state, struct ucl_object *a
return value; 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(); struct ucl_object *value = ucl_nil_create();
FOREACH_LIST(args, iter, form) { FOREACH_LIST(args, iter, form) {
value = ucl_evaluate(state, form); value = ucl_evaluate(scope, form);
if (ucl_truthy_bool(value)) { if (ucl_truthy_bool(value)) {
return value; return value;
} }

View File

@@ -3,14 +3,14 @@
#include "uclisp.h" #include "uclisp.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);
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);
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);
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);
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);
struct ucl_object *ucl_special_progn(struct ucl_state *state, 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_state *state, 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_state *state, 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_state *state, struct ucl_object *args); struct ucl_object *ucl_special_or(struct ucl_scope *scope, struct ucl_object *args);
#endif #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_object *cdr;
}; };
struct ucl_state; struct ucl_scope;
typedef struct ucl_object *(*ucl_lisp)(struct ucl_state* state, struct ucl_object *args); typedef struct ucl_object *(*ucl_lisp)(struct ucl_scope* state, struct ucl_object *args);
struct ucl_object { struct ucl_object {
union { union {
@@ -41,11 +41,11 @@ struct ucl_parse_result {
struct ucl_cell *statement; struct ucl_cell *statement;
}; };
struct ucl_state; // TODO struct ucl_scope; // TODO
struct ucl_object *ucl_tokenize(const char *source); struct ucl_object *ucl_tokenize(const char *source);
struct ucl_object *ucl_parse(const char *sexp); 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) // TODO: State encapsulation is all wonky here)
void ucl_gc(); 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; struct ucl_object *result = NULL;
FOREACH_LIST(forms, iter, form) { FOREACH_LIST(forms, iter, form) {
result = ucl_evaluate(state, 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_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_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); void ucl_print_obj(struct ucl_object *obj);

View File

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

View File

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

View File

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

View File

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