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}