Add function evaluation

This commit is contained in:
2022-11-04 09:16:02 -04:00
parent ddb5a8f842
commit d5b1729deb
7 changed files with 108 additions and 58 deletions

View File

@@ -8,4 +8,4 @@ for test in $TESTS; do
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
exit $ret exit $ret
fi fi
done done | tee | grep "Tests"

View File

@@ -154,41 +154,6 @@ LISP_FUNC_0(ucl_builtin_now_millis_mono, state) {
return NULL; 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("<builtin %p>", 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) { LISP_FUNC_1(ucl_builtin_print, state, arg0) {
ucl_print_obj(arg0); ucl_print_obj(arg0);

View File

@@ -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 *fun = ucl_car(evaluated_list);
struct ucl_object *args = ucl_cdr(evaluated_list);
struct ucl_object *result = NULL; struct ucl_object *result = NULL;
assert(fun->type == UCL_TYPE_BUILTIN);
if (fun->type == UCL_TYPE_BUILTIN) { if (fun->type == UCL_TYPE_BUILTIN) {
struct ucl_object *args = ucl_cdr(evaluated_list);
result = fun->builtin(state, args); 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 // 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) { 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; 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) { struct ucl_object *ucl_evaluate_list(struct ucl_state *state, struct ucl_object *list) {
if (list->cell.car == NULL) { 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) { if (fun->type == UCL_TYPE_SPECIAL) {
return ucl_evaluate_special_form(state, list); 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); return ucl_evaluate_builtin_form(state, list);
} else { } else {
assert(0); assert(0);

View File

@@ -1,5 +1,5 @@
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include "uclisp.h" #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, "let", ucl_special_create(ucl_special_let));
ucl_state_put(state, "if", ucl_special_create(ucl_special_if)); 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, "print", ucl_builtin_create(ucl_builtin_print));
ucl_state_put(state, "list", ucl_builtin_create(ucl_builtin_list)); 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, "int-p", ucl_builtin_create(ucl_builtin_int_p));
ucl_state_put(state, "list-p", ucl_builtin_create(ucl_builtin_list_p)); ucl_state_put(state, "list-p", ucl_builtin_create(ucl_builtin_list_p));
struct ucl_object *sexp = ucl_parse(argv[1]); if (argc < 2) {
struct ucl_object *result = ucl_evaluate(state, ucl_car(sexp)); 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) { struct ucl_object *sexp = ucl_parse(line);
printf("%s", result->error); struct ucl_object *result = ucl_evaluate(state, ucl_car(sexp));
return -1; 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))'

View File

@@ -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); ucl_state_put(let_state, sym->symbol, value);
} }
struct ucl_object *result = NULL; struct ucl_object *result = ucl_progn(state, expressions);
FOREACH_LIST(expressions, iter, item) {
result = ucl_evaluate(let_state, item);
if (result->type == UCL_TYPE_ERROR) {
return result;
}
}
ucl_state_delete(let_state); ucl_state_delete(let_state);
return result; return result;
} }

View File

@@ -4,8 +4,10 @@
#include "utility.h" #include "utility.h"
#include <stddef.h> #include <stddef.h>
#include <assert.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <stdio.h>
struct ucl_object *ucl_car(struct ucl_object *list) { struct ucl_object *ucl_car(struct ucl_object *list) {
UCL_COND_OR_RET_ERROR( 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; 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("<builtin %p>", 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;
}

View File

@@ -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_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);
void ucl_print_obj(struct ucl_object *obj);
#define UCL_RET_IF_ERROR(obj) \ #define UCL_RET_IF_ERROR(obj) \
do { \ do { \