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    prim8,
93    prim16,
94    prim32,
95    prim64,
96}
97
98// Type of a function
99#[derive(Debug, Clone, PartialEq, Hash)]
100pub struct TyFunc {
101    /// Types of func params
102    pub params: Vec<TyFuncParam>,
103
104    /// Type of the function body
105    pub body: Option<Box<Ty>>,
106
107    pub ty_params: Vec<TyParam>,
108}
109
110/// Parameter of type of a function
111#[derive(Debug, Clone, PartialEq, Hash)]
112pub struct TyFuncParam {
113    pub constant: bool,
114    pub label: Option<String>,
115    pub ty: Option<Ty>,
116}
117
118impl TyFuncParam {
119    pub fn simple(ty: Option<Ty>) -> Self {
120        TyFuncParam {
121            constant: false,
122            label: None,
123            ty,
124        }
125    }
126}
127
128// Type parameter
129#[derive(Debug, Clone)]
130pub struct TyParam {
131    /// Assigned name of this generic type param
132    pub name: String,
133
134    pub domain: TyDomain,
135
136    pub span: Option<Span>,
137}
138
139/// Type domain.
140/// Given some unknown type, domain describes restrictions that this type must
141/// adhere to, for the program to be valid.
142#[derive(Debug, Clone)]
143pub enum TyDomain {
144    /// Can be any type
145    Open,
146
147    /// Must be one of the following
148    OneOf(Vec<Ty>),
149
150    /// Must be a tuple with following fields
151    TupleHasFields(Vec<TyDomainTupleField>),
152
153    /// Must be a tuple with exactly N fields
154    TupleLen { n: usize },
155
156    /// Must be an enum with following variants
157    EnumVariants(Vec<TyDomainEnumVariant>),
158}
159
160#[derive(Clone)]
161pub struct TyDomainTupleField {
162    pub location: super::Lookup,
163    pub ty: Ty,
164
165    pub span: Span,
166}
167
168#[derive(Debug, Clone)]
169pub struct TyDomainEnumVariant {
170    pub name: String,
171    pub ty: Ty,
172}
173
174#[derive(Debug, Clone, PartialEq, Hash)]
175pub struct TyTupleComprehension {
176    pub tuple: Box<Ty>,
177
178    pub variable_name: String,
179    pub variable_ty: String,
180
181    pub body_name: Option<String>,
182    pub body_ty: Box<Ty>,
183}
184
185impl Ty {
186    pub fn new(kind: impl Into<TyKind>) -> Ty {
187        Ty {
188            kind: kind.into(),
189            span: None,
190            name: None,
191            target: None,
192            scope_id: None,
193            variants_force_ptr: Vec::new(),
194        }
195    }
196
197    pub fn new_with_span(kind: impl Into<TyKind>, span: Span) -> Ty {
198        Ty {
199            kind: kind.into(),
200            span: Some(span),
201            name: None,
202            target: None,
203            scope_id: None,
204            variants_force_ptr: Vec::new(),
205        }
206    }
207
208    pub fn new_std(name: &str) -> Self {
209        Ty::new(TyKind::Ident(Path::new([NS_STD, name])))
210    }
211
212    pub fn with_span(mut self, span: Span) -> Self {
213        self.span = Some(span);
214        self
215    }
216}
217
218impl From<TyPrimitive> for TyKind {
219    fn from(value: TyPrimitive) -> Self {
220        TyKind::Primitive(value)
221    }
222}
223
224impl From<TyFunc> for TyKind {
225    fn from(value: TyFunc) -> Self {
226        TyKind::Func(value)
227    }
228}
229
230impl From<Path> for TyKind {
231    fn from(value: Path) -> Self {
232        TyKind::Ident(value)
233    }
234}
235
236impl PartialEq for Ty {
237    fn eq(&self, other: &Self) -> bool {
238        self.kind == other.kind
239    }
240}
241
242impl Eq for Ty {}
243
244impl std::hash::Hash for Ty {
245    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
246        self.kind.hash(state);
247    }
248}
249
250impl PartialEq for TyParam {
251    fn eq(&self, other: &Self) -> bool {
252        self.name == other.name
253        // && self.domain == other.domain
254    }
255}
256
257impl Eq for TyParam {}
258
259impl std::hash::Hash for TyParam {
260    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
261        self.name.hash(state);
262        // self.domain.hash(state);
263    }
264}
265
266impl TyTupleField {
267    pub(crate) fn matches_name(&self, name: &str) -> bool {
268        self.name.as_ref().is_some_and(|n| n == name)
269    }
270}
271
272impl std::fmt::Debug for TyDomainTupleField {
273    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
274        f.debug_struct("TyDomainTupleField")
275            .field("location", &self.location)
276            .field("ty", &self.ty)
277            .finish()
278    }
279}