diff --git a/builtins.c b/builtins.c index 9607610..c229628 100644 --- a/builtins.c +++ b/builtins.c @@ -1,7 +1,7 @@ #include "lisp.h" Node *lisp_function_addition(Nodes *args, Scopes *scopes) { - (void)(scopes); + UNUSED(scopes); if (args->count != 2) { printf("'+' expects two arguments!\n"); @@ -35,3 +35,79 @@ Node *lisp_function_println(Nodes *args, Scopes *scopes) { return result; } + +Node *lisp_function_list(Nodes *args, Scopes *scopes) { + UNUSED(scopes); + + Node *node = malloc(sizeof(Node)); + node->kind = NODE_KIND_LIST; + node->as_list = args; + return node; +} + +Node *lisp_function_append(Nodes *args, Scopes *scopes) { + UNUSED(scopes); + + if (args->count != 2) { + printf("'append' expects two arguments!\n"); + return NULL; + } + + Node *node = malloc(sizeof(Node)); + node->kind = NODE_KIND_LIST; + + if (args->items[0].kind != NODE_KIND_LIST || + args->items[1].kind != NODE_KIND_LIST) { + printf("'append' can only append two lists!\n"); + return NULL; + } + + Nodes *nodes = malloc(sizeof(Nodes)); + + Nodes *a = args->items[0].as_list; + nob_da_append_many(nodes, a->items, a->count); + + Nodes *b = args->items[1].as_list; + nob_da_append_many(nodes, b->items, b->count); + + node->as_list = nodes; + return node; +} + +Node *lisp_function_length(Nodes *args, Scopes *scopes) { + UNUSED(scopes); + + if (args->count != 1) { + printf("'length' expects one argument!\n"); + return NULL; + } + + if (args->items[0].kind != NODE_KIND_LIST) { + printf("'length' can only be used on lists!\n"); + return NULL; + } + + Node *node = malloc(sizeof(Node)); + node->kind = NODE_KIND_NUMBER; + node->as_number = args->items[0].as_list->count; + return node; +} + +Node *lisp_function_isnull(Nodes *args, Scopes *scopes) { + UNUSED(scopes); + + if (args->count != 1) { + printf("'null?' expects one argument!\n"); + return NULL; + } + + if (args->items[0].kind != NODE_KIND_LIST) { + printf("'null?' can only be used on lists!\n"); + return NULL; + } + + Node *node = malloc(sizeof(Node)); + node->kind = NODE_KIND_NUMBER; + node->as_number = args->items[0].as_list->count == 0 ? 1 : 0; + return node; +} diff --git a/lisp.c b/lisp.c index 11f6a0f..ee61f40 100644 --- a/lisp.c +++ b/lisp.c @@ -15,39 +15,24 @@ static Node *scope_lookup(Scopes *scopes, Nob_String_View name) { return NULL; } -void build_scopes(Scopes *scopes) { - // clang-format off - Nob_String_View obj_name = (Nob_String_View){ - .items = "+", - .count = 1 - }; +static void scope_add_function(Scope *scope, const char *name, + LispFunction function) { + Nob_String_View obj_name = nob_sv_from_cstr(name); ScopeObject obj = (ScopeObject){ .name = obj_name, - .node = (Node){ - .kind = NODE_KIND_FUNCTION, - .as_function = { - .name = obj_name, - .apply = lisp_function_addition - } - } - }; - nob_da_append(&globalScope, obj); + .node = (Node){.kind = NODE_KIND_FUNCTION, + .as_function = {.name = obj_name, .apply = function}}}; + nob_da_append(scope, obj); +} - obj_name = (Nob_String_View){ - .items = "println", - .count = 7 - }; - obj = (ScopeObject){ - .name = obj_name, - .node = (Node){ - .kind = NODE_KIND_FUNCTION, - .as_function = { - .name = obj_name, - .apply = lisp_function_println - } - } - }; - nob_da_append(&globalScope, obj); +void build_scopes(Scopes *scopes) { + // clang-format off + scope_add_function(&globalScope, "+", lisp_function_addition); + scope_add_function(&globalScope, "println", lisp_function_println); + scope_add_function(&globalScope, "list", lisp_function_list); + scope_add_function(&globalScope, "append", lisp_function_append); + scope_add_function(&globalScope, "length", lisp_function_length); + scope_add_function(&globalScope, "null?", lisp_function_isnull); // clang-format on nob_da_append(scopes, globalScope); diff --git a/lisp.h b/lisp.h index db2dd71..53f6b78 100644 --- a/lisp.h +++ b/lisp.h @@ -82,5 +82,9 @@ Node *eval(Node *node, Scopes *scopes); // builtins Node *lisp_function_addition(Nodes *args, Scopes *scopes); Node *lisp_function_println(Nodes *args, Scopes *scopes); +Node *lisp_function_list(Nodes *args, Scopes *scopes); +Node *lisp_function_append(Nodes *args, Scopes *scopes); +Node *lisp_function_length(Nodes *args, Scopes *scopes); +Node *lisp_function_isnull(Nodes *args, Scopes *scopes); #endif // LISP_H