From 6d022219c3ca3114e1dfff7882deb674a340ca6c Mon Sep 17 00:00:00 2001 From: Tim Teichmann Date: Tue, 21 Jul 2026 22:16:50 +0200 Subject: [PATCH] feat: floating point numbers --- builtins.c | 43 ++++++++++++++++++++++++++++++++++++++++--- lisp.c | 26 ++++++++++++++------------ lisp.h | 6 ++++-- 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/builtins.c b/builtins.c index f3afd8f..e990671 100644 --- a/builtins.c +++ b/builtins.c @@ -1,5 +1,7 @@ #include "lisp.h" +#include + #define func_arithmetic_ex(name, operator, operator_name) \ int name(Nodes args, Scopes *scopes, Node *result) { \ UNUSED(scopes); \ @@ -14,8 +16,8 @@ "else!\n"); \ return 1; \ } \ - long long a = args.items[0].as_number; \ - long long b = args.items[1].as_number; \ + double a = args.items[0].as_number; \ + double b = args.items[1].as_number; \ result->as_number = a operator b; \ result->kind = NODE_KIND_NUMBER; \ return 0; \ @@ -28,7 +30,6 @@ func_arithmetic(lisp_function_add, +); func_arithmetic(lisp_function_sub, -); func_arithmetic(lisp_function_div, /); func_arithmetic(lisp_function_mul, *); -func_arithmetic(lisp_function_mod, %); func_arithmetic_ex(lisp_function_eq, ==, "="); func_arithmetic(lisp_function_lt, <); func_arithmetic(lisp_function_gt, >); @@ -151,3 +152,39 @@ int lisp_function_builtins(Nodes args, Scopes *scopes, Node *result) { result->kind = NODE_KIND_LIST; return 0; } + +int lisp_function_floor(Nodes args, Scopes *scopes, Node *result) { + UNUSED(scopes); + + if (args.count != 1) { + printf("'floor' expects one argument!\n"); + return 1; + } + + if (args.items[0].kind != NODE_KIND_NUMBER) { + printf("'floor' can only be used on numbers!\n"); + return 1; + } + + result->kind = NODE_KIND_NUMBER; + result->as_number = floor(args.items[0].as_number); + return 0; +} + +int lisp_function_ceil(Nodes args, Scopes *scopes, Node *result) { + UNUSED(scopes); + + if (args.count != 1) { + printf("'ceil' expects one argument!\n"); + return 1; + } + + if (args.items[0].kind != NODE_KIND_NUMBER) { + printf("'ceil' can only be used on numbers!\n"); + return 1; + } + + result->kind = NODE_KIND_NUMBER; + result->as_number = ceil(args.items[0].as_number); + return 0; +} diff --git a/lisp.c b/lisp.c index 13b3995..bdec395 100644 --- a/lisp.c +++ b/lisp.c @@ -38,12 +38,10 @@ static bool node_is_true(Node node) { } void build_scopes(Scopes *scopes) { - // clang-format off scope_add_function(&global_scope, "+", lisp_function_add); scope_add_function(&global_scope, "-", lisp_function_sub); scope_add_function(&global_scope, "/", lisp_function_div); scope_add_function(&global_scope, "*", lisp_function_mul); - scope_add_function(&global_scope, "%", lisp_function_mod); scope_add_function(&global_scope, "=", lisp_function_eq); scope_add_function(&global_scope, "<", lisp_function_lt); scope_add_function(&global_scope, ">", lisp_function_gt); @@ -55,8 +53,9 @@ void build_scopes(Scopes *scopes) { scope_add_function(&global_scope, "append", lisp_function_append); scope_add_function(&global_scope, "length", lisp_function_length); scope_add_function(&global_scope, "null?", lisp_function_isnull); - scope_add_function(&global_scope, "builtins", lisp_function_builtins); - // clang-format on + + scope_add_function(&global_scope, "floor", lisp_function_floor); + scope_add_function(&global_scope, "ceil", lisp_function_ceil); nob_da_append(scopes, &global_scope); } @@ -79,7 +78,7 @@ const char *token_kind_name(TokenKind kind) { void node_print(Node node) { switch (node.kind) { case NODE_KIND_NUMBER: { - printf("%lld", node.as_number); + printf("%f", node.as_number); } break; case NODE_KIND_SYMBOL: { printf(SV_Fmt, SV_Arg(node.as_symbol)); @@ -138,9 +137,11 @@ int tokenize(Nob_String_View content, Tokens *tokens) { } Nob_String_Builder sb = {0}; - while (isdigit(c)) { + bool condition = isdigit(c); + while (condition) { nob_sb_appendf(&sb, "%c", c); c = content.data[++i]; + condition = isdigit(c) || c == '.'; } if (sb.count > 0) { @@ -153,8 +154,8 @@ int tokenize(Nob_String_View content, Tokens *tokens) { } // symbols shouldn't start with a digit - bool condition = isascii(c) && !isdigit(c) && !isblank(c) && - !iscntrl(c) && c != '(' && c != ')'; + condition = isascii(c) && !isdigit(c) && !isblank(c) && !iscntrl(c) && + c != '(' && c != ')'; while (condition) { nob_sb_appendf(&sb, "%c", c); c = content.data[++i]; @@ -221,10 +222,11 @@ int parse_one(Tokens *tokens, Node *node) { return 1; } case TOKEN_KIND_NUMBER: { - long long num = strtoll(tok.data.data, NULL, 10); - // TODO: - // - error checking - // - double support + double num = strtod(tok.data.data, NULL); + if (errno != 0) { + printf("Failed to read number!\n"); + return 1; + } node->kind = NODE_KIND_NUMBER; node->as_number = num; diff --git a/lisp.h b/lisp.h index 4f13394..4a8ee70 100644 --- a/lisp.h +++ b/lisp.h @@ -41,7 +41,7 @@ struct s_Node { union { Nob_String_View as_symbol; Nodes *as_list; - long long as_number; + double as_number; struct { Nob_String_View name; LispFunction apply; @@ -90,7 +90,6 @@ int lisp_function_add(Nodes args, Scopes *scopes, Node *result); int lisp_function_sub(Nodes args, Scopes *scope, Node *result); int lisp_function_div(Nodes args, Scopes *scope, Node *result); int lisp_function_mul(Nodes args, Scopes *scope, Node *result); -int lisp_function_mod(Nodes args, Scopes *scope, Node *result); int lisp_function_eq(Nodes args, Scopes *scope, Node *result); int lisp_function_lt(Nodes args, Scopes *scope, Node *result); @@ -105,4 +104,7 @@ int lisp_function_length(Nodes args, Scopes *scope, Node *result); int lisp_function_isnull(Nodes args, Scopes *scope, Node *result); int lisp_function_builtins(Nodes args, Scopes *scopes, Node *result); +int lisp_function_floor(Nodes args, Scopes *scopes, Node *result); +int lisp_function_ceil(Nodes args, Scopes *scopes, Node *result); + #endif // LISP_H