rename env to scope, and free pointers before they leak
This commit is contained in:
parent
2f32c928d6
commit
f36482afc7
1 changed files with 35 additions and 28 deletions
|
|
@ -17,7 +17,7 @@ struct Cell {
|
|||
|
||||
typedef struct {
|
||||
struct Cell* next;
|
||||
} Environment;
|
||||
} Scope;
|
||||
|
||||
Memory new_memory() {
|
||||
unsigned size = 1024;
|
||||
|
|
@ -33,12 +33,12 @@ Memory new_memory() {
|
|||
};
|
||||
}
|
||||
|
||||
Environment new_environment() {
|
||||
return (Environment) { .next = NULL };
|
||||
Scope new_scope() {
|
||||
return (Scope) { .next = NULL };
|
||||
}
|
||||
|
||||
int lookup_env(char* name, Environment env) {
|
||||
struct Cell* cell = env.next;
|
||||
int lookup_scope(char* name, Scope scope) {
|
||||
struct Cell* cell = scope.next;
|
||||
while (cell != NULL) {
|
||||
if (strcmp(cell->name, name) == 0) {
|
||||
return cell->index;
|
||||
|
|
@ -49,18 +49,18 @@ int lookup_env(char* name, Environment env) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
Environment insert(char* name, int n, Memory memory, Environment env) {
|
||||
Scope insert(char* name, int n, Memory memory, Scope scope) {
|
||||
if (*memory.i + 1 < memory.memory.length) {
|
||||
((int*)(memory.memory.elements))[*memory.i] = n;
|
||||
struct Cell* cell = (struct Cell*)malloc(sizeof(struct Cell));
|
||||
*cell = (struct Cell) {
|
||||
.name = name,
|
||||
.index = *memory.i,
|
||||
.next = env.next,
|
||||
.next = scope.next,
|
||||
};
|
||||
++*memory.i;
|
||||
Environment new_env = (Environment) {.next = cell};
|
||||
return new_env;
|
||||
Scope new_scope = (Scope) {.next = cell};
|
||||
return new_scope;
|
||||
}
|
||||
fprintf(stderr, "Error: out of memory.");
|
||||
exit(1);
|
||||
|
|
@ -73,8 +73,8 @@ int* lookup_mem(int index, Memory mem) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int* lookup(char* name, Memory memory, Environment env) {
|
||||
int index = lookup_env(name, env);
|
||||
int* lookup(char* name, Memory memory, Scope scope) {
|
||||
int index = lookup_scope(name, scope);
|
||||
if (index >= 0) {
|
||||
int* result = lookup_mem(index, memory);
|
||||
if (result != NULL) {
|
||||
|
|
@ -84,14 +84,14 @@ int* lookup(char* name, Memory memory, Environment env) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int eval_expr(Expr expr, Memory memory, Environment env) {
|
||||
int eval_expr(Expr expr, Memory memory, Scope scope) {
|
||||
switch (expr.tag) {
|
||||
default:
|
||||
case LITERAL: {
|
||||
return expr.data.integer;
|
||||
}
|
||||
case VARIABLE: {
|
||||
int* result = lookup(expr.data.variable, memory, env);
|
||||
int* result = lookup(expr.data.variable, memory, scope);
|
||||
if (result == NULL) {
|
||||
fprintf(stderr, "Error: variable not found '%s'\n", expr.data.variable);
|
||||
exit(1);
|
||||
|
|
@ -102,7 +102,7 @@ int eval_expr(Expr expr, Memory memory, Environment env) {
|
|||
case FUNCTION: {
|
||||
if (strcmp(expr.data.function.name, "print") == 0) {
|
||||
if (expr.data.function.args.length == 1) {
|
||||
int arg = eval_expr(((Expr*)expr.data.function.args.elements)[0], memory, env);
|
||||
int arg = eval_expr(((Expr*)expr.data.function.args.elements)[0], memory, scope);
|
||||
printf("%d\n", arg);
|
||||
return 0;
|
||||
} else {
|
||||
|
|
@ -112,8 +112,8 @@ int eval_expr(Expr expr, Memory memory, Environment env) {
|
|||
}
|
||||
else if (strcmp(expr.data.function.name, "add") == 0) {
|
||||
if (expr.data.function.args.length == 2) {
|
||||
int arg1 = eval_expr(((Expr*)expr.data.function.args.elements)[0], memory, env);
|
||||
int arg2 = eval_expr(((Expr*)expr.data.function.args.elements)[1], memory, env);
|
||||
int arg1 = eval_expr(((Expr*)expr.data.function.args.elements)[0], memory, scope);
|
||||
int arg2 = eval_expr(((Expr*)expr.data.function.args.elements)[1], memory, scope);
|
||||
return arg1 + arg2;
|
||||
} else {
|
||||
fprintf(stderr, "Error: negate expects a single argument.\n");
|
||||
|
|
@ -122,7 +122,7 @@ int eval_expr(Expr expr, Memory memory, Environment env) {
|
|||
}
|
||||
else if (strcmp(expr.data.function.name, "negate") == 0) {
|
||||
if (expr.data.function.args.length == 1) {
|
||||
int arg = eval_expr(((Expr*)expr.data.function.args.elements)[0], memory, env);
|
||||
int arg = eval_expr(((Expr*)expr.data.function.args.elements)[0], memory, scope);
|
||||
return 0 - arg;
|
||||
} else {
|
||||
fprintf(stderr, "Error: negate expects a single argument.\n");
|
||||
|
|
@ -134,40 +134,47 @@ int eval_expr(Expr expr, Memory memory, Environment env) {
|
|||
}
|
||||
}
|
||||
|
||||
Environment interpret_stmt(Stmt stmt, Memory memory, Environment env) {
|
||||
Scope interpret_stmt(Stmt stmt, Memory memory, Scope scope) {
|
||||
switch (stmt.tag) {
|
||||
case SET: {
|
||||
int result = eval_expr(stmt.data.Set.expr, memory, env);
|
||||
int* index = lookup(stmt.data.Set.name, memory, env);
|
||||
int result = eval_expr(stmt.data.Set.expr, memory, scope);
|
||||
int* index = lookup(stmt.data.Set.name, memory, scope);
|
||||
if (index != NULL) {
|
||||
*index = result;
|
||||
} else {
|
||||
return insert(stmt.data.Set.name, result, memory, env);
|
||||
return insert(stmt.data.Set.name, result, memory, scope);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WHILE: {
|
||||
while (eval_expr(stmt.data.While.condition, memory, env)) {
|
||||
Environment new_env = env;
|
||||
while (eval_expr(stmt.data.While.condition, memory, scope)) {
|
||||
Scope new_scope = scope;
|
||||
for (unsigned i = 0; i < stmt.data.While.block.length; ++i) {
|
||||
Stmt current = ((Stmt*)stmt.data.While.block.elements)[i];
|
||||
new_env = interpret_stmt(current, memory, new_env);
|
||||
new_scope = interpret_stmt(current, memory, new_scope);
|
||||
}
|
||||
// free pointers before they leak
|
||||
struct Cell* next = new_scope.next;
|
||||
while (next != NULL && next != scope.next) {
|
||||
struct Cell* nextnext = next->next;
|
||||
free(next);
|
||||
next = nextnext;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EXPR:
|
||||
eval_expr(stmt.data.Expr.expr, memory, env);
|
||||
eval_expr(stmt.data.Expr.expr, memory, scope);
|
||||
break;
|
||||
}
|
||||
return env;
|
||||
return scope;
|
||||
}
|
||||
|
||||
void execute(StmtArray stmts) {
|
||||
Memory memory = new_memory();
|
||||
Environment environment = new_environment();
|
||||
Scope scope = new_scope();
|
||||
for (unsigned pc = 0; pc < stmts.length; ++pc) {
|
||||
Stmt stmt = stmts.stmts[pc];
|
||||
environment = interpret_stmt(stmt, memory, environment);
|
||||
scope = interpret_stmt(stmt, memory, scope);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue