1#![allow(dead_code, unused_variables, unused_imports)]
2use crate::components::context::Context;
18use crate::components::r#type::argument_type::ArgumentType;
19use crate::components::r#type::Type;
20use std::fmt::Write as _;
21use std::hash::Hasher;
22
23fn canonical_arg_debug(arg: &ArgumentType) -> String {
27 let label = format!("{:?}", arg.0);
28 let typ = canonical_type_debug(&arg.1);
29 let embedded = arg.2;
30 let variadic = arg.3;
31 let default = format!("{:?}", arg.4);
32 format!(
33 "ArgumentType({}, {}, {}, {}, {})",
34 label, typ, embedded, variadic, default
35 )
36}
37
38pub fn canonical_type_debug(t: &Type) -> String {
45 match t {
46 Type::Record(fields, h) => {
47 let mut v: Vec<String> = fields.iter().map(canonical_arg_debug).collect();
48 v.sort();
49 format!("Record({:?}, {:?})", v, h)
50 }
51 Type::Interface(fields, h) => {
52 let mut v: Vec<String> = fields.iter().map(canonical_arg_debug).collect();
53 v.sort();
54 format!("Interface({:?}, {:?})", v, h)
55 }
56 Type::RClass(set, h) => {
57 let mut v: Vec<String> = set.iter().cloned().collect();
58 v.sort();
59 format!("RClass({:?}, {:?})", v, h)
60 }
61 Type::Function(args, ret, h) => format!(
62 "Function({:?}, {:?}, {:?})",
63 args.iter().map(canonical_arg_debug).collect::<Vec<_>>(),
64 canonical_type_debug(ret),
65 h
66 ),
67 Type::Vec(vt, size, inner, h) => format!(
68 "Vec({:?}, {:?}, {:?}, {:?})",
69 vt,
70 canonical_type_debug(size),
71 canonical_type_debug(inner),
72 h
73 ),
74 Type::Tuple(elems, h) => format!(
75 "Tuple({:?}, {:?})",
76 elems.iter().map(canonical_type_debug).collect::<Vec<_>>(),
77 h
78 ),
79 Type::Params(ts, h) => format!(
80 "Params({:?}, {:?})",
81 ts.iter().map(canonical_type_debug).collect::<Vec<_>>(),
82 h
83 ),
84 Type::Module(args, names, h) => format!(
85 "Module({:?}, {:?}, {:?})",
86 args.iter().map(canonical_arg_debug).collect::<Vec<_>>(),
87 names,
88 h
89 ),
90 Type::Alias(name, params, opaque, h) => format!(
91 "Alias({:?}, {:?}, {:?}, {:?})",
92 name,
93 params.iter().map(canonical_type_debug).collect::<Vec<_>>(),
94 opaque,
95 h
96 ),
97 Type::Tag(name, body, h) => format!("Tag({:?}, {:?}, {:?})", name, canonical_type_debug(body), h),
98 Type::If(cond, branches, h) => format!(
99 "If({:?}, {:?}, {:?})",
100 canonical_type_debug(cond),
101 branches.iter().map(canonical_type_debug).collect::<Vec<_>>(),
102 h
103 ),
104 Type::Condition(a, b, c, h) => format!(
105 "Condition({:?}, {:?}, {:?}, {:?})",
106 canonical_type_debug(a),
107 canonical_type_debug(b),
108 canonical_type_debug(c),
109 h
110 ),
111 Type::Operator(op, a, b, h) => format!(
112 "Operator({:?}, {:?}, {:?}, {:?})",
113 op,
114 canonical_type_debug(a),
115 canonical_type_debug(b),
116 h
117 ),
118 Type::Multi(body, h) => format!("Multi({:?}, {:?})", canonical_type_debug(body), h),
119 _ => format!("{:?}", t),
120 }
121}
122
123struct HashWriter<'a, H: Hasher>(&'a mut H);
126
127impl<H: Hasher> std::fmt::Write for HashWriter<'_, H> {
128 fn write_str(&mut self, s: &str) -> std::fmt::Result {
129 self.0.write(s.as_bytes());
130 Ok(())
131 }
132}
133
134impl Context {
135 pub fn fingerprint(&self) -> u64 {
138 let mut hasher = std::collections::hash_map::DefaultHasher::new();
139 let mut w = HashWriter(&mut hasher);
140
141 for pair in self.typing_context.variables.iter() {
147 let _ = write!(w, "v{:?}|{}", pair.0, canonical_type_debug(&pair.1));
148 }
149 for pair in self.typing_context.aliases.iter() {
150 let _ = write!(w, "a{:?}|{}", pair.0, canonical_type_debug(&pair.1));
151 }
152 for pair in self.typing_context.std.iter() {
153 let _ = write!(w, "s{:?}|{}", pair.0, canonical_type_debug(&pair.1));
154 }
155 let mut counter: Vec<String> = self
158 .typing_context
159 .alias_counter
160 .clone()
161 .into_iter()
162 .map(|(category, count)| format!("{:?}={}", category, count))
163 .collect();
164 counter.sort();
165 let _ = write!(w, "c{:?}", counter);
166
167 let _ = write!(w, "g{}", self.subtypes.structure_debug());
169
170 let _ = write!(w, "tc{:?}", self.type_constructors);
173 {
174 let ra: Vec<String> = self
175 .record_aliases
176 .iter()
177 .map(|(name, typ)| format!("{}={}", name, canonical_type_debug(typ)))
178 .collect();
179 let _ = write!(w, "ra{:?}", ra);
180 }
181 let _ = write!(w, "em{:?}", self.embedded_methods);
182 let _ = write!(w, "ef{:?}", self.extern_fns);
183 let _ = write!(w, "if{:?}", self.import_from_fns);
184 let _ = write!(w, "sf{:?}", self.signature_fns);
185 let _ = write!(w, "vf{:?}", self.vectorizable_fns);
186
187 let mut constraints: Vec<String> = self
189 .interface_constraints
190 .iter()
191 .map(|(name, typ)| format!("{}={:?}", name, typ))
192 .collect();
193 constraints.sort();
194 let _ = write!(w, "ic{:?}", constraints);
195
196 let mut processed: Vec<String> = self
197 .processed_modules
198 .iter()
199 .map(|(name, typ)| format!("{}={:?}", name, typ))
200 .collect();
201 processed.sort();
202 let _ = write!(w, "pm{:?}", processed);
203
204 let _ = write!(w, "rc{}", self.rigid_counter);
205 let _ = write!(w, "cf{:?}", self.config);
208
209 hasher.finish()
210 }
211}
212
213#[cfg(test)]
214mod tests {
215 use super::*;
216 use crate::components::language::var::Var;
217 use crate::utils::builder;
218
219 #[test]
220 fn fingerprint_is_deterministic_for_identical_contexts() {
221 let a = Context::default();
222 let b = Context::default();
223 assert_eq!(a.fingerprint(), b.fingerprint());
224 }
225
226 #[test]
227 fn fingerprint_changes_when_a_binding_is_added() {
228 let base = Context::default();
229 let with_var = base
230 .clone()
231 .push_var_type(Var::from_name("x"), builder::integer_type_default(), &base);
232 assert_ne!(base.fingerprint(), with_var.fingerprint());
233 }
234
235 #[test]
236 fn fingerprint_survives_clone() {
237 let base = Context::default();
238 let with_var = base
239 .clone()
240 .push_var_type(Var::from_name("x"), builder::integer_type_default(), &base);
241 assert_eq!(with_var.fingerprint(), with_var.clone().fingerprint());
242 }
243}