use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ScopeId(pub u64);
impl std::fmt::Display for ScopeId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "scope#{}", self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MacroVar {
pub name: String,
pub scope: ScopeId,
}
impl MacroVar {
pub fn new(name: impl Into<String>, scope: ScopeId) -> Self {
Self {
name: name.into(),
scope,
}
}
}
impl std::fmt::Display for MacroVar {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}@{}", self.name, self.scope)
}
}
#[derive(Debug, Clone)]
pub struct HygieneCtx {
pub current_scope: ScopeId,
pub bindings: HashMap<String, Vec<(ScopeId, String)>>,
pub(super) counter: u64,
pub(super) scope_stack: Vec<ScopeId>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MacroDef {
pub name: String,
pub params: Vec<String>,
pub body: String,
pub def_scope: ScopeId,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MacroCall {
pub name: String,
pub args: Vec<String>,
pub call_scope: ScopeId,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExpandResult {
pub expanded: String,
pub introduced_names: Vec<MacroVar>,
pub used_names: Vec<MacroVar>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ViolationKind {
CapturingFree,
CapturingBound,
ShadowingOuter,
}
impl std::fmt::Display for ViolationKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ViolationKind::CapturingFree => write!(f, "capturing-free"),
ViolationKind::CapturingBound => write!(f, "capturing-bound"),
ViolationKind::ShadowingOuter => write!(f, "shadowing-outer"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HygieneViolation {
pub name: String,
pub def_scope: ScopeId,
pub use_scope: ScopeId,
pub kind: ViolationKind,
}
impl std::fmt::Display for HygieneViolation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"hygiene violation ({}) for '{}': defined in {} but used in {}",
self.kind, self.name, self.def_scope, self.use_scope
)
}
}