impl scopes more or less properly

This commit is contained in:
2026-07-21 14:34:26 +02:00
parent 772bf99de9
commit b0fee03ec0
4 changed files with 104 additions and 31 deletions
+16 -1
View File
@@ -1,6 +1,8 @@
#include "lisp.h" #include "lisp.h"
Node *lisp_function_addition(Nodes *args) { Node *lisp_function_addition(Nodes *args, Scopes *scopes) {
(void)(scopes);
if (args->count != 2) { if (args->count != 2) {
printf("'+' expects two arguments!\n"); printf("'+' expects two arguments!\n");
return NULL; return NULL;
@@ -20,3 +22,16 @@ Node *lisp_function_addition(Nodes *args) {
node->as_number = a + b; node->as_number = a + b;
return node; return node;
} }
Node *lisp_function_println(Nodes *args, Scopes *scopes) {
if (args->count != 1) {
printf("'+' expects one argument!\n");
return NULL;
}
Node *result = eval(&args->items[0], scopes);
node_print(*result);
printf("\n");
return result;
}
+53 -19
View File
@@ -1,16 +1,13 @@
#include "lisp.h" #include "lisp.h"
static LispFunction globalScope[] = { static Scope globalScope = {0};
(LispFunction){.name = (Nob_String_View){.items = "+", .count = 1},
.apply = lisp_function_addition}};
static Node *lisp_function_lookup(Nob_String_View name) { static Node *scope_lookup(Scopes *scopes, Nob_String_View name) {
for (size_t i = 0; i < NOB_ARRAY_LEN(globalScope); i++) { nob_da_foreach(Scope, scope, scopes) {
if (nob_sv_eq(globalScope[i].name, name)) { nob_da_foreach(ScopeObject, scopeObject, scope) {
Node *node = malloc(sizeof(Node)); if (nob_sv_eq(name, scopeObject->name)) {
node->kind = NODE_KIND_FUNCTION; return &scopeObject->node;
node->as_function = globalScope[i]; }
return node;
} }
} }
@@ -18,6 +15,44 @@ static Node *lisp_function_lookup(Nob_String_View name) {
return NULL; return NULL;
} }
void build_scopes(Scopes *scopes) {
// clang-format off
Nob_String_View obj_name = (Nob_String_View){
.items = "+",
.count = 1
};
ScopeObject obj = (ScopeObject){
.name = obj_name,
.node = (Node){
.kind = NODE_KIND_FUNCTION,
.as_function = {
.name = obj_name,
.apply = lisp_function_addition
}
}
};
nob_da_append(&globalScope, obj);
obj_name = (Nob_String_View){
.items = "println",
.count = 7
};
obj = (ScopeObject){
.name = obj_name,
.node = (Node){
.kind = NODE_KIND_FUNCTION,
.as_function = {
.name = obj_name,
.apply = lisp_function_println
}
}
};
nob_da_append(&globalScope, obj);
// clang-format on
nob_da_append(scopes, globalScope);
}
const char *token_kind_name(TokenKind kind) { const char *token_kind_name(TokenKind kind) {
switch (kind) { switch (kind) {
case TOKEN_KIND_PAR_LEFT: case TOKEN_KIND_PAR_LEFT:
@@ -54,8 +89,8 @@ void node_print(Node node) {
printf(")"); printf(")");
} break; } break;
case NODE_KIND_FUNCTION: { case NODE_KIND_FUNCTION: {
LispFunction func = node.as_function; Nob_String_View func_name = node.as_function.name;
printf(SV_Fmt, SV_Arg(func.name)); printf(SV_Fmt, SV_Arg(func_name));
} break; } break;
} }
} }
@@ -180,15 +215,15 @@ Node *parse(Tokens *tokens) {
return node; return node;
} }
Node *eval(Node *node) { Node *eval(Node *node, Scopes *scopes) {
if (node == NULL) if (node == NULL || scopes == NULL)
return NULL; return NULL;
switch (node->kind) { switch (node->kind) {
case NODE_KIND_NUMBER: case NODE_KIND_NUMBER:
return node; return node;
case NODE_KIND_SYMBOL: { case NODE_KIND_SYMBOL: {
return lisp_function_lookup(node->as_symbol); return scope_lookup(scopes, node->as_symbol);
} }
case NODE_KIND_LIST: { case NODE_KIND_LIST: {
Nodes *children = node->as_list; Nodes *children = node->as_list;
@@ -196,16 +231,15 @@ Node *eval(Node *node) {
return node; return node;
Node *head = &children->items[0]; Node *head = &children->items[0];
Node *func_node = eval(head); Node *func_node = eval(head, scopes);
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], scopes));
} }
if (func_node->kind == NODE_KIND_FUNCTION) { if (func_node->kind == NODE_KIND_FUNCTION) {
LispFunction func = func_node->as_function; return func_node->as_function.apply(args, scopes);
return func.apply(args);
} }
printf("Not a function: '"); printf("Not a function: '");
+30 -10
View File
@@ -30,22 +30,22 @@ typedef enum e_NodeKind {
typedef struct s_Node Node; typedef struct s_Node Node;
typedef struct s_Nodes Nodes; typedef struct s_Nodes Nodes;
typedef struct s_Scopes Scopes;
typedef Node *(*lisp_function_ptr)(Nodes *args); typedef Node *(*LispFunction)(Nodes *args, Scopes *scopes);
typedef struct s_LispFunction {
Nob_String_View name;
lisp_function_ptr apply;
} LispFunction;
typedef struct s_Node { struct s_Node {
NodeKind kind; NodeKind kind;
union { union {
Nob_String_View as_symbol; Nob_String_View as_symbol;
Nodes *as_list; Nodes *as_list;
long long as_number; long long as_number;
LispFunction as_function; struct {
Nob_String_View name;
LispFunction apply;
} as_function;
}; };
} Node; };
struct s_Nodes { struct s_Nodes {
Node *items; Node *items;
@@ -53,14 +53,34 @@ struct s_Nodes {
size_t capacity; size_t capacity;
}; };
typedef struct s_ScopeObject {
Nob_String_View name;
Node node;
} ScopeObject;
// TODO: use hashtable
typedef struct s_Scope {
ScopeObject *items;
size_t count;
size_t capacity;
} Scope;
struct s_Scopes {
Scope *items;
size_t count;
size_t capacity;
};
const char *token_kind_name(TokenKind kind); const char *token_kind_name(TokenKind kind);
void node_print(Node node); void node_print(Node node);
void build_scopes(Scopes *scopes);
void tokenize(Nob_String_View content, Tokens *tokens); void tokenize(Nob_String_View content, Tokens *tokens);
Node *parse(Tokens *tokens); Node *parse(Tokens *tokens);
Node *eval(Node *node); Node *eval(Node *node, Scopes *scopes);
// builtins // builtins
Node *lisp_function_addition(Nodes *args); Node *lisp_function_addition(Nodes *args, Scopes *scopes);
Node *lisp_function_println(Nodes *args, Scopes *scopes);
#endif // LISP_H #endif // LISP_H
+5 -1
View File
@@ -37,11 +37,15 @@ int main(int argc, char **argv) {
} }
#endif #endif
Scopes scopes = {0};
build_scopes(&scopes);
Node *result = parse(&tokens); Node *result = parse(&tokens);
if (result == NULL) if (result == NULL)
return 1; return 1;
result = eval(result); result = eval(result, &scopes);
printf("= ");
node_print(*result); node_print(*result);
printf("\n"); printf("\n");