From b8006ecd24830c849a989554b059bc452371e5b2 Mon Sep 17 00:00:00 2001 From: Flavian Kaufmann Date: Thu, 22 May 2025 07:00:20 +0200 Subject: hashmap iter inplace --- include/hashmap.h | 11 +++++----- src/hashmap.c | 65 ++++++++++++++++++++++++------------------------------- src/interpreter.c | 52 ++++++++++++++++++++++++-------------------- 3 files changed, 61 insertions(+), 67 deletions(-) diff --git a/include/hashmap.h b/include/hashmap.h index c62a319..5273497 100644 --- a/include/hashmap.h +++ b/include/hashmap.h @@ -3,7 +3,8 @@ typedef struct HashMap *hashmap_t; -typedef struct HashMapKeys *hashmap_keys_t; + +typedef struct HashMapKeysIter *hashmap_keys_iter_t; hashmap_t hashmap_create(void); @@ -13,11 +14,9 @@ void **hashmap_get(hashmap_t map, const char *key); void hashmap_insert(hashmap_t map, const char *key, void *value); int hashmap_delete(hashmap_t map, const char *key); -void hashmap_iterate(hashmap_t map, void (*callback)(const char *key, void *value)); -hashmap_keys_t hashmap_keys_create(hashmap_t map); -const char *hashmap_keys_next(hashmap_keys_t iter); -void hashmap_keys_free(hashmap_keys_t iter); - +hashmap_keys_iter_t hashmap_keys_iter_create(hashmap_t map); +const char *hashmap_keys_iter_next(hashmap_keys_iter_t iter); +void hashmap_keys_iter_free(hashmap_keys_iter_t iter); #endif \ No newline at end of file diff --git a/src/hashmap.c b/src/hashmap.c index a712134..bf214d8 100644 --- a/src/hashmap.c +++ b/src/hashmap.c @@ -21,11 +21,11 @@ typedef struct HashMap { size_t count; } HashMap; -typedef struct HashMapKeys { - char **keys; - size_t count; - size_t index; -} HashMapKeys; +typedef struct HashMapKeysIter { + HashMap *map; + size_t bucket_index; + Pair *current; +} HashMapKeysIter; static unsigned int hash(const char *key, size_t size) { @@ -125,45 +125,36 @@ void hashmap_free(HashMap *map) { free(map); } -void hashmap_iterate(HashMap *map, void (*callback)(const char *key, void *value)) { - for (size_t i = 0; i < map->size; ++i) { - Pair *pair = map->table[i]; - while (pair) { - callback(pair->key, pair->value); - pair = pair->next; - } - } -} - -HashMapKeys *hashmap_keys_create(HashMap *map) { - HashMapKeys *iter = malloc(sizeof(HashMapKeys)); +HashMapKeysIter *hashmap_keys_iter_create(HashMap *map) { + HashMapKeysIter *iter = (HashMapKeysIter*)malloc(sizeof(HashMapKeysIter)); assert(iter); - iter->keys = malloc(map->count * sizeof(char*)); - assert(iter->keys); - iter->count = 0; - iter->index = 0; - for (size_t i = 0; i < map->size; ++i) { - Pair *pair = map->table[i]; - while (pair) { - iter->keys[iter->count++] = strdup(pair->key); - pair = pair->next; - } + iter->map = map; + iter->bucket_index = 0; + iter->current = NULL; + while (iter->bucket_index < map->size && map->table[iter->bucket_index] == NULL) { + iter->bucket_index++; + } + if (iter->bucket_index < map->size) { + iter->current = map->table[iter->bucket_index]; } return iter; } -const char *hashmap_keys_next(HashMapKeys *iter) { - if (iter->index < iter->count) { - return iter->keys[iter->index++]; +const char *hashmap_keys_iter_next(HashMapKeysIter *iter) { + if (!iter->current) return NULL; + const char *key = iter->current->key; + if (iter->current->next) { + iter->current = iter->current->next; + } else { + iter->bucket_index++; + while (iter->bucket_index < iter->map->size && iter->map->table[iter->bucket_index] == NULL) { + iter->bucket_index++; + } + iter->current = (iter->bucket_index < iter->map->size) ? iter->map->table[iter->bucket_index] : NULL; } - return NULL; + return key; } -void hashmap_keys_free(HashMapKeys *iter) { - if (!iter) return; - for (size_t i = 0; i < iter->count; ++i) { - free(iter->keys[i]); - } - free(iter->keys); +void hashmap_keys_iter_free(HashMapKeysIter *iter) { free(iter); } \ No newline at end of file diff --git a/src/interpreter.c b/src/interpreter.c index af487c6..bf147df 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -20,6 +20,15 @@ typedef struct Context{ hashmap_t proc_table; } Context; +static ASTNode *context_get_proc(Context *context, const char *name) { + ASTNode **procdecl = (ASTNode**)hashmap_get(context->proc_table, name); + if (procdecl) return *procdecl; + return NULL; +} + +static void context_set_proc(Context *context, const char *name, ASTNode *procdecl) { + hashmap_insert(context->proc_table, name, (void*)procdecl); +} Context *context_create(void) { Context *context = malloc(sizeof(Context)); @@ -29,13 +38,16 @@ Context *context_create(void) { return context; } -static void free_procdecl(const char *name, void *procdecl) { - ast_free((ASTNode*)procdecl); -} - void context_free(Context *context) { hashmap_free(context->var_table); - hashmap_iterate(context->proc_table, free_procdecl); + hashmap_keys_iter_t iter = hashmap_keys_iter_create(context->proc_table); + const char *key; + while ((key = hashmap_keys_iter_next(iter)) != NULL) { + ASTNode *procdecl = context_get_proc(context, key); + assert(procdecl); + ast_free(procdecl); + } + hashmap_keys_iter_free(iter); hashmap_free(context->proc_table); free(context); } @@ -50,22 +62,14 @@ void context_set_var(Context *context, const char *name, int val) { hashmap_insert(context->var_table, name, (void*)val); } -static void print_var(const char *name, void *val) { - printf("%s = %d\n", name, (int)val); -} - void context_print_var_table(Context *context) { - hashmap_iterate(context->var_table, print_var); -} - -static ASTNode *context_get_proc(Context *context, const char *name) { - ASTNode **procdecl = (ASTNode**)hashmap_get(context->proc_table, name); - if (procdecl) return *procdecl; - return NULL; -} - -static void context_set_proc(Context *context, const char *name, ASTNode *procdecl) { - hashmap_insert(context->proc_table, name, (void*)procdecl); + hashmap_keys_iter_t iter = hashmap_keys_iter_create(context->var_table); + const char *key; + while ((key = hashmap_keys_iter_next(iter)) != NULL) { + int val = context_get_var(context, key); + printf("%s = %d\n", key, val); + } + hashmap_keys_iter_free(iter); } static int eval_aexpr(Context *context, ASTNode *node) { @@ -159,14 +163,14 @@ void interp_ast(Context *context, ASTNode *node) { ASTNodeList *caller_args = node->u.d_proccall.args; ASTNodeList *callee_args = procdecl->u.d_procdecl.args; Context *proc_context = context_create(); - hashmap_keys_t keys = hashmap_keys_create(context->proc_table); + hashmap_keys_iter_t iter = hashmap_keys_iter_create(context->proc_table); const char *key; - while ((key = hashmap_keys_next(keys)) != NULL) { + while ((key = hashmap_keys_iter_next(iter)) != NULL) { ASTNode *proc = context_get_proc(context, key); assert(proc); context_set_proc(proc_context, key, ast_clone(proc)); } - hashmap_keys_free(keys); + hashmap_keys_iter_free(iter); while (caller_args && callee_args) { char *caller_arg_name = caller_args->node->u.d_var.name; char *callee_arg_name = callee_args->node->u.d_var.name; @@ -217,4 +221,4 @@ int interp_str (Context *context, const char *str) { } yy_delete_buffer(buf); return 0; -} +} \ No newline at end of file -- cgit v1.2.3