diff --git a/builtins.c b/builtins.c index ef1c667..c991e05 100644 --- a/builtins.c +++ b/builtins.c @@ -193,3 +193,33 @@ int builtin_ceil(Nodes args, Scopes *scopes, Node *result) { result->as_number = ceil(args.items[0].as_number); return 0; } + +int builtin_nth(Nodes args, Scopes *scopes, Node *result) { + UNUSED(scopes); + + if (args.count != 2) { + printf("'nth' expects two arguments!\n"); + return 1; + } + + Node node_idx = args.items[0]; + if (node_idx.kind != NODE_KIND_NUMBER) { + printf("'nth' expects an index as the first argument!\n"); + return 1; + } + + Node node_list = args.items[1]; + if (node_list.kind != NODE_KIND_LIST) { + printf("'nth' expects a list as the second argument!\n"); + return 1; + } + + uint64_t idx = node_idx.as_number; + if (idx >= node_list.as_list->count) { + printf("Index out of bounds!"); + return 1; + } + + *result = node_list.as_list->items[idx]; + return 0; +} diff --git a/lisp.c b/lisp.c index 1ee4edc..aa7abc8 100644 --- a/lisp.c +++ b/lisp.c @@ -13,6 +13,10 @@ static LispFunction special_forms[] = { { .name = (Nob_String_View){.count = 6, .data = "lambda"}, .apply = special_form_lambda, + }, + { + .name = (Nob_String_View){.count = 5, .data = "quote"}, + .apply = special_form_quote, }}; static int scope_lookup(Scopes *scopes, Nob_String_View name, Node *result) { @@ -49,16 +53,17 @@ void build_scopes(Scopes *scopes) { scope_add_function(&global_scope, ">", builtin_gt); scope_add_function(&global_scope, "<=", builtin_lt_eq); scope_add_function(&global_scope, ">=", builtin_gt_eq); + scope_add_function(&global_scope, "floor", builtin_floor); + scope_add_function(&global_scope, "ceil", builtin_ceil); - scope_add_function(&global_scope, "println", builtin_println); scope_add_function(&global_scope, "list", builtin_list); scope_add_function(&global_scope, "append", builtin_append); scope_add_function(&global_scope, "length", builtin_length); scope_add_function(&global_scope, "null?", builtin_isnull); - scope_add_function(&global_scope, "builtins", builtin_builtins); + scope_add_function(&global_scope, "nth", builtin_nth); - scope_add_function(&global_scope, "floor", builtin_floor); - scope_add_function(&global_scope, "ceil", builtin_ceil); + scope_add_function(&global_scope, "println", builtin_println); + scope_add_function(&global_scope, "builtins", builtin_builtins); nob_da_append(scopes, &global_scope); } diff --git a/lisp.h b/lisp.h index 95c22e8..8b167ce 100644 --- a/lisp.h +++ b/lisp.h @@ -105,27 +105,30 @@ int special_form_if(Nodes args, Scopes *scopes, Node *result); int special_form_define(Nodes args, Scopes *scopes, Node *result); int special_form_let(Nodes args, Scopes *scopes, Node *result); int special_form_lambda(Nodes args, Scopes *scopes, Node *result); +int special_form_quote(Nodes args, Scopes *scopes, Node *result); // builtins int builtin_add(Nodes args, Scopes *scopes, Node *result); -int builtin_sub(Nodes args, Scopes *scope, Node *result); -int builtin_div(Nodes args, Scopes *scope, Node *result); -int builtin_mul(Nodes args, Scopes *scope, Node *result); - -int builtin_eq(Nodes args, Scopes *scope, Node *result); -int builtin_lt(Nodes args, Scopes *scope, Node *result); -int builtin_gt(Nodes args, Scopes *scope, Node *result); -int builtin_lt_eq(Nodes args, Scopes *scope, Node *result); -int builtin_gt_eq(Nodes args, Scopes *scope, Node *result); - -int builtin_println(Nodes args, Scopes *scopes, Node *result); -int builtin_list(Nodes args, Scopes *scopes, Node *result); -int builtin_append(Nodes args, Scopes *scope, Node *result); -int builtin_length(Nodes args, Scopes *scope, Node *result); -int builtin_isnull(Nodes args, Scopes *scope, Node *result); -int builtin_builtins(Nodes args, Scopes *scopes, Node *result); +int builtin_sub(Nodes args, Scopes *scopes, Node *result); +int builtin_div(Nodes args, Scopes *scopes, Node *result); +int builtin_mul(Nodes args, Scopes *scopes, Node *result); int builtin_floor(Nodes args, Scopes *scopes, Node *result); int builtin_ceil(Nodes args, Scopes *scopes, Node *result); +int builtin_eq(Nodes args, Scopes *scopes, Node *result); +int builtin_lt(Nodes args, Scopes *scopes, Node *result); +int builtin_gt(Nodes args, Scopes *scopes, Node *result); +int builtin_lt_eq(Nodes args, Scopes *scopes, Node *result); +int builtin_gt_eq(Nodes args, Scopes *scopes, Node *result); + +int builtin_list(Nodes args, Scopes *scopes, Node *result); +int builtin_append(Nodes args, Scopes *scopes, Node *result); +int builtin_length(Nodes args, Scopes *scopes, Node *result); +int builtin_isnull(Nodes args, Scopes *scopes, Node *result); +int builtin_nth(Nodes args, Scopes *scopes, Node *result); + +int builtin_println(Nodes args, Scopes *scopes, Node *result); +int builtin_builtins(Nodes args, Scopes *scopes, Node *result); + #endif // LISP_H diff --git a/special_forms.c b/special_forms.c index a761fd1..d57812b 100644 --- a/special_forms.c +++ b/special_forms.c @@ -168,3 +168,16 @@ int special_form_lambda(Nodes args, Scopes *scopes, Node *result) { result->as_lambda.body = body; return 0; } + +int special_form_quote(Nodes args, Scopes *scopes, Node *result) { + UNUSED(scopes); + + if (args.count != 1) { + printf("'quote' expects one argument!\n"); + return 1; + } + + Node n = args.items[0]; + *result = n; + return 0; +}