#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct TypeSystem {
pub name: String,
pub type_constructors: Vec<TypeConstructor>,
pub term_constructors: Vec<TermConstructor>,
pub typing_rules: Vec<TypingRule>,
pub reduction_rules: Vec<ReductionRule>,
pub equivalence_rules: Vec<EquivalenceRule>,
pub structural: StructuralRules,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct TypeConstructor {
pub name: String,
pub symbol: String,
pub arity: usize,
pub kind: TypeConstructorKind,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum TypeConstructorKind {
Base,
Unit,
Empty,
Product,
Coproduct,
Exponential,
Tensor,
LinearHom,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct TermConstructor {
pub name: String,
pub symbol: String,
pub kind: TermConstructorKind,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum TermConstructorKind {
Variable,
UnitIntro,
PairIntro,
PairElimFst,
PairElimSnd,
Abstraction,
Application,
InjLeft,
InjRight,
Case,
Absurd,
LetPair,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct TypingRule {
pub name: String,
pub premises: Vec<String>,
pub conclusion: String,
pub side_conditions: Vec<String>,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ReductionRule {
pub name: String,
pub lhs: String,
pub rhs: String,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct EquivalenceRule {
pub name: String,
pub lhs: String,
pub rhs: String,
pub condition: Option<String>,
}
#[derive(Clone, Debug, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct StructuralRules {
pub weakening: bool,
pub contraction: bool,
pub exchange: bool,
}
impl std::fmt::Display for TypeSystem {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "# {} Type System", self.name)?;
writeln!(f)?;
writeln!(f, "## Types")?;
writeln!(f)?;
for tc in &self.type_constructors {
writeln!(f, " {} ({})", tc.symbol, tc.name)?;
}
writeln!(f)?;
writeln!(f, "## Terms")?;
writeln!(f)?;
for tc in &self.term_constructors {
writeln!(f, " {} ({})", tc.symbol, tc.name)?;
}
writeln!(f)?;
writeln!(f, "## Typing Rules")?;
writeln!(f)?;
for rule in &self.typing_rules {
writeln!(f, "### {}", rule.name)?;
for premise in &rule.premises {
writeln!(f, " {}", premise)?;
}
if !rule.premises.is_empty() {
writeln!(f, " ────────────────────")?;
}
writeln!(f, " {}", rule.conclusion)?;
writeln!(f)?;
}
writeln!(f, "## Reduction Rules")?;
writeln!(f)?;
for rule in &self.reduction_rules {
writeln!(f, " {} → {} ({})", rule.lhs, rule.rhs, rule.name)?;
}
writeln!(f)?;
writeln!(f, "## Structural Rules")?;
writeln!(f)?;
writeln!(f, " Weakening: {}", if self.structural.weakening { "✓" } else { "✗" })?;
writeln!(f, " Contraction: {}", if self.structural.contraction { "✓" } else { "✗" })?;
writeln!(f, " Exchange: {}", if self.structural.exchange { "✓" } else { "✗" })?;
Ok(())
}
}