use midenc_session::Session;
use super::{AnalysisManager, Chain, PassInfo};
use crate::diagnostics::Report;
pub type ConversionResult<T> = Result<T, Report>;
pub trait ConversionPassInfo: PassInfo + ConversionPass {}
impl<P> ConversionPassInfo for P where P: PassInfo + ConversionPass {}
pub trait ConversionPass {
type From;
type To;
fn convert(
&mut self,
entity: Self::From,
analyses: &mut AnalysisManager,
session: &Session,
) -> ConversionResult<Self::To>;
fn chain<P>(self, next: P) -> Chain<Self, P>
where
Self: Sized,
P: ConversionPass<From = Self::To>,
{
Chain::new(self, next)
}
}
impl<P, T, U> ConversionPass for Box<P>
where
P: ?Sized + ConversionPass<From = T, To = U>,
{
type From = T;
type To = U;
fn convert(
&mut self,
entity: Self::From,
analyses: &mut AnalysisManager,
session: &Session,
) -> ConversionResult<Self::To> {
(**self).convert(entity, analyses, session)
}
}
type ConversionPassCtor<T, U> = fn() -> Box<dyn ConversionPass<From = T, To = U>>;
#[doc(hidden)]
pub struct ConversionPassRegistration<T, U> {
pub name: &'static str,
pub summary: &'static str,
pub description: &'static str,
ctor: ConversionPassCtor<T, U>,
}
impl<T, U> ConversionPassRegistration<T, U> {
pub const fn new<P>() -> Self
where
P: ConversionPass<From = T, To = U> + PassInfo + Default + 'static,
{
Self {
name: <P as PassInfo>::FLAG,
summary: <P as PassInfo>::SUMMARY,
description: <P as PassInfo>::DESCRIPTION,
ctor: dyn_conversion_pass_ctor::<P, T, U>,
}
}
#[inline]
pub const fn name(&self) -> &'static str {
self.name
}
#[inline]
pub const fn summary(&self) -> &'static str {
self.summary
}
#[inline]
pub const fn description(&self) -> &'static str {
self.description
}
#[inline]
pub fn get(&self) -> Box<dyn ConversionPass<From = T, To = U>> {
(self.ctor)()
}
}
fn dyn_conversion_pass_ctor<P, T, U>() -> Box<dyn ConversionPass<From = T, To = U>>
where
P: Default + ConversionPass<From = T, To = U> + 'static,
{
Box::<P>::default()
}