Skip to main content

lutra_compiler/pr/
types.rs

1use enum_as_inner::EnumAsInner;
2
3use crate::Span;
4use crate::pr::path::Path;
5use crate::resolver::NS_STD;
6
7use super::Ref;
8
9#[derive(Debug, Clone)]
10pub struct Ty {
11    pub kind: TyKind,
12
13    pub span: Option<Span>,
14
15    /// Name inferred from the type's definition.
16    pub name: Option<String>,
17
18    /// When this expr is the root of a new scope, this holds the id of
19    /// that scope. This will always be set for [TyKind::Function], but
20    /// might be set for other nodes too.
21    pub scope_id: Option<usize>,
22
23    /// When this type expr is an ident, this holds information
24    /// what is being referenced by the ident.
25    pub target: Option<Ref>,
26
27    pub variants_force_ptr: Vec<u16>,
28}
29
30/// Memory layout of a type.
31#[derive(Debug, Clone)]
32pub struct TyLayout {
33    /// Number of bits required to store the type's the head
34    /// (the part whose size is known at compile time).
35    pub head_size: u32,
36
37    /// Position of the body pointer within the head.
38    /// It is measured bytes from the start of the head.
39    /// Pointer itself is relative to own position (and the start of the head).
40    pub body_ptrs: Vec<u32>,
41}
42
43#[derive(Debug, Clone, PartialEq, Hash, EnumAsInner, strum::AsRefStr)]
44pub enum TyKind {
45    /// Identifier that still needs to be resolved.
46    Ident(Path),
47
48    /// Type of a built-in primitive type
49    Primitive(TyPrimitive),
50
51    /// Type of tuples (product)
52    Tuple(Vec<TyTupleField>),
53
54    /// Type of arrays
55    Array(Box<Ty>),
56
57    /// Syntactic sugar for enum { none, some: T }
58    Option(Box<Ty>),
59
60    /// Type of functions with defined params and return types.
61    Enum(Vec<TyEnumVariant>),
62
63    /// Type of functions with defined params and return types.
64    Func(TyFunc),
65
66    /// Tuple that is constructed by iterating over fields of a tuple
67    TupleComprehension(TyTupleComprehension),
68    // /// Tuples that have fields of `base` tuple, but don't have fields of `except` tuple.
69    // /// Implies that `base` has all fields of `except`.
70    // Exclude { base: Box<Ty>, except: Box<Ty> },
71}
72
73#[derive(Debug, Clone, PartialEq, Hash)]
74pub struct TyTupleField {
75    pub name: Option<String>,
76
77    pub unpack: bool,
78
79    pub ty: Ty,
80}
81
82#[derive(Debug, Clone, PartialEq, Hash)]
83pub struct TyEnumVariant {
84    pub name: String,
85    pub ty: Ty,
86}
87
88/// Built-in sets.
89#[derive(Debug, Clone, PartialEq, Eq, Hash, strum::Display)]
90#[allow(non_camel_case_types)]
91pub enum TyPrimitive {
92    #[strum(to_string = "Prim8")]
93    prim8,
94    #[strum(to_string = "Prim16")]
95    prim16,
96    #[strum(to_string = "Prim32")]
97    prim32,
98    #[strum(to_string = "Prim64")]
99    prim64,
100}
101
102// Type of a function
103#[derive(Debug, Clone, PartialEq, Hash)]
104pub struct TyFunc {
105    /// Types of func params
106    pub params: Vec<TyFuncParam>,
107
108    /// Type of the function body
109    pub body: Option<Box<Ty>>,
110
111    pub ty_params: Vec<TyParam>,
112}
113
114/// Parameter of type of a function
115#[derive(Debug, Clone, PartialEq, Hash)]
116pub struct TyFuncParam {
117    pub constant: bool,
118    pub label: Option<String>,
119    pub ty: Option<Ty>,
120}
121
122impl TyFuncParam {
123    pub fn simple(ty: Option<Ty>) -> Self {
124        TyFuncParam {
125            constant: false,
126            label: None,
127            ty,
128        }
129    }
130}
131
132// Type parameter
133#[derive(Debug, Clone)]
134pub struct TyParam {
135    /// Assigned name of this generic type param
136    pub name: String,
137
138    pub domain: TyDomain,
139
140    pub span: Option<Span>,
141}
142
143/// Type domain.
144/// Given some unknown type, domain describes restrictions that this type must
145/// adhere to, for the program to be valid.
146#[derive(Debug, Clone)]
147pub enum TyDomain {
148    /// Can be any type
149    Open,
150
151    /// Must be one of the following
152    OneOf(Vec<Ty>),
153
154    /// Must be a tuple with following fields
155    TupleHasFields(Vec<TyDomainTupleField>),
156
157    /// Must be a tuple with exactly N fields
158    TupleLen { n: usize },
159
160    /// Must be an enum with following variants
161    EnumVariants(Vec<TyDomainEnumVariant>),
162}
163
164#[derive(Clone)]
165pub struct TyDomainTupleField {
166    pub location: super::Lookup,
167    pub ty: Ty,
168
169    pub span: Span,
170}
171
172#[derive(Debug, Clone)]
173pub struct TyDomainEnumVariant {
174    pub name: String,
175    pub ty: Ty,
176}
177
178#[derive(Debug, Clone, PartialEq, Hash)]
179pub struct TyTupleComprehension {
180    pub tuple: Box<Ty>,
181
182    pub variable_name: String,
183    pub variable_ty: String,
184
185    pub body_name: Option<String>,
186    pub body_ty: Box<Ty>,
187}
188
189impl Ty {
190    pub fn new(kind: impl Into<TyKind>) -> Ty {
191        Ty {
192            kind: kind.into(),
193            span: None,
194            name: None,
195            target: None,
196            scope_id: None,
197            variants_force_ptr: Vec::new(),
198        }
199    }
200
201    pub fn new_with_span(kind: impl Into<TyKind>, span: Span) -> Ty {
202        Ty {
203            kind: kind.into(),
204            span: Some(span),
205            name: None,
206            target: None,
207            scope_id: None,
208            variants_force_ptr: Vec::new(),
209        }
210    }
211
212    pub fn new_std(name: &str) -> Self {
213        Ty::new(TyKind::Ident(Path::new([NS_STD, name])))
214    }
215
216    pub fn with_span(mut self, span: Span) -> Self {
217        self.span = Some(span);
218        self
219    }
220}
221
222impl From<TyPrimitive> for TyKind {
223    fn from(value: TyPrimitive) -> Self {
224        TyKind::Primitive(value)
225    }
226}
227
228impl From<TyFunc> for TyKind {
229    fn from(value: TyFunc) -> Self {
230        TyKind::Func(value)
231    }
232}
233
234impl From<Path> for TyKind {
235    fn from(value: Path) -> Self {
236        TyKind::Ident(value)
237    }
238}
239
240impl PartialEq for Ty {
241    fn eq(&self, other: &Self) -> bool {
242        self.kind == other.kind
243    }
244}
245
246impl Eq for Ty {}
247
248impl std::hash::Hash for Ty {
249    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
250        self.kind.hash(state);
251    }
252}
253
254impl PartialEq for TyParam {
255    fn eq(&self, other: &Self) -> bool {
256        self.name == other.name
257        // && self.domain == other.domain
258    }
259}
260
261impl Eq for TyParam {}
262
263impl std::hash::Hash for TyParam {
264    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
265        self.name.hash(state);
266        // self.domain.hash(state);
267    }
268}
269
270impl TyTupleField {
271    pub(crate) fn matches_name(&self, name: &str) -> bool {
272        self.name.as_ref().is_some_and(|n| n == name)
273    }
274}
275
276impl std::fmt::Debug for TyDomainTupleField {
277    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
278        f.debug_struct("TyDomainTupleField")
279            .field("location", &self.location)
280            .field("ty", &self.ty)
281            .finish()
282    }
283}