use std::ops::Deref;
use super::AnyEnt;
use super::AnyEntKind;
use super::EntRef;
use crate::analysis::region::NamedEntities;
use crate::analysis::region::Region;
use crate::analysis::visibility::Visibility;
use crate::ast::Designator;
use crate::ast::HasDesignator;
use crate::ast::WithRef;
use crate::data::WithPos;
use crate::Diagnostic;
use crate::SrcPos;
pub enum Design<'a> {
Entity(Visibility<'a>, Region<'a>),
Configuration,
Package(Visibility<'a>, Region<'a>),
UninstPackage(Visibility<'a>, Region<'a>),
PackageInstance(Region<'a>),
Context(Region<'a>),
}
impl<'a> Design<'a> {
pub fn describe(&self) -> &'static str {
use Design::*;
match self {
Entity(..) => "entity",
Configuration => "configuration",
Package(..) => "package",
UninstPackage(..) => "uninstantiated package",
PackageInstance(..) => "package instance",
Context(..) => "context",
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct DesignEnt<'a>(pub EntRef<'a>);
impl<'a> DesignEnt<'a> {
pub fn from_any(ent: &'a AnyEnt) -> Result<DesignEnt<'a>, EntRef<'a>> {
if matches!(ent.kind(), AnyEntKind::Design(..)) {
Ok(DesignEnt(ent))
} else {
Err(ent)
}
}
pub fn kind(&self) -> &Design<'a> {
if let AnyEntKind::Design(typ) = self.0.kind() {
typ
} else {
unreachable!("Must be a design");
}
}
pub fn selected(
&self,
prefix_pos: &SrcPos,
suffix: &WithPos<WithRef<Designator>>,
) -> Result<NamedEntities<'a>, Diagnostic> {
match self.kind() {
Design::Package(_, ref region) | Design::PackageInstance(ref region) => {
if let Some(decl) = region.lookup_immediate(suffix.designator()) {
Ok(decl.clone())
} else {
Err(Diagnostic::no_declaration_within(
self,
&suffix.pos,
&suffix.item.item,
))
}
}
_ => Err(Diagnostic::invalid_selected_name_prefix(self, prefix_pos)),
}
}
}
impl<'a> From<DesignEnt<'a>> for EntRef<'a> {
fn from(ent: DesignEnt<'a>) -> Self {
ent.0
}
}
impl<'a> Deref for DesignEnt<'a> {
type Target = AnyEnt<'a>;
fn deref(&self) -> EntRef<'a> {
self.0
}
}