midenc_hir/pass/
conversion.rs

1use midenc_session::Session;
2
3use super::{AnalysisManager, Chain, PassInfo};
4use crate::diagnostics::Report;
5
6/// A convenient type alias for `Result<T, ConversionError>`
7pub type ConversionResult<T> = Result<T, Report>;
8
9/// This is a marker trait for [ConversionPass] impls which also implement [PassInfo]
10///
11/// It is automatically implemented for you.
12pub trait ConversionPassInfo: PassInfo + ConversionPass {}
13impl<P> ConversionPassInfo for P where P: PassInfo + ConversionPass {}
14
15/// A [ConversionPass] is a pass which applies a change in representation to some compiler entity.
16///
17/// Specifically, this is used to convert between intermediate representations/dialects in the
18/// compiler.
19///
20/// For example, a conversion pass would be used to lower a `midenc_hir::parser::ast::Module`
21/// to a `midenc_hir::Module`. Each conversion between dialects like this can be thought of
22/// as delineating compilation phases (e.g. parsing, semantic analysis, elaboration, optimization,
23/// etc.).
24pub trait ConversionPass {
25    type From;
26    type To;
27
28    /// Apply this conversion to `entity`
29    fn convert(
30        &mut self,
31        entity: Self::From,
32        analyses: &mut AnalysisManager,
33        session: &Session,
34    ) -> ConversionResult<Self::To>;
35
36    /// Chains two conversions together to form a new, fused conversion
37    fn chain<P>(self, next: P) -> Chain<Self, P>
38    where
39        Self: Sized,
40        P: ConversionPass<From = Self::To>,
41    {
42        Chain::new(self, next)
43    }
44}
45impl<P, T, U> ConversionPass for Box<P>
46where
47    P: ?Sized + ConversionPass<From = T, To = U>,
48{
49    type From = T;
50    type To = U;
51
52    fn convert(
53        &mut self,
54        entity: Self::From,
55        analyses: &mut AnalysisManager,
56        session: &Session,
57    ) -> ConversionResult<Self::To> {
58        (**self).convert(entity, analyses, session)
59    }
60}
61
62type ConversionPassCtor<T, U> = fn() -> Box<dyn ConversionPass<From = T, To = U>>;
63
64#[doc(hidden)]
65pub struct ConversionPassRegistration<T, U> {
66    pub name: &'static str,
67    pub summary: &'static str,
68    pub description: &'static str,
69    ctor: ConversionPassCtor<T, U>,
70}
71impl<T, U> ConversionPassRegistration<T, U> {
72    pub const fn new<P>() -> Self
73    where
74        P: ConversionPass<From = T, To = U> + PassInfo + Default + 'static,
75    {
76        Self {
77            name: <P as PassInfo>::FLAG,
78            summary: <P as PassInfo>::SUMMARY,
79            description: <P as PassInfo>::DESCRIPTION,
80            ctor: dyn_conversion_pass_ctor::<P, T, U>,
81        }
82    }
83
84    /// Get the name of the registered pass
85    #[inline]
86    pub const fn name(&self) -> &'static str {
87        self.name
88    }
89
90    /// Get a summary of the registered pass
91    #[inline]
92    pub const fn summary(&self) -> &'static str {
93        self.summary
94    }
95
96    /// Get a rich description of the registered pass
97    #[inline]
98    pub const fn description(&self) -> &'static str {
99        self.description
100    }
101
102    /// Get an instance of the registered pass
103    #[inline]
104    pub fn get(&self) -> Box<dyn ConversionPass<From = T, To = U>> {
105        (self.ctor)()
106    }
107}
108
109fn dyn_conversion_pass_ctor<P, T, U>() -> Box<dyn ConversionPass<From = T, To = U>>
110where
111    P: Default + ConversionPass<From = T, To = U> + 'static,
112{
113    Box::<P>::default()
114}