1use std::fmt;
2
3use derive_generic_visitor::{Drive, DriveMut, DriveTwo};
4use index_vec::Idx;
5use itertools::Itertools;
6use serde::{Deserialize, Serialize};
7use serde_state::{DeserializeState, SerializeState};
8
9use crate::ast::*;
10use crate::formatter::{FmtCtx, IntoFormatter};
11use crate::ids::{IndexMap, IndexVec};
12use crate::pretty::FmtWithCtx;
13use crate::utils::serialize_map_to_array::SeqHashMapToArray;
14use macros::{EnumAsGetters, EnumIsA, VariantIndexArity, VariantName};
15
16pub type TargetTriple = String;
18
19#[derive(Default, Clone, Drive, DriveMut, DriveTwo, SerializeState, DeserializeState)]
35#[serde_state(state_implements = HashConsSerializerState)]
36pub struct TranslatedCrate {
37 pub crate_name: String,
39
40 #[serde_state(stateless)]
43 pub options: crate::options::CliOpts,
44
45 #[serde(with = "SeqHashMapToArray::<TargetTriple, TargetInfo>")]
49 pub target_information: SeqHashMap<TargetTriple, TargetInfo>,
50
51 #[serde_state(stateless)]
56 pub files: IndexVec<FileId, File>,
57
58 #[serde(with = "SeqHashMapToArray::<ItemId, Name>")]
63 pub item_names: SeqHashMap<ItemId, Name>,
64 pub assoc_item_names: IndexMap<TraitDeclId, AssocItemNames>,
69 #[serde(with = "SeqHashMapToArray::<ItemId, Name>")]
71 pub short_names: SeqHashMap<ItemId, Name>,
72
73 pub type_decls: IndexMap<TypeDeclId, TypeDecl>,
75 pub fun_decls: IndexMap<FunDeclId, FunDecl>,
80 pub global_decls: IndexMap<GlobalDeclId, GlobalDecl>,
82 pub trait_decls: IndexMap<TraitDeclId, TraitDecl>,
84 pub trait_impls: IndexMap<TraitImplId, TraitImpl>,
86 #[serde_state(stateless)]
98 pub ordered_decls: Option<Vec<DeclarationGroup>>,
99}
100
101#[derive(
104 Debug, Clone, VariantIndexArity, VariantName, EnumAsGetters, EnumIsA, Serialize, Deserialize,
105)]
106#[cfg_attr(feature = "charon_on_charon", charon::variants_suffix("Group"))]
107pub enum GDeclarationGroup<Id> {
108 NonRec(Id),
110 Rec(Vec<Id>),
112}
113
114#[derive(
116 Debug, Clone, VariantIndexArity, VariantName, EnumAsGetters, EnumIsA, Serialize, Deserialize,
117)]
118#[cfg_attr(feature = "charon_on_charon", charon::variants_suffix("Group"))]
119pub enum DeclarationGroup {
120 Type(GDeclarationGroup<TypeDeclId>),
122 Fun(GDeclarationGroup<FunDeclId>),
124 Global(GDeclarationGroup<GlobalDeclId>),
126 TraitDecl(GDeclarationGroup<TraitDeclId>),
127 TraitImpl(GDeclarationGroup<TraitImplId>),
128 Mixed(GDeclarationGroup<ItemId>),
130}
131
132#[derive(Default, Clone, Drive, DriveMut, DriveTwo, SerializeState, DeserializeState)]
133pub struct AssocItemNames {
134 pub types: IndexVec<AssocTypeId, TraitItemName>,
135 pub methods: IndexVec<TraitMethodId, TraitItemName>,
136 pub consts: IndexVec<AssocConstId, TraitItemName>,
137}
138
139impl TranslatedCrate {
140 pub fn item_name(&self, id: impl Into<ItemId>) -> &Name {
141 self.item_names.get(&id.into()).unwrap()
144 }
145 pub fn assoc_item_name(
146 &self,
147 trait_id: TraitDeclId,
148 id: impl Into<AssocItemId>,
149 ) -> TraitItemName {
150 let names = &self.assoc_item_names[trait_id];
151 match id.into() {
152 AssocItemId::Type(id) => names.types[id],
153 AssocItemId::Method(id) => names.methods[id],
154 AssocItemId::Const(id) => names.consts[id],
155 }
156 }
157
158 pub fn item_short_name(&self, id: impl Into<ItemId>) -> &Name {
159 let id = id.into();
160 self.short_names
161 .get(&id)
162 .unwrap_or_else(|| self.item_name(id))
163 }
164
165 pub fn get_item(&self, trans_id: impl Into<ItemId>) -> Option<ItemRef<'_>> {
166 match trans_id.into() {
167 ItemId::Type(id) => self.type_decls.get(id).map(ItemRef::Type),
168 ItemId::Fun(id) => self.fun_decls.get(id).map(ItemRef::Fun),
169 ItemId::Global(id) => self.global_decls.get(id).map(ItemRef::Global),
170 ItemId::TraitDecl(id) => self.trait_decls.get(id).map(ItemRef::TraitDecl),
171 ItemId::TraitImpl(id) => self.trait_impls.get(id).map(ItemRef::TraitImpl),
172 }
173 }
174 pub fn get_item_mut(&mut self, trans_id: ItemId) -> Option<ItemRefMut<'_>> {
175 match trans_id {
176 ItemId::Type(id) => self.type_decls.get_mut(id).map(ItemRefMut::Type),
177 ItemId::Fun(id) => self.fun_decls.get_mut(id).map(ItemRefMut::Fun),
178 ItemId::Global(id) => self.global_decls.get_mut(id).map(ItemRefMut::Global),
179 ItemId::TraitDecl(id) => self.trait_decls.get_mut(id).map(ItemRefMut::TraitDecl),
180 ItemId::TraitImpl(id) => self.trait_impls.get_mut(id).map(ItemRefMut::TraitImpl),
181 }
182 }
183
184 pub fn remove_item(&mut self, trans_id: ItemId) -> Option<ItemByVal> {
188 self.short_names.swap_remove(&trans_id);
189 self.item_names.swap_remove(&trans_id);
190 self.remove_item_temporarily(trans_id)
191 }
192 pub fn set_new_item_slot(&mut self, id: ItemId, item: impl Into<ItemByVal>) {
194 let item = item.into();
195 self.item_names
196 .insert(id, item.as_ref().item_meta().name.clone());
197 self.put_item_back(id, item);
198 }
199 pub fn remove_item_temporarily(&mut self, trans_id: ItemId) -> Option<ItemByVal> {
205 match trans_id {
206 ItemId::Type(id) => self.type_decls.remove(id).map(ItemByVal::Type),
207 ItemId::Fun(id) => self.fun_decls.remove(id).map(ItemByVal::Fun),
208 ItemId::Global(id) => self.global_decls.remove(id).map(ItemByVal::Global),
209 ItemId::TraitDecl(id) => self.trait_decls.remove(id).map(ItemByVal::TraitDecl),
210 ItemId::TraitImpl(id) => self.trait_impls.remove(id).map(ItemByVal::TraitImpl),
211 }
212 }
213 pub fn put_item_back(&mut self, id: ItemId, item: impl Into<ItemByVal>) {
217 match item.into() {
218 ItemByVal::Type(decl) => self.type_decls.set_slot(*id.as_type().unwrap(), decl),
219 ItemByVal::Fun(decl) => self.fun_decls.set_slot(*id.as_fun().unwrap(), decl),
220 ItemByVal::Global(decl) => self.global_decls.set_slot(*id.as_global().unwrap(), decl),
221 ItemByVal::TraitDecl(decl) => self
222 .trait_decls
223 .set_slot(*id.as_trait_decl().unwrap(), decl),
224 ItemByVal::TraitImpl(decl) => self
225 .trait_impls
226 .set_slot(*id.as_trait_impl().unwrap(), decl),
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 pub fn the_target_information(&self) -> &TargetInfo {
265 self.target_information
266 .values()
267 .exactly_one()
268 .ok()
269 .expect("called `the_target_information` on a multi-target crate")
270 }
271}
272
273impl fmt::Display for TranslatedCrate {
274 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
275 let fmt: &FmtCtx = &self.into_fmt();
276 match &self.ordered_decls {
277 None => {
278 for d in &self.type_decls {
280 writeln!(f, "{}\n", d.with_ctx(fmt))?
281 }
282 for d in &self.global_decls {
283 writeln!(f, "{}\n", d.with_ctx(fmt))?
284 }
285 for d in &self.trait_decls {
286 writeln!(f, "{}\n", d.with_ctx(fmt))?
287 }
288 for d in &self.trait_impls {
289 writeln!(f, "{}\n", d.with_ctx(fmt))?
290 }
291 for d in &self.fun_decls {
292 writeln!(f, "{}\n", d.with_ctx(fmt))?
293 }
294 }
295 Some(ordered_decls) => {
296 for gr in ordered_decls {
297 for id in gr.get_ids() {
298 writeln!(f, "{}\n", fmt.format_decl_id(id))?
299 }
300 }
301 }
302 }
303 fmt::Result::Ok(())
304 }
305}
306
307impl<'a> IntoFormatter for &'a TranslatedCrate {
308 type C = FmtCtx<'a>;
309
310 fn into_fmt(self) -> Self::C {
311 FmtCtx {
312 translated: Some(self),
313 ..Default::default()
314 }
315 }
316}
317
318pub trait HasIdxMapOf<Id: Idx>: std::ops::Index<Id, Output: Sized> {
319 fn get_idx_map(&self) -> &IndexMap<Id, Self::Output>;
320 fn get_idx_map_mut(&mut self) -> &mut IndexMap<Id, Self::Output>;
321}
322
323macro_rules! mk_index_impls {
325 ($ty:ident.$field:ident[$idx:ty]: $output:ty) => {
326 impl std::ops::Index<$idx> for $ty {
327 type Output = $output;
328 fn index(&self, index: $idx) -> &Self::Output {
329 &self.$field[index]
330 }
331 }
332 impl std::ops::IndexMut<$idx> for $ty {
333 fn index_mut(&mut self, index: $idx) -> &mut Self::Output {
334 &mut self.$field[index]
335 }
336 }
337 impl HasIdxMapOf<$idx> for $ty {
338 fn get_idx_map(&self) -> &IndexMap<$idx, Self::Output> {
339 &self.$field
340 }
341 fn get_idx_map_mut(&mut self) -> &mut IndexMap<$idx, Self::Output> {
342 &mut self.$field
343 }
344 }
345 };
346}
347mk_index_impls!(TranslatedCrate.type_decls[TypeDeclId]: TypeDecl);
348mk_index_impls!(TranslatedCrate.fun_decls[FunDeclId]: FunDecl);
349mk_index_impls!(TranslatedCrate.global_decls[GlobalDeclId]: GlobalDecl);
350mk_index_impls!(TranslatedCrate.trait_decls[TraitDeclId]: TraitDecl);
351mk_index_impls!(TranslatedCrate.trait_impls[TraitImplId]: TraitImpl);