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 {
|
typedef struct {
|
||||||
struct Cell* next;
|
struct Cell* next;
|
||||||
} Environment;
|
} Scope;
|
||||||
|
|
||||||
Memory new_memory() {
|
Memory new_memory() {
|
||||||
unsigned size = 1024;
|
unsigned size = 1024;
|
||||||
|
|
@ -33,12 +33,12 @@ Memory new_memory() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Environment new_environment() {
|
Scope new_scope() {
|
||||||
return (Environment) { .next = NULL };
|
return (Scope) { .next = NULL };
|
||||||
}
|
}
|
||||||
|
|
||||||
int lookup_env(char* name, Environment env) {
|
int lookup_scope(char* name, Scope scope) {
|
||||||
struct Cell* cell = env.next;
|
struct Cell* cell = scope.next;
|
||||||
while (cell != NULL) {
|
while (cell != NULL) {
|
||||||
if (strcmp(cell->name, name) == 0) {
|
if (strcmp(cell->name, name) == 0) {
|
||||||
return cell->index;
|
return cell->index;
|
||||||
|
|
@ -49,18 +49,18 @@ int lookup_env(char* name, Environment env) {
|
||||||
return -1;
|
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) {
|
if (*memory.i + 1 < memory.memory.length) {
|
||||||
((int*)(memory.memory.elements))[*memory.i] = n;
|
((int*)(memory.memory.elements))[*memory.i] = n;
|
||||||
struct Cell* cell = (struct Cell*)malloc(sizeof(struct Cell));
|
struct Cell* cell = (struct Cell*)malloc(sizeof(struct Cell));
|
||||||
*cell = (struct Cell) {
|
*cell = (struct Cell) {
|
||||||
.name = name,
|
.name = name,
|
||||||
.index = *memory.i,
|
.index = *memory.i,
|
||||||
.next = env.next,
|
.next = scope.next,
|
||||||
};
|
};
|
||||||
++*memory.i;
|
++*memory.i;
|
||||||
Environment new_env = (Environment) {.next = cell};
|
Scope new_scope = (Scope) {.next = cell};
|
||||||
return new_env;
|
return new_scope;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "Error: out of memory.");
|
fprintf(stderr, "Error: out of memory.");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
@ -73,8 +73,8 @@ int* lookup_mem(int index, Memory mem) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int* lookup(char* name, Memory memory, Environment env) {
|
int* lookup(char* name, Memory memory, Scope scope) {
|
||||||
int index = lookup_env(name, env);
|
int index = lookup_scope(name, scope);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
int* result = lookup_mem(index, memory);
|
int* result = lookup_mem(index, memory);
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
|
|
@ -84,14 +84,14 @@ int* lookup(char* name, Memory memory, Environment env) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int eval_expr(Expr expr, Memory memory, Environment env) {
|
int eval_expr(Expr expr, Memory memory, Scope scope) {
|
||||||
switch (expr.tag) {
|
switch (expr.tag) {
|
||||||
default:
|
default:
|
||||||
case LITERAL: {
|
case LITERAL: {
|
||||||
return expr.data.integer;
|
return expr.data.integer;
|
||||||
}
|
}
|
||||||
case VARIABLE: {
|
case VARIABLE: {
|
||||||
int* result = lookup(expr.data.variable, memory, env);
|
int* result = lookup(expr.data.variable, memory, scope);
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
fprintf(stderr, "Error: variable not found '%s'\n", expr.data.variable);
|
fprintf(stderr, "Error: variable not found '%s'\n", expr.data.variable);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
@ -102,7 +102,7 @@ int eval_expr(Expr expr, Memory memory, Environment env) {
|
||||||
case FUNCTION: {
|
case FUNCTION: {
|
||||||
if (strcmp(expr.data.function.name, "print") == 0) {
|
if (strcmp(expr.data.function.name, "print") == 0) {
|
||||||
if (expr.data.function.args.length == 1) {
|
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);
|
printf("%d\n", arg);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -112,8 +112,8 @@ int eval_expr(Expr expr, Memory memory, Environment env) {
|
||||||
}
|
}
|
||||||
else if (strcmp(expr.data.function.name, "add") == 0) {
|
else if (strcmp(expr.data.function.name, "add") == 0) {
|
||||||
if (expr.data.function.args.length == 2) {
|
if (expr.data.function.args.length == 2) {
|
||||||
int arg1 = eval_expr(((Expr*)expr.data.function.args.elements)[0], 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, env);
|
int arg2 = eval_expr(((Expr*)expr.data.function.args.elements)[1], memory, scope);
|
||||||
return arg1 + arg2;
|
return arg1 + arg2;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Error: negate expects a single argument.\n");
|
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) {
|
else if (strcmp(expr.data.function.name, "negate") == 0) {
|
||||||
if (expr.data.function.args.length == 1) {
|
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;
|
return 0 - arg;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Error: negate expects a single argument.\n");
|
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) {
|
switch (stmt.tag) {
|
||||||
case SET: {
|
case SET: {
|
||||||
int result = eval_expr(stmt.data.Set.expr, memory, env);
|
int result = eval_expr(stmt.data.Set.expr, memory, scope);
|
||||||
int* index = lookup(stmt.data.Set.name, memory, env);
|
int* index = lookup(stmt.data.Set.name, memory, scope);
|
||||||
if (index != NULL) {
|
if (index != NULL) {
|
||||||
*index = result;
|
*index = result;
|
||||||
} else {
|
} else {
|
||||||
return insert(stmt.data.Set.name, result, memory, env);
|
return insert(stmt.data.Set.name, result, memory, scope);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WHILE: {
|
case WHILE: {
|
||||||
while (eval_expr(stmt.data.While.condition, memory, env)) {
|
while (eval_expr(stmt.data.While.condition, memory, scope)) {
|
||||||
Environment new_env = env;
|
Scope new_scope = scope;
|
||||||
for (unsigned i = 0; i < stmt.data.While.block.length; ++i) {
|
for (unsigned i = 0; i < stmt.data.While.block.length; ++i) {
|
||||||
Stmt current = ((Stmt*)stmt.data.While.block.elements)[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;
|
break;
|
||||||
}
|
}
|
||||||
case EXPR:
|
case EXPR:
|
||||||
eval_expr(stmt.data.Expr.expr, memory, env);
|
eval_expr(stmt.data.Expr.expr, memory, scope);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return env;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(StmtArray stmts) {
|
void execute(StmtArray stmts) {
|
||||||
Memory memory = new_memory();
|
Memory memory = new_memory();
|
||||||
Environment environment = new_environment();
|
Scope scope = new_scope();
|
||||||
for (unsigned pc = 0; pc < stmts.length; ++pc) {
|
for (unsigned pc = 0; pc < stmts.length; ++pc) {
|
||||||
Stmt stmt = stmts.stmts[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