use crate::node::PortType;
use super::name::ChildName;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct SourceContext {
pub label: String,
pub file: Option<String>,
pub line_range: Option<(usize, usize)>,
}
impl SourceContext {
pub fn new(label: impl Into<String>) -> Self {
Self {
label: label.into(),
file: None,
line_range: None,
}
}
pub fn for_phase(name: &str) -> Self {
Self::new(format!("phase:{name}"))
}
pub fn for_op(name: &str) -> Self {
Self::new(format!("op:{name}"))
}
pub fn with_file(mut self, file: impl Into<String>) -> Self {
self.file = Some(file.into());
self
}
pub fn with_lines(mut self, start: usize, end: usize) -> Self {
self.line_range = Some((start, end));
self
}
pub fn display(&self) -> String {
let mut s = self.label.clone();
if let Some(f) = &self.file {
s.push_str(&format!(" ({f}"));
if let Some((a, b)) = self.line_range {
s.push_str(&format!(":{a}-{b}"));
}
s.push(')');
} else if let Some((a, b)) = self.line_range {
s.push_str(&format!(" ({a}-{b})"));
}
s
}
}
#[derive(Debug, Clone)]
pub enum ContractViolation {
UnboundImport {
import: String,
site: SourceContext,
},
Type {
import: String,
required: PortType,
parent_export: PortType,
site: SourceContext,
},
Modifier {
import: String,
detail: String,
site: SourceContext,
},
FinalShadow {
export: String,
site: SourceContext,
},
Phase2WriteThrough {
export: String,
site: SourceContext,
note: &'static str,
},
DuplicateChild {
name: ChildName,
prior_site: SourceContext,
this_site: SourceContext,
},
Compile(String),
}
impl std::fmt::Display for ContractViolation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::UnboundImport { import, site } => write!(
f,
"unbound import `{import}` (parent does not export it) at {}",
site.display()
),
Self::Type {
import,
required,
parent_export,
site,
} => write!(
f,
"type mismatch on import `{import}`: required {required:?}, parent exports {parent_export:?} at {}",
site.display()
),
Self::Modifier { import, detail, site } => write!(
f,
"modifier mismatch on import `{import}`: {detail} at {}",
site.display()
),
Self::FinalShadow { export, site } => write!(
f,
"child export `{export}` shadows parent's `final` export at {}",
site.display()
),
Self::Phase2WriteThrough { export, site, note } => write!(
f,
"TODO(Phase 2): write-through rewrite for shared export `{export}` at {} — {note}",
site.display()
),
Self::DuplicateChild {
name,
prior_site,
this_site,
} => write!(
f,
"duplicate spawn of child `{name}`: prior at {}, this at {}",
prior_site.display(),
this_site.display()
),
Self::Compile(msg) => write!(f, "compile error: {msg}"),
}
}
}
impl std::error::Error for ContractViolation {}