refactor: use union instead of void*
This commit is contained in:
@@ -34,16 +34,8 @@ typedef enum e_NodeKind {
|
|||||||
NODE_KIND_FUNCTION,
|
NODE_KIND_FUNCTION,
|
||||||
} NodeKind;
|
} NodeKind;
|
||||||
|
|
||||||
typedef struct s_Node {
|
typedef struct s_Node Node;
|
||||||
NodeKind kind;
|
typedef struct s_Nodes Nodes;
|
||||||
void *data;
|
|
||||||
} Node;
|
|
||||||
|
|
||||||
typedef struct s_Nodes {
|
|
||||||
Node *items;
|
|
||||||
size_t count;
|
|
||||||
size_t capacity;
|
|
||||||
} Nodes;
|
|
||||||
|
|
||||||
typedef Node *(*lisp_function_ptr)(Nodes *args);
|
typedef Node *(*lisp_function_ptr)(Nodes *args);
|
||||||
typedef struct s_LispFunction {
|
typedef struct s_LispFunction {
|
||||||
@@ -51,6 +43,22 @@ typedef struct s_LispFunction {
|
|||||||
lisp_function_ptr apply;
|
lisp_function_ptr apply;
|
||||||
} LispFunction;
|
} 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) {
|
Node *lisp_function_addition(Nodes *args) {
|
||||||
if (args->count != 2) {
|
if (args->count != 2) {
|
||||||
printf("'+' expects two arguments!\n");
|
printf("'+' expects two arguments!\n");
|
||||||
@@ -66,13 +74,9 @@ Node *lisp_function_addition(Nodes *args) {
|
|||||||
Node *node = malloc(sizeof(Node));
|
Node *node = malloc(sizeof(Node));
|
||||||
node->kind = NODE_KIND_NUMBER;
|
node->kind = NODE_KIND_NUMBER;
|
||||||
|
|
||||||
long long *num = malloc(sizeof(long long));
|
intptr_t a = args->items[0].as_number;
|
||||||
// trust me, this is safe :)
|
intptr_t b = args->items[1].as_number;
|
||||||
long long a = *((long long *)args->items[0].data);
|
node->as_number = a + b;
|
||||||
long long b = *((long long *)args->items[1].data);
|
|
||||||
*num = a + b;
|
|
||||||
|
|
||||||
node->data = num;
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,9 +89,7 @@ Node *lisp_function_lookup(Nob_String_View name) {
|
|||||||
if (nob_sv_eq(globalScope[i].name, name)) {
|
if (nob_sv_eq(globalScope[i].name, name)) {
|
||||||
Node *node = malloc(sizeof(Node));
|
Node *node = malloc(sizeof(Node));
|
||||||
node->kind = NODE_KIND_FUNCTION;
|
node->kind = NODE_KIND_FUNCTION;
|
||||||
// taking the reference should be fine because globalScope is in the
|
node->as_function = globalScope[i];
|
||||||
// static memory
|
|
||||||
node->data = &globalScope[i];
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,7 +202,7 @@ Node *parse(Tokens *tokens) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
node->kind = NODE_KIND_LIST;
|
node->kind = NODE_KIND_LIST;
|
||||||
node->data = nodes;
|
node->as_list = nodes;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,18 +213,17 @@ Node *parse(Tokens *tokens) {
|
|||||||
|
|
||||||
switch (tok.kind) {
|
switch (tok.kind) {
|
||||||
case TOKEN_KIND_NUMBER: {
|
case TOKEN_KIND_NUMBER: {
|
||||||
long long *num = malloc(sizeof(long long));
|
long long num = strtoll(tok.data.data, NULL, 10);
|
||||||
*num = strtoll(tok.data.data, NULL, 10);
|
// TODO:
|
||||||
|
// - error checking
|
||||||
|
// - double support
|
||||||
|
|
||||||
node->kind = NODE_KIND_NUMBER;
|
node->kind = NODE_KIND_NUMBER;
|
||||||
node->data = num;
|
node->as_number = num;
|
||||||
} break;
|
} break;
|
||||||
case TOKEN_KIND_SYMBOL: {
|
case TOKEN_KIND_SYMBOL: {
|
||||||
Nob_String_View *dat = malloc(sizeof(Nob_String_View));
|
|
||||||
*dat = tok.data;
|
|
||||||
|
|
||||||
node->kind = NODE_KIND_SYMBOL;
|
node->kind = NODE_KIND_SYMBOL;
|
||||||
node->data = dat;
|
node->as_symbol = tok.data;
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
UNREACHABLE("");
|
UNREACHABLE("");
|
||||||
@@ -234,27 +235,25 @@ Node *parse(Tokens *tokens) {
|
|||||||
void node_print(Node node) {
|
void node_print(Node node) {
|
||||||
switch (node.kind) {
|
switch (node.kind) {
|
||||||
case NODE_KIND_NUMBER: {
|
case NODE_KIND_NUMBER: {
|
||||||
long long num = *((long long *)node.data);
|
printf("%lld", node.as_number);
|
||||||
printf("%lld", num);
|
|
||||||
} break;
|
} break;
|
||||||
case NODE_KIND_SYMBOL: {
|
case NODE_KIND_SYMBOL: {
|
||||||
Nob_String_View sv = *((Nob_String_View *)node.data);
|
printf(SV_Fmt, SV_Arg(node.as_symbol));
|
||||||
printf(SV_Fmt, SV_Arg(sv));
|
|
||||||
} break;
|
} break;
|
||||||
case NODE_KIND_LIST: {
|
case NODE_KIND_LIST: {
|
||||||
Nodes nodes = *((Nodes *)node.data);
|
Nodes *children = node.as_list;
|
||||||
printf("(");
|
printf("(");
|
||||||
for (size_t i = 0; i < nodes.count; i++) {
|
for (size_t i = 0; i < children->count; i++) {
|
||||||
Node node = nodes.items[i];
|
Node node = children->items[i];
|
||||||
node_print(node);
|
node_print(node);
|
||||||
if (i != nodes.count - 1) {
|
if (i != children->count - 1) {
|
||||||
printf(" ");
|
printf(" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf(")");
|
printf(")");
|
||||||
} break;
|
} break;
|
||||||
case NODE_KIND_FUNCTION: {
|
case NODE_KIND_FUNCTION: {
|
||||||
LispFunction func = *((LispFunction *)node.data);
|
LispFunction func = node.as_function;
|
||||||
printf(SV_Fmt, SV_Arg(func.name));
|
printf(SV_Fmt, SV_Arg(func.name));
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
@@ -268,30 +267,28 @@ Node *eval(Node *node) {
|
|||||||
case NODE_KIND_NUMBER:
|
case NODE_KIND_NUMBER:
|
||||||
return node;
|
return node;
|
||||||
case NODE_KIND_SYMBOL: {
|
case NODE_KIND_SYMBOL: {
|
||||||
// trust me, this is safe :)
|
return lisp_function_lookup(node->as_symbol);
|
||||||
Nob_String_View sv = *((Nob_String_View *)node->data);
|
|
||||||
return lisp_function_lookup(sv);
|
|
||||||
}
|
}
|
||||||
case NODE_KIND_LIST: {
|
case NODE_KIND_LIST: {
|
||||||
Nodes children = *((Nodes *)node->data);
|
Nodes *children = node->as_list;
|
||||||
if (children.count == 0)
|
if (children->count == 0)
|
||||||
return node;
|
return node;
|
||||||
|
|
||||||
Node *head = &children.items[0];
|
Node *head = &children->items[0];
|
||||||
Node *function = eval(head);
|
Node *func_node = eval(head);
|
||||||
|
|
||||||
Nodes *args = malloc(sizeof(Nodes));
|
Nodes *args = malloc(sizeof(Nodes));
|
||||||
for (size_t i = 1; i < children.count; i++) {
|
for (size_t i = 1; i < children->count; i++) {
|
||||||
nob_da_append(args, *eval(&children.items[i]));
|
nob_da_append(args, *eval(&children->items[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (function->kind == NODE_KIND_FUNCTION) {
|
if (func_node->kind == NODE_KIND_FUNCTION) {
|
||||||
LispFunction func = *((LispFunction *)function->data);
|
LispFunction func = func_node->as_function;
|
||||||
return func.apply(args);
|
return func.apply(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Not a function: '");
|
printf("Not a function: '");
|
||||||
node_print(*function);
|
node_print(*func_node);
|
||||||
printf("'\n");
|
printf("'\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user