diff --git a/src/front/glsl/ast.rs b/src/front/glsl/ast.rs index a832a6fde2..b85a7f8e8a 100644 --- a/src/front/glsl/ast.rs +++ b/src/front/glsl/ast.rs @@ -1,9 +1,9 @@ use super::{super::Typifier, constants::ConstantSolver, error::ErrorKind}; use crate::{ - proc::ResolveContext, Arena, BinaryOperator, Binding, Constant, Expression, FastHashMap, - Function, FunctionArgument, GlobalVariable, Handle, Interpolation, LocalVariable, Module, - RelationalFunction, ResourceBinding, Sampling, ShaderStage, Statement, StorageClass, Type, - UnaryOperator, + proc::ResolveContext, Arena, ArraySize, BinaryOperator, Binding, Constant, Expression, + FastHashMap, Function, FunctionArgument, GlobalVariable, Handle, Interpolation, LocalVariable, + Module, RelationalFunction, ResourceBinding, Sampling, ShaderStage, Statement, StorageClass, + Type, UnaryOperator, }; #[derive(Debug)] @@ -144,6 +144,51 @@ impl<'a> Program<'a> { .solve(root) .map_err(|_| ErrorKind::SemanticError("Can't solve constant".into())) } + + pub fn type_size(&self, ty: Handle) -> Result { + Ok(match self.module.types[ty].inner { + crate::TypeInner::Scalar { width, .. } => width, + crate::TypeInner::Vector { size, width, .. } => size as u8 * width, + crate::TypeInner::Matrix { + columns, + rows, + width, + } => columns as u8 * rows as u8 * width, + crate::TypeInner::Pointer { .. } => { + return Err(ErrorKind::NotImplemented("type size of pointer")) + } + crate::TypeInner::ValuePointer { .. } => { + return Err(ErrorKind::NotImplemented("type size of value pointer")) + } + crate::TypeInner::Array { size, stride, .. } => { + stride as u8 + * match size { + ArraySize::Dynamic => { + return Err(ErrorKind::NotImplemented("type size of dynamic array")) + } + ArraySize::Constant(constant) => { + match self.module.constants[constant].inner { + crate::ConstantInner::Scalar { width, .. } => width, + crate::ConstantInner::Composite { .. } => { + return Err(ErrorKind::NotImplemented( + "type size of array with composite item size", + )) + } + } + } + } + } + crate::TypeInner::Struct { .. } => { + return Err(ErrorKind::NotImplemented("type size of struct")) + } + crate::TypeInner::Image { .. } => { + return Err(ErrorKind::NotImplemented("type size of image")) + } + crate::TypeInner::Sampler { .. } => { + return Err(ErrorKind::NotImplemented("type size of sampler")) + } + }) + } } #[derive(Debug)] diff --git a/src/front/glsl/parser.rs b/src/front/glsl/parser.rs index 276529b0b4..20a9716e12 100644 --- a/src/front/glsl/parser.rs +++ b/src/front/glsl/parser.rs @@ -6,7 +6,7 @@ pomelo! { use super::super::{error::ErrorKind, token::*, ast::*}; use crate::{ BOOL_WIDTH, - Arena, BinaryOperator, Binding, Block, Constant, + Arena, ArraySize, BinaryOperator, Binding, Block, Constant, ConstantInner, Expression, Function, FunctionArgument, FunctionResult, GlobalVariable, Handle, Interpolation, @@ -592,6 +592,34 @@ pomelo! { ty, } } + + single_declaration ::= fully_specified_type(t) Identifier(i) LeftBracket additive_expression(exp) RightBracket { + let ty_item = t.1.ok_or_else(|| ErrorKind::SemanticError("Empty type for declaration".into()))?; + + let array_size = if let Ok(constant) = extra.solve_constant(exp.expression) { + ArraySize::Constant(constant) + } else { + ArraySize::Dynamic + }; + + let item_size = extra.type_size(ty_item)?; + + let ty = extra.module.types.fetch_or_append(Type { + inner: TypeInner::Array { + base: ty_item, + size: array_size, + stride: item_size as u32, + }, + name: None, + }); + + VarDeclaration { + type_qualifiers: t.0, + ids_initializers: vec![(Some(i.1), None)], + ty, + } + } + // single_declaration ::= fully_specified_type Identifier array_specifier; // single_declaration ::= fully_specified_type Identifier array_specifier Equal initializer; single_declaration ::= fully_specified_type(t) Identifier(i) Equal initializer(init) {