diff --git a/CMakeLists.txt b/CMakeLists.txt index c6a5755..2ba81da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,3 +53,5 @@ endif() # Benchmark is broken since the addition to coroutines # add_executable(ink_bench bench.c) # target_link_libraries(ink_bench PUBLIC ink) + +# Valgrind testing should run `./test/test01.nk ./test/test03.nk ./test/test06.nk` as arguments \ No newline at end of file diff --git a/include/ink.h b/include/ink.h index 430e0f3..5105173 100644 --- a/include/ink.h +++ b/include/ink.h @@ -251,6 +251,13 @@ void ink_make_context_inplace(struct context* location, void*(*malloc)(struct co struct context* ink_make_default_context(void); #endif +/** + * Destroys a context and frees the memory from it + * @param ctx The context to destroy + * @return the panic value of the context + */ +int ink_destroy(struct context* ctx); + /** * Steps the current routine by one execution step * @param pContext The context of the routine to advance diff --git a/lib.c b/lib.c index 10fbd48..ee5e0d0 100644 --- a/lib.c +++ b/lib.c @@ -307,6 +307,47 @@ void ink_pop(struct context* ctx) { ctx->routines[ctx->routine_current].top--; } + +int ink_destroy(struct context* ctx) { + int panic = ctx->panic; + int i, j; + for (i = 0; i < ctx->types_top; ++i) { + struct ink_type* t = ctx->types + i; + if (t->element_size > 0 && t->elements_top > 0) { + for (j = 0; i < t->element_size; ++i) { + if (t->elements[j].in_use) { + t->collect(ctx, t->elements[j].data); + ctx->free(ctx, t->elements[j].data); + } + } + ctx->free(ctx, t->elements); + } + /* Type names are not freed, for they are not copied */ + /* ctx->inner_free(ctx, t->name); */ + } + for (i = 0; i < ctx->words_top; ++i) { + ctx->inner_free(ctx, ctx->words[i].name); + ctx->free(ctx, ctx->words[i].things); + } + for (i = 0; i < ctx->native_words_top; ++i) { + ctx->inner_free(ctx, ctx->native_words[i].name); + } + for (i = 0; i < ctx->routines_top; ++i) { + ctx->free(ctx, ctx->routines[i].function_stack); + ctx->free(ctx, ctx->routines[i].stack); + } + for (i = 0; i < ctx->lex_reserved_words_top; ++i) { + ctx->free(ctx, ctx->lex_reserved_words[i]); + } + ctx->inner_free(ctx, ctx->lex_reserved_words); + ctx->inner_free(ctx, ctx->native_words); + ctx->inner_free(ctx, ctx->routines); + ctx->free(ctx, ctx->words); + ctx->inner_free(ctx, ctx->types); + ctx->inner_free(ctx, ctx); + return panic; +} + struct context* ink_make_context(void*(*malloc)(struct context*, size_t), void*(*realloc)(struct context*, void*, size_t), void(*free)(struct context*, void*), int(*putchar)(struct context*, int)) { struct context* ctx; ctx = (struct context*)malloc(NULL, sizeof(struct context)); diff --git a/main.c b/main.c index c2a8b5d..9d7c888 100644 --- a/main.c +++ b/main.c @@ -52,5 +52,5 @@ int main(int argc, char** argv) { s_total += (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec) / 1.0e9; s_total = ctx->steps / s_total; printf("\nExecuted in %u steps\nCollected %u times\nExecution freq: %lfHz\n", ctx->steps, ctx->collections, s_total); - return ctx->panic; + return ink_destroy(ctx); } \ No newline at end of file