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));
76
77#[derive(
79 Debug, Clone, Copy, EnumIsA, EnumAsGetters, VariantName, VariantIndexArity, Drive, DriveMut,
80)]
81pub enum AnyTransItem<'ctx> {
82 Type(&'ctx TypeDecl),
83 Fun(&'ctx FunDecl),
84 Global(&'ctx GlobalDecl),
85 TraitDecl(&'ctx TraitDecl),
86 TraitImpl(&'ctx TraitImpl),
87}
88
89#[derive(Debug, EnumIsA, EnumAsGetters, VariantName, VariantIndexArity, Drive, DriveMut)]
91pub enum AnyTransItemMut<'ctx> {
92 Type(&'ctx mut TypeDecl),
93 Fun(&'ctx mut FunDecl),
94 Global(&'ctx mut GlobalDecl),
95 TraitDecl(&'ctx mut TraitDecl),
96 TraitImpl(&'ctx mut TraitImpl),
97}
98
99#[derive(Default, Clone, Drive, DriveMut, Serialize, Deserialize)]
100pub struct TargetInfo {
101 pub target_pointer_size: types::ByteCount,
103 pub is_little_endian: bool,
105}
106
107#[derive(Default, Clone, Drive, DriveMut, Serialize, Deserialize)]
109pub struct TranslatedCrate {
110 #[drive(skip)]
112 pub crate_name: String,
113
114 #[drive(skip)]
118 pub options: crate::options::CliOpts,
119
120 #[drive(skip)]
122 pub target_information: TargetInfo,
123
124 #[serde(with = "HashMapToArray::<AnyTransId, Name>")]
129 pub item_names: HashMap<AnyTransId, Name>,
130 #[serde(with = "HashMapToArray::<AnyTransId, Name>")]
132 pub short_names: HashMap<AnyTransId, Name>,
133
134 #[drive(skip)]
136 pub files: Vector<FileId, File>,
137 pub type_decls: Vector<TypeDeclId, TypeDecl>,
139 pub fun_decls: Vector<FunDeclId, FunDecl>,
141 pub global_decls: Vector<GlobalDeclId, GlobalDecl>,
143 pub trait_decls: Vector<TraitDeclId, TraitDecl>,
145 pub trait_impls: Vector<TraitImplId, TraitImpl>,
147 #[drive(skip)]
149 pub ordered_decls: Option<DeclarationsGroups>,
150}
151
152impl TranslatedCrate {
153 pub fn item_name(&self, id: impl Into<AnyTransId>) -> Option<&Name> {
154 self.item_names.get(&id.into())
155 }
156
157 pub fn item_short_name(&self, id: impl Into<AnyTransId>) -> Option<&Name> {
158 let id = id.into();
159 self.short_names.get(&id).or_else(|| self.item_name(id))
160 }
161
162 pub fn get_item(&self, trans_id: impl Into<AnyTransId>) -> Option<AnyTransItem<'_>> {
163 match trans_id.into() {
164 AnyTransId::Type(id) => self.type_decls.get(id).map(AnyTransItem::Type),
165 AnyTransId::Fun(id) => self.fun_decls.get(id).map(AnyTransItem::Fun),
166 AnyTransId::Global(id) => self.global_decls.get(id).map(AnyTransItem::Global),
167 AnyTransId::TraitDecl(id) => self.trait_decls.get(id).map(AnyTransItem::TraitDecl),
168 AnyTransId::TraitImpl(id) => self.trait_impls.get(id).map(AnyTransItem::TraitImpl),
169 }
170 }
171
172 pub fn get_item_mut(&mut self, trans_id: AnyTransId) -> Option<AnyTransItemMut<'_>> {
173 match trans_id {
174 AnyTransId::Type(id) => self.type_decls.get_mut(id).map(AnyTransItemMut::Type),
175 AnyTransId::Fun(id) => self.fun_decls.get_mut(id).map(AnyTransItemMut::Fun),
176 AnyTransId::Global(id) => self.global_decls.get_mut(id).map(AnyTransItemMut::Global),
177 AnyTransId::TraitDecl(id) => {
178 self.trait_decls.get_mut(id).map(AnyTransItemMut::TraitDecl)
179 }
180 AnyTransId::TraitImpl(id) => {
181 self.trait_impls.get_mut(id).map(AnyTransItemMut::TraitImpl)
182 }
183 }
184 }
185
186 pub fn all_ids(&self) -> impl Iterator<Item = AnyTransId> + use<> {
187 self.type_decls
188 .all_indices()
189 .map(AnyTransId::Type)
190 .chain(self.trait_decls.all_indices().map(AnyTransId::TraitDecl))
191 .chain(self.trait_impls.all_indices().map(AnyTransId::TraitImpl))
192 .chain(self.global_decls.all_indices().map(AnyTransId::Global))
193 .chain(self.fun_decls.all_indices().map(AnyTransId::Fun))
194 }
195 pub fn all_items(&self) -> impl Iterator<Item = AnyTransItem<'_>> {
196 self.type_decls
197 .iter()
198 .map(AnyTransItem::Type)
199 .chain(self.trait_decls.iter().map(AnyTransItem::TraitDecl))
200 .chain(self.trait_impls.iter().map(AnyTransItem::TraitImpl))
201 .chain(self.global_decls.iter().map(AnyTransItem::Global))
202 .chain(self.fun_decls.iter().map(AnyTransItem::Fun))
203 }
204 pub fn all_items_mut(&mut self) -> impl Iterator<Item = AnyTransItemMut<'_>> {
205 self.type_decls
206 .iter_mut()
207 .map(AnyTransItemMut::Type)
208 .chain(self.trait_impls.iter_mut().map(AnyTransItemMut::TraitImpl))
209 .chain(self.trait_decls.iter_mut().map(AnyTransItemMut::TraitDecl))
210 .chain(self.fun_decls.iter_mut().map(AnyTransItemMut::Fun))
211 .chain(self.global_decls.iter_mut().map(AnyTransItemMut::Global))
212 }
213 pub fn all_items_with_ids(&self) -> impl Iterator<Item = (AnyTransId, AnyTransItem<'_>)> {
214 self.all_items().map(|item| (item.id(), item))
215 }
216}
217
218impl<'ctx> AnyTransItem<'ctx> {
219 pub fn id(&self) -> AnyTransId {
220 match self {
221 AnyTransItem::Type(d) => d.def_id.into(),
222 AnyTransItem::Fun(d) => d.def_id.into(),
223 AnyTransItem::Global(d) => d.def_id.into(),
224 AnyTransItem::TraitDecl(d) => d.def_id.into(),
225 AnyTransItem::TraitImpl(d) => d.def_id.into(),
226 }
227 }
228
229 pub fn item_meta(&self) -> &'ctx ItemMeta {
230 match self {
231 AnyTransItem::Type(d) => &d.item_meta,
232 AnyTransItem::Fun(d) => &d.item_meta,
233 AnyTransItem::Global(d) => &d.item_meta,
234 AnyTransItem::TraitDecl(d) => &d.item_meta,
235 AnyTransItem::TraitImpl(d) => &d.item_meta,
236 }
237 }
238
239 pub fn generic_params(&self) -> &'ctx GenericParams {
241 match self {
242 AnyTransItem::Type(d) => &d.generics,
243 AnyTransItem::Fun(d) => &d.signature.generics,
244 AnyTransItem::Global(d) => &d.generics,
245 AnyTransItem::TraitDecl(d) => &d.generics,
246 AnyTransItem::TraitImpl(d) => &d.generics,
247 }
248 }
249
250 pub fn parent_info(&self) -> &'ctx ItemKind {
252 match self {
253 AnyTransItem::Fun(d) => &d.kind,
254 AnyTransItem::Global(d) => &d.kind,
255 AnyTransItem::Type(_) | AnyTransItem::TraitDecl(_) | AnyTransItem::TraitImpl(_) => {
256 &ItemKind::TopLevel
257 }
258 }
259 }
260
261 pub fn identity_args(&self) -> GenericArgs {
263 self.generic_params().identity_args()
264 }
265
266 pub fn drive<V: VisitAst>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
269 match *self {
270 AnyTransItem::Type(d) => visitor.visit(d),
271 AnyTransItem::Fun(d) => visitor.visit(d),
272 AnyTransItem::Global(d) => visitor.visit(d),
273 AnyTransItem::TraitDecl(d) => visitor.visit(d),
274 AnyTransItem::TraitImpl(d) => visitor.visit(d),
275 }
276 }
277
278 pub fn dyn_visit<T: AstVisitable>(&self, f: impl FnMut(&T)) {
280 match *self {
281 AnyTransItem::Type(d) => d.dyn_visit(f),
282 AnyTransItem::Fun(d) => d.dyn_visit(f),
283 AnyTransItem::Global(d) => d.dyn_visit(f),
284 AnyTransItem::TraitDecl(d) => d.dyn_visit(f),
285 AnyTransItem::TraitImpl(d) => d.dyn_visit(f),
286 }
287 }
288}
289
290impl<'ctx> AnyTransItemMut<'ctx> {
291 pub fn as_ref(&self) -> AnyTransItem<'_> {
292 match self {
293 AnyTransItemMut::Type(d) => AnyTransItem::Type(d),
294 AnyTransItemMut::Fun(d) => AnyTransItem::Fun(d),
295 AnyTransItemMut::Global(d) => AnyTransItem::Global(d),
296 AnyTransItemMut::TraitDecl(d) => AnyTransItem::TraitDecl(d),
297 AnyTransItemMut::TraitImpl(d) => AnyTransItem::TraitImpl(d),
298 }
299 }
300
301 pub fn generic_params(&mut self) -> &mut GenericParams {
303 match self {
304 AnyTransItemMut::Type(d) => &mut d.generics,
305 AnyTransItemMut::Fun(d) => &mut d.signature.generics,
306 AnyTransItemMut::Global(d) => &mut d.generics,
307 AnyTransItemMut::TraitDecl(d) => &mut d.generics,
308 AnyTransItemMut::TraitImpl(d) => &mut d.generics,
309 }
310 }
311
312 pub fn drive_mut<V: VisitAstMut>(&mut self, visitor: &mut V) -> ControlFlow<V::Break> {
315 match self {
316 AnyTransItemMut::Type(d) => visitor.visit(*d),
317 AnyTransItemMut::Fun(d) => visitor.visit(*d),
318 AnyTransItemMut::Global(d) => visitor.visit(*d),
319 AnyTransItemMut::TraitDecl(d) => visitor.visit(*d),
320 AnyTransItemMut::TraitImpl(d) => visitor.visit(*d),
321 }
322 }
323
324 pub fn dyn_visit_mut<T: AstVisitable>(&mut self, f: impl FnMut(&mut T)) {
326 match self {
327 AnyTransItemMut::Type(d) => d.dyn_visit_mut(f),
328 AnyTransItemMut::Fun(d) => d.dyn_visit_mut(f),
329 AnyTransItemMut::Global(d) => d.dyn_visit_mut(f),
330 AnyTransItemMut::TraitDecl(d) => d.dyn_visit_mut(f),
331 AnyTransItemMut::TraitImpl(d) => d.dyn_visit_mut(f),
332 }
333 }
334}
335
336impl fmt::Display for TranslatedCrate {
337 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
338 let fmt: &FmtCtx = &self.into_fmt();
339 match &self.ordered_decls {
340 None => {
341 for d in &self.type_decls {
343 writeln!(f, "{}\n", d.with_ctx(fmt))?
344 }
345 for d in &self.global_decls {
346 writeln!(f, "{}\n", d.with_ctx(fmt))?
347 }
348 for d in &self.trait_decls {
349 writeln!(f, "{}\n", d.with_ctx(fmt))?
350 }
351 for d in &self.trait_impls {
352 writeln!(f, "{}\n", d.with_ctx(fmt))?
353 }
354 for d in &self.fun_decls {
355 writeln!(f, "{}\n", d.with_ctx(fmt))?
356 }
357 }
358 Some(ordered_decls) => {
359 for gr in ordered_decls {
360 for id in gr.get_ids() {
361 writeln!(f, "{}\n", fmt.format_decl_id(id))?
362 }
363 }
364 }
365 }
366 fmt::Result::Ok(())
367 }
368}
369
370impl<'tcx, 'ctx, 'a> IntoFormatter for &'a TranslatedCrate {
371 type C = FmtCtx<'a>;
372
373 fn into_fmt(self) -> Self::C {
374 FmtCtx {
375 translated: Some(self),
376 ..Default::default()
377 }
378 }
379}
380
381pub trait HasVectorOf<Id: Idx>: std::ops::Index<Id, Output: Sized> {
382 fn get_vector(&self) -> &Vector<Id, Self::Output>;
383 fn get_vector_mut(&mut self) -> &mut Vector<Id, Self::Output>;
384}
385
386macro_rules! mk_index_impls {
388 ($ty:ident.$field:ident[$idx:ty]: $output:ty) => {
389 impl std::ops::Index<$idx> for $ty {
390 type Output = $output;
391 fn index(&self, index: $idx) -> &Self::Output {
392 &self.$field[index]
393 }
394 }
395 impl std::ops::IndexMut<$idx> for $ty {
396 fn index_mut(&mut self, index: $idx) -> &mut Self::Output {
397 &mut self.$field[index]
398 }
399 }
400 impl HasVectorOf<$idx> for $ty {
401 fn get_vector(&self) -> &Vector<$idx, Self::Output> {
402 &self.$field
403 }
404 fn get_vector_mut(&mut self) -> &mut Vector<$idx, Self::Output> {
405 &mut self.$field
406 }
407 }
408 };
409}
410pub(crate) use mk_index_impls;
411
412mk_index_impls!(TranslatedCrate.type_decls[TypeDeclId]: TypeDecl);
413mk_index_impls!(TranslatedCrate.fun_decls[FunDeclId]: FunDecl);
414mk_index_impls!(TranslatedCrate.global_decls[GlobalDeclId]: GlobalDecl);
415mk_index_impls!(TranslatedCrate.trait_decls[TraitDeclId]: TraitDecl);
416mk_index_impls!(TranslatedCrate.trait_impls[TraitImplId]: TraitImpl);