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    #[derive(Clone, Copy, Debug, Default)]
35    pub enum List<'parent, T> {
36        Cons(&'parent List<'parent, T>, T),
37        #[default]
38        Nil,
39    }
40
41    impl<'parent, T> List<'parent, T> {
42        pub fn new(value: T) -> List<'static, T> {
43            List::Cons(&List::Nil, value)
44        }
45
46        pub fn enter<'a>(&'a self, value: T) -> List<'a, T>
47        where T: 'a {
48            List::Cons(self, value)
49        }
50
51        pub fn parent(&self) -> Option<&List<'parent, T>> {
52            match self {
53                Self::Cons(parent, _) => Some(parent),
54                Self::Nil => None,
55            }
56        }
57
58        pub fn iter(&self) -> ListIter<'_, T> {
59            ListIter(self)
60        }
61    }
62
63    pub struct ListIter<'p, T>(&'p List<'p, T>);
64    impl<'p, T> Iterator for ListIter<'p, T> {
65        type Item = &'p T;
66
67        fn next(&mut self) -> Option<Self::Item> {
68            let List::Cons(list, value) = self.0 else {
69                return None;
70            };
71            self.0 = *list;
72            Some(value)
73        }
74    }
75
76    impl From<List<'_, Symbol>> for Path {
77        fn from(value: List<'_, Symbol>) -> Self {
78            fn inner(path: &List<'_, Symbol>, vec: &mut Vec<Symbol>) {
79                match path {
80                    List::Nil => {}
81                    &List::Cons(nested, name) => {
82                        inner(nested, vec);
83                        vec.push(name);
84                    }
85                }
86            }
87
88            let mut parts = vec![];
89            inner(&value, &mut parts);
90            Self { parts }
91        }
92    }
93}
94
95pub mod consteval;
96
97pub mod table;
98
99pub mod handle;
100
101pub mod entry;
102
103pub mod type_kind;
104
105pub mod type_expression;
106
107pub mod stage {
108    //! Type collection, evaluation, checking, and inference passes.
109    //!
110    //! # Order of operations
111    //! 1. [mod@populate]: Populate the graph with nodes for every named item.
112    //! 2. [mod@categorize]: Categorize the nodes according to textual type information.
113    //!    - Creates anonymous types (`fn(T) -> U`, `&T`, `[T]`, etc.) as necessary to fill in the
114    //!      type graph
115    //!    - Creates a new struct type for every enum struct-variant.
116    //! 3. [mod@implement]: Import members of implementation modules into types.
117    //! 4. [mod@infer]: Infer the types of the AST using HM type inference
118
119    pub use populate::Populator;
120    /// Stage 1: Populate the graph with nodes.
121    pub mod populate;
122
123    /// Stage 2: Categorize the nodes according to textual type information.
124    pub mod categorize;
125    pub use categorize::categorize;
126
127    /// Stage 3: Import members of `impl` blocks into their corresponding types.
128    pub mod implement;
129    pub use implement::implement;
130
131    // TODO: Make type inference stage 5
132    // TODO: Use the type information stored in the [table]
133    pub mod infer;
134}