use crate::core::table::FileId;
use crate::diagnostics::CycleReport;
use crate::diagnostics::InvalidReport;
use crate::diagnostics::LoweringBail;
pub use crate::dsl::resolver::lower::LoweringContext;
pub trait IrNodeLowering: Sized + Clone {
type Ast;
fn cached(
_ast: &Self::Ast,
_ctx: &LoweringContext,
) -> Option<Option<Result<Self, LoweringBail>>> {
None
}
fn cache(_ast: &Self::Ast, _result: Result<Self, LoweringBail>, _ctx: &mut LoweringContext) {}
fn check_cycle(_ast: &Self::Ast, _ctx: &LoweringContext) -> Option<CycleReport> {
None
}
fn push_in_progress(_ast: &Self::Ast, _ctx: &mut LoweringContext) {}
fn pop_in_progress(_ctx: &mut LoweringContext) {}
fn lower(
ast: &Self::Ast,
file: &FileId,
ctx: &mut LoweringContext,
) -> Result<Self, LoweringBail>;
fn from_ast(
ast: &Self::Ast,
file: &FileId,
ctx: &mut LoweringContext,
) -> Result<Self, LoweringBail> {
match Self::cached(ast, ctx) {
None => Self::lower(ast, file, ctx),
Some(Some(result)) => result,
Some(None) => {
if let Some(cycle) = Self::check_cycle(ast, ctx) {
let bail = LoweringBail::invalid(InvalidReport::cycle(cycle));
Self::cache(ast, Err(bail.clone()), ctx);
return Err(bail);
}
Self::push_in_progress(ast, ctx);
let result = Self::lower(ast, file, ctx);
Self::pop_in_progress(ctx);
Self::cache(ast, result.clone(), ctx);
result
}
}
}
}