use super::*;
use std::{cell::LazyCell, collections::HashMap};
use terl::{Span, WithSpan};
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct GroupIdx {
pub(crate) idx: usize,
}
impl GroupIdx {
pub fn new(idx: usize) -> Self {
Self { idx }
}
}
#[derive(Debug, Clone)]
pub enum DeclareState {
Empty,
Declared(usize, Type),
Declaring(HashMap<usize, Type>),
}
impl DeclareState {
pub fn alives<'t, A, T: 't>(&'t self, gidx: GroupIdx, active: A) -> T
where
A: FnOnce(&mut dyn Iterator<Item = (Branch, &'t Type)>) -> T,
{
let alives: &mut dyn Iterator<Item = (Branch, &Type)> = match self {
DeclareState::Empty => &mut std::iter::empty(),
DeclareState::Declared(branch, ty) => {
&mut std::iter::once((Branch::new(gidx, *branch), ty))
}
DeclareState::Declaring(alives) => &mut alives
.iter()
.map(|(branch, ty)| (Branch::new(gidx, *branch), ty)),
};
active(alives)
}
}
impl From<(usize, Type)> for DeclareState {
fn from((v1, v2): (usize, Type)) -> Self {
Self::Declared(v1, v2)
}
}
impl From<HashMap<usize, Type>> for DeclareState {
fn from(v: HashMap<usize, Type>) -> Self {
match v.len() {
0 => Self::Empty,
1 => {
let Some((branch, unique)) = v.into_iter().next() else {
unreachable!()
};
Self::Declared(branch, unique)
}
_ => Self::Declaring(v),
}
}
}
impl FromIterator<Type> for DeclareState {
fn from_iter<T: IntoIterator<Item = Type>>(iter: T) -> Self {
Self::from_iter(iter.into_iter().enumerate())
}
}
impl FromIterator<(usize, Type)> for DeclareState {
fn from_iter<T: IntoIterator<Item = (usize, Type)>>(iter: T) -> Self {
let mut iter = iter.into_iter().peekable();
let Some(next) = iter.next() else {
return Self::Empty;
};
if iter.peek().is_some() {
Self::Declaring(std::iter::once(next).chain(iter).collect())
} else {
Self::Declared(next.0, next.1)
}
}
}
#[derive(Debug, Clone)]
pub struct DeclareGroup {
span: Span,
group: GroupIdx,
failds: HashMap<usize, DeclareError>,
status: DeclareState,
}
impl DeclareGroup {
pub fn new(
span: Span,
group: GroupIdx,
fails: HashMap<usize, DeclareError>,
status: DeclareState,
) -> Self {
Self {
span,
group,
failds: fails,
status,
}
}
pub fn push_error(&mut self, at: usize, error: DeclareError) {
self.failds.insert(at, error);
}
fn update_state<U>(&mut self, updater: U)
where
U: FnOnce(DeclareState) -> DeclareState,
{
let previous = std::mem::replace(&mut self.status, DeclareState::Empty);
self.status = updater(previous);
}
pub fn filter_alive<F, C>(&mut self, mut filter: F) -> C
where
F: FnMut(Branch, Type) -> Result<(Branch, Type), DeclareError>,
C: Default + Extend<(Branch, DeclareError)>,
{
let mut remove = C::default();
let belong_to = self.group;
let filter_map = |(branch, ty)| {
let branch = Branch::new(belong_to, branch);
filter(branch, ty)
.map_err(|e| remove.extend(Some((branch, e))))
.map(|(branch, ty)| (branch.branch_idx, ty))
.ok()
};
self.update_state(|state| match state {
DeclareState::Empty => DeclareState::Empty,
DeclareState::Declared(branch, ty) => {
let iter = std::iter::once((branch, ty)).filter_map(filter_map);
DeclareState::from_iter(iter)
}
DeclareState::Declaring(branches) => {
let iter = branches.into_iter().filter_map(filter_map);
DeclareState::from_iter(iter)
}
});
remove
}
pub fn remove_branch(&mut self, branch: usize, reason: DeclareError) -> DeclareError {
let mut new_reason = DeclareError::Empty;
self.update_state(|state| match state {
DeclareState::Declared(unique, previous) => {
if unique == branch {
new_reason = reason.with_previous(previous);
DeclareState::Empty
} else {
DeclareState::Declared(unique, previous)
}
}
DeclareState::Declaring(mut items) => {
let previous = items.remove(&branch);
new_reason = reason.with_previous(previous.unwrap_or_else(|| unreachable!()));
items.into()
}
_ => unreachable!(),
});
new_reason
}
pub fn remove_branches<F, R>(&mut self, remove_if: F, reason: R) -> Vec<(Branch, DeclareError)>
where
F: Fn(Branch, &Type) -> bool,
R: FnOnce() -> DeclareError,
{
let reason = LazyCell::new(reason);
self.filter_alive(move |branch, ty| {
if remove_if(branch, &ty) {
Err((*reason).clone().with_previous(ty))
} else {
Ok((branch, ty))
}
})
}
pub fn alives<'t, A, T: 't>(&'t self, active: A) -> T
where
A: FnOnce(&mut dyn Iterator<Item = (Branch, &'t Type)>) -> T,
{
self.status.alives(self.group, active)
}
pub fn is_declared(&self) -> bool {
matches!(self.status, DeclareState::Declared(..))
}
pub fn result(&self) -> &Type {
match &self.status {
DeclareState::Declared(_, ty) => ty,
_ => panic!("group is not declared yet"),
}
}
pub fn make_error(&self) -> terl::Error {
let mut err = <Self as terl::WithSpan>::make_error(self, "cant infer type");
match &self.status {
DeclareState::Empty => err += "this cant be declared as any type!",
DeclareState::Declaring(alives) => {
err += "this cant be declared as:";
for alives in alives.values() {
err += format!("\t{alives}")
}
}
DeclareState::Declared(_, _) => unreachable!(),
}
err.extend(self.failds.values().flat_map(|faild| faild.generate()));
err
}
pub fn get_branch(&self, branch: Branch) -> &Type {
debug_assert_eq!(
branch.belong_to, self.group,
"the branch is not belong to this group"
);
let branch = branch.branch_idx;
match &self.status {
DeclareState::Declared(idx, ty) if *idx == branch => ty,
DeclareState::Declaring(alives) if alives.contains_key(&branch) => &alives[&branch],
_ => panic!("the branch isnot exist, or faild"),
}
}
}
impl WithSpan for DeclareGroup {
fn get_span(&self) -> Span {
self.span
}
}
pub struct GroupBuilder {
pub(crate) span: Span,
pub(crate) branches: Vec<BranchesBuilder>,
}
impl GroupBuilder {
pub fn new(span: Span, branches: Vec<BranchesBuilder>) -> GroupBuilder {
GroupBuilder { span, branches }
}
}
impl WithSpan for GroupBuilder {
fn get_span(&self) -> Span {
self.span
}
}