From 98c3d8fbc924c62e2be571ed71b22053b9e8baa3 Mon Sep 17 00:00:00 2001
From: Kimplul <kimi.h.kuparinen@gmail.com>
Date: Fri, 20 Dec 2024 14:52:34 +0200
Subject: add enough type checking to compile uniq.fwd

---
 src/ast.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 106 insertions(+)

(limited to 'src/ast.c')

diff --git a/src/ast.c b/src/ast.c
index 4baad56..17a4461 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -133,6 +133,9 @@ struct type *tgen_type(enum type_kind kind,
 
 void ast_append(struct ast **list, struct ast *elem)
 {
+	assert(list);
+	assert(elem);
+
 	struct ast *cur = *list;
 	if (!cur) {
 		*list = elem;
@@ -145,6 +148,23 @@ void ast_append(struct ast **list, struct ast *elem)
 	cur->n = elem;
 }
 
+void type_append(struct type **list, struct type *elem)
+{
+	assert(list);
+	assert(elem);
+
+	struct type *cur = *list;
+	if (!cur) {
+		*list = elem;
+		return;
+	}
+
+	while (cur->n)
+		cur = cur->n;
+
+	cur->n = elem;
+}
+
 struct ast *ast_prepend(struct ast *list, struct ast *elem)
 {
 	elem->n = list;
@@ -295,6 +315,41 @@ struct ast *clone_ast_list(struct ast *root)
 	return new_root;
 }
 
+struct type *clone_type(struct type *type)
+{
+	if (!type)
+		return NULL;
+
+	struct type *new = create_empty_type();
+	if (!new)
+		return NULL;
+
+	new->k = type->k;
+	if (type->id && !(new->id = strdup(type->id)))
+		return NULL;
+
+	if (type->t0 && !(new->t0 = clone_type_list(type->t0)))
+		return NULL;
+
+	return new;
+}
+
+struct type *clone_type_list(struct type *root)
+{
+	struct type *n = root, *new_root = NULL, *prev = NULL;
+	while (n) {
+		struct type *new = clone_type(n);
+
+		if (prev) prev->n = new;
+		else new_root = new;
+
+		prev = new;
+		n = n->n;
+	}
+
+	return new_root;
+}
+
 int ast_visit(ast_callback_t before, ast_callback_t after, struct ast *n,
               void *d)
 {
@@ -346,6 +401,17 @@ size_t ast_list_len(struct ast *node)
 	return count;
 }
 
+size_t type_list_len(struct type *node)
+{
+	size_t count = 0;
+	while (node) {
+		count++;
+		node = node->n;
+	}
+
+	return count;
+}
+
 struct ast *ast_last(struct ast *list)
 {
 	if (!list)
@@ -482,3 +548,43 @@ void fix_closures(struct ast *root)
 		root = next;
 	}
 }
+
+bool types_match(struct type *a, struct type *b)
+{
+	if (!a && !b)
+		return true;
+
+	if (a && !b)
+		return false;
+
+	if (!a && b)
+		return false;
+
+	if (a->k != b->k)
+		return false;
+
+	if (a->id && b->id && strcmp(a->id, b->id) != 0)
+		return false;
+
+	if (!type_lists_match(a->t0, b->t0))
+		return false;
+
+	return true;
+}
+
+bool type_lists_match(struct type *al, struct type *bl)
+{
+	if (type_list_len(al) != type_list_len(bl))
+		return false;
+
+	struct type *a = al;
+	struct type *b = bl;
+	while (a && b) {
+		if (!types_match(a, b))
+			return false;
+
+		a = a->n;
+		b = b->n;
+	}
+	return true;
+}
-- 
cgit v1.2.3