diff options
Diffstat (limited to 'scope.c')
| -rw-r--r-- | scope.c | 148 |
1 files changed, 37 insertions, 111 deletions
@@ -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; |
