diff options
| author | Tomaki <> | 2026-04-14 23:33:51 +0200 |
|---|---|---|
| committer | Tomaki <> | 2026-04-14 23:33:51 +0200 |
| commit | ab1d01ee72a163d8267315d53b1380119201d6ae (patch) | |
| tree | 4cbc785a079c3b3c757125692b754ce60acccd75 | |
| parent | f81a794db3b0a7249842fbb3acf92fce30161cb1 (diff) | |
| -rw-r--r-- | source/forest.c | 79 |
1 files changed, 74 insertions, 5 deletions
diff --git a/source/forest.c b/source/forest.c index 3e756fb..3b01131 100644 --- a/source/forest.c +++ b/source/forest.c @@ -12,15 +12,15 @@ #include <gmp.h> +#define NOB_IMPLEMENTATION +#include "nob.h" + #define ARENA_IMPLEMENTATION #include "arena.h" #define HT_IMPLEMENTATION #include "ht.h" -#define NOB_IMPLEMENTATION -#include "nob.h" - #if defined(Y) || defined(N) #error "Can only use stb_c_lexer in contexts where the preprocessor symbols 'Y' and 'N' are not defined" #endif @@ -160,10 +160,73 @@ struct Node { }; +typedef Ht(String_View, Node *) Symbol_Table; + +typedef struct Scope Scope; +struct Scope { + Scope *parent; + Symbol_Table symbols; +}; + +static Scope * +scope_new(Arena *arena, Scope *parent); +static void +scope_free(Scope *scope); + +static void +scope_insert(Scope *scope, String_View name, Node *node); +static Node * +scope_lookup(Scope *scope, String_View name); +static Node * +scope_lookup_current(Scope *scope, String_View name); + +static Scope * +scope_new(Arena *arena, Scope *parent) { + // TODO: We can move the allocation and zeroing to a separate function. + Scope *scope = arena_alloc(arena, sizeof(Scope)); + assert(scope != NULL); + memset(scope, 0, sizeof(Scope)); + + scope->parent = parent; + scope->symbols.hasheq = ht_sv_hasheq; + + return scope; +} + +static void +scope_free(Scope *scope) { + // NOTE: Even if the hash table allocates on the heap, that is fine because + // scopes are meant to be freed individually. + ht_free(&scope->symbols); +} + +static void +scope_insert(Scope *scope, String_View name, Node *node) { + *ht_find_or_put(&scope->symbols, name) = node; +} + +static Node * +scope_lookup(Scope *scope, String_View name) { + Node *result = NULL; + while (!result && scope) { + result = scope_lookup_current(scope, name); + scope = scope->parent; + } + return result; +} + +static Node * +scope_lookup_current(Scope *scope, String_View name) { + return *ht_find(&scope->symbols, name); +} + + // TODO: Add diagnostics, symbol table, options, etc. typedef struct Context Context; struct Context { Arena arena; + Scope *global_scope; + Scope *current_scope; }; @@ -236,7 +299,7 @@ parser_parse_expr(Parser *parser) { static Node * parser_parse_list(Parser *parser) { - // TODO: We can move the allocation and zeroing to a separate function that accepts the context. + // TODO: We can move the allocation and zeroing to a separate function. Node *list = arena_alloc(&parser->context->arena, sizeof(Node)); assert(list != NULL); memset(list, 0, sizeof(Node)); @@ -259,7 +322,7 @@ parser_parse_list(Parser *parser) { static Node * parser_parse_atom(Parser *parser) { - // TODO: We can move the allocation and zeroing to a separate function that accepts the context. + // TODO: We can move the allocation and zeroing to a separate function. Node *atom = arena_alloc(&parser->context->arena, sizeof(Node)); assert(atom != NULL); memset(atom, 0, sizeof(Node)); @@ -335,6 +398,10 @@ main(int argc, char **argv) { .arena = {0}, }; + Scope *scope = scope_new(context.arena, NULL); + context.global_scope = scope; + context.current_scope = scope; + Parser parser = { .context = &context, .lexer = {0}, @@ -349,5 +416,7 @@ main(int argc, char **argv) { Node *root = parser_parse(&parser); (void) root; + scope_free(scope); + return 0; } |
