Skip to main content

lutra_compiler/pr/
types.rs

1use enum_as_inner::EnumAsInner;
2
3use crate::Span;
4use crate::pr::path::Path;
5
6use super::Ref;
7
8#[derive(Debug, Clone)]
9pub struct Ty {
10    pub kind: TyKind,
11
12    pub span: Option<Span>,
13
14    /// Name inferred from the type's definition.
15    pub name: Option<String>,
16
17    /// When this expr is the root of a new scope, this holds the id of
18    /// that scope. This will always be set for [TyKind::Function], but
19    /// might be set for other nodes too.
20    pub scope_id: Option<usize>,
21
22    /// When this type expr is an ident, this holds information
23    /// what is being referenced by the ident.
24    pub target: Option<Ref>,
25
26    pub variants_force_ptr: Vec<u16>,
27}
28
29/// Memory layout of a type.
30#[derive(Debug, Clone)]
31pub struct TyLayout {
32    /// Number of bits required to store the type's the head
33    /// (the part whose size is known at compile time).
34    pub head_size: u32,
35
36    /// Position of the body pointer within the head.
37    /// It is measured bytes from the start of the head.
38    /// Pointer itself is relative to own position (and the start of the head).
39    pub body_ptrs: Vec<u32>,
40}
41
42#[derive(Debug, Clone, PartialEq, Hash, EnumAsInner, strum::AsRefStr)]
43pub enum TyKind {
44    /// Identifier that still needs to be resolved.
45    Ident(Path),
46
47    /// Type of a built-in primitive type
48    Primitive(TyPrimitive),
49
50    /// Type of tuples (product)
51    Tuple(Vec<TyTupleField>),
52
53    /// Type of arrays
54    Array(Box<Ty>),
55
56    /// Type of functions with defined params and return types.
57    Enum(Vec<TyEnumVariant>),
58
59    /// Type of functions with defined params and return types.
60    Func(TyFunc),
61
62    /// Tuple that is constructed by iterating over fields of a tuple
63    TupleComprehension(TyTupleComprehension),
64    // /// Tuples that have fields of `base` tuple, but don't have fields of `except` tuple.
65    // /// Implies that `base` has all fields of `except`.
66    // Exclude { base: Box<Ty>, except: Box<Ty> },
67}
68
69#[derive(Debug, Clone, PartialEq, Hash)]
70pub struct TyTupleField {
71    pub name: Option<String>,
72
73    pub unpack: bool,
74
75    pub ty: Ty,
76}
77
78#[derive(Debug, Clone, PartialEq, Hash)]
79pub struct TyEnumVariant {
80    pub name: String,
81    pub ty: Ty,
82}
83
84/// Built-in sets.
85#[derive(Debug, Clone, PartialEq, Eq, Hash, strum::Display)]
86#[allow(non_camel_case_types)]
87pub enum TyPrimitive {
88    int8,
89    int16,
90    int32,
91    int64,
92    uint8,
93    uint16,
94    uint32,
95    uint64,
96    float32,
97    float64,
98    bool,
99    text,
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
213impl From<TyPrimitive> for TyKind {
214    fn from(value: TyPrimitive) -> Self {
215        TyKind::Primitive(value)
216    }
217}
218
219impl From<TyFunc> for TyKind {
220    fn from(value: TyFunc) -> Self {
221        TyKind::Func(value)
222    }
223}
224
225impl From<Path> for TyKind {
226    fn from(value: Path) -> Self {
227        TyKind::Ident(value)
228    }
229}
230
231impl PartialEq for Ty {
232    fn eq(&self, other: &Self) -> bool {
233        self.kind == other.kind
234    }
235}
236
237impl Eq for Ty {}
238
239impl std::hash::Hash for Ty {
240    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
241        self.kind.hash(state);
242    }
243}
244
245impl PartialEq for TyParam {
246    fn eq(&self, other: &Self) -> bool {
247        self.name == other.name
248        // && self.domain == other.domain
249    }
250}
251
252impl Eq for TyParam {}
253
254impl std::hash::Hash for TyParam {
255    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
256        self.name.hash(state);
257        // self.domain.hash(state);
258    }
259}
260
261impl TyTupleField {
262    pub(crate) fn matches_name(&self, name: &str) -> bool {
263        self.name.as_ref().is_some_and(|n| n == name)
264    }
265}
266
267impl std::fmt::Debug for TyDomainTupleField {
268    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
269        f.debug_struct("TyDomainTupleField")
270            .field("location", &self.location)
271            .field("ty", &self.ty)
272            .finish()
273    }
274}