From fb40d83244cec580018dc21bb797c6ab0ca553fb Mon Sep 17 00:00:00 2001 From: Tim Teichmann Date: Tue, 21 Jul 2026 11:53:10 +0200 Subject: [PATCH] refactor: spread across files --- builtins.c | 22 +++++++ lisp.c | 175 ++++++++++------------------------------------------ lisp.h | 66 ++++++++++++++++++++ main.c | 34 ++++++++++ test/1.lisp | 18 ++++++ 5 files changed, 173 insertions(+), 142 deletions(-) create mode 100644 builtins.c create mode 100644 lisp.h create mode 100644 main.c create mode 100644 test/1.lisp diff --git a/builtins.c b/builtins.c new file mode 100644 index 0000000..f6dbc1b --- /dev/null +++ b/builtins.c @@ -0,0 +1,22 @@ +#include "lisp.h" + +Node *lisp_function_addition(Nodes *args) { + if (args->count != 2) { + printf("'+' expects two arguments!\n"); + return NULL; + } + + if (args->items[0].kind != NODE_KIND_NUMBER || + args->items[1].kind != NODE_KIND_NUMBER) { + printf("'+' can only add numbers, you specified something else!\n"); + return NULL; + } + + Node *node = malloc(sizeof(Node)); + node->kind = NODE_KIND_NUMBER; + + intptr_t a = args->items[0].as_number; + intptr_t b = args->items[1].as_number; + node->as_number = a + b; + return node; +} diff --git a/lisp.c b/lisp.c index e5beb2c..f184aad 100644 --- a/lisp.c +++ b/lisp.c @@ -1,90 +1,10 @@ -#include -#include -#include -#include -#include -#include -#include - -#define NOB_IMPLEMENTATION -#include "nob.h" - -typedef enum e_TokenKind { - TOKEN_KIND_PAR_LEFT, - TOKEN_KIND_PAR_RIGHT, - TOKEN_KIND_NUMBER, - TOKEN_KIND_SYMBOL, -} TokenKind; - -typedef struct s_Token { - TokenKind kind; - Nob_String_View data; -} Token; - -typedef struct s_Tokens { - Token *items; - size_t count; - size_t capacity; -} Tokens; - -typedef enum e_NodeKind { - NODE_KIND_SYMBOL, - NODE_KIND_LIST, - NODE_KIND_NUMBER, - NODE_KIND_FUNCTION, -} NodeKind; - -typedef struct s_Node Node; -typedef struct s_Nodes Nodes; - -typedef Node *(*lisp_function_ptr)(Nodes *args); -typedef struct s_LispFunction { - Nob_String_View name; - lisp_function_ptr apply; -} LispFunction; - -typedef struct s_Node { - NodeKind kind; - union { - Nob_String_View as_symbol; - Nodes *as_list; - long long as_number; - LispFunction as_function; - }; -} Node; - -struct s_Nodes { - Node *items; - size_t count; - size_t capacity; -}; - -Node *lisp_function_addition(Nodes *args) { - if (args->count != 2) { - printf("'+' expects two arguments!\n"); - return NULL; - } - - if (args->items[0].kind != NODE_KIND_NUMBER || - args->items[1].kind != NODE_KIND_NUMBER) { - printf("'+' can only add numbers, you specified something else!\n"); - return NULL; - } - - Node *node = malloc(sizeof(Node)); - node->kind = NODE_KIND_NUMBER; - - intptr_t a = args->items[0].as_number; - intptr_t b = args->items[1].as_number; - node->as_number = a + b; - return node; -} +#include "lisp.h" static LispFunction globalScope[] = { (LispFunction){.name = (Nob_String_View){.items = "+", .count = 1}, .apply = lisp_function_addition}}; -Node *lisp_function_lookup(Nob_String_View name) { +static Node *lisp_function_lookup(Nob_String_View name) { for (size_t i = 0; i < NOB_ARRAY_LEN(globalScope); i++) { if (nob_sv_eq(globalScope[i].name, name)) { Node *node = malloc(sizeof(Node)); @@ -113,6 +33,33 @@ const char *token_kind_name(TokenKind kind) { } } +void node_print(Node node) { + switch (node.kind) { + case NODE_KIND_NUMBER: { + printf("%lld", node.as_number); + } break; + case NODE_KIND_SYMBOL: { + printf(SV_Fmt, SV_Arg(node.as_symbol)); + } break; + case NODE_KIND_LIST: { + Nodes *children = node.as_list; + printf("("); + for (size_t i = 0; i < children->count; i++) { + Node node = children->items[i]; + node_print(node); + if (i != children->count - 1) { + printf(" "); + } + } + printf(")"); + } break; + case NODE_KIND_FUNCTION: { + LispFunction func = node.as_function; + printf(SV_Fmt, SV_Arg(func.name)); + } break; + } +} + void tokenize(Nob_String_View content, Tokens *tokens) { for (size_t i = 0; i < content.count; i++) { char c = content.data[i]; @@ -149,12 +96,13 @@ void tokenize(Nob_String_View content, Tokens *tokens) { } // symbols shouldn't start with a digit - bool condition = - isascii(c) && !isdigit(c) && !isblank(c) && c != '(' && c != ')'; + bool condition = isascii(c) && !isdigit(c) && !isblank(c) && + !iscntrl(c) && c != '(' && c != ')'; while (condition) { nob_sb_appendf(&sb, "%c", c); c = content.data[++i]; - condition = isascii(c) && !isblank(c) && c != '(' && c != ')'; + condition = isascii(c) && !isblank(c) && !iscntrl(c) && c != '(' && + c != ')'; } if (sb.count > 0) { @@ -232,33 +180,6 @@ Node *parse(Tokens *tokens) { return node; } -void node_print(Node node) { - switch (node.kind) { - case NODE_KIND_NUMBER: { - printf("%lld", node.as_number); - } break; - case NODE_KIND_SYMBOL: { - printf(SV_Fmt, SV_Arg(node.as_symbol)); - } break; - case NODE_KIND_LIST: { - Nodes *children = node.as_list; - printf("("); - for (size_t i = 0; i < children->count; i++) { - Node node = children->items[i]; - node_print(node); - if (i != children->count - 1) { - printf(" "); - } - } - printf(")"); - } break; - case NODE_KIND_FUNCTION: { - LispFunction func = node.as_function; - printf(SV_Fmt, SV_Arg(func.name)); - } break; - } -} - Node *eval(Node *node) { if (node == NULL) return NULL; @@ -297,33 +218,3 @@ Node *eval(Node *node) { } return NULL; } - -int main(int argc, char **argv) { - if (argc < 2) - return 1; - - argv++; - const char *line = *argv++; - Nob_String_View view = nob_sv_from_cstr(line); - - Tokens tokens = {0}; - tokenize(view, &tokens); - -#if 0 - for (size_t i = 0; i < tokens.count; i++) { - Token tok = tokens.items[i]; - printf("Token(kind=%s, data=" SV_Fmt ")\n", token_kind_name(tok.kind), - SV_Arg(tok.data)); - } -#endif - - Node *result = parse(&tokens); - if (result == NULL) - return 1; - - result = eval(result); - node_print(*result); - printf("\n"); - - return 0; -} diff --git a/lisp.h b/lisp.h new file mode 100644 index 0000000..294c847 --- /dev/null +++ b/lisp.h @@ -0,0 +1,66 @@ +#ifndef LISP_H +#define LISP_H + +#include "nob.h" + +typedef enum e_TokenKind { + TOKEN_KIND_PAR_LEFT, + TOKEN_KIND_PAR_RIGHT, + TOKEN_KIND_NUMBER, + TOKEN_KIND_SYMBOL, +} TokenKind; + +typedef struct s_Token { + TokenKind kind; + Nob_String_View data; +} Token; + +typedef struct s_Tokens { + Token *items; + size_t count; + size_t capacity; +} Tokens; + +typedef enum e_NodeKind { + NODE_KIND_SYMBOL, + NODE_KIND_LIST, + NODE_KIND_NUMBER, + NODE_KIND_FUNCTION, +} NodeKind; + +typedef struct s_Node Node; +typedef struct s_Nodes Nodes; + +typedef Node *(*lisp_function_ptr)(Nodes *args); +typedef struct s_LispFunction { + Nob_String_View name; + lisp_function_ptr apply; +} LispFunction; + +typedef struct s_Node { + NodeKind kind; + union { + Nob_String_View as_symbol; + Nodes *as_list; + long long as_number; + LispFunction as_function; + }; +} Node; + +struct s_Nodes { + Node *items; + size_t count; + size_t capacity; +}; + +const char *token_kind_name(TokenKind kind); +void node_print(Node node); + +void tokenize(Nob_String_View content, Tokens *tokens); +Node *parse(Tokens *tokens); +Node *eval(Node *node); + +// builtins +Node *lisp_function_addition(Nodes *args); + +#endif // LISP_H diff --git a/main.c b/main.c new file mode 100644 index 0000000..3fcf964 --- /dev/null +++ b/main.c @@ -0,0 +1,34 @@ +#include + +#define NOB_IMPLEMENTATION +#include "lisp.h" + +int main(int argc, char **argv) { + if (argc < 2) + return 1; + + argv++; + const char *line = *argv++; + Nob_String_View view = nob_sv_from_cstr(line); + + Tokens tokens = {0}; + tokenize(view, &tokens); + +#if 0 + for (size_t i = 0; i < tokens.count; i++) { + Token tok = tokens.items[i]; + printf("Token(kind=%s, data=" SV_Fmt ")\n", token_kind_name(tok.kind), + SV_Arg(tok.data)); + } +#endif + + Node *result = parse(&tokens); + if (result == NULL) + return 1; + + result = eval(result); + node_print(*result); + printf("\n"); + + return 0; +} diff --git a/test/1.lisp b/test/1.lisp new file mode 100644 index 0000000..c3e25af --- /dev/null +++ b/test/1.lisp @@ -0,0 +1,18 @@ +( + println ( + let ( + (x 2) + ) + ( + cond + ( + (= x 2) + 5 + ) + ( + else + 1 + ) + ) + ) +)