From fd5aad95dcec68419214ed46dc2b3d628f9e51ff Mon Sep 17 00:00:00 2001 From: Max Regan Date: Wed, 16 Nov 2022 21:38:01 -0500 Subject: [PATCH] Add iteration (dotimes, dolist, while) --- src/main.c | 7 +++--- src/special.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/special.h | 3 +++ 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/main.c b/src/main.c index 127d6ec..dc0f4d4 100644 --- a/src/main.c +++ b/src/main.c @@ -25,9 +25,6 @@ int main(int argc, const char **argv) { 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_scope_put(scope, "print", ucl_builtin_create(ucl_builtin_print)); ucl_scope_put(scope, "printl", ucl_builtin_create(ucl_builtin_printl)); // TODO: @@ -65,6 +62,10 @@ int main(int argc, const char **argv) { ucl_scope_put(scope, "mapcar", ucl_builtin_create(ucl_builtin_mapcar)); ucl_scope_put(scope, "equal", ucl_builtin_create(ucl_builtin_mapcar)); + ucl_scope_put(scope, "dotimes", ucl_special_create(ucl_special_dotimes)); + ucl_scope_put(scope, "dolist", ucl_special_create(ucl_special_dolist)); + ucl_scope_put(scope, "while", ucl_special_create(ucl_special_while)); + // TODO: // - reduce diff --git a/src/special.c b/src/special.c index 68cf6af..ce35aab 100644 --- a/src/special.c +++ b/src/special.c @@ -1,5 +1,6 @@ #include "scope.h" #include "lisp.h" +#include "uclisp.h" #include "utility.h" #include "internal.h" @@ -84,6 +85,69 @@ struct ucl_object *ucl_special_lambda(struct ucl_scope *scope, struct ucl_object return args; } +struct ucl_object *ucl_special_dotimes(struct ucl_scope *scope, struct ucl_object *args) { + // TODO: Check arguments + struct ucl_object *assignment = ucl_car(args); + struct ucl_object *body = ucl_cdr(args); + + struct ucl_object *var = ucl_car(assignment); + struct ucl_object *times = ucl_evaluate(scope, ucl_list_nth(assignment, 1)); + + 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(scope); + + for (int i = 0; i < times->integer; i++) { + ucl_scope_put(let_scope, var->symbol, ucl_int_create(i)); + struct ucl_object *iterval = ucl_progn(let_scope, body); + UCL_RET_IF_ERROR(iterval); + } + + return ucl_nil_create(); +} + +struct ucl_object *ucl_special_dolist(struct ucl_scope *scope, struct ucl_object *args) { + // TODO: Check arguments + struct ucl_object *assignment = ucl_car(args); + struct ucl_object *body = ucl_cdr(args); + + struct ucl_object *var = ucl_car(assignment); + struct ucl_object *list = ucl_evaluate(scope, ucl_list_nth(assignment, 1)); + + 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(scope); + + FOREACH_LIST(list, iter, item) { + ucl_scope_put(let_scope, var->symbol, item); + struct ucl_object *iterval = ucl_progn(let_scope, body); + if (iterval->type == UCL_TYPE_ERROR) { + ucl_scope_delete(let_scope); + } + UCL_RET_IF_ERROR(iterval); + } + + return ucl_nil_create(); +} + +struct ucl_object *ucl_special_while(struct ucl_scope *scope, struct ucl_object *args) { + // TODO: Check arguments + struct ucl_object *condition = ucl_car(args); + struct ucl_object *body = ucl_cdr(args); + + while (1) { + struct ucl_object* cond_val = ucl_evaluate(scope, condition); + UCL_RET_IF_ERROR(cond_val); + if (!ucl_truthy_bool(cond_val)) { + return ucl_nil_create(); + } + + struct ucl_object *val = ucl_progn(scope, body); + UCL_RET_IF_ERROR(val); + } +} struct ucl_object *ucl_special_setq(struct ucl_scope *scope, struct ucl_object *args) { // TODO: Check arguments diff --git a/src/special.h b/src/special.h index 7c43554..01e0bec 100644 --- a/src/special.h +++ b/src/special.h @@ -7,6 +7,9 @@ struct ucl_object *ucl_special_let(struct ucl_scope *scope, struct ucl_object *a 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_dotimes(struct ucl_scope *scope, struct ucl_object *args); +struct ucl_object *ucl_special_dolist(struct ucl_scope *scope, struct ucl_object *args); +struct ucl_object *ucl_special_while(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);