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.id, 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::IS_BLITTABLE)
74    }
75
76    #[inline]
77    #[must_use]
78    pub const fn can_be_stored_in_variable(&self) -> bool {
79        self.flags.contains(TypeFlags::IS_BLITTABLE)
80    }
81
82    #[inline]
83    #[must_use]
84    pub const fn is_storage(&self) -> bool {
85        self.flags.contains(TypeFlags::IS_STORAGE)
86    }
87
88    #[inline]
89    #[must_use]
90    pub const fn allowed_as_return_type(&self) -> bool {
91        self.flags.contains(TypeFlags::IS_ALLOWED_RETURN)
92    }
93
94    #[inline]
95    #[must_use]
96    pub const fn allowed_as_parameter_type(&self) -> bool {
97        self.flags.contains(TypeFlags::IS_ALLOWED_RETURN)
98    }
99
100    #[inline]
101    #[must_use]
102    pub const fn is_blittable(&self) -> bool {
103        self.flags.contains(TypeFlags::IS_BLITTABLE)
104    }
105
106    /// Check if this type requires explicit collection storage allocation from caller
107    /// This includes all aggregate types including optionals that need memory
108    /// allocation and proper setup of the r0 register by the caller
109    #[must_use]
110    pub fn collection_view_that_needs_explicit_storage(&self) -> bool {
111        match &*self.kind {
112            // Dynamic collections that need explicit storage
113            TypeKind::DynamicLengthVecView(_)
114            | TypeKind::DynamicLengthMapView(_, _)
115            | TypeKind::StackView(_)
116            | TypeKind::QueueView(_)
117            | TypeKind::SparseView(_)
118            | TypeKind::GridView(_)
119            | TypeKind::SliceView(_) => true,
120
121            // Optional types that contain types needing storage
122            TypeKind::Optional(inner_type) => {
123                inner_type.collection_view_that_needs_explicit_storage()
124            }
125
126            _ => false,
127        }
128    }
129}