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

---
 include/fwd/ast.h   | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 include/fwd/debug.h | 16 +++++++++------
 2 files changed, 65 insertions(+), 7 deletions(-)

(limited to 'include')

diff --git a/include/fwd/ast.h b/include/fwd/ast.h
index 34fcd64..62766fb 100644
--- a/include/fwd/ast.h
+++ b/include/fwd/ast.h
@@ -5,6 +5,7 @@
 #define AST_H
 
 #include <stddef.h>
+#include <assert.h>
 #include <stdbool.h>
 
 /**
@@ -30,7 +31,7 @@ struct src_loc {
 struct ast;
 
 enum type_kind {
-	TYPE_ID = 1, TYPE_CONSTRUCT, TYPE_REF, TYPE_PTR, TYPE_CALLABLE
+	TYPE_ID = 1, TYPE_CONSTRUCT, TYPE_REF, TYPE_PTR, TYPE_CALLABLE, TYPE_VOID
 };
 
 struct type {
@@ -115,6 +116,11 @@ enum ast_kind {
 	AST_CONST_STR,
 };
 
+enum ast_flag {
+	AST_FLAG_ANALYZED	= (1 << 0),
+	AST_FLAG_PREANALYZIS	= (1 << 1),
+};
+
 struct ast {
 	enum ast_kind k;
 	double d;
@@ -129,8 +135,21 @@ struct ast {
 	struct ast *n;
 	struct src_loc loc;
 	struct scope *scope;
+
+	struct type *t;
+	enum ast_flag flags;
 };
 
+static inline bool ast_flags(struct ast *node, enum ast_flag flags)
+{
+	return node->flags & flags;
+}
+
+static inline void ast_set_flags(struct ast *node, enum ast_flag flags)
+{
+	node->flags |= flags;
+}
+
 struct ast *gen_ast(enum ast_kind kind,
                     struct ast *a0,
                     struct ast *a1,
@@ -241,6 +260,9 @@ static inline bool is_const(struct ast *x)
 #define return_id(x, kind) *({assert((x)->k == kind); &(x)->id;})
 #define return_t0(x, kind) *({assert((x)->k == kind); &(x)->t0;})
 
+#define tgen_void(loc) \
+	tgen_type(TYPE_VOID, NULL, NULL, loc)
+
 #define tid_str(x) return_id(x, TYPE_ID)
 #define tgen_id(id, loc) \
 	tgen_type(TYPE_ID, NULL, id, loc)
@@ -355,10 +377,18 @@ static inline bool is_const(struct ast *x)
 struct ast *clone_ast(struct ast *n);
 struct ast *clone_ast_list(struct ast *l);
 
+struct type *clone_type(struct type *type);
+struct type *clone_type_list(struct type *types);
+
 void ast_dump_list(int depth, struct ast *root);
 void ast_dump(int depth, struct ast *node);
 void ast_append(struct ast **list, struct ast *elem);
 
+void type_append(struct type **list, struct type *elem);
+
+bool types_match(struct type *a, struct type *b);
+bool type_lists_match(struct type *al, struct type *bl);
+
 struct ast *ast_prepend(struct ast *list, struct ast *elem);
 
 typedef int (*ast_callback_t)(struct ast *, void *);
@@ -375,6 +405,7 @@ int ast_visit_list(ast_callback_t before, ast_callback_t after,
  * @return Number of elements in \p list.
  */
 size_t ast_list_len(struct ast *list);
+size_t type_list_len(struct type *list);
 
 /**
  * Get last nose in ASt list.
@@ -410,4 +441,27 @@ void fix_closures(struct ast *root);
 #define foreach_type(iter, types) \
 	for (struct type *iter = types; iter; iter = iter->n)
 
+static inline bool is_callable(struct type *t)
+{
+	if (t->k == TYPE_PTR)
+		return (tptr_base(t))->k == TYPE_CALLABLE;
+
+	if (t->k == TYPE_REF)
+		return (tref_base(t))->k == TYPE_CALLABLE;
+
+	return t->k == TYPE_CALLABLE;
+}
+
+static inline struct type *callable_types(struct type *t)
+{
+	assert(is_callable(t));
+	if (t->k == TYPE_REF)
+		return callable_types(tptr_base(t));
+
+	if (t->k == TYPE_PTR)
+		return callable_types(tref_base(t));
+
+	return tcallable_args(t);
+}
+
 #endif /* AST_H */
diff --git a/include/fwd/debug.h b/include/fwd/debug.h
index 85ed9db..cc20c83 100644
--- a/include/fwd/debug.h
+++ b/include/fwd/debug.h
@@ -68,7 +68,7 @@ struct file_ctx {
  * @param node AST node to print message with.
  * @param fmt Format string. Follows standard printf() formatting.
  */
-void semantic_info(struct file_ctx ctx, struct ast *node, const char *fmt, ...);
+void semantic_info(struct scope *scope, struct ast *node, const char *fmt, ...);
 
 /**
  * Print warning that relates to a specific AST node.
@@ -83,8 +83,7 @@ void semantic_info(struct file_ctx ctx, struct ast *node, const char *fmt, ...);
  * @param node AST node to print message with.
  * @param fmt Format string. Follows standard printf() formatting.
  */
-void semantic_warn(struct file_ctx ctx, struct ast *node, const char *fmt,
-                   ...);
+void semantic_warn(struct scope *scope, struct ast *node, const char *fmt, ...);
 
 /**
  * Print warning that relates to a specific AST node.
@@ -94,9 +93,9 @@ void semantic_warn(struct file_ctx ctx, struct ast *node, const char *fmt,
  * @param node AST node to print message with.
  * @param fmt Format string. Follows standard printf() formatting.
  */
-void semantic_error(struct file_ctx ctx, struct ast *node, const char *fmt,
-                    ...);
-void loc_error(struct file_ctx ctx, struct src_loc loc, const char *fmt, ...);
+void semantic_error(struct scope *scope, struct ast *node, const char *fmt, ...);
+
+void loc_error(struct scope *scope, struct src_loc loc, const char *fmt, ...);
 
 /**
  * Print internal error.
@@ -135,4 +134,9 @@ struct src_issue {
  */
 void src_issue(struct src_issue issue, const char *err_msg, ...);
 
+void type_mismatch(struct scope *scope, struct ast *node,
+		struct type *l, struct type *r);
+
+const char *type_str(struct type *t);
+
 #endif /* FWD_DEBUG_H */
-- 
cgit v1.2.3