feat: floating point numbers

This commit is contained in:
2026-07-21 22:16:50 +02:00
parent 62dc0f30eb
commit 6d022219c3
3 changed files with 58 additions and 17 deletions
+40 -3
View File
@@ -1,5 +1,7 @@
#include "lisp.h" #include "lisp.h"
#include <math.h>
#define func_arithmetic_ex(name, operator, operator_name) \ #define func_arithmetic_ex(name, operator, operator_name) \
int name(Nodes args, Scopes *scopes, Node *result) { \ int name(Nodes args, Scopes *scopes, Node *result) { \
UNUSED(scopes); \ UNUSED(scopes); \
@@ -14,8 +16,8 @@
"else!\n"); \ "else!\n"); \
return 1; \ return 1; \
} \ } \
long long a = args.items[0].as_number; \ double a = args.items[0].as_number; \
long long b = args.items[1].as_number; \ double b = args.items[1].as_number; \
result->as_number = a operator b; \ result->as_number = a operator b; \
result->kind = NODE_KIND_NUMBER; \ result->kind = NODE_KIND_NUMBER; \
return 0; \ return 0; \
@@ -28,7 +30,6 @@ func_arithmetic(lisp_function_add, +);
func_arithmetic(lisp_function_sub, -); func_arithmetic(lisp_function_sub, -);
func_arithmetic(lisp_function_div, /); func_arithmetic(lisp_function_div, /);
func_arithmetic(lisp_function_mul, *); func_arithmetic(lisp_function_mul, *);
func_arithmetic(lisp_function_mod, %);
func_arithmetic_ex(lisp_function_eq, ==, "="); func_arithmetic_ex(lisp_function_eq, ==, "=");
func_arithmetic(lisp_function_lt, <); func_arithmetic(lisp_function_lt, <);
func_arithmetic(lisp_function_gt, >); func_arithmetic(lisp_function_gt, >);
@@ -151,3 +152,39 @@ int lisp_function_builtins(Nodes args, Scopes *scopes, Node *result) {
result->kind = NODE_KIND_LIST; result->kind = NODE_KIND_LIST;
return 0; 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;
}
+14 -12
View File
@@ -38,12 +38,10 @@ static bool node_is_true(Node node) {
} }
void build_scopes(Scopes *scopes) { void build_scopes(Scopes *scopes) {
// clang-format off
scope_add_function(&global_scope, "+", lisp_function_add); scope_add_function(&global_scope, "+", lisp_function_add);
scope_add_function(&global_scope, "-", lisp_function_sub); scope_add_function(&global_scope, "-", lisp_function_sub);
scope_add_function(&global_scope, "/", lisp_function_div); scope_add_function(&global_scope, "/", lisp_function_div);
scope_add_function(&global_scope, "*", lisp_function_mul); 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_eq);
scope_add_function(&global_scope, "<", lisp_function_lt); scope_add_function(&global_scope, "<", lisp_function_lt);
scope_add_function(&global_scope, ">", lisp_function_gt); 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, "append", lisp_function_append);
scope_add_function(&global_scope, "length", lisp_function_length); scope_add_function(&global_scope, "length", lisp_function_length);
scope_add_function(&global_scope, "null?", lisp_function_isnull); 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); nob_da_append(scopes, &global_scope);
} }
@@ -79,7 +78,7 @@ const char *token_kind_name(TokenKind kind) {
void node_print(Node node) { void node_print(Node node) {
switch (node.kind) { switch (node.kind) {
case NODE_KIND_NUMBER: { case NODE_KIND_NUMBER: {
printf("%lld", node.as_number); printf("%f", node.as_number);
} break; } break;
case NODE_KIND_SYMBOL: { case NODE_KIND_SYMBOL: {
printf(SV_Fmt, SV_Arg(node.as_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}; Nob_String_Builder sb = {0};
while (isdigit(c)) { bool condition = isdigit(c);
while (condition) {
nob_sb_appendf(&sb, "%c", c); nob_sb_appendf(&sb, "%c", c);
c = content.data[++i]; c = content.data[++i];
condition = isdigit(c) || c == '.';
} }
if (sb.count > 0) { if (sb.count > 0) {
@@ -153,8 +154,8 @@ int tokenize(Nob_String_View content, Tokens *tokens) {
} }
// symbols shouldn't start with a digit // symbols shouldn't start with a digit
bool condition = isascii(c) && !isdigit(c) && !isblank(c) && condition = isascii(c) && !isdigit(c) && !isblank(c) && !iscntrl(c) &&
!iscntrl(c) && c != '(' && c != ')'; c != '(' && c != ')';
while (condition) { while (condition) {
nob_sb_appendf(&sb, "%c", c); nob_sb_appendf(&sb, "%c", c);
c = content.data[++i]; c = content.data[++i];
@@ -221,10 +222,11 @@ int parse_one(Tokens *tokens, Node *node) {
return 1; return 1;
} }
case TOKEN_KIND_NUMBER: { case TOKEN_KIND_NUMBER: {
long long num = strtoll(tok.data.data, NULL, 10); double num = strtod(tok.data.data, NULL);
// TODO: if (errno != 0) {
// - error checking printf("Failed to read number!\n");
// - double support return 1;
}
node->kind = NODE_KIND_NUMBER; node->kind = NODE_KIND_NUMBER;
node->as_number = num; node->as_number = num;
+4 -2
View File
@@ -41,7 +41,7 @@ struct s_Node {
union { union {
Nob_String_View as_symbol; Nob_String_View as_symbol;
Nodes *as_list; Nodes *as_list;
long long as_number; double as_number;
struct { struct {
Nob_String_View name; Nob_String_View name;
LispFunction apply; 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_sub(Nodes args, Scopes *scope, Node *result);
int lisp_function_div(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_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_eq(Nodes args, Scopes *scope, Node *result);
int lisp_function_lt(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_isnull(Nodes args, Scopes *scope, Node *result);
int lisp_function_builtins(Nodes args, Scopes *scopes, 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 #endif // LISP_H