aboutsummaryrefslogtreecommitdiff
path: root/ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'ast.c')
-rw-r--r--ast.c69
1 files changed, 30 insertions, 39 deletions
diff --git a/ast.c b/ast.c
index 4663cd2..760f259 100644
--- a/ast.c
+++ b/ast.c
@@ -130,15 +130,7 @@ void free_ast(ASTNode *node) {
free(node);
}
-typedef struct Env {
- char *name;
- int val;
- struct Env *next;
-} Env;
-
-static Env *env = NULL;
-
-static int env_lookup(const char *name) {
+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;
@@ -147,8 +139,8 @@ static int env_lookup(const char *name) {
exit(EXIT_FAILURE);
}
-static void env_update(const char *name, int val) {
- for (Env *e = env; e; e = e->next) {
+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;
@@ -157,26 +149,25 @@ static void env_update(const char *name, int val) {
Env *e = malloc(sizeof(Env));
e->name = strdup(name);
e->val = val;
- e->next = env;
- env = e;
+ e->next = *env;
+ *env = e;
}
-void env_print(void) {
- Env *current_env = env;
- while (current_env) {
- printf("%s = %d\n", current_env->name, current_env->val);
- current_env = current_env->next;
+void env_print(Env *env) {
+ Env *e = env;
+ while (e) {
+ printf("%s = %d\n", e->name, e->val);
+ e = e->next;
}
}
-
-static int eval_aexpr(ASTNode *node) {
+static int eval_aexpr(Env **env, ASTNode *node) {
switch (node->type) {
case NT_INT: return node->u.d_int.val;
- case NT_VAR: return env_lookup(node->u.d_var.name);
+ case NT_VAR: return env_lookup(*env, node->u.d_var.name);
case NT_AOP: {
- int aexp1 = eval_aexpr(node->u.d_aop.aexp1);
- int aexp2 = eval_aexpr(node->u.d_aop.aexp2);
+ int aexp1 = eval_aexpr(env, node->u.d_aop.aexp1);
+ int aexp2 = eval_aexpr(env, node->u.d_aop.aexp2);
switch (node->u.d_aop.aop) {
case AOP_ADD: return aexp1 + aexp2;
case AOP_SUB: return aexp1 - aexp2;
@@ -189,21 +180,21 @@ static int eval_aexpr(ASTNode *node) {
}
}
-static int eval_bexpr(ASTNode *node) {
+static int eval_bexpr(Env **env, ASTNode *node) {
switch (node->type) {
case NT_BOP: {
- int bexp1 = eval_bexpr(node->u.d_bop.bexp1);
- int bexp2 = eval_bexpr(node->u.d_bop.bexp2);
+ int bexp1 = eval_bexpr(env, node->u.d_bop.bexp1);
+ int bexp2 = eval_bexpr(env, 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(node->u.d_not.bexp);
+ return !eval_bexpr(env, node->u.d_not.bexp);
case NT_ROP: {
- int aexp1 = eval_aexpr(node->u.d_rop.aexp1);
- int aexp2 = eval_aexpr(node->u.d_rop.aexp2);
+ int aexp1 = eval_aexpr(env, node->u.d_rop.aexp1);
+ int aexp2 = eval_aexpr(env, node->u.d_rop.aexp2);
switch (node->u.d_rop.rop) {
case ROP_EQ: return aexp1 == aexp2;
case ROP_NE: return aexp1 != aexp2;
@@ -219,30 +210,30 @@ static int eval_bexpr(ASTNode *node) {
}
}
-void exec_stmt(ASTNode *node) {
+void exec_stmt(Env **env, 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(node->u.d_assign.aexp);
- env_update(var, val);
+ int val = eval_aexpr(env, node->u.d_assign.aexp);
+ env_update(env, var, val);
return;
}
case NT_SEQ:
- exec_stmt(node->u.d_seq.stm1);
- exec_stmt(node->u.d_seq.stm2);
+ exec_stmt(env, node->u.d_seq.stm1);
+ exec_stmt(env, node->u.d_seq.stm2);
return;
case NT_IF:
- if (eval_bexpr(node->u.d_if.bexp))
- exec_stmt(node->u.d_if.stm1);
+ if (eval_bexpr(env, node->u.d_if.bexp))
+ exec_stmt(env, node->u.d_if.stm1);
else
- exec_stmt(node->u.d_if.stm2);
+ exec_stmt(env, node->u.d_if.stm2);
return;
case NT_WHILE:
- while (eval_bexpr(node->u.d_while.bexp)) {
- exec_stmt(node->u.d_while.stm);
+ while (eval_bexpr(env, node->u.d_while.bexp)) {
+ exec_stmt(env, node->u.d_while.stm);
}
return;
default: