]> git.lizzy.rs Git - nothing.git/blobdiff - src/script/gc.c
(#408) use stdbool in camera unit
[nothing.git] / src / script / gc.c
index 9955e0fc6501e750d208474c655a8f8e7f5653a8..0bff5c3d4e650263d7b2e266d00777573952bdbc 100644 (file)
@@ -3,6 +3,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "builtins.h"
 #include "expr.h"
 #include "gc.h"
 #include "system/error.h"
@@ -19,29 +20,25 @@ struct Gc
     size_t capacity;
 };
 
+static long int value_of_expr(struct Expr expr)
+{
+    if (expr.type == EXPR_CONS) {
+        return (long int) expr.cons;
+    } else if (expr.type == EXPR_ATOM) {
+        return (long int) expr.atom;
+    } else {
+        return 0;
+    }
+}
+
 static int compare_exprs(const void *a, const void *b)
 {
     assert(a);
     assert(b);
 
-    const struct Expr *expr_a = (const struct Expr *)a;
-    const struct Expr *expr_b = (const struct Expr *)b;
-
-    const void *ptr_a = NULL;
-    if (expr_a->type == EXPR_CONS) {
-        ptr_a = expr_a->cons;
-    } else if (expr_a->type == EXPR_ATOM) {
-        ptr_a = expr_a->atom;
-    }
-
-    const void *ptr_b = NULL;
-    if (expr_b->type == EXPR_CONS) {
-        ptr_b = expr_b->cons;
-    } else if (expr_b->type == EXPR_ATOM) {
-        ptr_b = expr_b->atom;
-    }
-
-    const long int d = (long int) ptr_b - (long int) ptr_a;
+    const long int ptr_a = value_of_expr(*(const struct Expr *)a);
+    const long int ptr_b = value_of_expr(*(const struct Expr *)b);
+    const long int d = ptr_b - ptr_a;
 
     if (d < 0) {
         return -1;
@@ -87,6 +84,11 @@ Gc *create_gc(void)
 void destroy_gc(Gc *gc)
 {
     assert(gc);
+
+    for (size_t i = 0; i < gc->size; ++i) {
+        destroy_expr(gc->exprs[i]);
+    }
+
     RETURN_LT0(gc->lt);
 }
 
@@ -113,11 +115,38 @@ int gc_add_expr(Gc *gc, struct Expr expr)
     return 0;
 }
 
+static long int gc_find_expr(Gc *gc, struct Expr expr)
+{
+    assert(gc);
+    (void) expr;
+
+    struct Expr *result =
+        (struct Expr *) bsearch(&expr, gc->exprs, gc->size,
+                                sizeof(struct Expr), compare_exprs);
+
+    if (result == NULL) {
+        return -1;
+    }
+
+    return (long int) (result - gc->exprs);
+}
+
 static void gc_traverse_expr(Gc *gc, struct Expr root)
 {
     assert(gc);
-    (void) root;
-    /* TODO: gc_traverse_expr is not implemented */
+    const long int root_index = gc_find_expr(gc, root);
+    assert(root_index >= 0);
+
+    if (gc->visited[root_index]) {
+        return;
+    }
+
+    if (cons_p(root)) {
+        gc_traverse_expr(gc, root.cons->car);
+        gc_traverse_expr(gc, root.cons->cdr);
+    }
+
+    gc->visited[root_index] = 1;
 }
 
 void gc_collect(Gc *gc, struct Expr root)
@@ -147,3 +176,15 @@ void gc_collect(Gc *gc, struct Expr root)
         }
     }
 }
+
+void gc_inspect(const Gc *gc)
+{
+    for (size_t i = 0; i < gc->size; ++i) {
+        if (gc->exprs[i].type == EXPR_VOID) {
+            printf(".");
+        } else {
+            printf("+");
+        }
+    }
+    printf("\n");
+}