summaryrefslogtreecommitdiff
path: root/scope.c
diff options
context:
space:
mode:
Diffstat (limited to 'scope.c')
-rw-r--r--scope.c99
1 files changed, 93 insertions, 6 deletions
diff --git a/scope.c b/scope.c
index 076f1a6..2fe62e1 100644
--- a/scope.c
+++ b/scope.c
@@ -1,9 +1,27 @@
#include "scope.h"
#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#define DEFAULT_SIZE 16
-static void scope_init(struct scope* scope) {}
+static void scope_init(struct scope* scope) {
+ scope->types = calloc(DEFAULT_SIZE, sizeof(struct type_def*));
+ scope->type_cap = DEFAULT_SIZE;
+ scope->vars = calloc(DEFAULT_SIZE, sizeof(struct var_def*));
+ scope->var_cap = DEFAULT_SIZE;
+}
+
+static void scope_destroy(struct scope* scope) {
+ for (unsigned long long i = 0; i < scope->type_cap; i++) {
+ if (scope->types[i] != NULL) free(scope->types[i]);
+ }
+ free(scope->types);
-static void scope_destroy(struct scope* scope) {}
+ for (unsigned long long i = 0; i < scope->var_cap; i++) {
+ if (scope->vars[i] != NULL) free(scope->vars[i]);
+ }
+ free(scope->vars);
+}
unsigned long long hash_name(const char* name) {
unsigned long long hash = 0, i = 0;
@@ -11,6 +29,42 @@ unsigned long long hash_name(const char* name) {
return hash;
}
+static struct type_def** type_cell(
+ const struct scope* scope,
+ const char* name
+) {
+ unsigned long long orig_idx = hash_name(name) % scope->type_cap;
+ unsigned long long idx = orig_idx;
+
+ do {
+ if (scope->types[idx] == NULL
+ || strcmp(name, scope->types[idx]->name) == 0)
+ return &scope->types[idx];
+ } while ((idx = (idx + 1) % scope->type_cap) != orig_idx);
+
+ /* TODO: rehashing :'( */
+ fprintf(stderr, "ccc: would have to rehash and I don't wanna\n");
+ exit(1);
+}
+
+static struct var_def** var_cell(
+ const struct scope* scope,
+ const char* name
+) {
+ unsigned long long orig_idx = hash_name(name) % scope->var_cap;
+ unsigned long long idx = orig_idx;
+
+ do {
+ if (scope->vars[idx] == NULL
+ || strcmp(name, scope->vars[idx]->name) == 0)
+ return &scope->vars[idx];
+ } while ((idx = (idx + 1) % scope->var_cap) != orig_idx);
+
+ /* TODO: rehashing :'( */
+ fprintf(stderr, "ccc: would have to rehash and I don't wanna\n");
+ exit(1);
+}
+
void scope_push(struct scope** p_scope) {
struct scope* inner_scope = calloc(1, sizeof(struct scope));
scope_init(inner_scope);
@@ -29,14 +83,47 @@ bool scope_get_type(
const struct scope* scope,
struct type_def* p_entry,
const char* name
-) {}
+) {
+ struct type_def* type_def = *type_cell(scope, name);
+ if (type_def == NULL) return false;
+ *p_entry = *type_def;
+ return true;
+}
-void scope_define_type(struct scope* scope, struct type_def type) {}
+void scope_define_type(struct scope* scope, struct type_def type) {
+ struct type_def** cell = type_cell(scope, type.name);
+ if (*cell != NULL) {
+ fprintf(stderr, "ccc: error: redefined type %s\n", type.name);
+ exit(1);
+ }
+ *cell = calloc(1, sizeof(struct type_def));
+ if (*cell == NULL) {
+ fprintf(stderr, "ccc: out of memory\n");
+ exit(1);
+ }
+ **cell = type;
+}
bool scope_get_var(
const struct scope* scope,
struct var_def* p_entry,
const char* name
-) {}
+) {
+ struct var_def* var_def = *var_cell(scope, name);
+ if (var_def == NULL) return false;
+ *p_entry = *var_def;
+ return true;
+}
-void scope_define_var(struct scope* scope, struct var_def var) {}
+void scope_define_var(struct scope* scope, struct var_def var) {
+ struct var_def** cell = var_cell(scope, var.name);
+ if (*cell == NULL) {
+ *cell = calloc(1, sizeof(struct var_def));
+ if (*cell == NULL) {
+ fprintf(stderr, "ccc: out of memory\n");
+ exit(1);
+ }
+ }
+ /* technically C allows redefinition :/ */
+ **cell = var;
+}