use hax_frontend_exporter::{DefKind, DisambiguatedDefPathItem};
use hax_rust_engine_macros::*;
pub mod view;
#[derive_group_for_ast]
pub struct DefId {
pub krate: String,
pub path: Vec<DisambiguatedDefPathItem>,
pub parent: Option<Box<DefId>>,
pub kind: DefKind,
}
#[derive_group_for_ast]
struct ExplicitDefId {
is_constructor: bool,
def_id: DefId,
}
impl ExplicitDefId {
pub fn parent(&self) -> Option<Self> {
let def_id = &self.def_id;
let is_constructor = matches!(&def_id.kind, DefKind::Field);
Some(Self {
is_constructor,
def_id: def_id.parent.as_ref()?.as_ref().clone(),
})
}
pub fn parents(&self) -> impl Iterator<Item = Self> {
std::iter::successors(Some(self.clone()), |id| id.parent())
}
}
#[derive_group_for_ast]
struct FreshModule {
id: usize,
hints: Vec<ExplicitDefId>,
label: String,
}
#[derive_group_for_ast]
enum ReservedSuffix {
Pre,
Post,
Cast,
}
#[derive_group_for_ast]
pub struct ConcreteId {
def_id: ExplicitDefId,
moved: Option<FreshModule>,
suffix: Option<ReservedSuffix>,
}
#[derive_group_for_ast]
pub enum GlobalId {
Concrete(ConcreteId),
Projector(ConcreteId),
}
impl GlobalId {
pub fn krate(&self) -> String {
match self {
GlobalId::Concrete(concrete_id) | GlobalId::Projector(concrete_id) => {
concrete_id.def_id.def_id.krate.clone()
}
}
}
pub fn is_empty(&self) -> bool {
self.to_debug_string() == "_"
}
pub fn def_id(&self) -> DefId {
let (GlobalId::Concrete(concrete_id) | GlobalId::Projector(concrete_id)) = self;
concrete_id.def_id.def_id.clone()
}
pub fn to_debug_string(&self) -> String {
match self {
GlobalId::Concrete(concrete_id) => concrete_id
.def_id
.def_id
.clone()
.path
.into_iter()
.map(|def| {
let data = match def.clone().data {
hax_frontend_exporter::DefPathItem::ValueNs(s)
| hax_frontend_exporter::DefPathItem::MacroNs(s)
| hax_frontend_exporter::DefPathItem::TypeNs(s) => s.clone(),
hax_frontend_exporter::DefPathItem::Impl => "impl".to_string(),
other => unimplemented!("{other:?}"),
};
if def.disambiguator != 0 && !data.is_empty() && data != "_" {
format!("_{}_{}", def.disambiguator, data)
} else {
data
}
})
.collect::<Vec<String>>()
.join("_"),
GlobalId::Projector(_concrete_id) => todo!(),
}
}
pub fn as_concrete(&self) -> Option<ConcreteId> {
match self {
GlobalId::Concrete(concrete_id) => Some(concrete_id.clone()),
_ => None,
}
}
pub fn as_projector(&self) -> Option<ConcreteId> {
match self {
GlobalId::Projector(concrete_id) => Some(concrete_id.clone()),
_ => None,
}
}
}
impl ConcreteId {
pub fn view(&self) -> view::View {
self.def_id.clone().into()
}
pub fn mod_only_closest_parent(&self) -> Self {
let mut parents = self.def_id.parents().collect::<Vec<_>>();
parents.reverse();
let def_id = parents
.into_iter()
.take_while(|id| matches!(id.def_id.kind, DefKind::Mod))
.next()
.expect("Invariant broken: a DefId must always contain at least on `mod` segment (the crate)");
Self {
def_id,
moved: self.moved.clone(),
suffix: None,
}
}
pub fn into_concrete(self) -> GlobalId {
GlobalId::Concrete(self)
}
}
impl PartialEq<DefId> for GlobalId {
fn eq(&self, other: &DefId) -> bool {
if let Self::Concrete(concrete) = self {
&concrete.def_id.def_id == other
} else {
false
}
}
}
impl PartialEq<GlobalId> for DefId {
fn eq(&self, other: &GlobalId) -> bool {
other == self
}
}