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