Skip to main content

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}