diff --git a/src/front/glsl/parser/declarations.rs b/src/front/glsl/parser/declarations.rs index acc200ba25..d39245d8d3 100644 --- a/src/front/glsl/parser/declarations.rs +++ b/src/front/glsl/parser/declarations.rs @@ -120,7 +120,7 @@ impl<'source> ParsingContext<'source> { pub fn parse_init_declarator_list( &mut self, parser: &mut Parser, - ty: Handle, + mut ty: Handle, ctx: &mut DeclarationContext, ) -> Result<()> { // init_declarator_list: @@ -169,8 +169,7 @@ impl<'source> ParsingContext<'source> { // parse an array specifier if it exists // NOTE: unlike other parse methods this one doesn't expect an array specifier and // returns Ok(None) rather than an error if there is not one - let array_specifier = self.parse_array_specifier(parser)?; - let ty = parser.maybe_array(ty, meta, array_specifier); + self.parse_array_specifier(parser, &mut meta, &mut ty)?; let init = self .bump_if(parser, TokenValue::Assign) @@ -463,7 +462,7 @@ impl<'source> ParsingContext<'source> { body: &mut Block, qualifiers: &mut TypeQualifiers, ty_name: String, - meta: Span, + mut meta: Span, ) -> Result { let layout = match qualifiers.layout_qualifiers.remove(&QualifierKey::Layout) { Some((QualifierValue::Layout(l), _)) => l, @@ -498,8 +497,7 @@ impl<'source> ParsingContext<'source> { let name = match token.value { TokenValue::Semicolon => None, TokenValue::Identifier(name) => { - let array_specifier = self.parse_array_specifier(parser)?; - ty = parser.maybe_array(ty, token.meta, array_specifier); + self.parse_array_specifier(parser, &mut meta, &mut ty)?; self.expect(parser, TokenValue::Semicolon)?; @@ -561,13 +559,12 @@ impl<'source> ParsingContext<'source> { loop { // TODO: type_qualifier - let (ty, mut meta) = self.parse_type_non_void(parser)?; + let (mut ty, mut meta) = self.parse_type_non_void(parser)?; let (name, end_meta) = self.expect_ident(parser)?; meta.subsume(end_meta); - let array_specifier = self.parse_array_specifier(parser)?; - let ty = parser.maybe_array(ty, meta, array_specifier); + self.parse_array_specifier(parser, &mut meta, &mut ty)?; self.expect(parser, TokenValue::Semicolon)?; diff --git a/src/front/glsl/parser/functions.rs b/src/front/glsl/parser/functions.rs index 797e48dea5..ce6f56d8eb 100644 --- a/src/front/glsl/parser/functions.rs +++ b/src/front/glsl/parser/functions.rs @@ -575,7 +575,7 @@ impl<'source> ParsingContext<'source> { loop { if self.peek_type_name(parser) || self.peek_parameter_qualifier(parser) { let qualifier = self.parse_parameter_qualifier(parser); - let ty = self.parse_type_non_void(parser)?.0; + let mut ty = self.parse_type_non_void(parser)?.0; match self.expect_peek(parser)?.value { TokenValue::Comma => { @@ -584,12 +584,10 @@ impl<'source> ParsingContext<'source> { continue; } TokenValue::Identifier(_) => { - let name_meta = self.expect_ident(parser)?; + let mut name = self.expect_ident(parser)?; + self.parse_array_specifier(parser, &mut name.1, &mut ty)?; - let array_specifier = self.parse_array_specifier(parser)?; - let ty = parser.maybe_array(ty, name_meta.1, array_specifier); - - context.add_function_arg(parser, body, Some(name_meta), ty, qualifier); + context.add_function_arg(parser, body, Some(name), ty, qualifier); if self.bump_if(parser, TokenValue::Comma).is_some() { continue; diff --git a/src/front/glsl/parser/types.rs b/src/front/glsl/parser/types.rs index 7163ab4bc0..acf0df4840 100644 --- a/src/front/glsl/parser/types.rs +++ b/src/front/glsl/parser/types.rs @@ -10,45 +10,76 @@ use crate::{ }; impl<'source> ParsingContext<'source> { - /// Parses an optional array_specifier returning `Ok(None)` if there is no - /// LeftBracket + /// Parses an optional array_specifier returning wether or not it's present + /// and modifying the type handle if it exists pub fn parse_array_specifier( &mut self, parser: &mut Parser, - ) -> Result> { - if let Some(Token { mut meta, .. }) = self.bump_if(parser, TokenValue::LeftBracket) { - if let Some(Token { meta: end_meta, .. }) = - self.bump_if(parser, TokenValue::RightBracket) - { - meta.subsume(end_meta); - return Ok(Some((ArraySize::Dynamic, meta))); - } + span: &mut Span, + ty: &mut Handle, + ) -> Result<()> { + while self.parse_array_specifier_single(parser, span, ty)? {} + Ok(()) + } - let (value, span) = self.parse_uint_constant(parser)?; - let constant = parser.module.constants.fetch_or_append( - crate::Constant { + /// Implementation of [`Self::parse_array_specifier`] for a single array_specifier + fn parse_array_specifier_single( + &mut self, + parser: &mut Parser, + span: &mut Span, + ty: &mut Handle, + ) -> Result { + if self.bump_if(parser, TokenValue::LeftBracket).is_some() { + let size = + if let Some(Token { meta, .. }) = self.bump_if(parser, TokenValue::RightBracket) { + span.subsume(meta); + ArraySize::Dynamic + } else { + let (value, constant_span) = self.parse_uint_constant(parser)?; + let constant = parser.module.constants.fetch_or_append( + crate::Constant { + name: None, + specialization: None, + inner: crate::ConstantInner::Scalar { + width: 4, + value: crate::ScalarValue::Uint(value as u64), + }, + }, + constant_span, + ); + let end_span = self.expect(parser, TokenValue::RightBracket)?.meta; + span.subsume(end_span); + ArraySize::Constant(constant) + }; + + parser + .layouter + .update(&parser.module.types, &parser.module.constants) + .unwrap(); + let stride = parser.layouter[*ty].to_stride(); + *ty = parser.module.types.insert( + Type { name: None, - specialization: None, - inner: crate::ConstantInner::Scalar { - width: 4, - value: crate::ScalarValue::Uint(value as u64), + inner: TypeInner::Array { + base: *ty, + size, + stride, }, }, - span, + *span, ); - let end_meta = self.expect(parser, TokenValue::RightBracket)?.meta; - meta.subsume(end_meta); - Ok(Some((ArraySize::Constant(constant), meta))) + + Ok(true) } else { - Ok(None) + Ok(false) } } pub fn parse_type(&mut self, parser: &mut Parser) -> Result<(Option>, Span)> { let token = self.bump(parser)?; - let handle = match token.value { - TokenValue::Void => None, - TokenValue::TypeName(ty) => Some(parser.module.types.insert(ty, token.meta)), + let mut handle = match token.value { + TokenValue::Void => return Ok((None, token.meta)), + TokenValue::TypeName(ty) => parser.module.types.insert(ty, token.meta), TokenValue::Struct => { let mut meta = token.meta; let ty_name = self.expect_ident(parser)?.0; @@ -66,10 +97,10 @@ impl<'source> ParsingContext<'source> { meta, ); parser.lookup_type.insert(ty_name, ty); - Some(ty) + ty } TokenValue::Identifier(ident) => match parser.lookup_type.get(&ident) { - Some(ty) => Some(*ty), + Some(ty) => *ty, None => { return Err(Error { kind: ErrorKind::UnknownType(ident), @@ -92,12 +123,9 @@ impl<'source> ParsingContext<'source> { } }; - let token_meta = token.meta; - let array_specifier = self.parse_array_specifier(parser)?; - let handle = handle.map(|ty| parser.maybe_array(ty, token_meta, array_specifier)); - let mut meta = array_specifier.map_or(token_meta, |(_, meta)| meta); - meta.subsume(token_meta); - Ok((handle, meta)) + let mut span = token.meta; + self.parse_array_specifier(parser, &mut span, &mut handle)?; + Ok((Some(handle), span)) } pub fn parse_type_non_void(&mut self, parser: &mut Parser) -> Result<(Handle, Span)> { diff --git a/src/front/glsl/types.rs b/src/front/glsl/types.rs index 3900fe12d8..cf38f9d737 100644 --- a/src/front/glsl/types.rs +++ b/src/front/glsl/types.rs @@ -1,7 +1,7 @@ use super::{constants::ConstantSolver, context::Context, Error, ErrorKind, Parser, Result, Span}; use crate::{ - proc::ResolveContext, ArraySize, Bytes, Constant, Expression, Handle, ImageClass, - ImageDimension, ScalarKind, Type, TypeInner, VectorSize, + proc::ResolveContext, Bytes, Constant, Expression, Handle, ImageClass, ImageDimension, + ScalarKind, Type, TypeInner, VectorSize, }; pub fn parse_type(type_name: &str) -> Option { @@ -299,29 +299,4 @@ impl Parser { meta, }) } - - pub(crate) fn maybe_array( - &mut self, - base: Handle, - mut meta: Span, - array_specifier: Option<(ArraySize, Span)>, - ) -> Handle { - match array_specifier { - Some((size, size_meta)) => { - meta.subsume(size_meta); - self.layouter - .update(&self.module.types, &self.module.constants) - .unwrap(); - let stride = self.layouter[base].to_stride(); - self.module.types.insert( - Type { - name: None, - inner: TypeInner::Array { base, size, stride }, - }, - meta, - ) - } - None => base, - } - } } diff --git a/tests/in/glsl/declarations.vert b/tests/in/glsl/declarations.vert index 4d2054caa6..75122bc46c 100644 --- a/tests/in/glsl/declarations.vert +++ b/tests/in/glsl/declarations.vert @@ -18,6 +18,8 @@ struct TestStruct { float b; }; +float array_2d[2][2]; +float array_toomanyd[2][2][2][2][2][2][2]; void main() { const vec3 positions[2] = vec3[2]( @@ -26,5 +28,7 @@ void main() { ); const TestStruct strct = TestStruct( 1, 2 ); const vec4 from_input_array = in_array[1]; + const float a = array_2d[0][0]; + const float b = array_toomanyd[0][0][0][0][0][0][0]; out_array[0] = vec4(2.0); } diff --git a/tests/out/wgsl/declarations-vert.wgsl b/tests/out/wgsl/declarations-vert.wgsl index ba1cdd58d6..42de93fd8a 100644 --- a/tests/out/wgsl/declarations-vert.wgsl +++ b/tests/out/wgsl/declarations-vert.wgsl @@ -24,14 +24,22 @@ var vert: VertexData; var frag: FragmentData; var in_array_2: array,2u>; var out_array: array,2u>; +var array_2d: array,2u>; +var array_toomanyd: array,2u>,2u>,2u>,2u>,2u>,2u>; fn main_1() { var positions: array,2u> = array,2u>(vec3(-1.0, 1.0, 0.0), vec3(-1.0, -1.0, 0.0)); var strct: TestStruct = TestStruct(1.0, 2.0); var from_input_array: vec4; + var a_1: f32; + var b: f32; - let _e32 = in_array_2; - from_input_array = _e32[1]; + let _e34 = in_array_2; + from_input_array = _e34[1]; + let _e39 = array_2d; + a_1 = _e39[0][0]; + let _e50 = array_toomanyd; + b = _e50[0][0][0][0][0][0][0]; out_array[0] = vec4(2.0); return; } @@ -43,9 +51,9 @@ fn main(@location(0) position: vec2, @location(1) a: vec2, @location(2 in_array_2[0] = in_array; in_array_2[1] = in_array_1; main_1(); - let _e26 = frag.position; - let _e28 = frag.a; - let _e31 = out_array[0]; - let _e33 = out_array[1]; - return VertexOutput(_e26, _e28, _e31, _e33); + let _e30 = frag.position; + let _e32 = frag.a; + let _e35 = out_array[0]; + let _e37 = out_array[1]; + return VertexOutput(_e30, _e32, _e35, _e37); }