Use pinned, immutable errors

This allows for extra refactoring to reduce the reliance on 'struct ucl'
for allocation strictly for allocating error responses.
This commit is contained in:
2022-11-22 16:55:41 -05:00
parent 7a2cbb2f26
commit e02d8433fa
5 changed files with 28 additions and 26 deletions

View File

@@ -72,8 +72,8 @@ LISP_FUNC_1(ucl_builtin_cdr, state, scope, arg) {
}
LISP_FUNC_2(ucl_builtin_nth, state, scope, n, list) {
UCL_COND_OR_RET_ERROR(state, n->type == UCL_TYPE_INT, "First argument to nth must be an integer");
UCL_COND_OR_RET_ERROR(state, list->type == UCL_TYPE_CELL, "Second argument to nth must be a 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(state, list, n->integer);
}
@@ -123,7 +123,7 @@ LISP_FUNC_2(ucl_builtin_div, state, scope, arg0, arg1) {
return ucl_error_create(state, "Invalid type of argument 1 to 'div'");
}
UCL_COND_OR_RET_ERROR(state, arg1->integer != 0, "Division by zero");
UCL_COND_OR_RET_ERROR(arg1->integer != 0, "Division by zero");
return ucl_int_create(state, arg0->integer / arg1->integer);
}
@@ -230,32 +230,32 @@ LISP_FUNC_2(ucl_builtin_equal, state, scope, arg0, arg1) {
}
LISP_FUNC_2(ucl_builtin_gt, state, scope, arg0, arg1) {
UCL_COND_OR_RET_ERROR(state, arg0->type == UCL_TYPE_INT, "First argument to > must be an integer");
UCL_COND_OR_RET_ERROR(state, arg0->type == UCL_TYPE_INT, "Second 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");
return ucl_predicate(state, arg0->integer > arg1->integer);
}
LISP_FUNC_2(ucl_builtin_ge, state, scope, arg0, arg1) {
UCL_COND_OR_RET_ERROR(state, arg0->type == UCL_TYPE_INT, "First argument to >= must be an integer");
UCL_COND_OR_RET_ERROR(state, arg0->type == UCL_TYPE_INT, "Second 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");
return ucl_predicate(state, arg0->integer > arg1->integer);
}
LISP_FUNC_2(ucl_builtin_lt, state, scope, arg0, arg1) {
UCL_COND_OR_RET_ERROR(state, arg0->type == UCL_TYPE_INT, "First argument to < must be an integer");
UCL_COND_OR_RET_ERROR(state, arg0->type == UCL_TYPE_INT, "Second 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");
return ucl_predicate(state, arg0->integer < arg1->integer);
}
LISP_FUNC_2(ucl_builtin_le, state, scope, arg0, arg1) {
UCL_COND_OR_RET_ERROR(state, arg0->type == UCL_TYPE_INT, "First argument to <= must be an integer");
UCL_COND_OR_RET_ERROR(state, arg0->type == UCL_TYPE_INT, "Second 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");
return ucl_predicate(state, arg0->integer < arg1->integer);
}
LISP_FUNC_2(ucl_builtin_num_eq, state, scope, arg0, arg1) {
UCL_COND_OR_RET_ERROR(state, arg0->type == UCL_TYPE_INT, "First argument to = must be an integer");
UCL_COND_OR_RET_ERROR(state, arg0->type == UCL_TYPE_INT, "Second 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");
return ucl_predicate(state, arg0->integer == arg1->integer);
}

View File

@@ -23,10 +23,15 @@
} \
} while(0)
#define UCL_COND_OR_RET_ERROR(ucl, cond, msg) \
#define UCL_COND_OR_RET_ERROR(cond, msg) \
do { \
static struct ucl_object err = { \
.type = UCL_TYPE_ERROR, \
.error = (msg), \
.flags = UCL_OBJ_FLAG_PINNED \
}; \
if (!(cond)) { \
return ucl_error_create(ucl, msg); \
return &err; \
} \
} while(0)

View File

