Skip to content
This repository has been archived by the owner on Jan 29, 2025. It is now read-only.

Commit

Permalink
impl eval_new
Browse files Browse the repository at this point in the history
  • Loading branch information
teoxoy committed Mar 29, 2023
1 parent e94ed40 commit f29942a
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 26 deletions.
137 changes: 116 additions & 21 deletions src/front/glsl/constants.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{
arena::{Arena, Handle, UniqueArena},
BinaryOperator, Constant, Expression, Literal, ScalarKind, Type, TypeInner, UnaryOperator,
ArraySize, BinaryOperator, Constant, Expression, Literal, ScalarKind, Type, TypeInner,
UnaryOperator,
};

#[derive(Debug)]
Expand Down Expand Up @@ -59,6 +60,8 @@ pub enum ConstantSolvingError {
SplatScalarOnly,
#[error("Can only swizzle vector constants")]
SwizzleVectorOnly,
#[error("Type is not constructible")]
TypeNotConstructible,
#[error("Not implemented as constant expression: {0}")]
NotImplemented(String),
}
Expand Down Expand Up @@ -89,7 +92,6 @@ impl<'a> ConstantSolver<'a> {
};
let span = expressions.get_span(expr);
match expressions[expr] {
// TODO: transform New into Literal | Compose
ref expression @ (Expression::Literal(_) | Expression::New(_)) => match expr_type {
ExprType::Regular => Ok(self.register_constant(expression.clone(), span)),
ExprType::Constant => Ok(expr),
Expand Down Expand Up @@ -316,18 +318,20 @@ impl<'a> ConstantSolver<'a> {
let array = self.solve_impl(expr, expr_type, false)?;

match self.const_expressions[array] {
Expression::Compose { ty, .. } => match self.types[ty].inner {
TypeInner::Array { size, .. } => match size {
crate::ArraySize::Constant(len) => {
let expr = Expression::Literal(Literal::U32(len.get()));
Ok(self.register_constant(expr, span))
}
crate::ArraySize::Dynamic => {
Err(ConstantSolvingError::ArrayLengthDynamic)
}
},
_ => Err(ConstantSolvingError::InvalidArrayLengthArg),
},
Expression::New(ty) | Expression::Compose { ty, .. } => {
match self.types[ty].inner {
TypeInner::Array { size, .. } => match size {
crate::ArraySize::Constant(len) => {
let expr = Expression::Literal(Literal::U32(len.get()));
Ok(self.register_constant(expr, span))
}
crate::ArraySize::Dynamic => {
Err(ConstantSolvingError::ArrayLengthDynamic)
}
},
_ => Err(ConstantSolvingError::InvalidArrayLengthArg),
}
}
_ => Err(ConstantSolvingError::InvalidArrayLengthArg),
}
}
Expand Down Expand Up @@ -400,13 +404,102 @@ impl<'a> ConstantSolver<'a> {
}
}

/// Transforms a `Expression::New` into either `Expression::Literal` or `Expression::Compose`
fn eval_new(
&mut self,
expr: Handle<Expression>,
span: crate::Span,
) -> Result<Handle<Expression>, ConstantSolvingError> {
match self.const_expressions[expr] {
Expression::New(ty) => self.eval_new_impl(ty, span),
_ => Ok(expr),
}
}

fn eval_new_impl(
&mut self,
ty: Handle<Type>,
span: crate::Span,
) -> Result<Handle<Expression>, ConstantSolvingError> {
match self.types[ty].inner {
TypeInner::Scalar { kind, width } => {
let expr = Expression::Literal(
Literal::zero(kind, width).ok_or(ConstantSolvingError::TypeNotConstructible)?,
);
Ok(self.register_constant(expr, span))
}
TypeInner::Vector { size, kind, width } => {
let scalar_ty = self.types.insert(
Type {
name: None,
inner: TypeInner::Scalar { kind, width },
},
span,
);
let el = self.eval_new_impl(scalar_ty, span)?;
let expr = Expression::Compose {
ty,
components: vec![el; size as usize],
};
Ok(self.register_constant(expr, span))
}
TypeInner::Matrix {
columns,
rows,
width,
} => {
let vec_ty = self.types.insert(
Type {
name: None,
inner: TypeInner::Vector {
size: rows,
kind: ScalarKind::Float,
width,
},
},
span,
);
let el = self.eval_new_impl(vec_ty, span)?;
let expr = Expression::Compose {
ty,
components: vec![el; columns as usize],
};
Ok(self.register_constant(expr, span))
}
TypeInner::Array {
base,
size: ArraySize::Constant(size),
..
} => {
let el = self.eval_new_impl(base, span)?;
let expr = Expression::Compose {
ty,
components: vec![el; size.get() as usize],
};
Ok(self.register_constant(expr, span))
}
TypeInner::Struct { ref members, .. } => {
let types: Vec<_> = members.iter().map(|m| m.ty).collect();
let mut components = Vec::with_capacity(members.len());
for ty in types {
components.push(self.eval_new_impl(ty, span)?);
}
let expr = Expression::Compose { ty, components };
Ok(self.register_constant(expr, span))
}
_ => Err(ConstantSolvingError::TypeNotConstructible),
}
}

fn cast(
&mut self,
constant: Handle<Expression>,
kind: ScalarKind,
target_width: crate::Bytes,
span: crate::Span,
) -> Result<Handle<Expression>, ConstantSolvingError> {
let constant = self.eval_new(constant, span)?;

let expr = match self.const_expressions[constant] {
Expression::Literal(literal) => {
let literal = match (kind, target_width) {
Expand All @@ -415,28 +508,28 @@ impl<'a> ConstantSolver<'a> {
Literal::U32(v) => v as i32,
Literal::F32(v) => v as i32,
Literal::Bool(v) => v as i32,
_ => return Err(ConstantSolvingError::InvalidCastArg),
Literal::F64(_) => return Err(ConstantSolvingError::InvalidCastArg),
}),
(ScalarKind::Uint, 4) => Literal::U32(match literal {
Literal::I32(v) => v as u32,
Literal::U32(v) => v,
Literal::F32(v) => v as u32,
Literal::Bool(v) => v as u32,
_ => return Err(ConstantSolvingError::InvalidCastArg),
Literal::F64(_) => return Err(ConstantSolvingError::InvalidCastArg),
}),
(ScalarKind::Float, 4) => Literal::F32(match literal {
Literal::I32(v) => v as f32,
Literal::U32(v) => v as f32,
Literal::F32(v) => v,
Literal::Bool(v) => v as u32 as f32,
_ => return Err(ConstantSolvingError::InvalidCastArg),
Literal::F64(_) => return Err(ConstantSolvingError::InvalidCastArg),
}),
(ScalarKind::Bool, crate::BOOL_WIDTH) => Literal::Bool(match literal {
Literal::I32(v) => v != 0,
Literal::U32(v) => v != 0,
Literal::F32(v) => v != 0.0,
Literal::Bool(v) => v,
_ => return Err(ConstantSolvingError::InvalidCastArg),
Literal::F64(_) => return Err(ConstantSolvingError::InvalidCastArg),
}),
_ => return Err(ConstantSolvingError::InvalidCastArg),
};
Expand Down Expand Up @@ -470,6 +563,8 @@ impl<'a> ConstantSolver<'a> {
constant: Handle<Expression>,
span: crate::Span,
) -> Result<Handle<Expression>, ConstantSolvingError> {
let constant = self.eval_new(constant, span)?;

let expr = match self.const_expressions[constant] {
Expression::Literal(value) => Expression::Literal(match op {
UnaryOperator::Negate => match value {
Expand All @@ -484,9 +579,6 @@ impl<'a> ConstantSolver<'a> {
_ => return Err(ConstantSolvingError::InvalidUnaryOpArg),
},
}),
Expression::New(ty) => {
todo!()
}
Expression::Compose {
ty,
components: ref src_components,
Expand Down Expand Up @@ -516,6 +608,9 @@ impl<'a> ConstantSolver<'a> {
right: Handle<Expression>,
span: crate::Span,
) -> Result<Handle<Expression>, ConstantSolvingError> {
let left = self.eval_new(left, span)?;
let right = self.eval_new(right, span)?;

let expr = match (
&self.const_expressions[left],
&self.const_expressions[right],
Expand Down
12 changes: 7 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -887,11 +887,13 @@ impl std::hash::Hash for Literal {

impl Literal {
pub const fn new(value: u8, kind: ScalarKind, width: Bytes) -> Option<Self> {
match (kind, width) {
(ScalarKind::Float, 8) => Some(Self::F64(value as _)),
(ScalarKind::Float, 4) => Some(Self::F32(value as _)),
(ScalarKind::Uint, 4) => Some(Self::U32(value as _)),
(ScalarKind::Sint, 4) => Some(Self::I32(value as _)),
match (value, kind, width) {
(value, ScalarKind::Float, 8) => Some(Self::F64(value as _)),
(value, ScalarKind::Float, 4) => Some(Self::F32(value as _)),
(value, ScalarKind::Uint, 4) => Some(Self::U32(value as _)),
(value, ScalarKind::Sint, 4) => Some(Self::I32(value as _)),
(1, ScalarKind::Bool, 4) => Some(Self::Bool(true)),
(0, ScalarKind::Bool, 4) => Some(Self::Bool(false)),
_ => None,
}
}
Expand Down

0 comments on commit f29942a

Please sign in to comment.