rename env to scope, and free pointers before they leak

This commit is contained in:
me 2026-01-11 11:08:40 +02:00
parent 2f32c928d6
commit f36482afc7

View file

@ -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);
}
}