use super::ast::RawTheoryArrow;
use hexpr::{Operation, Signature};
use open_hypergraphs::lax::OpenHypergraph;
use std::collections::BTreeMap;
pub type Term = OpenHypergraph<(), Operation>;
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TheoryId(pub Operation);
#[derive(Clone, Debug)]
pub struct TheorySet {
pub theories: BTreeMap<TheoryId, Theory>,
}
#[derive(Clone, Debug)]
pub enum Theory {
Nat,
Theory {
syntax: TheoryId,
arrows: BTreeMap<Operation, TheoryArrow>,
},
}
#[derive(Clone, Debug)]
pub struct TheoryArrow {
pub raw: RawTheoryArrow,
pub name: Operation,
pub type_maps: (Term, Term),
pub definition: Option<Term>,
}
#[derive(Clone, Debug, thiserror::Error)]
pub enum SignatureError {
#[error("No such operation {0}")]
NoSuchOperation(Operation),
}
impl TheoryId {
pub fn new(name: Operation) -> Self {
Self(name)
}
}
impl std::fmt::Display for TheoryId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl Theory {
pub fn get_arrow(&self, op: &Operation) -> Option<&TheoryArrow> {
match self {
Theory::Nat => None,
Theory::Theory { arrows, .. } => arrows.get(op),
}
}
pub fn coarity_of(&self, op: &Operation) -> Option<usize> {
match self {
Theory::Nat => op.as_str().parse().ok(),
Theory::Theory { arrows, .. } => Some(arrows.get(op)?.type_maps.1.targets.len()),
}
}
pub fn local_signature(&self) -> TheorySignature<'_> {
TheorySignature { theory: self }
}
}
pub struct TheorySignature<'a> {
pub theory: &'a Theory,
}
impl Signature for TheorySignature<'_> {
type Arr = Operation;
type Obj = ();
type Error = SignatureError;
fn try_parse_op(&self, op: &Operation) -> Result<Self::Arr, Self::Error> {
self.theory
.get_arrow(op)
.map(|_| op.clone())
.ok_or_else(|| SignatureError::NoSuchOperation(op.clone()))
}
fn profile(&self, op: &Self::Arr) -> (Vec<Option<Self::Obj>>, Vec<Option<Self::Obj>>) {
let arrow = self
.theory
.get_arrow(op)
.expect("TheorySignature::profile called on unresolved operation");
let (source_map, target_map) = &arrow.type_maps;
(
vec![Some(()); source_map.targets.len()],
vec![Some(()); target_map.targets.len()],
)
}
}