1use crate::{
2 decl_engine::{parsed_engine::ParsedDeclEngine, DeclEngine},
3 query_engine::QueryEngine,
4 type_system::TypeEngine,
5};
6use std::{
7 cmp::Ordering,
8 fmt,
9 hash::{BuildHasher, Hash, Hasher},
10 sync::Arc,
11};
12use sway_types::{SourceEngine, Span};
13
14#[derive(Clone, Debug, Default)]
15pub struct Engines {
16 type_engine: TypeEngine,
17 decl_engine: DeclEngine,
18 parsed_decl_engine: ParsedDeclEngine,
19 query_engine: QueryEngine,
20 source_engine: SourceEngine,
21}
22
23impl Engines {
24 pub fn te(&self) -> &TypeEngine {
25 &self.type_engine
26 }
27
28 pub fn de(&self) -> &DeclEngine {
29 &self.decl_engine
30 }
31
32 pub fn pe(&self) -> &ParsedDeclEngine {
33 &self.parsed_decl_engine
34 }
35
36 pub fn qe(&self) -> &QueryEngine {
37 &self.query_engine
38 }
39
40 pub fn se(&self) -> &SourceEngine {
41 &self.source_engine
42 }
43
44 pub fn clear_program(&mut self, program_id: &sway_types::ProgramId) {
47 self.type_engine.clear_program(program_id);
48 self.decl_engine.clear_program(program_id);
49 self.parsed_decl_engine.clear_program(program_id);
50 self.query_engine.clear_program(program_id);
51 }
52
53 pub fn clear_module(&mut self, source_id: &sway_types::SourceId) {
58 self.type_engine.clear_module(source_id);
59 self.decl_engine.clear_module(source_id);
60 self.parsed_decl_engine.clear_module(source_id);
61 self.query_engine.clear_module(source_id);
62
63 if let Some(autogenerated_source_id) =
66 self.se().get_associated_autogenerated_source_id(source_id)
67 {
68 if autogenerated_source_id == *source_id {
69 return;
70 }
71
72 self.type_engine.clear_module(&autogenerated_source_id);
73 self.decl_engine.clear_module(&autogenerated_source_id);
74 self.parsed_decl_engine
75 .clear_module(&autogenerated_source_id);
76 self.query_engine.clear_module(&autogenerated_source_id);
77 }
78 }
79
80 pub fn help_out<T>(&self, thing: T) -> WithEngines<'_, T> {
82 WithEngines {
83 thing,
84 engines: self,
85 }
86 }
87}
88
89#[derive(Clone, Copy)]
90pub struct WithEngines<'a, T> {
91 pub thing: T,
92 pub engines: &'a Engines,
93}
94
95impl<'a, T> WithEngines<'a, T> {
96 pub fn new(thing: T, engines: &'a Engines) -> Self {
97 WithEngines { thing, engines }
98 }
99}
100
101impl<T: DisplayWithEngines> fmt::Display for WithEngines<'_, T> {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 self.thing.fmt(f, self.engines)
105 }
106}
107
108impl<T: DebugWithEngines> fmt::Debug for WithEngines<'_, T> {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 self.thing.fmt(f, self.engines)
112 }
113}
114
115impl<T: HashWithEngines> Hash for WithEngines<'_, T> {
116 fn hash<H: Hasher>(&self, state: &mut H) {
117 self.thing.hash(state, self.engines)
118 }
119}
120
121impl<T: PartialEqWithEngines> PartialEq for WithEngines<'_, T> {
122 fn eq(&self, rhs: &Self) -> bool {
123 self.thing
124 .eq(&rhs.thing, &PartialEqWithEnginesContext::new(self.engines))
125 }
126}
127
128impl<T: EqWithEngines> Eq for WithEngines<'_, T> {}
129
130impl<T: OrdWithEngines> PartialOrd for WithEngines<'_, T>
131where
132 T: PartialEqWithEngines,
133{
134 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
135 Some(
136 self.thing
137 .cmp(&other.thing, &OrdWithEnginesContext::new(self.engines)),
138 )
139 }
140}
141
142impl<T: OrdWithEngines> Ord for WithEngines<'_, T>
143where
144 T: EqWithEngines,
145{
146 fn cmp(&self, other: &Self) -> Ordering {
147 self.thing
148 .cmp(&other.thing, &OrdWithEnginesContext::new(self.engines))
149 }
150}
151
152pub(crate) trait DisplayWithEngines {
153 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result;
154}
155
156impl<T: DisplayWithEngines> DisplayWithEngines for &T {
157 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
158 (*self).fmt(f, engines)
159 }
160}
161
162impl<T: DisplayWithEngines> DisplayWithEngines for Option<T> {
163 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
164 match self {
165 None => Ok(()),
166 Some(x) => x.fmt(f, engines),
167 }
168 }
169}
170
171impl<T: DisplayWithEngines> DisplayWithEngines for Box<T> {
172 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
173 (**self).fmt(f, engines)
174 }
175}
176
177impl<T: DisplayWithEngines> DisplayWithEngines for Vec<T> {
178 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
179 let text = self
180 .iter()
181 .map(|e| format!("{}", engines.help_out(e)))
182 .collect::<Vec<_>>()
183 .join(", ")
184 .to_string();
185 f.write_str(&text)
186 }
187}
188
189impl DisplayWithEngines for Span {
190 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
191 let file = self
192 .source_id()
193 .and_then(|id| engines.source_engine.get_file_name(id));
194 f.write_fmt(format_args!(
195 "Span {{ {:?}, {} }}",
196 file,
197 self.line_col_one_index()
198 ))
199 }
200}
201
202pub(crate) trait DebugWithEngines {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result;
204}
205
206impl<T: DebugWithEngines> DebugWithEngines for &T {
207 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
208 (*self).fmt(f, engines)
209 }
210}
211
212impl<T: DebugWithEngines> DebugWithEngines for std::sync::Arc<T> {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
214 (**self).fmt(f, engines)
215 }
216}
217
218impl<T: DebugWithEngines> DebugWithEngines for Option<T> {
219 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
220 match self {
221 None => Ok(()),
222 Some(x) => x.fmt(f, engines),
223 }
224 }
225}
226
227impl<T: DebugWithEngines> DebugWithEngines for Box<T> {
228 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
229 (**self).fmt(f, engines)
230 }
231}
232
233impl<T: DebugWithEngines> DebugWithEngines for Vec<T> {
234 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
235 let text = self
236 .iter()
237 .map(|e| format!("{:?}", engines.help_out(e)))
238 .collect::<Vec<_>>()
239 .join(", ")
240 .to_string();
241 f.write_str(&text)
242 }
243}
244
245impl DebugWithEngines for Span {
246 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
247 DisplayWithEngines::fmt(self, f, engines)
248 }
249}
250
251pub trait HashWithEngines {
252 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines);
253}
254
255impl<T: HashWithEngines + ?Sized> HashWithEngines for &T {
256 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
257 (*self).hash(state, engines)
258 }
259}
260
261impl<T: HashWithEngines> HashWithEngines for Option<T> {
262 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
263 match self {
264 None => state.write_u8(0),
265 Some(x) => x.hash(state, engines),
266 }
267 }
268}
269
270impl<T: HashWithEngines> HashWithEngines for [T] {
271 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
272 for x in self {
273 x.hash(state, engines)
274 }
275 }
276}
277
278impl<T: HashWithEngines> HashWithEngines for Box<T> {
279 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
280 (**self).hash(state, engines)
281 }
282}
283
284impl<T: HashWithEngines> HashWithEngines for Arc<T> {
285 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
286 (**self).hash(state, engines)
287 }
288}
289
290pub trait EqWithEngines: PartialEqWithEngines {}
291
292pub struct PartialEqWithEnginesContext<'a> {
293 engines: &'a Engines,
294 is_inside_trait_constraint: bool,
295}
296
297impl<'a> PartialEqWithEnginesContext<'a> {
298 pub(crate) fn new(engines: &'a Engines) -> Self {
299 Self {
300 engines,
301 is_inside_trait_constraint: false,
302 }
303 }
304
305 pub(crate) fn with_is_inside_trait_constraint(&self) -> Self {
306 Self {
307 is_inside_trait_constraint: true,
308 ..*self
309 }
310 }
311
312 pub(crate) fn engines(&self) -> &Engines {
313 self.engines
314 }
315
316 pub(crate) fn is_inside_trait_constraint(&self) -> bool {
317 self.is_inside_trait_constraint
318 }
319}
320
321pub trait PartialEqWithEngines {
322 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool;
323}
324
325pub struct OrdWithEnginesContext<'a> {
326 engines: &'a Engines,
327 is_inside_trait_constraint: bool,
328}
329
330impl<'a> OrdWithEnginesContext<'a> {
331 pub(crate) fn new(engines: &'a Engines) -> Self {
332 Self {
333 engines,
334 is_inside_trait_constraint: false,
335 }
336 }
337
338 pub(crate) fn with_is_inside_trait_constraint(&self) -> Self {
339 Self {
340 is_inside_trait_constraint: true,
341 ..*self
342 }
343 }
344
345 pub(crate) fn engines(&self) -> &Engines {
346 self.engines
347 }
348
349 pub(crate) fn is_inside_trait_constraint(&self) -> bool {
350 self.is_inside_trait_constraint
351 }
352}
353
354pub trait OrdWithEngines {
355 fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering;
356}
357
358impl<T: EqWithEngines + ?Sized> EqWithEngines for &T {}
359impl<T: PartialEqWithEngines + ?Sized> PartialEqWithEngines for &T {
360 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
361 (*self).eq(*other, ctx)
362 }
363}
364impl<T: OrdWithEngines + ?Sized> OrdWithEngines for &T {
365 fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering {
366 (*self).cmp(*other, ctx)
367 }
368}
369
370impl<T: OrdWithEngines> OrdWithEngines for Option<T> {
371 fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering {
372 match (self, other) {
373 (Some(x), Some(y)) => x.cmp(y, ctx),
374 (Some(_), None) => Ordering::Less,
375 (None, Some(_)) => Ordering::Greater,
376 (None, None) => Ordering::Equal,
377 }
378 }
379}
380
381impl<T: OrdWithEngines> OrdWithEngines for Box<T> {
382 fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering {
383 (**self).cmp(&(**other), ctx)
384 }
385}
386
387impl<T: EqWithEngines> EqWithEngines for Option<T> {}
388impl<T: PartialEqWithEngines> PartialEqWithEngines for Option<T> {
389 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
390 match (self, other) {
391 (None, None) => true,
392 (Some(x), Some(y)) => x.eq(y, ctx),
393 _ => false,
394 }
395 }
396}
397
398impl<T: EqWithEngines> EqWithEngines for Box<T> {}
399impl<T: PartialEqWithEngines> PartialEqWithEngines for Box<T> {
400 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
401 (**self).eq(&(**other), ctx)
402 }
403}
404
405impl<T: EqWithEngines> EqWithEngines for [T] {}
406impl<T: PartialEqWithEngines> PartialEqWithEngines for [T] {
407 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
408 self.len() == other.len() && self.iter().zip(other.iter()).all(|(x, y)| x.eq(y, ctx))
409 }
410}
411impl<T: OrdWithEngines> OrdWithEngines for [T] {
412 fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering {
413 let len_cmp = self.len().cmp(&other.len());
414 if len_cmp != Ordering::Equal {
415 return len_cmp;
416 }
417
418 for (a, b) in self.iter().zip(other.iter()) {
419 let cmp = a.cmp(b, ctx);
420 if cmp != Ordering::Equal {
421 return cmp;
422 }
423 }
424
425 Ordering::Equal
426 }
427}
428
429pub(crate) fn make_hasher<'a: 'b, 'b, K>(
430 hash_builder: &'a impl BuildHasher,
431 engines: &'b Engines,
432) -> impl Fn(&K) -> u64 + 'b
433where
434 K: HashWithEngines + ?Sized,
435{
436 move |key: &K| {
437 let mut state = hash_builder.build_hasher();
438 key.hash(&mut state, engines);
439 state.finish()
440 }
441}
442
443pub trait SpannedWithEngines {
444 fn span(&self, engines: &Engines) -> Span;
445}