diff options
Diffstat (limited to 'src/interpreter.c')
-rw-r--r-- | src/interpreter.c | 77 |
1 files changed, 32 insertions, 45 deletions
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: |