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