diff --git a/run_tests.sh.in b/run_tests.sh.in index d9a1be9..3868185 100755 --- a/run_tests.sh.in +++ b/run_tests.sh.in @@ -8,4 +8,4 @@ for test in $TESTS; do if [ $? -ne 0 ] ; then exit $ret fi -done +done | tee | grep "Tests" diff --git a/src/builtins.c b/src/builtins.c index 2be67ad..ac29223 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -154,41 +154,6 @@ LISP_FUNC_0(ucl_builtin_now_millis_mono, state) { return NULL; } -static void ucl_print_obj(struct ucl_object *obj) { - switch (obj->type) { - case UCL_TYPE_SYMBOL: - printf("%s", obj->symbol); - break; - case UCL_TYPE_INT: - printf("%d", obj->integer); - break; - case UCL_TYPE_STRING: - printf("\"%s\"", obj->string); - break; - case UCL_TYPE_ERROR: - printf("(error \"%s\")", obj->error); - break; - case UCL_TYPE_BUILTIN: - printf("", obj->builtin); - break; - case UCL_TYPE_CELL: { - int first = true; - printf("%s", "("); - FOREACH_LIST(obj, iter, item) { - if (!first) { - printf(" "); - } - ucl_print_obj(item); - first = false; - } - printf("%s", ")"); - break; - } - case UCL_TYPE_COUNT: - assert(0); - } -} - LISP_FUNC_1(ucl_builtin_print, state, arg0) { ucl_print_obj(arg0); diff --git a/src/evaluate.c b/src/evaluate.c index 9d6f358..c0fbd0c 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -19,17 +19,28 @@ struct ucl_object *ucl_evaluate_builtin_form(struct ucl_state *state, struct ucl }; struct ucl_object *fun = ucl_car(evaluated_list); - struct ucl_object *args = ucl_cdr(evaluated_list); struct ucl_object *result = NULL; - assert(fun->type == UCL_TYPE_BUILTIN); if (fun->type == UCL_TYPE_BUILTIN) { + struct ucl_object *args = ucl_cdr(evaluated_list); result = fun->builtin(state, args); + } else if (fun->type == UCL_TYPE_CELL) { + struct ucl_state *fun_state = ucl_state_create_child(state); + 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)); + i++; + } + result = ucl_progn(fun_state, fun_forms); + } else { + assert(0); } // TODO: cleanup - return result; + return (result == NULL) ? ucl_nil_create() : result; } struct ucl_object *ucl_evaluate_special_form(struct ucl_state *state, struct ucl_object *list) { @@ -45,7 +56,18 @@ struct ucl_object *ucl_evaluate_special_form(struct ucl_state *state, struct ucl return result; } +struct ucl_object *ucl_evaluate_lisp_form(struct ucl_state *state, struct ucl_object *list) { + // TODO: Recursively eval args + const char *fun_sym = ucl_car(list)->symbol; + struct ucl_object *fun = ucl_state_get(state, ucl_car(list)->symbol); + struct ucl_object *args = ucl_cdr(list); + struct ucl_object *result = NULL; + + result = fun->special(state, args); + + return result; +} struct ucl_object *ucl_evaluate_list(struct ucl_state *state, struct ucl_object *list) { if (list->cell.car == NULL) { @@ -61,7 +83,7 @@ struct ucl_object *ucl_evaluate_list(struct ucl_state *state, struct ucl_object if (fun->type == UCL_TYPE_SPECIAL) { return ucl_evaluate_special_form(state, list); - } else if (fun->type == UCL_TYPE_BUILTIN) { + } else if (fun->type == UCL_TYPE_BUILTIN || fun->type == UCL_TYPE_CELL) { return ucl_evaluate_builtin_form(state, list); } else { assert(0); diff --git a/src/main.c b/src/main.c index 8e76b9d..66c7bde 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,5 @@ -#include #include +#include #include "uclisp.h" @@ -15,7 +15,7 @@ int main(int argc, const char **argv) { 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, "print", ucl_builtin_create(ucl_builtin_print)); ucl_state_put(state, "list", ucl_builtin_create(ucl_builtin_list)); @@ -35,13 +35,32 @@ int main(int argc, const char **argv) { 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)); - struct ucl_object *sexp = ucl_parse(argv[1]); - struct ucl_object *result = ucl_evaluate(state, ucl_car(sexp)); + if (argc < 2) { + while (1) { + printf("> "); + char *line = NULL; + size_t len = 0; + ssize_t lineSize = 0; + lineSize = getline(&line, &len, stdin); - if (result->type == UCL_TYPE_ERROR) { - printf("%s", result->error); - return -1; + struct ucl_object *sexp = ucl_parse(line); + struct ucl_object *result = ucl_evaluate(state, ucl_car(sexp)); + ucl_print_obj(result); + printf("\n"); + + free(line); + } + } else { + struct ucl_object *sexp = ucl_parse(argv[1]); + struct ucl_object *result = ucl_evaluate(state, ucl_car(sexp)); + + if (result->type == UCL_TYPE_ERROR) { + printf("%s", result->error); + return -1; + } + + return 0; } - - return 0; } + +// '(let (()) (defun foo (a b) (+ a b)) (foo 1 2))' diff --git a/src/special.c b/src/special.c index 531e31d..1c5c9c7 100644 --- a/src/special.c +++ b/src/special.c @@ -27,15 +27,7 @@ struct ucl_object *ucl_special_let(struct ucl_state *state, struct ucl_object *a ucl_state_put(let_state, sym->symbol, value); } - struct ucl_object *result = NULL; - FOREACH_LIST(expressions, iter, item) { - result = ucl_evaluate(let_state, item); - if (result->type == UCL_TYPE_ERROR) { - return result; - } - } - - + struct ucl_object *result = ucl_progn(state, expressions); ucl_state_delete(let_state); return result; } diff --git a/src/utility.c b/src/utility.c index eba225b..93bf12f 100644 --- a/src/utility.c +++ b/src/utility.c @@ -4,8 +4,10 @@ #include "utility.h" #include +#include #include #include +#include struct ucl_object *ucl_car(struct ucl_object *list) { UCL_COND_OR_RET_ERROR( @@ -117,3 +119,50 @@ struct ucl_object *ucl_list_append(struct ucl_object *list, struct ucl_object *o return list; } + +void ucl_print_obj(struct ucl_object *obj) { + switch (obj->type) { + case UCL_TYPE_SYMBOL: + printf("%s", obj->symbol); + break; + case UCL_TYPE_INT: + printf("%d", obj->integer); + break; + case UCL_TYPE_STRING: + printf("\"%s\"", obj->string); + break; + case UCL_TYPE_ERROR: + printf("(error \"%s\")", obj->error); + break; + case UCL_TYPE_BUILTIN: + printf("", obj->builtin); + break; + case UCL_TYPE_CELL: { + int first = true; + printf("%s", "("); + FOREACH_LIST(obj, iter, item) { + if (!first) { + printf(" "); + } + ucl_print_obj(item); + first = false; + } + printf("%s", ")"); + break; + } + case UCL_TYPE_COUNT: + assert(0); + } +} + +struct ucl_object *ucl_progn(struct ucl_state *state, struct ucl_object *forms) { + struct ucl_object *result = NULL; + FOREACH_LIST(forms, iter, form) { + result = ucl_evaluate(state, form); + if (result->type == UCL_TYPE_ERROR) { + return result; + } + } + + return (result == NULL) ? ucl_nil_create() : result; +} diff --git a/src/utility.h b/src/utility.h index 3a06f91..11706f3 100644 --- a/src/utility.h +++ b/src/utility.h @@ -18,6 +18,9 @@ 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); + +void ucl_print_obj(struct ucl_object *obj); #define UCL_RET_IF_ERROR(obj) \ do { \