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    /// Syntactic sugar for enum { none, some: T }
57    Option(Box<Ty>),
58
59    /// Type of functions with defined params and return types.
60    Enum(Vec<TyEnumVariant>),
61
62    /// Type of functions with defined params and return types.
63    Func(TyFunc),
64
65    /// Tuple that is constructed by iterating over fields of a tuple
66    TupleComprehension(TyTupleComprehension),
67    // /// Tuples that have fields of `base` tuple, but don't have fields of `except` tuple.
68    // /// Implies that `base` has all fields of `except`.
69    // Exclude { base: Box<Ty>, except: Box<Ty> },
70}
71
72#[derive(Debug, Clone, PartialEq, Hash)]
73pub struct TyTupleField {
74    pub name: Option<String>,
75
76    pub unpack: bool,
77
78    pub ty: Ty,
79}
80
81#[derive(Debug, Clone, PartialEq, Hash)]
82pub struct TyEnumVariant {
83    pub name: String,
84    pub ty: Ty,
85}
86
87/// Built-in sets.
88#[derive(Debug, Clone, PartialEq, Eq, Hash, strum::Display)]
89#[allow(non_camel_case_types)]
90pub enum TyPrimitive {
91    int8,
92    int16,
93    int32,
94    int64,
95    uint8,
96    uint16,
97    uint32,
98    uint64,
99    float32,
100    float64,
101    bool,
102    text,
103}
104
105// Type of a function
106#[derive(Debug, Clone, PartialEq, Hash)]
107pub struct TyFunc {
108    /// Types of func params
109    pub params: Vec<TyFuncParam>,
110
111    /// Type of the function body
112    pub body: Option<Box<Ty>>,
113
114    pub ty_params: Vec<TyParam>,
115}
116
117/// Parameter of type of a function
118#[derive(Debug, Clone, PartialEq, Hash)]
119pub struct TyFuncParam {
120    pub constant: bool,
121    pub label: Option<String>,
122    pub ty: Option<Ty>,
123}
124
125impl TyFuncParam {
126    pub fn simple(ty: Option<Ty>) -> Self {
127        TyFuncParam {
128            constant: false,
129            label: None,
130            ty,
131        }
132    }
133}
134
135// Type parameter
136#[derive(Debug, Clone)]
137pub struct TyParam {
138    /// Assigned name of this generic type param
139    pub name: String,
140
141    pub domain: TyDomain,
142
143    pub span: Option<Span>,
144}
145
146/// Type domain.
147/// Given some unknown type, domain describes restrictions that this type must
148/// adhere to, for the program to be valid.
149#[derive(Debug, Clone)]
150pub enum TyDomain {
151    /// Can be any type
152    Open,
153
154    /// Must be one of the following
155    OneOf(Vec<Ty>),
156
157    /// Must be a tuple with following fields
158    TupleHasFields(Vec<TyDomainTupleField>),
159
160    /// Must be a tuple with exactly N fields
161    TupleLen { n: usize },
162
163    /// Must be an enum with following variants
164    EnumVariants(Vec<TyDomainEnumVariant>),
165}
166
167#[derive(Clone)]
168pub struct TyDomainTupleField {
169    pub location: super::Lookup,
170    pub ty: Ty,
171
172    pub span: Span,
173}
174
175#[derive(Debug, Clone)]
176pub struct TyDomainEnumVariant {
177    pub name: String,
178    pub ty: Ty,
179}
180
181#[derive(Debug, Clone, PartialEq, Hash)]
182pub struct TyTupleComprehension {
183    pub tuple: Box<Ty>,
184
185    pub variable_name: String,
186    pub variable_ty: String,
187
188    pub body_name: Option<String>,
189    pub body_ty: Box<Ty>,
190}
191
192impl Ty {
193    pub fn new(kind: impl Into<TyKind>) -> Ty {
194        Ty {
195            kind: kind.into(),
196            span: None,
197            name: None,
198            target: None,
199            scope_id: None,
200            variants_force_ptr: Vec::new(),
201        }
202    }
203
204    pub fn new_with_span(kind: impl Into<TyKind>, span: Span) -> Ty {
205        Ty {
206            kind: kind.into(),
207            span: Some(span),
208            name: None,
209            target: None,
210            scope_id: None,
211            variants_force_ptr: Vec::new(),
212        }
213    }
214}
215
216impl From<TyPrimitive> for TyKind {
217    fn from(value: TyPrimitive) -> Self {
218        TyKind::Primitive(value)
219    }
220}
221
222impl From<TyFunc> for TyKind {
223    fn from(value: TyFunc) -> Self {
224        TyKind::Func(value)
225    }
226}
227
228impl From<Path> for TyKind {
229    fn from(value: Path) -> Self {
230        TyKind::Ident(value)
231    }
232}
233
234impl PartialEq for Ty {
235    fn eq(&self, other: &Self) -> bool {
236        self.kind == other.kind
237    }
238}
239
240impl Eq for Ty {}
241
242impl std::hash::Hash for Ty {
243    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
244        self.kind.hash(state);
245    }
246}
247
248impl PartialEq for TyParam {
249    fn eq(&self, other: &Self) -> bool {
250        self.name == other.name
251        // && self.domain == other.domain
252    }
253}
254
255impl Eq for TyParam {}
256
257impl std::hash::Hash for TyParam {
258    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
259        self.name.hash(state);
260        // self.domain.hash(state);
261    }
262}
263
264impl TyTupleField {
265    pub(crate) fn matches_name(&self, name: &str) -> bool {
266        self.name.as_ref().is_some_and(|n| n == name)
267    }
268}
269
270impl std::fmt::Debug for TyDomainTupleField {
271    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
272        f.debug_struct("TyDomainTupleField")
273            .field("location", &self.location)
274            .field("ty", &self.ty)
275            .finish()
276    }
277}