cl_typeck/lib.rs
1//! # The Conlang Type Checker
2//!
3//! As a statically typed language, Conlang requires a robust type checker to enforce correctness.
4//!
5//! This crate is a major work-in-progress.
6//!
7//! # The [Table](table::Table)™
8//! A directed graph of nodes and their dependencies.
9//!
10//! Contains [item definitions](handle) and [type expression](type_expression) information.
11//!
12//! *Every* item is itself a module, and can contain arbitrarily nested items
13//! as part of the item graph
14//!
15//! The table, additionally, has some queues for use in external algorithms,
16//! detailed in the [stage] module.
17//!
18//! # Namespaces
19//! Each item in the graph is given its own namespace, which is further separated into
20//! two distinct parts:
21//! - Children of an item are direct descendents (i.e. their `parent` is a handle to the item)
22//! - Imports of an item are indirect descendents created by `use` or `impl` directives. They are
23//! shadowed by Children with the same name.
24//!
25//! # Order of operations:
26//! For order-of-operations information, see the [stage] module.
27#![warn(clippy::all)]
28
29pub(crate) mod format_utils;
30
31pub mod list {
32 use cl_ast::types::{Path, Symbol};
33
34 /// A (usually) stack-allocated linked list
35 #[derive(Clone, Copy, Debug, Default)]
36 pub enum List<'parent, T> {
37 Cons(&'parent List<'parent, T>, T),
38 #[default]
39 Nil,
40 }
41
42 impl<'parent, T> List<'parent, T> {
43 pub fn new(value: T) -> List<'static, T> {
44 List::Cons(&List::Nil, value)
45 }
46
47 pub fn enter<'a>(&'a self, value: T) -> List<'a, T>
48 where T: 'a {
49 List::Cons(self, value)
50 }
51
52 pub fn parent(&self) -> Option<&List<'parent, T>> {
53 match self {
54 Self::Cons(parent, _) => Some(parent),
55 Self::Nil => None,
56 }
57 }
58
59 pub fn iter(&self) -> ListIter<'_, T> {
60 ListIter(self)
61 }
62 }
63
64 pub struct ListIter<'p, T>(&'p List<'p, T>);
65 impl<'p, T> Iterator for ListIter<'p, T> {
66 type Item = &'p T;
67
68 fn next(&mut self) -> Option<Self::Item> {
69 let List::Cons(list, value) = self.0 else {
70 return None;
71 };
72 self.0 = *list;
73 Some(value)
74 }
75 }
76
77 impl From<List<'_, Symbol>> for Path {
78 fn from(value: List<'_, Symbol>) -> Self {
79 fn inner(path: &List<'_, Symbol>, vec: &mut Vec<Symbol>) {
80 match path {
81 List::Nil => {}
82 &List::Cons(nested, name) => {
83 inner(nested, vec);
84 vec.push(name);
85 }
86 }
87 }
88
89 let mut parts = vec![];
90 inner(&value, &mut parts);
91 Self { parts }
92 }
93 }
94}
95
96pub mod consteval;
97
98pub mod table;
99
100pub mod handle;
101
102pub mod entry;
103
104pub mod type_kind;
105
106pub mod type_expression;
107
108pub mod stage {
109 //! Type collection, evaluation, checking, and inference passes.
110 //!
111 //! # Order of operations
112 //! 1. [mod@populate]: Populate the graph with nodes for every named item.
113 //! 2. [mod@categorize]: Categorize the nodes according to textual type information.
114 //! - Creates anonymous types (`fn(T) -> U`, `&T`, `[T]`, etc.) as necessary to fill in the
115 //! type graph
116 //! - Creates a new struct type for every enum struct-variant.
117 //! 3. [mod@implement]: Import members of implementation modules into types.
118 //! 4. [mod@infer]: Infer the types of the AST using HM type inference
119
120 pub use populate::Populator;
121 /// Stage 1: Populate the graph with nodes.
122 pub mod populate;
123
124 /// Stage 2: Categorize the nodes according to textual type information.
125 pub mod categorize;
126 pub use categorize::categorize;
127
128 /// Stage 3: Import members of `impl` blocks into their corresponding types.
129 pub mod implement;
130 pub use implement::implement;
131
132 // TODO: Make type inference stage 5
133 // TODO: Use the type information stored in the [table]
134 pub mod infer;
135}