@@ -88,7 +88,7 @@ static struct ucl_object* ucl_object_alloc(struct ucl* ucl) {
}
static void ucl_object_delete_internal(struct ucl_arena* obj_arena, struct ucl_object *obj) {
if (obj == NULL) {
if (obj == NULL || obj->flags & UCL_OBJ_FLAG_PINNED) {
return;
}

View File

@@ -92,8 +92,8 @@ struct ucl_object *ucl_special_dotimes(struct ucl *state, struct ucl_scope *scop
struct ucl_object *var = ucl_car(state, assignment);
struct ucl_object *times = ucl_evaluate_in_scope(state, scope, ucl_list_nth(state, assignment, 1));
UCL_COND_OR_RET_ERROR(state, var->type == UCL_TYPE_SYMBOL, "'var' argument to dotimes must be an symbol");
UCL_COND_OR_RET_ERROR(state, times->type == UCL_TYPE_INT, "'times' argument to dotimes must be an int");
UCL_COND_OR_RET_ERROR(var->type == UCL_TYPE_SYMBOL, "'var' argument to dotimes must be an symbol");
UCL_COND_OR_RET_ERROR(times->type == UCL_TYPE_INT, "'times' argument to dotimes must be an int");
struct ucl_scope *let_scope = ucl_scope_create_child(state, scope);
@@ -114,8 +114,8 @@ struct ucl_object *ucl_special_dolist(struct ucl *state, struct ucl_scope *scope
struct ucl_object *var = ucl_car(state, assignment);
struct ucl_object *list = ucl_evaluate_in_scope(state, scope, ucl_list_nth(state, assignment, 1));
UCL_COND_OR_RET_ERROR(state, var->type == UCL_TYPE_SYMBOL, "'var' argument to dolist must be an symbol");
UCL_COND_OR_RET_ERROR(state, list->type == UCL_TYPE_CELL, "'list' argument to dolist must be a list");
UCL_COND_OR_RET_ERROR(var->type == UCL_TYPE_SYMBOL, "'var' argument to dolist must be an symbol");
UCL_COND_OR_RET_ERROR(list->type == UCL_TYPE_CELL, "'list' argument to dolist must be a list");
struct ucl_scope *let_scope = ucl_scope_create_child(state, scope);

View File

@@ -11,7 +11,6 @@
struct ucl_object *ucl_car(struct ucl *state, struct ucl_object *list) {
UCL_COND_OR_RET_ERROR(
state,
list != NULL && list->type == UCL_TYPE_CELL,
"Invalid type of argument 0 to 'ucl_car'");
@@ -24,7 +23,7 @@ struct ucl_object *ucl_car(struct ucl *state, struct ucl_object *list) {
}
struct ucl_object *ucl_cdr(struct ucl* state, struct ucl_object *list) {
UCL_COND_OR_RET_ERROR(state,
UCL_COND_OR_RET_ERROR(
list != NULL && list->type == UCL_TYPE_CELL,
"Invalid type of argument 0 to 'ucl_cdr'");
@@ -54,7 +53,6 @@ struct ucl_object *ucl_predicate(struct ucl* state, bool value) {
struct ucl_object *ucl_list_length(struct ucl *state, struct ucl_object *list) {
UCL_COND_OR_RET_ERROR(
state,
list != NULL && list->type == UCL_TYPE_CELL,
"Invalid type of argument 0 to 'ucl_list_length'");
@@ -74,13 +72,12 @@ struct ucl_object *ucl_list_length(struct ucl *state, struct ucl_object *list) {
struct ucl_object *ucl_list_nth(struct ucl *state, struct ucl_object *list, int n) {
UCL_COND_OR_RET_ERROR(
state,
list != NULL && list->type == UCL_TYPE_CELL,
"Invalid type of argument 0 to 'ucl_list_nth'");
int length = ucl_list_length(state, list)->integer;
UCL_COND_OR_RET_ERROR(state, length > n, "Position n >= list length in ucl_list_nth");
UCL_COND_OR_RET_ERROR(state, n >= 0, "Index to ucl_list_nth was less that zero");
UCL_COND_OR_RET_ERROR(length > n, "Position n >= list length in ucl_list_nth");
UCL_COND_OR_RET_ERROR(n >= 0, "Index to ucl_list_nth was less that zero");
struct ucl_object *node = list;
for (int i = 0; i < n; i++) {