swamp_types/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5
6mod cache;
7mod calc_compat;
8mod flags;
9pub mod prelude;
10mod pretty_print;
11mod supporting_types;
12mod type_kind;
13
14use crate::flags::TypeFlags;
15pub use crate::type_kind::TypeKind;
16use std::fmt::{Display, Formatter};
17use std::rc::Rc;
18
19#[derive(PartialEq, Clone, Eq, Hash, Copy, Debug)]
20pub struct TypeId(u32);
21
22impl TypeId {
23    pub const EMPTY: u32 = 0xffffffff;
24
25    #[must_use]
26    pub const fn new(id: u32) -> Self {
27        Self(id)
28    }
29
30    #[must_use]
31    pub const fn inner(&self) -> u32 {
32        self.0
33    }
34}
35
36impl Display for TypeId {
37    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
38        write!(f, "{}", self.0)
39    }
40}
41
42#[derive(Debug, Clone, PartialEq, Eq, Hash)]
43pub struct Type {
44    pub id: TypeId,
45    pub flags: TypeFlags,
46    pub kind: Rc<TypeKind>,
47}
48
49pub type TypeRef = Rc<Type>;
50
51impl Display for Type {
52    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
53        write!(f, "{}", self.kind)
54    }
55}
56
57impl Type {
58    #[inline]
59    #[must_use]
60    pub const fn is_scalar(&self) -> bool {
61        self.flags.contains(TypeFlags::IS_SCALAR)
62    }
63
64    #[inline]
65    #[must_use]
66    pub const fn can_be_stored_in_field(&self) -> bool {
67        self.flags.contains(TypeFlags::IS_STORAGE)
68    }
69
70    #[inline]
71    #[must_use]
72    pub const fn can_be_stored_in_transient_field(&self) -> bool {
73        self.flags.contains(TypeFlags::ALLOWED_FOR_SCOPED_BORROW)
74    }
75
76    #[inline]
77    #[must_use]
78    pub const fn can_be_stored_in_variable(&self) -> bool {
79        self.flags.contains(TypeFlags::ALLOWED_FOR_VARIABLE)
80    }
81
82    #[must_use]
83    pub fn is_option(&self) -> bool {
84        matches!(&*self.kind, TypeKind::Optional(_))
85    }
86
87    #[inline]
88    #[must_use]
89    pub const fn is_storage(&self) -> bool {
90        self.flags.contains(TypeFlags::IS_STORAGE)
91    }
92
93    #[inline]
94    #[must_use]
95    pub const fn allowed_as_return_type(&self) -> bool {
96        self.flags.contains(TypeFlags::IS_ALLOWED_RETURN)
97    }
98
99    #[inline]
100    #[must_use]
101    pub const fn allowed_as_parameter_type(&self) -> bool {
102        self.flags.contains(TypeFlags::IS_ALLOWED_RETURN)
103    }
104
105    #[inline]
106    #[must_use]
107    pub const fn allowed_for_scoped_borrow(&self) -> bool {
108        self.flags.contains(TypeFlags::ALLOWED_FOR_SCOPED_BORROW)
109    }
110
111    /// Check if this type requires explicit collection storage allocation from caller
112    /// This includes all aggregate types including optionals that need memory
113    /// allocation and proper setup of the r0 register by the caller
114    #[must_use]
115    pub fn collection_view_that_needs_explicit_storage(&self) -> bool {
116        match &*self.kind {
117            // Dynamic collections that need explicit storage
118            TypeKind::DynamicLengthVecView(_)
119            | TypeKind::DynamicLengthMapView(_, _)
120            | TypeKind::StackView(_)
121            | TypeKind::QueueView(_)
122            | TypeKind::SparseView(_)
123            | TypeKind::GridView(_)
124            | TypeKind::SliceView(_) => true,
125
126            // Optional types that contain types needing storage
127            TypeKind::Optional(inner_type) => {
128                inner_type.collection_view_that_needs_explicit_storage()
129            }
130
131            _ => false,
132        }
133    }
134}