diff --git a/src/evaluate.c b/src/evaluate.c index 2a055a2..45c69e7 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -2,26 +2,48 @@ #include #include "nihilispm.h" +#include "nihilispm_internal.h" +#include "nihilispm_utility.h" +#include "nihilispm_state.h" -struct nl_object *nl_evaluate_list(struct nl_object *list) { - return NULL; +struct nl_object *nl_evaluate_list(struct nl_state *state, struct nl_object *list) { + // TODO: Recursively eval args + struct nl_object *evaluated_list = nl_nil_create(); + + FOREACH_LIST(list, iter, item) { + struct nl_object *obj = nl_evaluate(state, item); + nl_list_append(evaluated_list, obj); + }; + + struct nl_object *fun = nl_car(evaluated_list); + struct nl_object *args = nl_cdr(evaluated_list); + struct nl_object *result = NULL; + + assert(fun->type == NL_TYPE_BUILTIN); + if (fun->type == NL_TYPE_BUILTIN) { + result = fun->builtin(args); + } + + // TODO: Non-builtins + + // TODO: cleanup + + return result; } -struct nl_object *nl_evaluate_symbol(struct nl_object *symbol) { - return NULL; -} - -struct nl_object *nl_evaluate(struct nl_object *obj) { +struct nl_object *nl_evaluate(struct nl_state *state, struct nl_object *obj) { assert(obj != NULL); switch (obj->type) { case NL_TYPE_CELL: - return nl_evaluate_list(obj); + return nl_evaluate_list(state, obj); case NL_TYPE_SYMBOL: - return NULL; //nl_evalute_symbol(obj); + return nl_state_get(state, obj->symbol); case NL_TYPE_INT: case NL_TYPE_STRING: + case NL_TYPE_ERROR: return obj; + case NL_TYPE_BUILTIN: case NL_TYPE_COUNT: assert(0); return NULL; diff --git a/src/main.c b/src/main.c index 50f10ef..2a0abc6 100644 --- a/src/main.c +++ b/src/main.c @@ -1,10 +1,29 @@ +#include #include + #include "nihilispm.h" #include "nihilispm_state.h" +#include "nihilispm_internal.h" +#include "nihilispm_utility.h" +#include "builtins.h" int main(int argc, const char **argv) { (void) argc, (void) argv; struct nl_state *state = nl_state_create(); + nl_state_put(state, "+", nl_builtin_create(nl_builtin_add)); + nl_state_put(state, "-", nl_builtin_create(nl_builtin_sub)); + nl_state_put(state, "*", nl_builtin_create(nl_builtin_mul)); + nl_state_put(state, "/", nl_builtin_create(nl_builtin_div)); + nl_state_put(state, "%", nl_builtin_create(nl_builtin_mod)); + + struct nl_object *sexp = nl_parse(argv[1]); + struct nl_object *result = nl_evaluate(state, nl_car(sexp)); + + assert(result != NULL); + assert(result->type == NL_TYPE_INT); + + printf("%d\n", result->integer); + return 0; } diff --git a/src/memory.c b/src/memory.c index 94d745f..fe90691 100644 --- a/src/memory.c +++ b/src/memory.c @@ -48,6 +48,15 @@ struct nl_object *nl_error_create(const char *error) return obj; } + +struct nl_object *nl_builtin_create(nl_builtin builtin) +{ + struct nl_object* obj = nl_object_alloc(); + obj->type = NL_TYPE_BUILTIN; + obj->builtin = builtin; + return obj; +} + static struct nl_object* nl_object_alloc() { return malloc(sizeof(struct nl_object)); } @@ -77,6 +86,7 @@ void nl_object_delete(struct nl_object *obj) { obj->error = NULL; break; case NL_TYPE_INT: + case NL_TYPE_BUILTIN: case NL_TYPE_COUNT: break; } diff --git a/src/nihilispm.h b/src/nihilispm.h index ee4c9a3..b92c111 100644 --- a/src/nihilispm.h +++ b/src/nihilispm.h @@ -7,7 +7,8 @@ enum nl_type { NL_TYPE_INT = 2, NL_TYPE_STRING = 3, NL_TYPE_ERROR = 4, - NL_TYPE_COUNT = 5, + NL_TYPE_BUILTIN = 5, + NL_TYPE_COUNT = 6, }; struct nl_cell { @@ -15,6 +16,8 @@ struct nl_cell { struct nl_object *cdr; }; +typedef struct nl_object *(*nl_builtin)(struct nl_object *args); + struct nl_object { enum nl_type type; union { @@ -23,6 +26,7 @@ struct nl_object { int integer; const char *string; const char *error; + nl_builtin builtin; }; }; @@ -37,6 +41,6 @@ struct nl_state; // TODO struct nl_object *nl_tokenize(const char *source); struct nl_object *nl_parse(const char *sexp); -struct nl_object *nl_evaluate(struct nl_object *sexp); +struct nl_object *nl_evaluate(struct nl_state *state, struct nl_object *sexp); #endif diff --git a/src/nihilispm_internal.h b/src/nihilispm_internal.h index bcbcf00..e1412dc 100644 --- a/src/nihilispm_internal.h +++ b/src/nihilispm_internal.h @@ -10,12 +10,12 @@ item_name != NULL && iter_name != NULL && (cond); \ iter_name = iter_name->cell.cdr, item_name = (iter_name == NULL) ? NULL : iter_name->cell.car) - struct nl_object *nl_cell_create(struct nl_object *car, struct nl_object *cdr); struct nl_object *nl_int_create(int integer); struct nl_object *nl_symbol_create(const char* symbol); struct nl_object *nl_string_create(const char* string); struct nl_object *nl_error_create(const char* error); +struct nl_object *nl_builtin_create(nl_builtin builtin); void nl_object_delete(struct nl_object *obj); diff --git a/src/parse.c b/src/parse.c index 6796e1a..2c7a533 100644 --- a/src/parse.c +++ b/src/parse.c @@ -67,8 +67,12 @@ struct nl_object *nl_token_next(const char **curr_src) { // -2 for removing start/end quotes str = strndup(start + 1, *curr_src - start - 2); return nl_cell_create(nl_string_create(str), NULL); - //case '0': - // TODO: Parse integers + case '0'...'9': { + char *end = NULL; + long value = strtol(*curr_src, &end, 0); + *curr_src = end; + return nl_cell_create(nl_int_create(value), NULL); + } default: while (!nl_is_delimiter(**curr_src)) { (*curr_src)++; @@ -116,8 +120,7 @@ struct nl_object *nl_parse_token_atom(struct nl_object *maybe_atom) { atom = nl_string_create(strdup(maybe_atom->string)); break; case NL_TYPE_INT: - // TODO: Copy the token - assert(0); + atom = nl_int_create(maybe_atom->integer); break; case NL_TYPE_COUNT: assert(false); @@ -152,7 +155,7 @@ static struct nl_object *nl_parse_tokens_recursive(struct nl_object **token_iter *token_iter = (*token_iter)->cell.cdr; while (1) { token = (*token_iter)->cell.car; - if (token->symbol[0] == END_LIST_CHAR) { + if (token->type == NL_TYPE_SYMBOL && token->symbol[0] == END_LIST_CHAR) { *token_iter = (*token_iter)->cell.cdr; if (list == NULL) { list = nl_cell_create(NULL, NULL);