aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFlavian Kaufmann <flavian@flaviankaufmann.ch>2025-05-20 11:31:50 +0200
committerFlavian Kaufmann <flavian@flaviankaufmann.ch>2025-05-20 11:31:50 +0200
commit9cf524df8c94920d7c7058692f2f83a95a4006e0 (patch)
tree526853cc7f935745bf703cbfaf7e5ebe7d32017e /src
parent3829a704150a06b2767d542b39179377a592da0f (diff)
downloadimp-9cf524df8c94920d7c7058692f2f83a95a4006e0.tar.gz
imp-9cf524df8c94920d7c7058692f2f83a95a4006e0.zip
hashmap for context
Diffstat (limited to 'src')
-rw-r--r--src/ast.c40
-rw-r--r--src/driver.c9
-rw-r--r--src/hash_map.c98
-rw-r--r--src/interpreter.c77
4 files changed, 116 insertions, 108 deletions
diff --git a/src/ast.c b/src/ast.c
index acc7c9e..5460c87 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -1,10 +1,13 @@
+#include "ast.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "ast.h"
+#include <assert.h>
+
static ASTNode *new_node(NodeType type) {
ASTNode *node = malloc(sizeof(ASTNode));
+ assert(node);
node->type = type;
return node;
}
@@ -51,6 +54,7 @@ ASTNode *ast_int(int val) {
ASTNode *ast_var(char *name) {
ASTNode *node = new_node(NT_VAR);
node->u.d_var.name = strdup(name);
+ assert(node->u.d_var.name);
return node;
}
@@ -84,27 +88,27 @@ ASTNode *ast_rop(ROp rop, ASTNode *aexp1, ASTNode *aexp2) {
return node;
}
-void free_ast(ASTNode *node) {
+void ast_free(ASTNode *node) {
if (!node) return;
switch (node->type) {
case NT_SKIP:
break;
case NT_ASSIGN:
- free_ast(node->u.d_assign.var);
- free_ast(node->u.d_assign.aexp);
+ ast_free(node->u.d_assign.var);
+ ast_free(node->u.d_assign.aexp);
break;
case NT_SEQ:
- free_ast(node->u.d_seq.stm1);
- free_ast(node->u.d_seq.stm2);
+ ast_free(node->u.d_seq.stm1);
+ ast_free(node->u.d_seq.stm2);
break;
case NT_IF:
- free_ast(node->u.d_if.bexp);
- free_ast(node->u.d_if.stm1);
- free_ast(node->u.d_if.stm2);
+ ast_free(node->u.d_if.bexp);
+ ast_free(node->u.d_if.stm1);
+ ast_free(node->u.d_if.stm2);
break;
case NT_WHILE:
- free_ast(node->u.d_while.bexp);
- free_ast(node->u.d_while.stm);
+ ast_free(node->u.d_while.bexp);
+ ast_free(node->u.d_while.stm);
break;
case NT_INT:
break;
@@ -112,19 +116,19 @@ void free_ast(ASTNode *node) {
free(node->u.d_var.name);
break;
case NT_AOP:
- free_ast(node->u.d_aop.aexp1);
- free_ast(node->u.d_aop.aexp2);
+ ast_free(node->u.d_aop.aexp1);
+ ast_free(node->u.d_aop.aexp2);
break;
case NT_BOP:
- free_ast(node->u.d_bop.bexp1);
- free_ast(node->u.d_bop.bexp2);
+ ast_free(node->u.d_bop.bexp1);
+ ast_free(node->u.d_bop.bexp2);
break;
case NT_ROP:
- free_ast(node->u.d_rop.aexp1);
- free_ast(node->u.d_rop.aexp2);
+ ast_free(node->u.d_rop.aexp1);
+ ast_free(node->u.d_rop.aexp2);
break;
case NT_NOT:
- free_ast(node->u.d_not.bexp);
+ ast_free(node->u.d_not.bexp);
break;
}
free(node);
diff --git a/src/driver.c b/src/driver.c
index 90ee892..597d7a8 100644
--- a/src/driver.c
+++ b/src/driver.c
@@ -22,10 +22,11 @@ int main(int argc, char **argv) {
return EXIT_FAILURE;
}
- Env *env = NULL;
- exec_stmt(&env, ast_root);
- env_print(env);
- free_ast(ast_root);
+ hashmap_t context = hashmap_create();
+ exec_stmt(context, ast_root);
+ context_print(context);
+ hashmap_free(context);
+ ast_free(ast_root);
return EXIT_SUCCESS;
}
diff --git a/src/hash_map.c b/src/hash_map.c
index b9c3b37..5f80205 100644
--- a/src/hash_map.c
+++ b/src/hash_map.c
@@ -1,8 +1,8 @@
+#include "hash_map.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
-#include "hash_map.h"
#define INITIAL_SIZE (16)
#define LOAD_FACTOR_THRESHOLD (0.75)
@@ -21,26 +21,16 @@ typedef struct HashMap {
static unsigned int hash(const char *key, size_t size) {
unsigned int hash_value = 0;
- while (*key)hash_value = (hash_value * 31) + *key++;
+ while (*key) hash_value = (hash_value * 31) + *key++;
return hash_value % size;
}
-hashmap_t hashmap_create(void) {
- HashMap *map = (HashMap *)malloc(sizeof(HashMap));
- assert(map);
- map->size = INITIAL_SIZE;
- map->count = 0;
- map->table = (Pair **)calloc(map->size, sizeof(Pair *));
- assert(map->table);
- return map;
-}
-
-static void resize(hashmap_t map) {
- size_t new_size = ((HashMap*)map)->size * 2;
- Pair **new_table = (Pair **)calloc(new_size, sizeof(Pair *));
+static void resize(HashMap *map) {
+ size_t new_size = map->size * 2;
+ Pair **new_table = (Pair**)calloc(new_size, sizeof(Pair*));
assert(new_table);
- for (size_t i = 0; i < ((HashMap*)map)->size; ++i) {
- Pair *pair = ((HashMap*)map)->table[i];
+ for (size_t i = 0; i < map->size; ++i) {
+ Pair *pair = map->table[i];
while (pair) {
unsigned int index = hash(pair->key, new_size);
Pair *next = pair->next;
@@ -49,27 +39,43 @@ static void resize(hashmap_t map) {
pair = next;
}
}
- free(((HashMap*)map)->table);
- ((HashMap*)map)->table = new_table;
- ((HashMap*)map)->size = new_size;
+
+ free(map->table);
+ map->table = new_table;
+ map->size = new_size;
+}
+
+HashMap *hashmap_create(void) {
+ HashMap *map = (HashMap*)malloc(sizeof(HashMap));
+ assert(map);
+ map->size = INITIAL_SIZE;
+ map->count = 0;
+ map->table = (Pair**)calloc(map->size, sizeof(Pair*));
+ assert(map->table);
+ return map;
}
-void hashmap_insert(hashmap_t map, const char *key, int value) {
- if ((float)((HashMap*)map)->count / ((HashMap*)map)->size > LOAD_FACTOR_THRESHOLD) resize(((HashMap*)map));
- unsigned int index = hash(key, ((HashMap*)map)->size);
- Pair *new_pair = (Pair *)malloc(sizeof(Pair));
+void hashmap_insert(HashMap *map, const char *key, int value) {
+ int *old_value = hashmap_get(map, key);
+ if (old_value) {
+ *old_value = value;
+ return;
+ }
+ if ((float)map->count / map->size > LOAD_FACTOR_THRESHOLD) resize(map);
+ unsigned int index = hash(key, map->size);
+ Pair *new_pair = (Pair*)malloc(sizeof(Pair));
assert(new_pair);
new_pair->key = strdup(key);
assert(new_pair->key);
new_pair->value = value;
- new_pair->next = ((HashMap*)map)->table[index];
- ((HashMap*)map)->table[index] = new_pair;
- ((HashMap*)map)->count++;
+ new_pair->next = map->table[index];
+ map->table[index] = new_pair;
+ map->count++;
}
-int *hashmap_get(hashmap_t map, const char *key) {
- unsigned int index = hash(key, ((HashMap*)map)->size);
- Pair *pair = ((HashMap*)map)->table[index];
+int *hashmap_get(HashMap *map, const char *key) {
+ unsigned int index = hash(key, map->size);
+ Pair *pair = map->table[index];
while (pair) {
if (strcmp(pair->key, key) == 0) return &pair->value;
pair = pair->next;
@@ -77,17 +83,17 @@ int *hashmap_get(hashmap_t map, const char *key) {
return NULL;
}
-void hashmap_delete(hashmap_t map, const char *key) {
- unsigned int index = hash(key, ((HashMap*)map)->size);
- Pair *pair = ((HashMap*)map)->table[index];
+void hashmap_delete(HashMap *map, const char *key) {
+ unsigned int index = hash(key, map->size);
+ Pair *pair = map->table[index];
Pair *prev = NULL;
while (pair) {
if (strcmp(pair->key, key) == 0) {
if (prev) prev->next = pair->next;
- else ((HashMap*)map)->table[index] = pair->next;
+ else map->table[index] = pair->next;
free(pair->key);
free(pair);
- ((HashMap*)map)->count--;
+ map->count--;
return;
}
prev = pair;
@@ -95,16 +101,26 @@ void hashmap_delete(hashmap_t map, const char *key) {
}
}
-void hashmap_free(hashmap_t map) {
- for (size_t i = 0; i < ((HashMap*)map)->size; ++i) {
- Pair *pair = ((HashMap*)map)->table[i];
- while (pair){
+void hashmap_free(HashMap *map) {
+ for (size_t i = 0; i < map->size; ++i) {
+ Pair *pair = map->table[i];
+ while (pair) {
Pair *temp = pair;
pair = pair->next;
free(temp->key);
free(temp);
}
}
- free(((HashMap*)map)->table);
- free(((HashMap*)map));
+ free(map->table);
+ free(map);
+}
+
+void hashmap_iterate(HashMap *map, void (*callback)(const char *key, int 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;
+ }
+ }
} \ No newline at end of file
diff --git a/src/interpreter.c b/src/interpreter.c
index 4d1f8f9..93b1bdb 100644
--- a/src/interpreter.c
+++ b/src/interpreter.c
@@ -3,44 +3,31 @@
#include <stdio.h>
#include <string.h>
-static void env_update(Env **env, const char *name, int val) {
- for (Env *e = *env; e; e = e->next) {
- if (strcmp(e->name, name) == 0) {
- e->val = val;
- return;
- }
- }
- Env *e = malloc(sizeof(Env));
- e->name = strdup(name);
- e->val = val;
- e->next = *env;
- *env = e;
+static void context_set(hashmap_t context, const char *name, int val) {
+ hashmap_insert(context, name, val);
}
-static int env_lookup(Env **env, const char *name) {
- for (Env *e = *env; e; e = e->next) {
- if (strcmp(e->name, name) == 0)
- return e->val;
- }
- env_update(env, name, 0);
- return env_lookup(env, name);
+static int context_get(hashmap_t context, const char *name) {
+ int *val = hashmap_get(context, name);
+ if (val) return *val;
+ return 0;
}
-void env_print(Env *env) {
- Env *e = env;
- while (e) {
- printf("%s = %d\n", e->name, e->val);
- e = e->next;
- }
+static void print_var(const char *name, int val) {
+ printf("%s = %d\n", name, val);
+}
+
+void context_print(hashmap_t context) {
+ hashmap_iterate(context, print_var);
}
-static int eval_aexpr(Env **env, ASTNode *node) {
+static int eval_aexpr(hashmap_t context, ASTNode *node) {
switch (node->type) {
case NT_INT: return node->u.d_int.val;
- case NT_VAR: return env_lookup(env, node->u.d_var.name);
+ case NT_VAR: return context_get(context, node->u.d_var.name);
case NT_AOP: {
- int aexp1 = eval_aexpr(env, node->u.d_aop.aexp1);
- int aexp2 = eval_aexpr(env, node->u.d_aop.aexp2);
+ int aexp1 = eval_aexpr(context, node->u.d_aop.aexp1);
+ int aexp2 = eval_aexpr(context, node->u.d_aop.aexp2);
switch (node->u.d_aop.aop) {
case AOP_ADD: return aexp1 + aexp2;
case AOP_SUB: return aexp1 - aexp2;
@@ -53,21 +40,21 @@ static int eval_aexpr(Env **env, ASTNode *node) {
}
}
-static int eval_bexpr(Env **env, ASTNode *node) {
+static int eval_bexpr(hashmap_t context, ASTNode *node) {
switch (node->type) {
case NT_BOP: {
- int bexp1 = eval_bexpr(env, node->u.d_bop.bexp1);
- int bexp2 = eval_bexpr(env, node->u.d_bop.bexp2);
+ int bexp1 = eval_bexpr(context, node->u.d_bop.bexp1);
+ int bexp2 = eval_bexpr(context, node->u.d_bop.bexp2);
switch (node->u.d_bop.bop) {
case BOP_AND: return bexp1 && bexp2;
case BOP_OR: return bexp1 || bexp2;
}
}
case NT_NOT:
- return !eval_bexpr(env, node->u.d_not.bexp);
+ return !eval_bexpr(context, node->u.d_not.bexp);
case NT_ROP: {
- int aexp1 = eval_aexpr(env, node->u.d_rop.aexp1);
- int aexp2 = eval_aexpr(env, node->u.d_rop.aexp2);
+ int aexp1 = eval_aexpr(context, node->u.d_rop.aexp1);
+ int aexp2 = eval_aexpr(context, node->u.d_rop.aexp2);
switch (node->u.d_rop.rop) {
case ROP_EQ: return aexp1 == aexp2;
case ROP_NE: return aexp1 != aexp2;
@@ -83,30 +70,30 @@ static int eval_bexpr(Env **env, ASTNode *node) {
}
}
-void exec_stmt(Env **env, ASTNode *node) {
+void exec_stmt(hashmap_t context, ASTNode *node) {
while (node) {
switch (node->type) {
case NT_SKIP:
return;
case NT_ASSIGN: {
char *var = node->u.d_assign.var->u.d_var.name;
- int val = eval_aexpr(env, node->u.d_assign.aexp);
- env_update(env, var, val);
+ int val = eval_aexpr(context, node->u.d_assign.aexp);
+ context_set(context, var, val);
return;
}
case NT_SEQ:
- exec_stmt(env, node->u.d_seq.stm1);
- exec_stmt(env, node->u.d_seq.stm2);
+ exec_stmt(context, node->u.d_seq.stm1);
+ exec_stmt(context, node->u.d_seq.stm2);
return;
case NT_IF:
- if (eval_bexpr(env, node->u.d_if.bexp))
- exec_stmt(env, node->u.d_if.stm1);
+ if (eval_bexpr(context, node->u.d_if.bexp))
+ exec_stmt(context, node->u.d_if.stm1);
else
- exec_stmt(env, node->u.d_if.stm2);
+ exec_stmt(context, node->u.d_if.stm2);
return;
case NT_WHILE:
- while (eval_bexpr(env, node->u.d_while.bexp)) {
- exec_stmt(env, node->u.d_while.stm);
+ while (eval_bexpr(context, node->u.d_while.bexp)) {
+ exec_stmt(context, node->u.d_while.stm);
}
return;
default: