summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-10-26 17:02:00 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2019-10-26 17:02:00 -0400
commit3f13dafdcb617286aae542ab6a2e1ab91d228836 (patch)
treeea6e59a6609d6aa186b3c32f86ddb1a1a596fdc4
parente7432359e33880e7d705d1e86397fe676e601505 (diff)
fixed leaks
-rw-r--r--eval.c73
-rw-r--r--main.c2
-rw-r--r--scope.c5
-rw-r--r--test.toc36
-rw-r--r--types.h4
5 files changed, 66 insertions, 54 deletions
diff --git a/eval.c b/eval.c
index f742e0a..cbe7798 100644
--- a/eval.c
+++ b/eval.c
@@ -6,10 +6,15 @@ static void block_exit(Block *b, Statement *stmts);
static void evalr_create(Evaluator *ev) {
allocr_create(&ev->allocr);
ev->returning = NULL;
+ ev->to_free = NULL;
}
static void evalr_free(Evaluator *ev) {
allocr_free_all(&ev->allocr);
+ typedef void *VoidPtr;
+ arr_foreach(ev->to_free, VoidPtr, f)
+ free(*f);
+ arr_clear(&ev->to_free);
}
static inline void *evalr_malloc(Evaluator *ev, size_t bytes) {
@@ -174,7 +179,7 @@ static void val_copy(Evaluator *ev, Value *dest, Value *src, Type *t) {
}
}
-static void val_free(Value *v, Type *t) {
+static void *val_ptr_to_free(Value *v, Type *t) {
switch (t->kind) {
case TYPE_BUILTIN:
case TYPE_FN:
@@ -182,14 +187,17 @@ static void val_free(Value *v, Type *t) {
case TYPE_SLICE:
case TYPE_VOID:
case TYPE_UNKNOWN:
- break;
+ return NULL;
case TYPE_ARR:
- free(v->arr);
- break;
+ return v->arr;
case TYPE_TUPLE:
- free(v->tuple);
- break;
+ return v->tuple;
}
+ assert(0); return NULL;
+}
+
+static void val_free(Value *v, Type *t) {
+ free(val_ptr_to_free(v, t));
}
#define builtin_casts_to_int(x) \
@@ -850,7 +858,8 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
} break;
case EXPR_TUPLE: {
size_t i, n = arr_len(e->tuple);
- v->tuple = evalr_malloc(ev, n * sizeof *v->tuple);
+ v->tuple = err_malloc(n * sizeof *v->tuple);
+ *(void **)arr_add(&ev->to_free) = v->tuple;
for (i = 0; i < n; i++) {
if (!eval_expr(ev, &e->tuple[i], &v->tuple[i]))
return false;
@@ -908,9 +917,8 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
return false;
}
if (ev->returning) {
- *v = *ev->returning;
- free(ev->returning);
- ev->returning = NULL;
+ *v = ev->ret_val;
+ ev->returning = false;
}
fn_exit(fn);
} break;
@@ -965,25 +973,28 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
static bool eval_decl(Evaluator *ev, Declaration *d) {
Value val = {0};
int has_expr = d->flags & DECL_FLAG_HAS_EXPR;
- if (has_expr) {
+ if (has_expr && (!(d->flags & DECL_FLAG_CONST) || !(d->flags & DECL_FLAG_FOUND_VAL))) {
if (!eval_expr(ev, &d->expr, &val))
return false;
- d->flags |= DECL_FLAG_HAS_EXPR;
+ d->flags |= DECL_FLAG_FOUND_VAL;
}
long index = 0;
arr_foreach(d->idents, Identifier, i) {
IdentDecl *id = ident_decl(*i);
- if (has_expr && d->expr.kind == EXPR_TUPLE) {
- val_copy(ev, &id->val, &val.tuple[index], &d->type.tuple[index]);
+ if (has_expr && d->type.kind == TYPE_TUPLE) {
+ val_copy(d->flags & DECL_FLAG_CONST ? ev : NULL, &id->val, &val.tuple[index], &d->type.tuple[index]);
index++;
} else if (!has_expr && d->type.kind == TYPE_ARR) {
/* "stack" array */
id->val.arr = err_calloc(d->type.arr.n, compiler_sizeof(d->type.arr.of));
} else {
- val_copy(ev, &id->val, &val, &d->type);
+ val_copy(d->flags & DECL_FLAG_CONST ? ev : NULL, &id->val, &val, &d->type);
}
id->flags |= IDECL_FLAG_HAS_VAL;
}
+ if (d->expr.kind == EXPR_TUPLE) {
+ val_free(&val, &d->type); /* free the tuple */
+ }
return true;
}
@@ -997,32 +1008,44 @@ static bool eval_stmt(Evaluator *ev, Statement *stmt) {
if (!eval_expr(ev, &stmt->expr, &unused))
return false;
} break;
- case STMT_RET:
- ev->returning = err_malloc(sizeof *ev->returning);
- if (!eval_expr(ev, &stmt->ret.expr, ev->returning))
+ case STMT_RET: {
+ Value r;
+ if (!eval_expr(ev, &stmt->ret.expr, &r))
return false;
- break;
+ val_copy(NULL, &ev->ret_val, &r, &stmt->ret.expr.type);
+ } break;
}
return true;
}
/* t is the type of the block. */
static bool eval_block(Evaluator *ev, Block *b, Type *t, Value *v) {
+ void **prev_to_free = ev->to_free;
+ ev->to_free = NULL;
block_enter(b, b->stmts, 0);
arr_foreach(b->stmts, Statement, stmt) {
if (!eval_stmt(ev, stmt))
return false;
if (ev->returning) break;
}
- Value *returning = ev->returning;
- Value r;
if (!ev->returning && b->ret_expr) {
- returning = &r;
- if (!eval_expr(ev, b->ret_expr, returning))
+ Value r;
+ if (!eval_expr(ev, b->ret_expr, &r))
return false;
+ /* make a copy so that r's data isn't freed when we exit the block */
+ val_copy(NULL, v, &r, &b->ret_expr->type);
+ void *free_ptr = val_ptr_to_free(v, t);
+ if (t->kind == TYPE_TUPLE) printf("WIll Free %p!!!\n",free_ptr);
+ if (free_ptr)
+ *(void **)arr_add(&prev_to_free) = free_ptr;
}
- if (returning) val_copy(NULL, v, returning, t); /* LEAK */adfjfhskjdahfkj
block_exit(b, b->stmts);
-
+ typedef void *VoidPtr;
+ arr_foreach(ev->to_free, VoidPtr, f) {
+ printf("Free %p\n", *f);
+ free(*f);
+ }
+ arr_clear(&ev->to_free);
+ ev->to_free = prev_to_free;
return true;
}
diff --git a/main.c b/main.c
index 1153983..468d6c8 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,5 @@
/*
TODO:
-array/slice values
-fix leaking of constant stack arrays
make sure initializers for global variables are compile-time constants
structs
length of slice/arr with .len
diff --git a/scope.c b/scope.c
index 8aed1a8..42e446a 100644
--- a/scope.c
+++ b/scope.c
@@ -24,15 +24,16 @@ static bool add_ident_decls(Block *b, Declaration *d, U32 flags) {
static void remove_ident_decls(Block *b, Declaration *d) {
U64 i = 0;
+ bool is_tuple = d->type.kind == TYPE_TUPLE;
arr_foreach(d->idents, Identifier, ident) {
IdentTree *id_info = *ident;
- IdentDecl **decls = &id_info->decls;
+ IdentDecl **decls = &id_info->decls;
IdentDecl *last_decl = arr_last(*decls);
if (last_decl && last_decl->scope == b) {
if ((last_decl->flags & IDECL_FLAG_HAS_VAL)
/* don't free const vals (there's only one per decl) */
&& !(last_decl->decl->flags & DECL_FLAG_CONST)) {
- val_free(&last_decl->decl->val, d->type.kind == TYPE_TUPLE ? &d->type.tuple[i++] : &d->type);
+ val_free(&last_decl->val, is_tuple ? &d->type.tuple[i++] : &d->type);
}
arr_remove_last(decls); /* remove that declaration */
}
diff --git a/test.toc b/test.toc
index b865734..c5af4fb 100644
--- a/test.toc
+++ b/test.toc
@@ -13,39 +13,27 @@ putf @= fn(x: float) {
");
};
+asdf @= fn() (int, int) {
+2,3};
-N @= 50;
-pascal @= fn() [N][]int {
- x: [N][]int;
- i := 0;
- while i < N {
- x[i] = new(int, i+1);
- i = i + 1;
- }
- i = 0;
- while i < N {
- x[i][0] = 1;
- x[i][i] = 1;
- j := 1;
- while j < i {
- x[i][j] = x[i-1][j-1] + x[i-1][j];
- j = j + 1;
- }
- i = i + 1;
- }
- x
+fdsa @= fn() int {
+ x, y := asdf();
+ x + y
};
foo @= fn() [3]int {
x : [3]int;
- x[0] = 0;
- x[1] = 1;
- x[2] = 2;
+ x[0] = 1;
+ x[1] = 2;
+ x[2] = 3;
x
};
main @= fn() {
// ptriangle @= pascal();
// puti(ptriangle[49][25]);
- x @= foo();
+ x : [fdsa()]int;
+
+ A, B @= 3, 5;
+ ASDF @= foo();
};
diff --git a/types.h b/types.h
index b0db0b1..2d4e7e4 100644
--- a/types.h
+++ b/types.h
@@ -509,7 +509,9 @@ typedef enum {
typedef struct {
Allocator allocr;
- Value *returning; /* NULL = not returning anything */
+ bool returning;
+ Value ret_val;
+ void **to_free; /* an array of data to free for this scope. */
} Evaluator;
typedef struct Typer {