graphcal_compiler/registry/
declared_type.rs1use crate::dag_id::DagId;
4use crate::syntax::dimension::Dimension;
5use crate::syntax::names::{NameDef, NameNamespace, ResolvedName, namespace};
6
7use crate::registry::time_scale::TimeScale;
8use crate::registry::types::{DimensionRegistry, NatRangeIndex, NatRangeIndexError};
9use crate::syntax::nat::NatPolyForm;
10
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
17pub struct TypeNameRef<Ns: NameNamespace> {
18 name: NameDef<Ns>,
19 resolved: ResolvedName<Ns>,
20}
21
22impl<Ns: NameNamespace> TypeNameRef<Ns> {
23 #[must_use]
25 pub fn from_resolved(resolved: ResolvedName<Ns>) -> Self {
26 Self {
27 name: resolved.to_unowned_def_name(),
28 resolved,
29 }
30 }
31
32 #[must_use]
39 pub const fn with_display_leaf(name: NameDef<Ns>, resolved: ResolvedName<Ns>) -> Self {
40 Self { name, resolved }
41 }
42
43 #[must_use]
45 pub fn with_owner(owner: DagId, name: NameDef<Ns>) -> Self {
46 Self::from_resolved(ResolvedName::from_def(owner, name))
47 }
48
49 #[must_use]
51 pub const fn name(&self) -> &NameDef<Ns> {
52 &self.name
53 }
54
55 #[must_use]
57 pub const fn resolved(&self) -> &ResolvedName<Ns> {
58 &self.resolved
59 }
60
61 #[must_use]
63 pub fn matches_ref(&self, other: &Self) -> bool {
64 self.resolved() == other.resolved()
65 }
66
67 #[must_use]
69 pub fn as_str(&self) -> &str {
70 self.name.as_str()
71 }
72
73 #[must_use]
75 pub fn to_unowned_name(&self) -> NameDef<Ns> {
76 self.name.clone()
77 }
78}
79
80impl<Ns: NameNamespace> From<ResolvedName<Ns>> for TypeNameRef<Ns> {
81 fn from(resolved: ResolvedName<Ns>) -> Self {
82 Self::from_resolved(resolved)
83 }
84}
85
86impl<Ns: NameNamespace> std::fmt::Display for TypeNameRef<Ns> {
87 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88 self.name.fmt(f)
89 }
90}
91
92#[derive(Debug, Clone, PartialEq, Eq, Hash)]
98pub enum NatRangeIndexRef {
99 Concrete(NatRangeIndex),
100 Symbolic(NatPolyForm),
101}
102
103impl NatRangeIndexRef {
104 pub fn from_form(form: NatPolyForm) -> Result<Self, NatRangeIndexError> {
110 if form.is_constant() {
111 NatRangeIndex::try_from_u64(form.constant()).map(Self::Concrete)
112 } else {
113 Ok(Self::Symbolic(form))
114 }
115 }
116
117 #[must_use]
119 pub const fn concrete_index(&self) -> Option<NatRangeIndex> {
120 match self {
121 Self::Concrete(index) => Some(*index),
122 Self::Symbolic(_) => None,
123 }
124 }
125
126 #[must_use]
128 pub fn form(&self) -> NatPolyForm {
129 match self {
130 Self::Concrete(index) => NatPolyForm::from_constant(index.size_u64()),
131 Self::Symbolic(form) => form.clone(),
132 }
133 }
134
135 #[must_use]
137 pub fn display_name(&self) -> NameDef<namespace::Index> {
138 match self {
139 Self::Concrete(index) => index.display_name(),
140 Self::Symbolic(form) => NameDef::new(format!("range({})", form.format())),
141 }
142 }
143
144 #[must_use]
146 pub fn matches_ref(&self, other: &Self) -> bool {
147 match (self, other) {
148 (Self::Concrete(lhs), Self::Concrete(rhs)) => lhs == rhs,
149 (Self::Symbolic(lhs), Self::Symbolic(rhs)) => lhs == rhs,
150 _ => false,
151 }
152 }
153}
154
155#[derive(Debug, Clone, PartialEq, Eq, Hash)]
160pub enum IndexTypeRef {
161 Declared(TypeNameRef<namespace::Index>),
162 NatRange(NatRangeIndexRef),
163}
164
165impl IndexTypeRef {
166 #[must_use]
168 pub fn from_resolved(resolved: ResolvedName<namespace::Index>) -> Self {
169 Self::Declared(TypeNameRef::from_resolved(resolved))
170 }
171
172 #[must_use]
174 pub fn with_owner(owner: DagId, name: NameDef<namespace::Index>) -> Self {
175 Self::Declared(TypeNameRef::with_owner(owner, name))
176 }
177
178 #[must_use]
181 pub const fn with_display_leaf(
182 name: NameDef<namespace::Index>,
183 resolved: ResolvedName<namespace::Index>,
184 ) -> Self {
185 Self::Declared(TypeNameRef::with_display_leaf(name, resolved))
186 }
187
188 #[must_use]
190 pub const fn from_nat_range(index: NatRangeIndex) -> Self {
191 Self::NatRange(NatRangeIndexRef::Concrete(index))
192 }
193
194 pub fn from_nat_range_form(form: NatPolyForm) -> Result<Self, NatRangeIndexError> {
200 NatRangeIndexRef::from_form(form).map(Self::NatRange)
201 }
202
203 #[must_use]
205 pub const fn from_nat_range_ref(reference: NatRangeIndexRef) -> Self {
206 Self::NatRange(reference)
207 }
208
209 #[must_use]
211 pub const fn declared_name(&self) -> Option<&NameDef<namespace::Index>> {
212 match self {
213 Self::Declared(reference) => Some(reference.name()),
214 Self::NatRange(_) => None,
215 }
216 }
217
218 #[must_use]
220 pub const fn declared_resolved(&self) -> Option<&ResolvedName<namespace::Index>> {
221 match self {
222 Self::Declared(reference) => Some(reference.resolved()),
223 Self::NatRange(_) => None,
224 }
225 }
226
227 #[must_use]
229 pub const fn nat_range_ref(&self) -> Option<&NatRangeIndexRef> {
230 match self {
231 Self::Declared(_) => None,
232 Self::NatRange(reference) => Some(reference),
233 }
234 }
235
236 #[must_use]
238 pub const fn nat_range(&self) -> Option<NatRangeIndex> {
239 match self {
240 Self::NatRange(reference) => reference.concrete_index(),
241 Self::Declared(_) => None,
242 }
243 }
244
245 #[must_use]
247 pub fn nat_range_form(&self) -> Option<NatPolyForm> {
248 self.nat_range_ref().map(NatRangeIndexRef::form)
249 }
250
251 #[must_use]
253 pub fn display_name(&self) -> NameDef<namespace::Index> {
254 match self {
255 Self::Declared(reference) => reference.to_unowned_name(),
256 Self::NatRange(reference) => reference.display_name(),
257 }
258 }
259
260 #[must_use]
262 pub fn matches_ref(&self, other: &Self) -> bool {
263 match (self, other) {
264 (Self::Declared(lhs), Self::Declared(rhs)) => lhs.matches_ref(rhs),
265 (Self::NatRange(lhs), Self::NatRange(rhs)) => lhs.matches_ref(rhs),
266 _ => false,
267 }
268 }
269
270 #[must_use]
272 pub fn to_unowned_name(&self) -> NameDef<namespace::Index> {
273 self.display_name()
274 }
275}
276
277impl From<ResolvedName<namespace::Index>> for IndexTypeRef {
278 fn from(resolved: ResolvedName<namespace::Index>) -> Self {
279 Self::from_resolved(resolved)
280 }
281}
282
283impl std::fmt::Display for IndexTypeRef {
284 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
285 self.display_name().fmt(f)
286 }
287}
288
289pub type StructTypeRef = TypeNameRef<namespace::StructType>;
291
292#[derive(Debug, Clone, PartialEq, Eq)]
294pub enum DeclaredType {
295 Scalar(Dimension),
296 Bool,
297 Int,
298 Datetime(TimeScale),
300 IndexArg(IndexTypeRef),
305 Struct(StructTypeRef, Vec<Self>),
307 Indexed {
308 element: Box<Self>,
309 index: IndexTypeRef,
310 },
311}
312
313impl DeclaredType {
314 #[must_use]
316 pub fn format(&self, dims: &DimensionRegistry) -> String {
317 match self {
318 Self::Scalar(d) => dims.format_dimension(d),
319 Self::Bool => "Bool".to_string(),
320 Self::Int => "Int".to_string(),
321 Self::Datetime(scale) => {
322 if scale.is_utc() {
323 "Datetime".to_string()
324 } else {
325 format!("Datetime<{scale}>")
326 }
327 }
328 Self::IndexArg(index) => format!("index {index}"),
329 Self::Struct(name, args) => {
330 if args.is_empty() {
331 name.to_string()
332 } else {
333 let args_str: Vec<String> = args.iter().map(|a| a.format(dims)).collect();
334 format!("{name}<{}>", args_str.join(", "))
335 }
336 }
337 Self::Indexed { element, index } => {
338 format!("{}[{index}]", element.format(dims))
339 }
340 }
341 }
342}