swamp_types/
lib.rs

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