1use crate::ast::*;
2use crate::formatter::{FmtCtx, IntoFormatter};
3use crate::ids::Vector;
4use crate::pretty::FmtWithCtx;
5use crate::reorder_decls::DeclarationsGroups;
6use derive_generic_visitor::{ControlFlow, Drive, DriveMut};
7use index_vec::Idx;
8use macros::{EnumAsGetters, EnumIsA, VariantIndexArity, VariantName};
9use serde::{Deserialize, Serialize};
10use serde_map_to_array::HashMapToArray;
11use std::cmp::{Ord, PartialOrd};
12use std::collections::HashMap;
13use std::fmt;
14
15generate_index_type!(FunDeclId, "Fun");
16generate_index_type!(TypeDeclId, "Adt");
17generate_index_type!(GlobalDeclId, "Global");
18generate_index_type!(TraitDeclId, "TraitDecl");
19generate_index_type!(TraitImplId, "TraitImpl");
20
21#[derive(
23 Copy,
24 Clone,
25 Debug,
26 PartialOrd,
27 Ord,
28 PartialEq,
29 Eq,
30 Hash,
31 EnumIsA,
32 EnumAsGetters,
33 VariantName,
34 VariantIndexArity,
35 Serialize,
36 Deserialize,
37 Drive,
38 DriveMut,
39)]
40#[charon::rename("AnyDeclId")]
41#[charon::variants_prefix("Id")]
42pub enum AnyTransId {
43 Type(TypeDeclId),
44 Fun(FunDeclId),
45 Global(GlobalDeclId),
46 TraitDecl(TraitDeclId),
47 TraitImpl(TraitImplId),
48}
49
50macro_rules! wrap_unwrap_enum {
52 ($enum:ident::$variant:ident($variant_ty:ident)) => {
53 impl TryFrom<$enum> for $variant_ty {
54 type Error = ();
55 fn try_from(x: $enum) -> Result<Self, Self::Error> {
56 match x {
57 $enum::$variant(x) => Ok(x),
58 _ => Err(()),
59 }
60 }
61 }
62
63 impl From<$variant_ty> for $enum {
64 fn from(x: $variant_ty) -> Self {
65 $enum::$variant(x)
66 }
67 }
68 };
69}
70
71wrap_unwrap_enum!(AnyTransId::Fun(FunDeclId));
72wrap_unwrap_enum!(AnyTransId::Global(GlobalDeclId));
73wrap_unwrap_enum!(AnyTransId::Type(TypeDeclId));
74wrap_unwrap_enum!(AnyTransId::TraitDecl(TraitDeclId));
75wrap_unwrap_enum!(AnyTransId::TraitImpl(TraitImplId));
76impl TryFrom<AnyTransId> for TypeId {
77 type Error = ();
78 fn try_from(x: AnyTransId) -> Result<Self, Self::Error> {
79 Ok(TypeId::Adt(x.try_into()?))
80 }
81}
82impl TryFrom<AnyTransId> for FunId {
83 type Error = ();
84 fn try_from(x: AnyTransId) -> Result<Self, Self::Error> {
85 Ok(FunId::Regular(x.try_into()?))
86 }
87}
88
89#[derive(
91 Debug, Clone, Copy, EnumIsA, EnumAsGetters, VariantName, VariantIndexArity, Drive, DriveMut,
92)]
93pub enum AnyTransItem<'ctx> {
94 Type(&'ctx TypeDecl),
95 Fun(&'ctx FunDecl),
96 Global(&'ctx GlobalDecl),
97 TraitDecl(&'ctx TraitDecl),
98 TraitImpl(&'ctx TraitImpl),
99}
100
101#[derive(Debug, EnumIsA, EnumAsGetters, VariantName, VariantIndexArity, Drive, DriveMut)]
103pub enum AnyTransItemMut<'ctx> {
104 Type(&'ctx mut TypeDecl),
105 Fun(&'ctx mut FunDecl),
106 Global(&'ctx mut GlobalDecl),
107 TraitDecl(&'ctx mut TraitDecl),
108 TraitImpl(&'ctx mut TraitImpl),
109}
110
111#[derive(Default, Clone, Drive, DriveMut, Serialize, Deserialize)]
112pub struct TargetInfo {
113 pub target_pointer_size: types::ByteCount,
115 pub is_little_endian: bool,
117}
118
119#[derive(Default, Clone, Drive, DriveMut, Serialize, Deserialize)]
121pub struct TranslatedCrate {
122 #[drive(skip)]
124 pub crate_name: String,
125
126 #[drive(skip)]
130 pub options: crate::options::CliOpts,
131
132 #[drive(skip)]
134 pub target_information: TargetInfo,
135
136 #[serde(with = "HashMapToArray::<AnyTransId, Name>")]
141 pub item_names: HashMap<AnyTransId, Name>,
142 #[serde(with = "HashMapToArray::<AnyTransId, Name>")]
144 pub short_names: HashMap<AnyTransId, Name>,
145
146 #[drive(skip)]
148 pub files: Vector<FileId, File>,
149 pub type_decls: Vector<TypeDeclId, TypeDecl>,
151 pub fun_decls: Vector<FunDeclId, FunDecl>,
153 pub global_decls: Vector<GlobalDeclId, GlobalDecl>,
155 pub trait_decls: Vector<TraitDeclId, TraitDecl>,
157 pub trait_impls: Vector<TraitImplId, TraitImpl>,
159 #[drive(skip)]
161 pub ordered_decls: Option<DeclarationsGroups>,
162}
163
164impl TranslatedCrate {
165 pub fn item_name(&self, id: impl Into<AnyTransId>) -> Option<&Name> {
166 self.item_names.get(&id.into())
167 }
168
169 pub fn item_short_name(&self, id: impl Into<AnyTransId>) -> Option<&Name> {
170 let id = id.into();
171 self.short_names.get(&id).or_else(|| self.item_name(id))
172 }
173
174 pub fn get_item(&self, trans_id: impl Into<AnyTransId>) -> Option<AnyTransItem<'_>> {
175 match trans_id.into() {
176 AnyTransId::Type(id) => self.type_decls.get(id).map(AnyTransItem::Type),
177 AnyTransId::Fun(id) => self.fun_decls.get(id).map(AnyTransItem::Fun),
178 AnyTransId::Global(id) => self.global_decls.get(id).map(AnyTransItem::Global),
179 AnyTransId::TraitDecl(id) => self.trait_decls.get(id).map(AnyTransItem::TraitDecl),
180 AnyTransId::TraitImpl(id) => self.trait_impls.get(id).map(AnyTransItem::TraitImpl),
181 }
182 }
183
184 pub fn get_item_mut(&mut self, trans_id: AnyTransId) -> Option<AnyTransItemMut<'_>> {
185 match trans_id {
186 AnyTransId::Type(id) => self.type_decls.get_mut(id).map(AnyTransItemMut::Type),
187 AnyTransId::Fun(id) => self.fun_decls.get_mut(id).map(AnyTransItemMut::Fun),
188 AnyTransId::Global(id) => self.global_decls.get_mut(id).map(AnyTransItemMut::Global),
189 AnyTransId::TraitDecl(id) => {
190 self.trait_decls.get_mut(id).map(AnyTransItemMut::TraitDecl)
191 }
192 AnyTransId::TraitImpl(id) => {
193 self.trait_impls.get_mut(id).map(AnyTransItemMut::TraitImpl)
194 }
195 }
196 }
197
198 pub fn all_ids(&self) -> impl Iterator<Item = AnyTransId> + use<> {
199 self.type_decls
200 .all_indices()
201 .map(AnyTransId::Type)
202 .chain(self.trait_decls.all_indices().map(AnyTransId::TraitDecl))
203 .chain(self.trait_impls.all_indices().map(AnyTransId::TraitImpl))
204 .chain(self.global_decls.all_indices().map(AnyTransId::Global))
205 .chain(self.fun_decls.all_indices().map(AnyTransId::Fun))
206 }
207 pub fn all_items(&self) -> impl Iterator<Item = AnyTransItem<'_>> {
208 self.type_decls
209 .iter()
210 .map(AnyTransItem::Type)
211 .chain(self.trait_decls.iter().map(AnyTransItem::TraitDecl))
212 .chain(self.trait_impls.iter().map(AnyTransItem::TraitImpl))
213 .chain(self.global_decls.iter().map(AnyTransItem::Global))
214 .chain(self.fun_decls.iter().map(AnyTransItem::Fun))
215 }
216 pub fn all_items_mut(&mut self) -> impl Iterator<Item = AnyTransItemMut<'_>> {
217 self.type_decls
218 .iter_mut()
219 .map(AnyTransItemMut::Type)
220 .chain(self.trait_impls.iter_mut().map(AnyTransItemMut::TraitImpl))
221 .chain(self.trait_decls.iter_mut().map(AnyTransItemMut::TraitDecl))
222 .chain(self.fun_decls.iter_mut().map(AnyTransItemMut::Fun))
223 .chain(self.global_decls.iter_mut().map(AnyTransItemMut::Global))
224 }
225 pub fn all_items_with_ids(&self) -> impl Iterator<Item = (AnyTransId, AnyTransItem<'_>)> {
226 self.all_items().map(|item| (item.id(), item))
227 }
228}
229
230impl<'ctx> AnyTransItem<'ctx> {
231 pub fn id(&self) -> AnyTransId {
232 match self {
233 AnyTransItem::Type(d) => d.def_id.into(),
234 AnyTransItem::Fun(d) => d.def_id.into(),
235 AnyTransItem::Global(d) => d.def_id.into(),
236 AnyTransItem::TraitDecl(d) => d.def_id.into(),
237 AnyTransItem::TraitImpl(d) => d.def_id.into(),
238 }
239 }
240
241 pub fn item_meta(&self) -> &'ctx ItemMeta {
242 match self {
243 AnyTransItem::Type(d) => &d.item_meta,
244 AnyTransItem::Fun(d) => &d.item_meta,
245 AnyTransItem::Global(d) => &d.item_meta,
246 AnyTransItem::TraitDecl(d) => &d.item_meta,
247 AnyTransItem::TraitImpl(d) => &d.item_meta,
248 }
249 }
250
251 pub fn generic_params(&self) -> &'ctx GenericParams {
253 match self {
254 AnyTransItem::Type(d) => &d.generics,
255 AnyTransItem::Fun(d) => &d.signature.generics,
256 AnyTransItem::Global(d) => &d.generics,
257 AnyTransItem::TraitDecl(d) => &d.generics,
258 AnyTransItem::TraitImpl(d) => &d.generics,
259 }
260 }
261
262 pub fn parent_info(&self) -> &'ctx ItemKind {
264 match self {
265 AnyTransItem::Fun(d) => &d.kind,
266 AnyTransItem::Global(d) => &d.kind,
267 AnyTransItem::Type(_) | AnyTransItem::TraitDecl(_) | AnyTransItem::TraitImpl(_) => {
268 &ItemKind::TopLevel
269 }
270 }
271 }
272
273 pub fn identity_args(&self) -> GenericArgs {
275 self.generic_params().identity_args()
276 }
277
278 pub fn drive<V: VisitAst>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
281 match *self {
282 AnyTransItem::Type(d) => visitor.visit(d),
283 AnyTransItem::Fun(d) => visitor.visit(d),
284 AnyTransItem::Global(d) => visitor.visit(d),
285 AnyTransItem::TraitDecl(d) => visitor.visit(d),
286 AnyTransItem::TraitImpl(d) => visitor.visit(d),
287 }
288 }
289
290 pub fn dyn_visit<T: AstVisitable>(&self, f: impl FnMut(&T)) {
292 match *self {
293 AnyTransItem::Type(d) => d.dyn_visit(f),
294 AnyTransItem::Fun(d) => d.dyn_visit(f),
295 AnyTransItem::Global(d) => d.dyn_visit(f),
296 AnyTransItem::TraitDecl(d) => d.dyn_visit(f),
297 AnyTransItem::TraitImpl(d) => d.dyn_visit(f),
298 }
299 }
300}
301
302impl<'ctx> AnyTransItemMut<'ctx> {
303 pub fn as_ref(&self) -> AnyTransItem<'_> {
304 match self {
305 AnyTransItemMut::Type(d) => AnyTransItem::Type(d),
306 AnyTransItemMut::Fun(d) => AnyTransItem::Fun(d),
307 AnyTransItemMut::Global(d) => AnyTransItem::Global(d),
308 AnyTransItemMut::TraitDecl(d) => AnyTransItem::TraitDecl(d),
309 AnyTransItemMut::TraitImpl(d) => AnyTransItem::TraitImpl(d),
310 }
311 }
312 pub fn reborrow(&mut self) -> AnyTransItemMut<'_> {
313 match self {
314 AnyTransItemMut::Type(d) => AnyTransItemMut::Type(d),
315 AnyTransItemMut::Fun(d) => AnyTransItemMut::Fun(d),
316 AnyTransItemMut::Global(d) => AnyTransItemMut::Global(d),
317 AnyTransItemMut::TraitDecl(d) => AnyTransItemMut::TraitDecl(d),
318 AnyTransItemMut::TraitImpl(d) => AnyTransItemMut::TraitImpl(d),
319 }
320 }
321
322 pub fn generic_params(&mut self) -> &mut GenericParams {
324 match self {
325 AnyTransItemMut::Type(d) => &mut d.generics,
326 AnyTransItemMut::Fun(d) => &mut d.signature.generics,
327 AnyTransItemMut::Global(d) => &mut d.generics,
328 AnyTransItemMut::TraitDecl(d) => &mut d.generics,
329 AnyTransItemMut::TraitImpl(d) => &mut d.generics,
330 }
331 }
332
333 pub fn drive_mut<V: VisitAstMut>(&mut self, visitor: &mut V) -> ControlFlow<V::Break> {
336 match self {
337 AnyTransItemMut::Type(d) => visitor.visit(*d),
338 AnyTransItemMut::Fun(d) => visitor.visit(*d),
339 AnyTransItemMut::Global(d) => visitor.visit(*d),
340 AnyTransItemMut::TraitDecl(d) => visitor.visit(*d),
341 AnyTransItemMut::TraitImpl(d) => visitor.visit(*d),
342 }
343 }
344
345 pub fn dyn_visit_mut<T: AstVisitable>(&mut self, f: impl FnMut(&mut T)) {
347 match self {
348 AnyTransItemMut::Type(d) => d.dyn_visit_mut(f),
349 AnyTransItemMut::Fun(d) => d.dyn_visit_mut(f),
350 AnyTransItemMut::Global(d) => d.dyn_visit_mut(f),
351 AnyTransItemMut::TraitDecl(d) => d.dyn_visit_mut(f),
352 AnyTransItemMut::TraitImpl(d) => d.dyn_visit_mut(f),
353 }
354 }
355}
356
357impl fmt::Display for TranslatedCrate {
358 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
359 let fmt: &FmtCtx = &self.into_fmt();
360 match &self.ordered_decls {
361 None => {
362 for d in &self.type_decls {
364 writeln!(f, "{}\n", d.with_ctx(fmt))?
365 }
366 for d in &self.global_decls {
367 writeln!(f, "{}\n", d.with_ctx(fmt))?
368 }
369 for d in &self.trait_decls {
370 writeln!(f, "{}\n", d.with_ctx(fmt))?
371 }
372 for d in &self.trait_impls {
373 writeln!(f, "{}\n", d.with_ctx(fmt))?
374 }
375 for d in &self.fun_decls {
376 writeln!(f, "{}\n", d.with_ctx(fmt))?
377 }
378 }
379 Some(ordered_decls) => {
380 for gr in ordered_decls {
381 for id in gr.get_ids() {
382 writeln!(f, "{}\n", fmt.format_decl_id(id))?
383 }
384 }
385 }
386 }
387 fmt::Result::Ok(())
388 }
389}
390
391impl<'tcx, 'ctx, 'a> IntoFormatter for &'a TranslatedCrate {
392 type C = FmtCtx<'a>;
393
394 fn into_fmt(self) -> Self::C {
395 FmtCtx {
396 translated: Some(self),
397 ..Default::default()
398 }
399 }
400}
401
402pub trait HasVectorOf<Id: Idx>: std::ops::Index<Id, Output: Sized> {
403 fn get_vector(&self) -> &Vector<Id, Self::Output>;
404 fn get_vector_mut(&mut self) -> &mut Vector<Id, Self::Output>;
405}
406
407macro_rules! mk_index_impls {
409 ($ty:ident.$field:ident[$idx:ty]: $output:ty) => {
410 impl std::ops::Index<$idx> for $ty {
411 type Output = $output;
412 fn index(&self, index: $idx) -> &Self::Output {
413 &self.$field[index]
414 }
415 }
416 impl std::ops::IndexMut<$idx> for $ty {
417 fn index_mut(&mut self, index: $idx) -> &mut Self::Output {
418 &mut self.$field[index]
419 }
420 }
421 impl HasVectorOf<$idx> for $ty {
422 fn get_vector(&self) -> &Vector<$idx, Self::Output> {
423 &self.$field
424 }
425 fn get_vector_mut(&mut self) -> &mut Vector<$idx, Self::Output> {
426 &mut self.$field
427 }
428 }
429 };
430}
431pub(crate) use mk_index_impls;
432
433mk_index_impls!(TranslatedCrate.type_decls[TypeDeclId]: TypeDecl);
434mk_index_impls!(TranslatedCrate.fun_decls[FunDeclId]: FunDecl);
435mk_index_impls!(TranslatedCrate.global_decls[GlobalDeclId]: GlobalDecl);
436mk_index_impls!(TranslatedCrate.trait_decls[TraitDeclId]: TraitDecl);
437mk_index_impls!(TranslatedCrate.trait_impls[TraitImplId]: TraitImpl);