summaryrefslogtreecommitdiff
path: root/scope.c
diff options
context:
space:
mode:
Diffstat (limited to 'scope.c')
-rw-r--r--scope.c148
1 files changed, 37 insertions, 111 deletions
diff --git a/scope.c b/scope.c
index 7077748..f47545e 100644
--- a/scope.c
+++ b/scope.c
@@ -1,121 +1,50 @@
#include "scope.h"
#include <stdlib.h>
-#include <stdio.h>
#include <string.h>
#define DEFAULT_SIZE 16
-static void scope_init(struct scope* scope) {
- scope->types = ccc_alloc(DEFAULT_SIZE * sizeof(struct type_def*));
- scope->type_cap = DEFAULT_SIZE;
- scope->vars = ccc_alloc(DEFAULT_SIZE * sizeof(struct var_def*));
- scope->var_cap = DEFAULT_SIZE;
-}
-
-static void var_destroy(struct var_def* var) {
- free(var->name);
-}
-
-void scope_destroy(struct scope* scope) {
- for (integral_t i = 0; i < scope->type_cap; i++) {
- if (scope->types[i] != NULL) {
- free(scope->types[i]);
- }
- }
- free(scope->types);
-
- for (integral_t i = 0; i < scope->var_cap; i++) {
- if (scope->vars[i] != NULL) {
- var_destroy(scope->vars[i]);
- free(scope->vars[i]);
- }
- }
- free(scope->vars);
-}
-
-static inline integral_t advance_hash(
- integral_t hash,
- integral_t val,
- integral_t cap
-) {
- return ((hash << 5) - hash + val) % cap;;
-}
-
static integral_t hash_name(const char* name, integral_t cap) {
integral_t hash = 0, i = 0;
- while (name[i] != 0) hash = advance_hash(hash, name[i++], cap);
+ while (name[i] != 0) ADVANCE_HASH(hash, name[i++], cap);
return hash;
}
-static struct type_alias** type_cell(
- const struct scope* scope,
- const char* name
-) {
- integral_t orig_idx = hash_name(name, scope->type_cap);
- integral_t 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);
- return NULL;
+static integral_t hash_type(const struct type_alias* type, integral_t cap) {
+ return hash_name(type->name, cap);
}
-static void rehash_types(struct scope* scope) {
- struct type_alias** old_types = scope->types;
- integral_t old_cap = scope->type_cap;
-
- scope->type_cap = (scope->type_cap + 1) << 1;
- scope->types = ccc_alloc(scope->type_cap * sizeof(struct type_def*));
-
- for (integral_t i = 0; i < old_cap; i++) {
- if (old_types[i] == NULL) continue;
-
- struct type_alias** cell = type_cell(scope, old_types[i]->name);
- if (cell == NULL) {
- fprintf(stderr, "ccc: types rehash failed, likely a bug\n");
- exit(1);
- }
- *cell = old_types[i];
- }
-
- free(old_types);
+static bool type_eq(const struct type_alias* a, const struct type_alias* b) {
+ return strcmp(a->name, b->name) == 0;
}
-static struct var_def** var_cell(
- const struct scope* scope,
- const char* name
-) {
- integral_t orig_idx = hash_name(name, scope->var_cap);
- integral_t 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);
- return NULL;
+static integral_t hash_var(const struct var_def* var, integral_t cap) {
+ return hash_name(var->name, cap);
}
-static void rehash_vars(struct scope* scope) {
- struct var_def** old_vars = scope->vars;
- integral_t old_cap = scope->var_cap;
-
- scope->var_cap = (scope->var_cap + 1) << 1;
- scope->vars = ccc_alloc(scope->var_cap * sizeof(struct var_def*));
+static bool var_eq(const struct var_def* a, const struct var_def* b) {
+ return strcmp(a->name, b->name) == 0;
+}
- for (integral_t i = 0; i < old_cap; i++) {
- if (old_vars[i] == NULL) continue;
+static void var_destroy(struct var_def* var) {
+ free(var->name);
+}
- struct var_def** cell = var_cell(scope, old_vars[i]->name);
- if (cell == NULL) {
- fprintf(stderr, "ccc: vars rehash failed, likely a bug\n");
- exit(1);
- }
- *cell = old_vars[i];
- }
+static void scope_init(struct scope* scope) {
+ hm_init(
+ &scope->types,
+ (hm_hash_fn) hash_type,
+ (hm_eq_fn) type_eq,
+ NULL);
+ hm_init(
+ &scope->vars,
+ (hm_hash_fn) hash_var,
+ (hm_eq_fn) var_eq,
+ (hm_destroy_fn) var_destroy);
+}
- free(old_vars);
+void scope_destroy(struct scope* scope) {
+ hm_destroy(&scope->types);
+ hm_destroy(&scope->vars);
}
void scope_push(struct scope** p_scope) {
@@ -135,7 +64,9 @@ bool scope_get_type(
const char* name
) {
for (; scope != NULL; scope = scope->next_out) {
- struct type_alias** cell = type_cell(scope, name);
+ const struct type_alias** cell = (const struct type_alias**) hm_cell_r(
+ &scope->types,
+ &(struct type_alias) { .name = name });
if (cell == NULL || *cell == NULL) continue;
if (p_entry != NULL) *p_entry = *cell;
return true;
@@ -147,11 +78,8 @@ const struct type_alias* scope_define_type(
struct scope* scope,
struct type_alias type
) {
- struct type_alias** cell = type_cell(scope, type.name);
- while (cell == NULL) {
- rehash_types(scope);
- cell = type_cell(scope, type.name);
- }
+ struct type_alias** cell =
+ (struct type_alias**) hm_cell_w(&scope->types, &type);
/* redefinition leaks memory, so refuse */
if (*cell != NULL) return NULL;
@@ -167,7 +95,9 @@ bool scope_get_var(
const char* name
) {
for (; scope != NULL; scope = scope->next_out) {
- struct var_def** cell = var_cell(scope, name);
+ struct var_def** cell = (struct var_def**) hm_cell_r(
+ &scope->vars,
+ &(struct var_def) {.name = (char*) name});
if (cell == NULL || *cell == NULL) continue;
if (p_entry != NULL) *p_entry = *cell;
return true;
@@ -176,11 +106,7 @@ bool scope_get_var(
}
struct var_def* scope_define_var(struct scope* scope, struct var_def var) {
- struct var_def** cell = var_cell(scope, var.name);
- while (cell == NULL) {
- rehash_vars(scope);
- cell = var_cell(scope, var.name);
- }
+ struct var_def** cell = (struct var_def**) hm_cell_w(&scope->vars, &var);
/* redefinition leaks memory, so refuse */
if (*cell != NULL) return NULL;