microcad_lang/ty/
tuple_type.rs1use crate::{syntax::*, ty::*};
7
8#[derive(Debug, Clone, Default, PartialEq, Eq)]
10pub struct TupleType {
11 pub(crate) named: std::collections::HashMap<Identifier, Type>,
12 pub(crate) unnamed: std::collections::HashSet<Type>,
13}
14impl TupleType {
15 pub fn new_vec2() -> Self {
17 [("x", Type::scalar()), ("y", Type::scalar())]
18 .into_iter()
19 .collect()
20 }
21
22 pub fn new_vec3() -> Self {
24 [
25 ("x", Type::scalar()),
26 ("y", Type::scalar()),
27 ("z", Type::scalar()),
28 ]
29 .into_iter()
30 .collect()
31 }
32
33 pub fn new_color() -> Self {
35 [
36 ("r", Type::scalar()),
37 ("g", Type::scalar()),
38 ("b", Type::scalar()),
39 ("a", Type::scalar()),
40 ]
41 .into_iter()
42 .collect()
43 }
44
45 pub fn new_size2() -> Self {
47 [("width", Type::length()), ("height", Type::length())]
48 .into_iter()
49 .collect()
50 }
51
52 pub fn matches(&self, other: &Self) -> bool {
57 if !self.unnamed.is_empty()
58 || self.named.len() != other.named.len()
59 || !self.unnamed.is_empty()
60 || !other.unnamed.is_empty()
61 {
62 return false;
63 }
64 other.named.iter().all(|k| self.named.contains_key(k.0))
65 }
66
67 fn matches_keys(&self, keys: &[&str]) -> bool {
69 if !self.unnamed.is_empty() || self.named.len() != keys.len() {
70 return false;
71 }
72 keys.iter()
73 .all(|k| self.named.contains_key(&Identifier::no_ref(k)))
74 }
75
76 fn is_scalar_only(&self) -> bool {
78 self.common_type().is_some_and(|ty| *ty == Type::scalar())
79 }
80
81 fn is_length_only(&self) -> bool {
83 self.common_type().is_some_and(|ty| *ty == Type::length())
84 }
85
86 pub(crate) fn common_type(&self) -> Option<&Type> {
88 let mut iter = self.unnamed.iter().chain(self.named.values());
89 if let Some(first) = iter.next() {
90 if iter.all(|x| x == first) {
91 return Some(first);
92 }
93 }
94 None
95 }
96
97 pub(crate) fn is_color(&self) -> bool {
99 self.is_scalar_only() && self.matches_keys(&["r", "g", "b", "a"])
100 }
101
102 pub(crate) fn is_vec2(&self) -> bool {
104 self.is_scalar_only() && self.matches_keys(&["x", "y"])
105 }
106
107 pub(crate) fn is_vec3(&self) -> bool {
109 self.is_scalar_only() && self.matches_keys(&["x", "y", "z"])
110 }
111
112 pub(crate) fn is_size2(&self) -> bool {
114 self.is_length_only() && self.matches_keys(&["width", "height"])
115 }
116}
117
118impl std::hash::Hash for TupleType {
119 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
120 self.named.iter().for_each(|(id, ty)| {
121 id.hash(state);
122 ty.hash(state)
123 });
124 self.unnamed.iter().for_each(|ty| ty.hash(state));
125 }
126}
127
128impl FromIterator<(Identifier, Type)> for TupleType {
129 fn from_iter<T: IntoIterator<Item = (Identifier, Type)>>(iter: T) -> Self {
130 let (unnamed, named) = iter.into_iter().partition(|(id, _)| id.is_empty());
131 Self {
132 named,
133 unnamed: unnamed.into_values().collect(),
134 }
135 }
136}
137
138impl<'a> FromIterator<(&'a str, Type)> for TupleType {
139 fn from_iter<T: IntoIterator<Item = (&'a str, Type)>>(iter: T) -> Self {
140 let (unnamed, named) = iter
141 .into_iter()
142 .map(|(id, ty)| (Identifier::no_ref(id), ty))
143 .partition(|(id, _)| id.is_empty());
144 Self {
145 named,
146 unnamed: unnamed.into_values().collect(),
147 }
148 }
149}
150
151impl std::fmt::Display for TupleType {
152 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
153 if self.is_color() {
154 return write!(f, "Color");
155 }
156 if self.is_vec2() {
157 return write!(f, "Vec2");
158 }
159 if self.is_vec3() {
160 return write!(f, "Vec3");
161 }
162 if self.is_size2() {
163 return write!(f, "Size2");
164 }
165
166 write!(f, "({})", {
167 let mut types = self
168 .named
169 .iter()
170 .map(|(id, ty)| format!("{id}: {ty}"))
171 .chain(self.unnamed.iter().map(|ty| ty.to_string()))
172 .collect::<Vec<_>>();
173
174 types.sort();
175 types.join(", ")
176 })
177 }
178}