use crate::common::{DiagnosticDebug, ForDebugWithTypes};
use crate::ir;
use crate::proc::overloads::constructor_set::ConstructorSize;
use crate::proc::TypeResolution;
use crate::UniqueArena;
use alloc::vec::Vec;
use core::fmt;
use core::result::Result;
#[derive(Clone)]
pub struct Rule {
pub arguments: Vec<TypeResolution>,
pub conclusion: Conclusion,
}
#[derive(Clone, Debug)]
pub enum Conclusion {
Value(ir::TypeInner),
Predeclared(ir::PredeclaredType),
}
impl Conclusion {
pub fn for_frexp_modf(
function: ir::MathFunction,
size: ConstructorSize,
scalar: ir::Scalar,
) -> Self {
use ir::MathFunction as Mf;
use ir::PredeclaredType as Pt;
let size = match size {
ConstructorSize::Scalar => None,
ConstructorSize::Vector(size) => Some(size),
ConstructorSize::Matrix { .. } => {
unreachable!("FrexpModf only supports scalars and vectors");
}
};
let predeclared = match function {
Mf::Frexp => Pt::FrexpResult { size, scalar },
Mf::Modf => Pt::ModfResult { size, scalar },
_ => {
unreachable!("FrexpModf only supports Frexp and Modf");
}
};
Conclusion::Predeclared(predeclared)
}
pub fn into_resolution(
self,
special_types: &ir::SpecialTypes,
) -> Result<TypeResolution, MissingSpecialType> {
match self {
Conclusion::Value(inner) => Ok(TypeResolution::Value(inner)),
Conclusion::Predeclared(predeclared) => {
let handle = *special_types
.predeclared_types
.get(&predeclared)
.ok_or(MissingSpecialType)?;
Ok(TypeResolution::Handle(handle))
}
}
}
}
#[derive(Debug, thiserror::Error)]
#[error("Special type is not registered within the module")]
pub struct MissingSpecialType;
impl ForDebugWithTypes for &Rule {}
impl fmt::Debug for DiagnosticDebug<(&Rule, &UniqueArena<ir::Type>)> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let (rule, arena) = self.0;
f.write_str("(")?;
for (i, argument) in rule.arguments.iter().enumerate() {
if i > 0 {
f.write_str(", ")?;
}
write!(f, "{:?}", argument.for_debug(arena))?;
}
write!(f, ") -> {:?}", rule.conclusion.for_debug(arena))
}
}
impl ForDebugWithTypes for &Conclusion {}
impl fmt::Debug for DiagnosticDebug<(&Conclusion, &UniqueArena<ir::Type>)> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let (conclusion, ctx) = self.0;
#[cfg(any(feature = "wgsl-in", feature = "wgsl-out"))]
{
use crate::common::wgsl::TypeContext;
ctx.write_type_conclusion(conclusion, f)?;
}
#[cfg(not(any(feature = "wgsl-in", feature = "wgsl-out")))]
{
let _ = ctx;
write!(f, "{conclusion:?}")?;
}
Ok(())
}
}