use sv_lang::{Symbol, SyntaxTree};
use crate::run::RunError;
use crate::sources::SourceSet;
pub(crate) fn refused(feature: &str, reason: &str, at: impl Into<String>) -> RunError {
RunError::AotRefused {
feature: feature.to_owned(),
reason: reason.to_owned(),
at: at.into(),
}
}
pub(crate) fn not_supported(what: &str) -> String {
format!("{what} is not supported in AOT output; run the design with `vj run`")
}
pub(crate) struct Locator<'t> {
trees: Vec<(&'t SyntaxTree, Vec<usize>)>,
files: Vec<String>,
fallback: String,
}
impl<'t> Locator<'t> {
pub(crate) fn new(trees: &'t [SyntaxTree], sources: &SourceSet) -> Self {
let line_starts = trees
.iter()
.map(|tree| {
let starts = std::iter::once(0)
.chain(tree.text().match_indices('\n').map(|(i, _)| i + 1))
.collect();
(tree, starts)
})
.collect();
let files = if sources.files.len() == trees.len() {
sources
.files
.iter()
.map(|f| f.display().to_string())
.collect()
} else {
Vec::new()
};
Locator {
trees: line_starts,
files,
fallback: sources.label().display().to_string(),
}
}
pub(crate) fn symbol(&self, sym: &Symbol<'_>) -> String {
for (i, (tree, starts)) in self.trees.iter().enumerate() {
if let Some(node) = sym.syntax(tree) {
let offset = node.byte_range().start;
let line = starts.partition_point(|&s| s <= offset).max(1);
let file = self.files.get(i).map_or(self.fallback.as_str(), |f| f);
return format!("{file}:{line}");
}
}
format!("{}:1", self.fallback)
}
}
pub(crate) fn runtime_refusal(_symbol: &str) -> Option<(&'static str, &'static str)> {
None
}
pub(crate) fn codegen_refusal(_message: &str) -> Option<(&'static str, &'static str)> {
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn no_runtime_symbol_is_refused() {
assert_eq!(runtime_refusal("sv_rt_vpi_systf"), None);
assert_eq!(runtime_refusal("sv_rt_dpi_call"), None);
}
}