use lean_rs::Obj;
use lean_rs::abi::structure::{take_ctor_objects, view};
use lean_rs::abi::traits::{TryFromLean, conversion_error};
use lean_rs::error::LeanResult;
use crate::host::elaboration::LeanElabFailure;
use crate::host::evidence::handle::LeanEvidence;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum EvidenceStatus {
Checked,
Rejected,
Unavailable,
Unsupported,
}
#[derive(Debug)]
pub enum LeanKernelOutcome<'lean> {
Checked(LeanEvidence<'lean>),
Rejected(LeanElabFailure),
Unavailable(LeanElabFailure),
Unsupported(LeanElabFailure),
}
impl LeanKernelOutcome<'_> {
#[must_use]
pub fn status(&self) -> EvidenceStatus {
match self {
Self::Checked(_) => EvidenceStatus::Checked,
Self::Rejected(_) => EvidenceStatus::Rejected,
Self::Unavailable(_) => EvidenceStatus::Unavailable,
Self::Unsupported(_) => EvidenceStatus::Unsupported,
}
}
}
impl<'lean> TryFromLean<'lean> for EvidenceStatus {
fn try_from_lean(obj: Obj<'lean>) -> LeanResult<Self> {
let obj_view = view(&obj);
let tag = if obj_view.is_scalar() {
obj_view.scalar_payload("EvidenceStatus")?
} else {
let heap_tag = obj_view.ctor()?.tag();
let _ = take_ctor_objects::<0>(obj, heap_tag, "EvidenceStatus")?;
usize::from(heap_tag)
};
match tag {
0 => Ok(Self::Checked),
1 => Ok(Self::Rejected),
2 => Ok(Self::Unavailable),
3 => Ok(Self::Unsupported),
other => Err(conversion_error(format!(
"expected Lean EvidenceStatus tag 0..=3, found {other}"
))),
}
}
}
impl<'lean> TryFromLean<'lean> for LeanKernelOutcome<'lean> {
fn try_from_lean(obj: Obj<'lean>) -> LeanResult<Self> {
let tag = view(&obj).ctor()?.tag();
match tag {
0 => {
let [payload] = take_ctor_objects::<1>(obj, 0, "KernelOutcome.checked")?;
Ok(Self::Checked(LeanEvidence::try_from_lean(payload)?))
}
1 => {
let [payload] = take_ctor_objects::<1>(obj, 1, "KernelOutcome.rejected")?;
Ok(Self::Rejected(LeanElabFailure::try_from_lean(payload)?))
}
2 => {
let [payload] = take_ctor_objects::<1>(obj, 2, "KernelOutcome.unavailable")?;
Ok(Self::Unavailable(LeanElabFailure::try_from_lean(payload)?))
}
3 => {
let [payload] = take_ctor_objects::<1>(obj, 3, "KernelOutcome.unsupported")?;
Ok(Self::Unsupported(LeanElabFailure::try_from_lean(payload)?))
}
other => Err(conversion_error(format!(
"expected Lean KernelOutcome ctor (tag 0..=3), found tag {other}"
))),
}
}
}