#include "scope.h" #include #include #define DEFAULT_SIZE 16 static integral_t hash_name(const char* name, integral_t cap) { integral_t hash = 0, i = 0; while (name[i] != 0) ADVANCE_HASH(hash, name[i++], cap); return hash; } static integral_t hash_type(const struct type_alias* type, integral_t cap) { return hash_name(type->name, cap); } static bool type_eq(const struct type_alias* a, const struct type_alias* b) { return strcmp(a->name, b->name) == 0; } static integral_t hash_var(const struct var_def* var, integral_t cap) { return hash_name(var->name, cap); } static bool var_eq(const struct var_def* a, const struct var_def* b) { return strcmp(a->name, b->name) == 0; } static void var_destroy(struct var_def* var) { free(var->name); } 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); } void scope_destroy(struct scope* scope) { hm_destroy(&scope->types); hm_destroy(&scope->vars); } void scope_push(struct scope** p_scope) { struct scope* inner_scope = ccc_alloc(sizeof(struct scope)); scope_init(inner_scope); inner_scope->next_out = *p_scope; *p_scope = inner_scope; } void scope_pop(struct scope** p_scope) { *p_scope = (*p_scope)->next_out; } bool scope_get_type( const struct scope* scope, const struct type_alias** p_entry, const char* name ) { for (; scope != NULL; scope = scope->next_out) { 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; } return false; } const struct type_alias* scope_define_type( struct scope* scope, struct type_alias type ) { struct type_alias** cell = (struct type_alias**) hm_cell_w(&scope->types, &type); /* redefinition leaks memory, so refuse */ if (*cell != NULL) return NULL; *cell = ccc_alloc(sizeof(struct type_alias)); **cell = type; return *cell; } bool scope_get_var( const struct scope* scope, struct var_def** p_entry, const char* name ) { for (; scope != NULL; scope = scope->next_out) { 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; } return false; } struct var_def* scope_define_var(struct scope* scope, struct var_def var) { struct var_def** cell = (struct var_def**) hm_cell_w(&scope->vars, &var); /* redefinition leaks memory, so refuse */ if (*cell != NULL) return NULL; if (*cell == NULL) *cell = ccc_alloc(sizeof(struct var_def)); **cell = var; return *cell; }