summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/forest.c79
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;
}