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