feat: floating point numbers
This commit is contained in:
+40
-3
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user