8 #include "system/error.h"
11 #define GC_INITIAL_CAPACITY 256
22 static int compare_exprs(const void *a, const void *b)
27 const struct Expr *expr_a = (const struct Expr *)a;
28 const struct Expr *expr_b = (const struct Expr *)b;
30 const void *ptr_a = NULL;
31 if (expr_a->type == EXPR_CONS) {
33 } else if (expr_a->type == EXPR_ATOM) {
37 const void *ptr_b = NULL;
38 if (expr_b->type == EXPR_CONS) {
40 } else if (expr_b->type == EXPR_ATOM) {
44 const long int d = (long int) ptr_b - (long int) ptr_a;
62 Gc *gc = PUSH_LT(lt, malloc(sizeof(Gc)), free);
64 throw_error(ERROR_TYPE_LIBC);
69 gc->exprs = PUSH_LT(lt, malloc(sizeof(struct Expr) * GC_INITIAL_CAPACITY), free);
70 if (gc->exprs == NULL) {
71 throw_error(ERROR_TYPE_LIBC);
75 gc->visited = PUSH_LT(lt, malloc(sizeof(int) * GC_INITIAL_CAPACITY), free);
76 if (gc->visited == NULL) {
77 throw_error(ERROR_TYPE_LIBC);
82 gc->capacity = GC_INITIAL_CAPACITY;
87 void destroy_gc(Gc *gc)
93 int gc_add_expr(Gc *gc, struct Expr expr)
97 if (gc->size >= gc->capacity) {
98 const size_t new_capacity = gc->capacity * 2;
99 struct Expr *const new_exprs = realloc(
101 sizeof(struct Expr) * new_capacity);
103 if (new_exprs == NULL) {
107 gc->capacity = new_capacity;
108 gc->exprs = REPLACE_LT(gc->lt, gc->exprs, new_exprs);
111 gc->exprs[gc->size++] = expr;
116 static void gc_traverse_expr(Gc *gc, struct Expr root)
120 /* TODO: gc_traverse_expr is not implemented */
123 void gc_collect(Gc *gc, struct Expr root)
128 /* Sort gc->exprs O(nlogn) */
129 qsort(gc->exprs, gc->size, sizeof(struct Expr), compare_exprs);
131 /* Defragment O(n) */
132 while(gc->size > 0 && gc->exprs[gc->size - 1].type == EXPR_VOID) {
136 /* Initialize visited array O(n) */
137 memset(gc->visited, 0, sizeof(int) * gc->size);
139 /* Traverse root O(nlogn) */
140 gc_traverse_expr(gc, root);
142 /* Dealloc unvisted O(n) */
143 for (size_t i = 0; i < gc->size; ++i) {
144 if (!gc->visited[i]) {
145 destroy_expr(gc->exprs[i]);
146 gc->exprs[i] = void_expr();