use std::sync::Arc;
use crate::{
ast::{Designator, InterfaceListType, Mode, ObjectClass},
Diagnostic, SrcPos,
};
use super::{
region::{NamedEntityKind, Object, TypeEnt},
NamedEntity,
};
#[derive(Clone)]
pub struct InterfaceEnt {
ent: Arc<NamedEntity>,
}
impl InterfaceEnt {
pub fn inner(&self) -> &Arc<NamedEntity> {
&self.ent
}
pub fn from_any(ent: Arc<NamedEntity>) -> Option<Self> {
match ent.kind() {
NamedEntityKind::Object(Object { mode: Some(_), .. })
| NamedEntityKind::InterfaceFile(..) => Some(InterfaceEnt { ent }),
_ => None,
}
}
pub fn has_default(&self) -> bool {
if let NamedEntityKind::Object(Object { has_default, .. }) = self.ent.kind() {
*has_default
} else {
false
}
}
pub fn is_signal(&self) -> bool {
match self.ent.kind() {
NamedEntityKind::Object(obj) => obj.class == ObjectClass::Signal,
_ => false,
}
}
pub fn is_output_signal(&self) -> bool {
match self.ent.kind() {
NamedEntityKind::Object(obj) => {
obj.class == ObjectClass::Signal && obj.mode == Some(Mode::Out)
}
_ => false,
}
}
pub fn type_mark(&self) -> &TypeEnt {
match self.ent.kind() {
NamedEntityKind::Object(obj) => obj.subtype.type_mark(),
NamedEntityKind::InterfaceFile(file_type) => file_type,
_ => {
unreachable!();
}
}
}
pub fn base_type(&self) -> &TypeEnt {
self.type_mark().base_type()
}
}
impl std::ops::Deref for InterfaceEnt {
type Target = NamedEntity;
fn deref(&self) -> &NamedEntity {
&self.ent
}
}
#[derive(Clone)]
pub struct FormalRegion {
pub typ: InterfaceListType,
entities: Vec<InterfaceEnt>,
}
impl FormalRegion {
pub fn new(typ: InterfaceListType) -> Self {
Self {
typ,
entities: Default::default(),
}
}
pub fn new_params() -> Self {
Self {
typ: InterfaceListType::Parameter,
entities: Default::default(),
}
}
pub fn new_with(typ: InterfaceListType, entities: Vec<InterfaceEnt>) -> Self {
Self { typ, entities }
}
pub fn lookup(
&self,
pos: &SrcPos,
designator: &Designator,
) -> Result<(usize, InterfaceEnt), Diagnostic> {
for (idx, ent) in self.entities.iter().enumerate() {
if ent.designator() == designator {
return Ok((idx, ent.clone()));
}
}
Err(Diagnostic::error(
pos,
format!("No declaration of '{}'", designator),
))
}
pub fn is_empty(&self) -> bool {
self.entities.is_empty()
}
pub fn len(&self) -> usize {
self.entities.len()
}
pub fn iter(&self) -> impl Iterator<Item = &InterfaceEnt> {
self.entities.iter()
}
pub fn add(&mut self, param: Arc<NamedEntity>) {
if let Some(ent) = InterfaceEnt::from_any(param) {
self.entities.push(ent);
} else {
debug_assert!(false);
}
}
pub fn nth(&self, idx: usize) -> Option<&InterfaceEnt> {
self.entities.get(idx)
}
}