diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | include/ast.h | 4 | ||||
-rw-r--r-- | include/hash_map.h | 3 | ||||
-rw-r--r-- | include/interpreter.h | 12 | ||||
-rw-r--r-- | src/ast.c | 40 | ||||
-rw-r--r-- | src/driver.c | 9 | ||||
-rw-r--r-- | src/hash_map.c | 98 | ||||
-rw-r--r-- | src/interpreter.c | 77 |
8 files changed, 127 insertions, 119 deletions
@@ -1 +1,2 @@ -build
\ No newline at end of file +build +.vscode diff --git a/include/ast.h b/include/ast.h index 9c6b6bd..c619c72 100644 --- a/include/ast.h +++ b/include/ast.h @@ -1,6 +1,7 @@ #ifndef AST_H #define AST_H + typedef enum { NT_SKIP, NT_ASSIGN, NT_SEQ, NT_IF, NT_WHILE, NT_INT, NT_VAR, NT_AOP, NT_BOP, NT_NOT, NT_ROP @@ -26,6 +27,7 @@ typedef struct ASTNode { } u; } ASTNode; + ASTNode *ast_skip(void); ASTNode *ast_assign(ASTNode *var, ASTNode *aexp); ASTNode *ast_seq(ASTNode *stm1, ASTNode *stm2); @@ -38,7 +40,7 @@ ASTNode *ast_bop(BOp bop, ASTNode *bexp1, ASTNode *bexp2); ASTNode *ast_not(ASTNode *bexp); ASTNode *ast_rop(ROp rop, ASTNode *aexp1, ASTNode *aexp2); -void free_ast(ASTNode *node); +void ast_free(ASTNode *node); #endif diff --git a/include/hash_map.h b/include/hash_map.h index ad873f8..6bc733f 100644 --- a/include/hash_map.h +++ b/include/hash_map.h @@ -1,12 +1,13 @@ #ifndef HASH_MAP_H #define HASH_MAP_H -typedef void *hashmap_t; +typedef struct HashMap *hashmap_t; hashmap_t hashmap_create(void); void hashmap_insert(hashmap_t map, const char *key, int value); int *hashmap_get(hashmap_t map, const char *key); void hashmap_delete(hashmap_t map, const char *key); void hashmap_free(hashmap_t map); +void hashmap_iterate(hashmap_t map, void (*callback)(const char *key, int value)); #endif
\ No newline at end of file diff --git a/include/interpreter.h b/include/interpreter.h index 182f2e5..301a3d8 100644 --- a/include/interpreter.h +++ b/include/interpreter.h @@ -1,17 +1,13 @@ #ifndef INTERPRETER_H #define INTERPRETER_H -#include "ast.h" +#include "ast.h" +#include "hash_map.h" -typedef struct Env { - char *name; - int val; - struct Env *next; -} Env; -void exec_stmt(Env **env, ASTNode *node); -void env_print(Env *env); +void exec_stmt(hashmap_t context, ASTNode *node); +void context_print(hashmap_t context); #endif
\ No newline at end of file @@ -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: |