diff --git a/src/builtins.c b/src/builtins.c index cda8551..b31b447 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -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); } diff --git a/src/common.h b/src/common.h index 66c13c8..197edb3 100644 --- a/src/common.h +++ b/src/common.h @@ -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) diff --git a/src/memory.c b/src/memory.c index 693369d..03db337 100644 --- a/src/memory.c +++ b/src/memory.c @@ -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; } diff --git a/src/special.c b/src/special.c index 87096b8..6df192b 100644 --- a/src/special.c +++ b/src/special.c @@ -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); diff --git a/src/utility.c b/src/utility.c index 6bd4e27..1e4b332 100644 --- a/src/utility.c +++ b/src/utility.c @@ -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++) {