1 //! Front end for consuming [WebGPU Shading Language][wgsl].
2 //!
3 //! [wgsl]: https://gpuweb.github.io/gpuweb/wgsl.html
4 
5 mod conv;
6 mod lexer;
7 mod number_literals;
8 #[cfg(test)]
9 mod tests;
10 
11 use crate::{
12     arena::{Arena, Handle, UniqueArena},
13     proc::{
14         ensure_block_returns, Alignment, Layouter, ResolveContext, ResolveError, TypeResolution,
15     },
16     span::Span as NagaSpan,
17     Bytes, ConstantInner, FastHashMap, ScalarValue,
18 };
19 
20 use self::{
21     lexer::Lexer,
22     number_literals::{
23         get_f32_literal, get_i32_literal, get_u32_literal, parse_generic_non_negative_int_literal,
24         parse_non_negative_sint_literal,
25     },
26 };
27 use codespan_reporting::{
28     diagnostic::{Diagnostic, Label},
29     files::{Files, SimpleFile},
30     term::{
31         self,
32         termcolor::{ColorChoice, ColorSpec, StandardStream, WriteColor},
33     },
34 };
35 use hexf_parse::ParseHexfError;
36 use std::{
37     borrow::Cow,
38     convert::TryFrom,
39     io::{self, Write},
40     num::{NonZeroU32, ParseFloatError, ParseIntError},
41     ops,
42 };
43 use thiserror::Error;
44 
45 type Span = ops::Range<usize>;
46 type TokenSpan<'a> = (Token<'a>, Span);
47 
48 #[derive(Copy, Clone, Debug, PartialEq)]
49 pub enum NumberType {
50     Sint,
51     Uint,
52     Float,
53 }
54 
55 #[derive(Copy, Clone, Debug, PartialEq)]
56 pub enum Token<'a> {
57     Separator(char),
58     DoubleColon,
59     Paren(char),
60     DoubleParen(char),
61     Number {
62         value: &'a str,
63         ty: NumberType,
64         width: Option<Bytes>,
65     },
66     String(&'a str),
67     Word(&'a str),
68     Operation(char),
69     LogicalOperation(char),
70     ShiftOperation(char),
71     AssignmentOperation(char),
72     Arrow,
73     Unknown(char),
74     UnterminatedString,
75     Trivia,
76     End,
77 }
78 
79 #[derive(Copy, Clone, Debug, PartialEq)]
80 pub enum ExpectedToken<'a> {
81     Token(Token<'a>),
82     Identifier,
83     Number {
84         ty: Option<NumberType>,
85         width: Option<Bytes>,
86     },
87     Integer,
88     Constant,
89     /// Expected: constant, parenthesized expression, identifier
90     PrimaryExpression,
91     /// Expected: ']]', ','
92     AttributeSeparator,
93     /// Expected: '}', identifier
94     FieldName,
95     /// Expected: ']]', 'access', 'stride'
96     TypeAttribute,
97     /// Expected: ';', '{', word
98     Statement,
99     /// Expected: 'case', 'default', '}'
100     SwitchItem,
101     /// Expected: ',', ')'
102     WorkgroupSizeSeparator,
103     /// Expected: 'struct', 'let', 'var', 'type', ';', 'fn', eof
104     GlobalItem,
105     /// Expected: ']]', 'size', 'align'
106     StructAttribute,
107 }
108 
109 #[derive(Clone, Debug, Error)]
110 pub enum BadIntError {
111     #[error(transparent)]
112     ParseIntError(#[from] ParseIntError),
113     #[error("non-hex negative zero integer literals are not allowed")]
114     NegativeZero,
115     #[error("leading zeros for non-hex integer literals are not allowed")]
116     LeadingZeros,
117 }
118 
119 #[derive(Clone, Debug, Error)]
120 pub enum BadFloatError {
121     #[error(transparent)]
122     ParseFloatError(#[from] ParseFloatError),
123     #[error(transparent)]
124     ParseHexfError(#[from] ParseHexfError),
125 }
126 
127 #[derive(Clone, Debug)]
128 pub enum Error<'a> {
129     Unexpected(TokenSpan<'a>, ExpectedToken<'a>),
130     BadU32(Span, BadIntError),
131     BadI32(Span, BadIntError),
132     /// A negative signed integer literal where both signed and unsigned,
133     /// but only non-negative literals are allowed.
134     NegativeInt(Span),
135     BadFloat(Span, BadFloatError),
136     BadU32Constant(Span),
137     BadScalarWidth(Span, Bytes),
138     BadAccessor(Span),
139     BadTexture(Span),
140     BadTypeCast {
141         span: Span,
142         from_type: String,
143         to_type: String,
144     },
145     BadTextureSampleType {
146         span: Span,
147         kind: crate::ScalarKind,
148         width: u8,
149     },
150     InvalidResolve(ResolveError),
151     InvalidForInitializer(Span),
152     InvalidGatherComponent(Span, i32),
153     ReservedIdentifierPrefix(Span),
154     UnknownStorageClass(Span),
155     UnknownAttribute(Span),
156     UnknownBuiltin(Span),
157     UnknownAccess(Span),
158     UnknownShaderStage(Span),
159     UnknownIdent(Span, &'a str),
160     UnknownScalarType(Span),
161     UnknownType(Span),
162     UnknownStorageFormat(Span),
163     UnknownConservativeDepth(Span),
164     ZeroStride(Span),
165     ZeroSizeOrAlign(Span),
166     InconsistentBinding(Span),
167     UnknownLocalFunction(Span),
168     InitializationTypeMismatch(Span, String),
169     MissingType(Span),
170     InvalidAtomicPointer(Span),
171     InvalidAtomicOperandType(Span),
172     Pointer(&'static str, Span),
173     NotPointer(Span),
174     NotReference(&'static str, Span),
175     ReservedKeyword(Span),
176     Redefinition {
177         previous: Span,
178         current: Span,
179     },
180     Other,
181 }
182 
183 impl<'a> Error<'a> {
as_parse_error(&self, source: &'a str) -> ParseError184     fn as_parse_error(&self, source: &'a str) -> ParseError {
185         match *self {
186             Error::Unexpected((_, ref unexpected_span), expected) => {
187                 let expected_str = match expected {
188                         ExpectedToken::Token(token) => {
189                             match token {
190                                 Token::Separator(c) => format!("'{}'", c),
191                                 Token::DoubleColon => "'::'".to_string(),
192                                 Token::Paren(c) => format!("'{}'", c),
193                                 Token::DoubleParen(c) => format!("'{}{}'", c, c),
194                                 Token::Number { value, .. } => {
195                                     format!("number ({})", value)
196                                 }
197                                 Token::String(s) => format!("string literal ('{}')", s),
198                                 Token::Word(s) => s.to_string(),
199                                 Token::Operation(c) => format!("operation ('{}')", c),
200                                 Token::LogicalOperation(c) => format!("logical operation ('{}')", c),
201                                 Token::ShiftOperation(c) => format!("bitshift ('{}{}')", c, c),
202                                 Token::AssignmentOperation(c) if c=='<' || c=='>' => format!("bitshift ('{}{}=')", c, c),
203                                 Token::AssignmentOperation(c) => format!("operation ('{}=')", c),
204                                 Token::Arrow => "->".to_string(),
205                                 Token::Unknown(c) => format!("unknown ('{}')", c),
206                                 Token::UnterminatedString => "unterminated string".to_string(),
207                                 Token::Trivia => "trivia".to_string(),
208                                 Token::End => "end".to_string(),
209                             }
210                         }
211                         ExpectedToken::Identifier => "identifier".to_string(),
212                         ExpectedToken::Number { ty, width } => {
213                             let literal_ty_str = match ty {
214                                 Some(NumberType::Float) => "floating-point",
215                                 Some(NumberType::Uint) => "unsigned integer",
216                                 Some(NumberType::Sint) => "signed integer",
217                                 None => "arbitrary number",
218                             };
219                             if let Some(width) = width {
220                                 format!(
221                                     "{} literal of {}-bit width",
222                                     literal_ty_str,
223                                     width as u32 * 8,
224                                 )
225                             } else {
226                                 format!(
227                                     "{} literal of arbitrary width",
228                                     literal_ty_str,
229                                 )
230                             }
231                         },
232                         ExpectedToken::Integer => "unsigned/signed integer literal".to_string(),
233                         ExpectedToken::Constant => "constant".to_string(),
234                         ExpectedToken::PrimaryExpression => "expression".to_string(),
235                         ExpectedToken::AttributeSeparator => "attribute separator (',') or an end of the attribute list (']]')".to_string(),
236                         ExpectedToken::FieldName => "field name or a closing curly bracket to signify the end of the struct".to_string(),
237                         ExpectedToken::TypeAttribute => "type attribute ('stride') or an end of the attribute list (']]')".to_string(),
238                         ExpectedToken::Statement => "statement".to_string(),
239                         ExpectedToken::SwitchItem => "switch item ('case' or 'default') or a closing curly bracket to signify the end of the switch statement ('}')".to_string(),
240                         ExpectedToken::WorkgroupSizeSeparator => "workgroup size separator (',') or a closing parenthesis".to_string(),
241                         ExpectedToken::GlobalItem => "global item ('struct', 'let', 'var', 'type', ';', 'fn') or the end of the file".to_string(),
242                         ExpectedToken::StructAttribute => "struct attribute ('size' or 'align') or an end of the attribute list (']]')".to_string(),
243                     };
244                     ParseError {
245                     message: format!(
246                         "expected {}, found '{}'",
247                         expected_str,
248                         &source[unexpected_span.clone()],
249                     ),
250                     labels: vec![(
251                         unexpected_span.clone(),
252                         format!("expected {}", expected_str).into(),
253                     )],
254                     notes: vec![],
255                 }
256             },
257             Error::BadU32(ref bad_span, ref err) => ParseError {
258                 message: format!(
259                     "expected unsigned integer literal, found `{}`",
260                     &source[bad_span.clone()],
261                 ),
262                 labels: vec![(bad_span.clone(), "expected unsigned integer".into())],
263                 notes: vec![err.to_string()],
264             },
265             Error::BadI32(ref bad_span, ref err) => ParseError {
266                 message: format!(
267                     "expected integer literal, found `{}`",
268                     &source[bad_span.clone()],
269                 ),
270                 labels: vec![(bad_span.clone(), "expected signed integer".into())],
271                 notes: vec![err.to_string()],
272             },
273             Error::NegativeInt(ref bad_span) => ParseError {
274                 message: format!(
275                     "expected non-negative integer literal, found `{}`",
276                     &source[bad_span.clone()],
277                 ),
278                 labels: vec![(bad_span.clone(), "expected non-negative integer".into())],
279                 notes: vec![],
280             },
281             Error::BadFloat(ref bad_span, ref err) => ParseError {
282                 message: format!(
283                     "expected floating-point literal, found `{}`",
284                     &source[bad_span.clone()],
285                 ),
286                 labels: vec![(bad_span.clone(), "expected floating-point literal".into())],
287                 notes: vec![err.to_string()],
288             },
289             Error::BadU32Constant(ref bad_span) => ParseError {
290                 message: format!(
291                     "expected unsigned integer constant expression, found `{}`",
292                     &source[bad_span.clone()],
293                 ),
294                 labels: vec![(bad_span.clone(), "expected unsigned integer".into())],
295                 notes: vec![],
296             },
297 
298             Error::BadScalarWidth(ref bad_span, width) => ParseError {
299                 message: format!("invalid width of `{}` bits for literal", width as u32 * 8,),
300                 labels: vec![(bad_span.clone(), "invalid width".into())],
301                 notes: vec!["the only valid width is 32 for now".to_string()],
302             },
303             Error::BadAccessor(ref accessor_span) => ParseError {
304                 message: format!(
305                     "invalid field accessor `{}`",
306                     &source[accessor_span.clone()],
307                 ),
308                 labels: vec![(accessor_span.clone(), "invalid accessor".into())],
309                 notes: vec![],
310             },
311             Error::UnknownIdent(ref ident_span, ident) => ParseError {
312                 message: format!("no definition in scope for identifier: '{}'", ident),
313                 labels: vec![(ident_span.clone(), "unknown identifier".into())],
314                 notes: vec![],
315             },
316             Error::UnknownScalarType(ref bad_span) => ParseError {
317                 message: format!("unknown scalar type: '{}'", &source[bad_span.clone()]),
318                 labels: vec![(bad_span.clone(), "unknown scalar type".into())],
319                 notes: vec!["Valid scalar types are f16, f32, f64, i8, i16, i32, i64, u8, u16, u32, u64, bool".into()],
320             },
321             Error::BadTextureSampleType { ref span, kind, width } => ParseError {
322                 message: format!("texture sample type must be one of f32, i32 or u32, but found {}", kind.to_wgsl(width)),
323                 labels: vec![(span.clone(), "must be one of f32, i32 or u32".into())],
324                 notes: vec![],
325             },
326             Error::BadTexture(ref bad_span) => ParseError {
327                 message: format!("expected an image, but found '{}' which is not an image", &source[bad_span.clone()]),
328                 labels: vec![(bad_span.clone(), "not an image".into())],
329                 notes: vec![],
330             },
331             Error::BadTypeCast { ref span, ref from_type, ref to_type } => {
332                 let msg = format!("cannot cast a {} to a {}", from_type, to_type);
333                 ParseError {
334                     message: msg.clone(),
335                     labels: vec![(span.clone(), msg.into())],
336                     notes: vec![],
337                 }
338             },
339             Error::InvalidResolve(ref resolve_error) => ParseError {
340                 message: resolve_error.to_string(),
341                 labels: vec![],
342                 notes: vec![],
343             },
344             Error::InvalidForInitializer(ref bad_span) => ParseError {
345                 message: format!("for(;;) initializer is not an assignment or a function call: '{}'", &source[bad_span.clone()]),
346                 labels: vec![(bad_span.clone(), "not an assignment or function call".into())],
347                 notes: vec![],
348             },
349             Error::InvalidGatherComponent(ref bad_span, component) => ParseError {
350                 message: format!("textureGather component {} doesn't exist, must be 0, 1, 2, or 3", component),
351                 labels: vec![(bad_span.clone(), "invalid component".into())],
352                 notes: vec![],
353             },
354             Error::ReservedIdentifierPrefix(ref bad_span) => ParseError {
355                 message: format!("Identifier starts with a reserved prefix: '{}'", &source[bad_span.clone()]),
356                 labels: vec![(bad_span.clone(), "invalid identifier".into())],
357                 notes: vec![],
358             },
359             Error::UnknownStorageClass(ref bad_span) => ParseError {
360                 message: format!("unknown storage class: '{}'", &source[bad_span.clone()]),
361                 labels: vec![(bad_span.clone(), "unknown storage class".into())],
362                 notes: vec![],
363             },
364             Error::UnknownAttribute(ref bad_span) => ParseError {
365                 message: format!("unknown attribute: '{}'", &source[bad_span.clone()]),
366                 labels: vec![(bad_span.clone(), "unknown attribute".into())],
367                 notes: vec![],
368             },
369             Error::UnknownBuiltin(ref bad_span) => ParseError {
370                 message: format!("unknown builtin: '{}'", &source[bad_span.clone()]),
371                 labels: vec![(bad_span.clone(), "unknown builtin".into())],
372                 notes: vec![],
373             },
374             Error::UnknownAccess(ref bad_span) => ParseError {
375                 message: format!("unknown access: '{}'", &source[bad_span.clone()]),
376                 labels: vec![(bad_span.clone(), "unknown access".into())],
377                 notes: vec![],
378             },
379             Error::UnknownShaderStage(ref bad_span) => ParseError {
380                 message: format!("unknown shader stage: '{}'", &source[bad_span.clone()]),
381                 labels: vec![(bad_span.clone(), "unknown shader stage".into())],
382                 notes: vec![],
383             },
384             Error::UnknownStorageFormat(ref bad_span) => ParseError {
385                 message: format!("unknown storage format: '{}'", &source[bad_span.clone()]),
386                 labels: vec![(bad_span.clone(), "unknown storage format".into())],
387                 notes: vec![],
388             },
389             Error::UnknownConservativeDepth(ref bad_span) => ParseError {
390                 message: format!("unknown conservative depth: '{}'", &source[bad_span.clone()]),
391                 labels: vec![(bad_span.clone(), "unknown conservative depth".into())],
392                 notes: vec![],
393             },
394             Error::UnknownType(ref bad_span) => ParseError {
395                 message: format!("unknown type: '{}'", &source[bad_span.clone()]),
396                 labels: vec![(bad_span.clone(), "unknown type".into())],
397                 notes: vec![],
398             },
399             Error::ZeroStride(ref bad_span) => ParseError {
400                 message: "array stride must not be zero".to_string(),
401                 labels: vec![(bad_span.clone(), "array stride must not be zero".into())],
402                 notes: vec![],
403             },
404             Error::ZeroSizeOrAlign(ref bad_span) => ParseError {
405                 message: "struct member size or alignment must not be 0".to_string(),
406                 labels: vec![(bad_span.clone(), "struct member size or alignment must not be 0".into())],
407                 notes: vec![],
408             },
409             Error::InconsistentBinding(ref span) => ParseError {
410                 message: "input/output binding is not consistent".to_string(),
411                 labels: vec![(span.clone(), "input/output binding is not consistent".into())],
412                 notes: vec![],
413             },
414             Error::UnknownLocalFunction(ref span) => ParseError {
415                 message: format!("unknown local function `{}`", &source[span.clone()]),
416                 labels: vec![(span.clone(), "unknown local function".into())],
417                 notes: vec![],
418             },
419             Error::InitializationTypeMismatch(ref name_span, ref expected_ty) => ParseError {
420                 message: format!("the type of `{}` is expected to be `{}`", &source[name_span.clone()], expected_ty),
421                 labels: vec![(name_span.clone(), format!("definition of `{}`", &source[name_span.clone()]).into())],
422                 notes: vec![],
423             },
424             Error::MissingType(ref name_span) => ParseError {
425                 message: format!("variable `{}` needs a type", &source[name_span.clone()]),
426                 labels: vec![(name_span.clone(), format!("definition of `{}`", &source[name_span.clone()]).into())],
427                 notes: vec![],
428             },
429             Error::InvalidAtomicPointer(ref span) => ParseError {
430                 message: "atomic operation is done on a pointer to a non-atomic".to_string(),
431                 labels: vec![(span.clone(), "atomic pointer is invalid".into())],
432                 notes: vec![],
433             },
434             Error::InvalidAtomicOperandType(ref span) => ParseError {
435                 message: "atomic operand type is inconsistent with the operation".to_string(),
436                 labels: vec![(span.clone(), "atomic operand type is invalid".into())],
437                 notes: vec![],
438             },
439             Error::NotPointer(ref span) => ParseError {
440                 message: "the operand of the `*` operator must be a pointer".to_string(),
441                 labels: vec![(span.clone(), "expression is not a pointer".into())],
442                 notes: vec![],
443             },
444             Error::NotReference(what, ref span) => ParseError {
445                 message: format!("{} must be a reference", what),
446                 labels: vec![(span.clone(), "expression is not a reference".into())],
447                 notes: vec![],
448             },
449             Error::Pointer(what, ref span) => ParseError {
450                 message: format!("{} must not be a pointer", what),
451                 labels: vec![(span.clone(), "expression is a pointer".into())],
452                 notes: vec![],
453             },
454             Error::ReservedKeyword(ref name_span) => ParseError {
455                 message: format!("name `{}` is a reserved keyword", &source[name_span.clone()]),
456                 labels: vec![(name_span.clone(), format!("definition of `{}`", &source[name_span.clone()]).into())],
457                 notes: vec![],
458             },
459             Error::Redefinition { ref previous, ref current } => ParseError {
460                 message: format!("redefinition of `{}`", &source[current.clone()]),
461                 labels: vec![(current.clone(), format!("redefinition of `{}`", &source[current.clone()]).into()),
462                              (previous.clone(), format!("previous definition of `{}`", &source[previous.clone()]).into())
463                 ],
464                 notes: vec![],
465             },
466             Error::Other => ParseError {
467                 message: "other error".to_string(),
468                 labels: vec![],
469                 notes: vec![],
470             },
471         }
472     }
473 }
474 
475 impl crate::StorageFormat {
to_wgsl(self) -> &'static str476     fn to_wgsl(self) -> &'static str {
477         use crate::StorageFormat as Sf;
478         match self {
479             Sf::R8Unorm => "r8unorm",
480             Sf::R8Snorm => "r8snorm",
481             Sf::R8Uint => "r8uint",
482             Sf::R8Sint => "r8sint",
483             Sf::R16Uint => "r16uint",
484             Sf::R16Sint => "r16sint",
485             Sf::R16Float => "r16float",
486             Sf::Rg8Unorm => "rg8unorm",
487             Sf::Rg8Snorm => "rg8snorm",
488             Sf::Rg8Uint => "rg8uint",
489             Sf::Rg8Sint => "rg8sint",
490             Sf::R32Uint => "r32uint",
491             Sf::R32Sint => "r32sint",
492             Sf::R32Float => "r32float",
493             Sf::Rg16Uint => "rg16uint",
494             Sf::Rg16Sint => "rg16sint",
495             Sf::Rg16Float => "rg16float",
496             Sf::Rgba8Unorm => "rgba8unorm",
497             Sf::Rgba8Snorm => "rgba8snorm",
498             Sf::Rgba8Uint => "rgba8uint",
499             Sf::Rgba8Sint => "rgba8sint",
500             Sf::Rgb10a2Unorm => "rgb10a2unorm",
501             Sf::Rg11b10Float => "rg11b10float",
502             Sf::Rg32Uint => "rg32uint",
503             Sf::Rg32Sint => "rg32sint",
504             Sf::Rg32Float => "rg32float",
505             Sf::Rgba16Uint => "rgba16uint",
506             Sf::Rgba16Sint => "rgba16sint",
507             Sf::Rgba16Float => "rgba16float",
508             Sf::Rgba32Uint => "rgba32uint",
509             Sf::Rgba32Sint => "rgba32sint",
510             Sf::Rgba32Float => "rgba32float",
511         }
512     }
513 }
514 
515 impl crate::TypeInner {
516     /// Formats the type as it is written in wgsl.
517     ///
518     /// For example `vec3<f32>`.
519     ///
520     /// Note: The names of a `TypeInner::Struct` is not known. Therefore this method will simply return "struct" for them.
to_wgsl( &self, types: &UniqueArena<crate::Type>, constants: &Arena<crate::Constant>, ) -> String521     fn to_wgsl(
522         &self,
523         types: &UniqueArena<crate::Type>,
524         constants: &Arena<crate::Constant>,
525     ) -> String {
526         use crate::TypeInner as Ti;
527 
528         match *self {
529             Ti::Scalar { kind, width } => kind.to_wgsl(width),
530             Ti::Vector { size, kind, width } => {
531                 format!("vec{}<{}>", size as u32, kind.to_wgsl(width))
532             }
533             Ti::Matrix {
534                 columns,
535                 rows,
536                 width,
537             } => {
538                 format!(
539                     "mat{}x{}<{}>",
540                     columns as u32,
541                     rows as u32,
542                     crate::ScalarKind::Float.to_wgsl(width),
543                 )
544             }
545             Ti::Atomic { kind, width } => {
546                 format!("atomic<{}>", kind.to_wgsl(width))
547             }
548             Ti::Pointer { base, .. } => {
549                 let base = &types[base];
550                 let name = base.name.as_deref().unwrap_or("unknown");
551                 format!("ptr<{}>", name)
552             }
553             Ti::ValuePointer { kind, width, .. } => {
554                 format!("ptr<{}>", kind.to_wgsl(width))
555             }
556             Ti::Array { base, size, .. } => {
557                 let member_type = &types[base];
558                 let base = member_type.name.as_deref().unwrap_or("unknown");
559                 match size {
560                     crate::ArraySize::Constant(size) => {
561                         let size = constants[size].name.as_deref().unwrap_or("unknown");
562                         format!("{}[{}]", base, size)
563                     }
564                     crate::ArraySize::Dynamic => format!("{}[]", base),
565                 }
566             }
567             Ti::Struct { .. } => {
568                 // TODO: Actually output the struct?
569                 "struct".to_string()
570             }
571             Ti::Image {
572                 dim,
573                 arrayed,
574                 class,
575             } => {
576                 let dim_suffix = match dim {
577                     crate::ImageDimension::D1 => "_1d",
578                     crate::ImageDimension::D2 => "_2d",
579                     crate::ImageDimension::D3 => "_3d",
580                     crate::ImageDimension::Cube => "_cube",
581                 };
582                 let array_suffix = if arrayed { "_array" } else { "" };
583 
584                 let class_suffix = match class {
585                     crate::ImageClass::Sampled { multi: true, .. } => "_multisampled",
586                     crate::ImageClass::Depth { multi: false } => "_depth",
587                     crate::ImageClass::Depth { multi: true } => "_depth_multisampled",
588                     crate::ImageClass::Sampled { multi: false, .. }
589                     | crate::ImageClass::Storage { .. } => "",
590                 };
591 
592                 let type_in_brackets = match class {
593                     crate::ImageClass::Sampled { kind, .. } => {
594                         // Note: The only valid widths are 4 bytes wide.
595                         // The lexer has already verified this, so we can safely assume it here.
596                         // https://gpuweb.github.io/gpuweb/wgsl/#sampled-texture-type
597                         let element_type = kind.to_wgsl(4);
598                         format!("<{}>", element_type)
599                     }
600                     crate::ImageClass::Depth { multi: _ } => String::new(),
601                     crate::ImageClass::Storage { format, access } => {
602                         if access.contains(crate::StorageAccess::STORE) {
603                             format!("<{},write>", format.to_wgsl())
604                         } else {
605                             format!("<{}>", format.to_wgsl())
606                         }
607                     }
608                 };
609 
610                 format!(
611                     "texture{}{}{}{}",
612                     class_suffix, dim_suffix, array_suffix, type_in_brackets
613                 )
614             }
615             Ti::Sampler { .. } => "sampler".to_string(),
616         }
617     }
618 }
619 
620 mod type_inner_tests {
621     #[test]
to_wgsl()622     fn to_wgsl() {
623         let mut types = crate::UniqueArena::new();
624         let mut constants = crate::Arena::new();
625         let c = constants.append(
626             crate::Constant {
627                 name: Some("C".to_string()),
628                 specialization: None,
629                 inner: crate::ConstantInner::Scalar {
630                     width: 4,
631                     value: crate::ScalarValue::Uint(32),
632                 },
633             },
634             Default::default(),
635         );
636 
637         let mytype1 = types.insert(
638             crate::Type {
639                 name: Some("MyType1".to_string()),
640                 inner: crate::TypeInner::Struct {
641                     members: vec![],
642                     span: 0,
643                 },
644             },
645             Default::default(),
646         );
647         let mytype2 = types.insert(
648             crate::Type {
649                 name: Some("MyType2".to_string()),
650                 inner: crate::TypeInner::Struct {
651                     members: vec![],
652                     span: 0,
653                 },
654             },
655             Default::default(),
656         );
657 
658         let array = crate::TypeInner::Array {
659             base: mytype1,
660             stride: 4,
661             size: crate::ArraySize::Constant(c),
662         };
663         assert_eq!(array.to_wgsl(&types, &constants), "MyType1[C]");
664 
665         let mat = crate::TypeInner::Matrix {
666             rows: crate::VectorSize::Quad,
667             columns: crate::VectorSize::Bi,
668             width: 8,
669         };
670         assert_eq!(mat.to_wgsl(&types, &constants), "mat2x4<f64>");
671 
672         let ptr = crate::TypeInner::Pointer {
673             base: mytype2,
674             class: crate::StorageClass::Storage {
675                 access: crate::StorageAccess::default(),
676             },
677         };
678         assert_eq!(ptr.to_wgsl(&types, &constants), "ptr<MyType2>");
679 
680         let img1 = crate::TypeInner::Image {
681             dim: crate::ImageDimension::D2,
682             arrayed: false,
683             class: crate::ImageClass::Sampled {
684                 kind: crate::ScalarKind::Float,
685                 multi: true,
686             },
687         };
688         assert_eq!(
689             img1.to_wgsl(&types, &constants),
690             "texture_multisampled_2d<f32>"
691         );
692 
693         let img2 = crate::TypeInner::Image {
694             dim: crate::ImageDimension::Cube,
695             arrayed: true,
696             class: crate::ImageClass::Depth { multi: false },
697         };
698         assert_eq!(img2.to_wgsl(&types, &constants), "texture_depth_cube_array");
699 
700         let img3 = crate::TypeInner::Image {
701             dim: crate::ImageDimension::D2,
702             arrayed: false,
703             class: crate::ImageClass::Depth { multi: true },
704         };
705         assert_eq!(
706             img3.to_wgsl(&types, &constants),
707             "texture_depth_multisampled_2d"
708         );
709     }
710 }
711 
712 impl crate::ScalarKind {
713     /// Format a scalar kind+width as a type is written in wgsl.
714     ///
715     /// Examples: `f32`, `u64`, `bool`.
to_wgsl(self, width: u8) -> String716     fn to_wgsl(self, width: u8) -> String {
717         let prefix = match self {
718             crate::ScalarKind::Sint => "i",
719             crate::ScalarKind::Uint => "u",
720             crate::ScalarKind::Float => "f",
721             crate::ScalarKind::Bool => return "bool".to_string(),
722         };
723         format!("{}{}", prefix, width * 8)
724     }
725 }
726 
727 trait StringValueLookup<'a> {
728     type Value;
lookup(&self, key: &'a str, span: Span) -> Result<Self::Value, Error<'a>>729     fn lookup(&self, key: &'a str, span: Span) -> Result<Self::Value, Error<'a>>;
730 }
731 impl<'a> StringValueLookup<'a> for FastHashMap<&'a str, TypedExpression> {
732     type Value = TypedExpression;
lookup(&self, key: &'a str, span: Span) -> Result<Self::Value, Error<'a>>733     fn lookup(&self, key: &'a str, span: Span) -> Result<Self::Value, Error<'a>> {
734         self.get(key).cloned().ok_or(Error::UnknownIdent(span, key))
735     }
736 }
737 
738 struct StatementContext<'input, 'temp, 'out> {
739     lookup_ident: &'temp mut FastHashMap<&'input str, TypedExpression>,
740     typifier: &'temp mut super::Typifier,
741     variables: &'out mut Arena<crate::LocalVariable>,
742     expressions: &'out mut Arena<crate::Expression>,
743     named_expressions: &'out mut FastHashMap<Handle<crate::Expression>, String>,
744     types: &'out mut UniqueArena<crate::Type>,
745     constants: &'out mut Arena<crate::Constant>,
746     global_vars: &'out Arena<crate::GlobalVariable>,
747     functions: &'out Arena<crate::Function>,
748     arguments: &'out [crate::FunctionArgument],
749 }
750 
751 impl<'a, 'temp> StatementContext<'a, 'temp, '_> {
reborrow(&mut self) -> StatementContext<'a, '_, '_>752     fn reborrow(&mut self) -> StatementContext<'a, '_, '_> {
753         StatementContext {
754             lookup_ident: self.lookup_ident,
755             typifier: self.typifier,
756             variables: self.variables,
757             expressions: self.expressions,
758             named_expressions: self.named_expressions,
759             types: self.types,
760             constants: self.constants,
761             global_vars: self.global_vars,
762             functions: self.functions,
763             arguments: self.arguments,
764         }
765     }
766 
as_expression<'t>( &'t mut self, block: &'t mut crate::Block, emitter: &'t mut super::Emitter, ) -> ExpressionContext<'a, 't, '_> where 'temp: 't,767     fn as_expression<'t>(
768         &'t mut self,
769         block: &'t mut crate::Block,
770         emitter: &'t mut super::Emitter,
771     ) -> ExpressionContext<'a, 't, '_>
772     where
773         'temp: 't,
774     {
775         ExpressionContext {
776             lookup_ident: self.lookup_ident,
777             typifier: self.typifier,
778             expressions: self.expressions,
779             types: self.types,
780             constants: self.constants,
781             global_vars: self.global_vars,
782             local_vars: self.variables,
783             functions: self.functions,
784             arguments: self.arguments,
785             block,
786             emitter,
787         }
788     }
789 }
790 
791 struct SamplingContext {
792     image: Handle<crate::Expression>,
793     arrayed: bool,
794 }
795 
796 struct ExpressionContext<'input, 'temp, 'out> {
797     lookup_ident: &'temp FastHashMap<&'input str, TypedExpression>,
798     typifier: &'temp mut super::Typifier,
799     expressions: &'out mut Arena<crate::Expression>,
800     types: &'out mut UniqueArena<crate::Type>,
801     constants: &'out mut Arena<crate::Constant>,
802     global_vars: &'out Arena<crate::GlobalVariable>,
803     local_vars: &'out Arena<crate::LocalVariable>,
804     arguments: &'out [crate::FunctionArgument],
805     functions: &'out Arena<crate::Function>,
806     block: &'temp mut crate::Block,
807     emitter: &'temp mut super::Emitter,
808 }
809 
810 impl<'a> ExpressionContext<'a, '_, '_> {
reborrow(&mut self) -> ExpressionContext<'a, '_, '_>811     fn reborrow(&mut self) -> ExpressionContext<'a, '_, '_> {
812         ExpressionContext {
813             lookup_ident: self.lookup_ident,
814             typifier: self.typifier,
815             expressions: self.expressions,
816             types: self.types,
817             constants: self.constants,
818             global_vars: self.global_vars,
819             local_vars: self.local_vars,
820             functions: self.functions,
821             arguments: self.arguments,
822             block: self.block,
823             emitter: self.emitter,
824         }
825     }
826 
resolve_type( &mut self, handle: Handle<crate::Expression>, ) -> Result<&crate::TypeInner, Error<'a>>827     fn resolve_type(
828         &mut self,
829         handle: Handle<crate::Expression>,
830     ) -> Result<&crate::TypeInner, Error<'a>> {
831         let resolve_ctx = ResolveContext {
832             constants: self.constants,
833             types: self.types,
834             global_vars: self.global_vars,
835             local_vars: self.local_vars,
836             functions: self.functions,
837             arguments: self.arguments,
838         };
839         match self.typifier.grow(handle, self.expressions, &resolve_ctx) {
840             Err(e) => Err(Error::InvalidResolve(e)),
841             Ok(()) => Ok(self.typifier.get(handle, self.types)),
842         }
843     }
844 
prepare_sampling( &mut self, image_name: &'a str, span: Span, ) -> Result<SamplingContext, Error<'a>>845     fn prepare_sampling(
846         &mut self,
847         image_name: &'a str,
848         span: Span,
849     ) -> Result<SamplingContext, Error<'a>> {
850         let image = self.lookup_ident.lookup(image_name, span.clone())?.handle;
851         Ok(SamplingContext {
852             image,
853             arrayed: match *self.resolve_type(image)? {
854                 crate::TypeInner::Image { arrayed, .. } => arrayed,
855                 _ => return Err(Error::BadTexture(span)),
856             },
857         })
858     }
859 
parse_binary_op( &mut self, lexer: &mut Lexer<'a>, classifier: impl Fn(Token<'a>) -> Option<crate::BinaryOperator>, mut parser: impl FnMut( &mut Lexer<'a>, ExpressionContext<'a, '_, '_>, ) -> Result<TypedExpression, Error<'a>>, ) -> Result<TypedExpression, Error<'a>>860     fn parse_binary_op(
861         &mut self,
862         lexer: &mut Lexer<'a>,
863         classifier: impl Fn(Token<'a>) -> Option<crate::BinaryOperator>,
864         mut parser: impl FnMut(
865             &mut Lexer<'a>,
866             ExpressionContext<'a, '_, '_>,
867         ) -> Result<TypedExpression, Error<'a>>,
868     ) -> Result<TypedExpression, Error<'a>> {
869         let start = lexer.current_byte_offset() as u32;
870         let mut accumulator = parser(lexer, self.reborrow())?;
871         while let Some(op) = classifier(lexer.peek().0) {
872             let _ = lexer.next();
873             // Binary expressions always apply the load rule to their operands.
874             let mut left = self.apply_load_rule(accumulator);
875             let unloaded_right = parser(lexer, self.reborrow())?;
876             let right = self.apply_load_rule(unloaded_right);
877             let end = lexer.current_byte_offset() as u32;
878             left = self.expressions.append(
879                 crate::Expression::Binary { op, left, right },
880                 NagaSpan::new(start, end),
881             );
882             // Binary expressions never produce references.
883             accumulator = TypedExpression::non_reference(left);
884         }
885         Ok(accumulator)
886     }
887 
parse_binary_splat_op( &mut self, lexer: &mut Lexer<'a>, classifier: impl Fn(Token<'a>) -> Option<crate::BinaryOperator>, mut parser: impl FnMut( &mut Lexer<'a>, ExpressionContext<'a, '_, '_>, ) -> Result<TypedExpression, Error<'a>>, ) -> Result<TypedExpression, Error<'a>>888     fn parse_binary_splat_op(
889         &mut self,
890         lexer: &mut Lexer<'a>,
891         classifier: impl Fn(Token<'a>) -> Option<crate::BinaryOperator>,
892         mut parser: impl FnMut(
893             &mut Lexer<'a>,
894             ExpressionContext<'a, '_, '_>,
895         ) -> Result<TypedExpression, Error<'a>>,
896     ) -> Result<TypedExpression, Error<'a>> {
897         let start = lexer.current_byte_offset() as u32;
898         let mut accumulator = parser(lexer, self.reborrow())?;
899         while let Some(op) = classifier(lexer.peek().0) {
900             let _ = lexer.next();
901             // Binary expressions always apply the load rule to their operands.
902             let mut left = self.apply_load_rule(accumulator);
903             let unloaded_right = parser(lexer, self.reborrow())?;
904             let mut right = self.apply_load_rule(unloaded_right);
905             let end = lexer.current_byte_offset() as u32;
906 
907             // Insert splats, if needed by the non-'*' operations.
908             // (`BinaryOperator::Multiply` handles splats itself.)
909             if op != crate::BinaryOperator::Multiply {
910                 let left_size = match *self.resolve_type(left)? {
911                     crate::TypeInner::Vector { size, .. } => Some(size),
912                     _ => None,
913                 };
914                 match (left_size, self.resolve_type(right)?) {
915                     (Some(size), &crate::TypeInner::Scalar { .. }) => {
916                         right = self.expressions.append(
917                             crate::Expression::Splat { size, value: right },
918                             self.expressions.get_span(right),
919                         );
920                     }
921                     (None, &crate::TypeInner::Vector { size, .. }) => {
922                         left = self.expressions.append(
923                             crate::Expression::Splat { size, value: left },
924                             self.expressions.get_span(left),
925                         );
926                     }
927                     _ => {}
928                 }
929             }
930             accumulator = TypedExpression::non_reference(self.expressions.append(
931                 crate::Expression::Binary { op, left, right },
932                 NagaSpan::new(start, end),
933             ));
934         }
935         Ok(accumulator)
936     }
937 
938     /// Add a single expression to the expression table that is not covered by `self.emitter`.
939     ///
940     /// This is useful for `CallResult` and `AtomicResult` expressions, which should not be covered by
941     /// `Emit` statements.
interrupt_emitter( &mut self, expression: crate::Expression, span: NagaSpan, ) -> Handle<crate::Expression>942     fn interrupt_emitter(
943         &mut self,
944         expression: crate::Expression,
945         span: NagaSpan,
946     ) -> Handle<crate::Expression> {
947         self.block.extend(self.emitter.finish(self.expressions));
948         let result = self.expressions.append(expression, span);
949         self.emitter.start(self.expressions);
950         result
951     }
952 
953     /// Apply the WGSL Load Rule to `expr`.
954     ///
955     /// If `expr` is has type `ref<SC, T, A>`, perform a load to produce a value of type
956     /// `T`. Otherwise, return `expr` unchanged.
apply_load_rule(&mut self, expr: TypedExpression) -> Handle<crate::Expression>957     fn apply_load_rule(&mut self, expr: TypedExpression) -> Handle<crate::Expression> {
958         if expr.is_reference {
959             let load = crate::Expression::Load {
960                 pointer: expr.handle,
961             };
962             let span = self.expressions.get_span(expr.handle);
963             self.expressions.append(load, span)
964         } else {
965             expr.handle
966         }
967     }
968 }
969 
970 /// A Naga [`Expression`] handle, with WGSL type information.
971 ///
972 /// Naga and WGSL types are very close, but Naga lacks WGSL's 'reference' types,
973 /// which we need to know to apply the Load Rule. This struct carries a Naga
974 /// `Handle<Expression>` along with enough information to determine its WGSL type.
975 ///
976 /// [`Expression`]: crate::Expression
977 #[derive(Debug, Copy, Clone)]
978 struct TypedExpression {
979     /// The handle of the Naga expression.
980     handle: Handle<crate::Expression>,
981 
982     /// True if this expression's WGSL type is a reference.
983     ///
984     /// When this is true, `handle` must be a pointer.
985     is_reference: bool,
986 }
987 
988 impl TypedExpression {
non_reference(handle: Handle<crate::Expression>) -> TypedExpression989     fn non_reference(handle: Handle<crate::Expression>) -> TypedExpression {
990         TypedExpression {
991             handle,
992             is_reference: false,
993         }
994     }
995 }
996 
997 enum Composition {
998     Single(u32),
999     Multi(crate::VectorSize, [crate::SwizzleComponent; 4]),
1000 }
1001 
1002 impl Composition {
1003     //TODO: could be `const fn` once MSRV allows
letter_component(letter: char) -> Option<crate::SwizzleComponent>1004     fn letter_component(letter: char) -> Option<crate::SwizzleComponent> {
1005         use crate::SwizzleComponent as Sc;
1006         match letter {
1007             'x' | 'r' => Some(Sc::X),
1008             'y' | 'g' => Some(Sc::Y),
1009             'z' | 'b' => Some(Sc::Z),
1010             'w' | 'a' => Some(Sc::W),
1011             _ => None,
1012         }
1013     }
1014 
extract_impl(name: &str, name_span: Span) -> Result<u32, Error>1015     fn extract_impl(name: &str, name_span: Span) -> Result<u32, Error> {
1016         let ch = name
1017             .chars()
1018             .next()
1019             .ok_or_else(|| Error::BadAccessor(name_span.clone()))?;
1020         match Self::letter_component(ch) {
1021             Some(sc) => Ok(sc as u32),
1022             None => Err(Error::BadAccessor(name_span)),
1023         }
1024     }
1025 
make(name: &str, name_span: Span) -> Result<Self, Error>1026     fn make(name: &str, name_span: Span) -> Result<Self, Error> {
1027         if name.len() > 1 {
1028             let mut components = [crate::SwizzleComponent::X; 4];
1029             for (comp, ch) in components.iter_mut().zip(name.chars()) {
1030                 *comp = Self::letter_component(ch)
1031                     .ok_or_else(|| Error::BadAccessor(name_span.clone()))?;
1032             }
1033 
1034             let size = match name.len() {
1035                 2 => crate::VectorSize::Bi,
1036                 3 => crate::VectorSize::Tri,
1037                 4 => crate::VectorSize::Quad,
1038                 _ => return Err(Error::BadAccessor(name_span)),
1039             };
1040             Ok(Composition::Multi(size, components))
1041         } else {
1042             Self::extract_impl(name, name_span).map(Composition::Single)
1043         }
1044     }
1045 }
1046 
1047 #[derive(Default)]
1048 struct TypeAttributes {
1049     stride: Option<NonZeroU32>,
1050 }
1051 
1052 #[derive(Clone, Debug, PartialEq)]
1053 pub enum Scope {
1054     Attribute,
1055     ImportDecl,
1056     VariableDecl,
1057     TypeDecl,
1058     FunctionDecl,
1059     Block,
1060     Statement,
1061     ConstantExpr,
1062     PrimaryExpr,
1063     SingularExpr,
1064     UnaryExpr,
1065     GeneralExpr,
1066 }
1067 
1068 type LocalFunctionCall = (Handle<crate::Function>, Vec<Handle<crate::Expression>>);
1069 
1070 #[derive(Default)]
1071 struct BindingParser {
1072     location: Option<u32>,
1073     built_in: Option<crate::BuiltIn>,
1074     interpolation: Option<crate::Interpolation>,
1075     sampling: Option<crate::Sampling>,
1076 }
1077 
1078 impl BindingParser {
parse<'a>( &mut self, lexer: &mut Lexer<'a>, name: &'a str, name_span: Span, ) -> Result<(), Error<'a>>1079     fn parse<'a>(
1080         &mut self,
1081         lexer: &mut Lexer<'a>,
1082         name: &'a str,
1083         name_span: Span,
1084     ) -> Result<(), Error<'a>> {
1085         match name {
1086             "location" => {
1087                 lexer.expect(Token::Paren('('))?;
1088                 self.location = Some(parse_non_negative_sint_literal(lexer, 4)?);
1089                 lexer.expect(Token::Paren(')'))?;
1090             }
1091             "builtin" => {
1092                 lexer.expect(Token::Paren('('))?;
1093                 let (raw, span) = lexer.next_ident_with_span()?;
1094                 self.built_in = Some(conv::map_built_in(raw, span)?);
1095                 lexer.expect(Token::Paren(')'))?;
1096             }
1097             "interpolate" => {
1098                 lexer.expect(Token::Paren('('))?;
1099                 let (raw, span) = lexer.next_ident_with_span()?;
1100                 self.interpolation = Some(conv::map_interpolation(raw, span)?);
1101                 if lexer.skip(Token::Separator(',')) {
1102                     let (raw, span) = lexer.next_ident_with_span()?;
1103                     self.sampling = Some(conv::map_sampling(raw, span)?);
1104                 }
1105                 lexer.expect(Token::Paren(')'))?;
1106             }
1107             _ => return Err(Error::UnknownAttribute(name_span)),
1108         }
1109         Ok(())
1110     }
1111 
finish<'a>(self, span: Span) -> Result<Option<crate::Binding>, Error<'a>>1112     fn finish<'a>(self, span: Span) -> Result<Option<crate::Binding>, Error<'a>> {
1113         match (
1114             self.location,
1115             self.built_in,
1116             self.interpolation,
1117             self.sampling,
1118         ) {
1119             (None, None, None, None) => Ok(None),
1120             (Some(location), None, interpolation, sampling) => {
1121                 // Before handing over the completed `Module`, we call
1122                 // `apply_default_interpolation` to ensure that the interpolation and
1123                 // sampling have been explicitly specified on all vertex shader output and fragment
1124                 // shader input user bindings, so leaving them potentially `None` here is fine.
1125                 Ok(Some(crate::Binding::Location {
1126                     location,
1127                     interpolation,
1128                     sampling,
1129                 }))
1130             }
1131             (None, Some(bi), None, None) => Ok(Some(crate::Binding::BuiltIn(bi))),
1132             (_, _, _, _) => Err(Error::InconsistentBinding(span)),
1133         }
1134     }
1135 }
1136 
1137 struct ParsedVariable<'a> {
1138     name: &'a str,
1139     name_span: Span,
1140     class: Option<crate::StorageClass>,
1141     ty: Handle<crate::Type>,
1142     init: Option<Handle<crate::Constant>>,
1143 }
1144 
1145 struct CalledFunction {
1146     result: Option<Handle<crate::Expression>>,
1147 }
1148 
1149 #[derive(Clone, Debug)]
1150 pub struct ParseError {
1151     message: String,
1152     labels: Vec<(Span, Cow<'static, str>)>,
1153     notes: Vec<String>,
1154 }
1155 
1156 impl ParseError {
diagnostic(&self) -> Diagnostic<()>1157     fn diagnostic(&self) -> Diagnostic<()> {
1158         let diagnostic = Diagnostic::error()
1159             .with_message(self.message.to_string())
1160             .with_labels(
1161                 self.labels
1162                     .iter()
1163                     .map(|label| {
1164                         Label::primary((), label.0.clone()).with_message(label.1.to_string())
1165                     })
1166                     .collect(),
1167             )
1168             .with_notes(
1169                 self.notes
1170                     .iter()
1171                     .map(|note| format!("note: {}", note))
1172                     .collect(),
1173             );
1174         diagnostic
1175     }
1176 
1177     /// Emits a summary of the error to standard error stream.
emit_to_stderr(&self, source: &str)1178     pub fn emit_to_stderr(&self, source: &str) {
1179         self.emit_to_stderr_with_path(source, "wgsl")
1180     }
1181 
1182     /// Emits a summary of the error to standard error stream.
emit_to_stderr_with_path(&self, source: &str, path: &str)1183     pub fn emit_to_stderr_with_path(&self, source: &str, path: &str) {
1184         let files = SimpleFile::new(path, source);
1185         let config = codespan_reporting::term::Config::default();
1186         let writer = StandardStream::stderr(ColorChoice::Always);
1187         term::emit(&mut writer.lock(), &config, &files, &self.diagnostic())
1188             .expect("cannot write error");
1189     }
1190 
1191     /// Emits a summary of the error to a string.
emit_to_string(&self, source: &str) -> String1192     pub fn emit_to_string(&self, source: &str) -> String {
1193         let files = SimpleFile::new("wgsl", source);
1194         let config = codespan_reporting::term::Config::default();
1195         let mut writer = StringErrorBuffer::new();
1196         term::emit(&mut writer, &config, &files, &self.diagnostic()).expect("cannot write error");
1197         writer.into_string()
1198     }
1199 
1200     /// Returns the 1-based line number and column of the first label in the
1201     /// error message.
location(&self, source: &str) -> (usize, usize)1202     pub fn location(&self, source: &str) -> (usize, usize) {
1203         let files = SimpleFile::new("wgsl", source);
1204         match self.labels.get(0) {
1205             Some(label) => {
1206                 let location = files
1207                     .location((), label.0.start)
1208                     .expect("invalid span location");
1209                 (location.line_number, location.column_number)
1210             }
1211             None => (1, 1),
1212         }
1213     }
1214 }
1215 
1216 impl std::fmt::Display for ParseError {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result1217     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1218         write!(f, "{}", self.message)
1219     }
1220 }
1221 
1222 impl std::error::Error for ParseError {
source(&self) -> Option<&(dyn std::error::Error + 'static)>1223     fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1224         None
1225     }
1226 }
1227 
1228 pub struct Parser {
1229     scopes: Vec<(Scope, usize)>,
1230     module_scope_identifiers: FastHashMap<String, Span>,
1231     lookup_type: FastHashMap<String, Handle<crate::Type>>,
1232     layouter: Layouter,
1233 }
1234 
1235 impl Parser {
new() -> Self1236     pub fn new() -> Self {
1237         Parser {
1238             scopes: Vec::new(),
1239             module_scope_identifiers: FastHashMap::default(),
1240             lookup_type: FastHashMap::default(),
1241             layouter: Default::default(),
1242         }
1243     }
1244 
push_scope(&mut self, scope: Scope, lexer: &Lexer<'_>)1245     fn push_scope(&mut self, scope: Scope, lexer: &Lexer<'_>) {
1246         self.scopes.push((scope, lexer.current_byte_offset()));
1247     }
1248 
pop_scope(&mut self, lexer: &Lexer<'_>) -> Span1249     fn pop_scope(&mut self, lexer: &Lexer<'_>) -> Span {
1250         let (_, initial) = self.scopes.pop().unwrap();
1251         lexer.span_from(initial)
1252     }
1253 
peek_scope(&mut self, lexer: &Lexer<'_>) -> Span1254     fn peek_scope(&mut self, lexer: &Lexer<'_>) -> Span {
1255         let &(_, initial) = self.scopes.last().unwrap();
1256         lexer.span_from(initial)
1257     }
1258 
get_constant_inner<'a>( word: &'a str, ty: NumberType, width: Option<Bytes>, token_span: TokenSpan<'a>, ) -> Result<ConstantInner, Error<'a>>1259     fn get_constant_inner<'a>(
1260         word: &'a str,
1261         ty: NumberType,
1262         width: Option<Bytes>,
1263         token_span: TokenSpan<'a>,
1264     ) -> Result<ConstantInner, Error<'a>> {
1265         let span = token_span.1;
1266 
1267         if let Some(width) = width {
1268             if width != 4 {
1269                 // Only 32-bit literals supported by the spec and naga for now!
1270                 return Err(Error::BadScalarWidth(span, width));
1271             }
1272         }
1273 
1274         let value = match ty {
1275             NumberType::Sint => {
1276                 get_i32_literal(word, span).map(|val| crate::ScalarValue::Sint(val as i64))?
1277             }
1278             NumberType::Uint => {
1279                 get_u32_literal(word, span).map(|val| crate::ScalarValue::Uint(val as u64))?
1280             }
1281             NumberType::Float => {
1282                 get_f32_literal(word, span).map(|val| crate::ScalarValue::Float(val as f64))?
1283             }
1284         };
1285 
1286         Ok(crate::ConstantInner::Scalar {
1287             value,
1288             width: width.unwrap_or(4),
1289         })
1290     }
1291 
parse_switch_value<'a>(lexer: &mut Lexer<'a>, uint: bool) -> Result<i32, Error<'a>>1292     fn parse_switch_value<'a>(lexer: &mut Lexer<'a>, uint: bool) -> Result<i32, Error<'a>> {
1293         let token_span = lexer.next();
1294         let word = match token_span.0 {
1295             Token::Number { value, width, .. } => {
1296                 if let Some(width) = width {
1297                     if width != 4 {
1298                         // Only 32-bit literals supported by the spec and naga for now!
1299                         return Err(Error::BadScalarWidth(token_span.1, width));
1300                     }
1301                 }
1302 
1303                 value
1304             }
1305             _ => return Err(Error::Unexpected(token_span, ExpectedToken::Integer)),
1306         };
1307 
1308         match uint {
1309             true => get_u32_literal(word, token_span.1).map(|v| v as i32),
1310             false => get_i32_literal(word, token_span.1),
1311         }
1312     }
1313 
parse_atomic_pointer<'a>( &mut self, lexer: &mut Lexer<'a>, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result<Handle<crate::Expression>, Error<'a>>1314     fn parse_atomic_pointer<'a>(
1315         &mut self,
1316         lexer: &mut Lexer<'a>,
1317         mut ctx: ExpressionContext<'a, '_, '_>,
1318     ) -> Result<Handle<crate::Expression>, Error<'a>> {
1319         let (pointer, pointer_span) =
1320             lexer.capture_span(|lexer| self.parse_general_expression(lexer, ctx.reborrow()))?;
1321         // Check if the pointer expression is to an atomic.
1322         // The IR uses regular `Expression::Load` and `Statement::Store` for atomic load/stores,
1323         // and it will not catch the use of a non-atomic variable here.
1324         match *ctx.resolve_type(pointer)? {
1325             crate::TypeInner::Pointer { base, .. } => match ctx.types[base].inner {
1326                 crate::TypeInner::Atomic { .. } => Ok(pointer),
1327                 ref other => {
1328                     log::error!("Pointer type to {:?} passed to atomic op", other);
1329                     Err(Error::InvalidAtomicPointer(pointer_span))
1330                 }
1331             },
1332             ref other => {
1333                 log::error!("Type {:?} passed to atomic op", other);
1334                 Err(Error::InvalidAtomicPointer(pointer_span))
1335             }
1336         }
1337     }
1338 
1339     /// Expects name to be peeked from lexer, does not consume if returns None.
parse_local_function_call<'a>( &mut self, lexer: &mut Lexer<'a>, name: &'a str, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result<Option<LocalFunctionCall>, Error<'a>>1340     fn parse_local_function_call<'a>(
1341         &mut self,
1342         lexer: &mut Lexer<'a>,
1343         name: &'a str,
1344         mut ctx: ExpressionContext<'a, '_, '_>,
1345     ) -> Result<Option<LocalFunctionCall>, Error<'a>> {
1346         let fun_handle = match ctx.functions.iter().find(|&(_, fun)| match fun.name {
1347             Some(ref string) => string == name,
1348             None => false,
1349         }) {
1350             Some((fun_handle, _)) => fun_handle,
1351             None => return Ok(None),
1352         };
1353 
1354         let count = ctx.functions[fun_handle].arguments.len();
1355         let mut arguments = Vec::with_capacity(count);
1356         let _ = lexer.next();
1357         lexer.open_arguments()?;
1358         while arguments.len() != count {
1359             if !arguments.is_empty() {
1360                 lexer.expect(Token::Separator(','))?;
1361             }
1362             let arg = self.parse_general_expression(lexer, ctx.reborrow())?;
1363             arguments.push(arg);
1364         }
1365         lexer.close_arguments()?;
1366         Ok(Some((fun_handle, arguments)))
1367     }
1368 
parse_atomic_helper<'a>( &mut self, lexer: &mut Lexer<'a>, fun: crate::AtomicFunction, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result<Handle<crate::Expression>, Error<'a>>1369     fn parse_atomic_helper<'a>(
1370         &mut self,
1371         lexer: &mut Lexer<'a>,
1372         fun: crate::AtomicFunction,
1373         mut ctx: ExpressionContext<'a, '_, '_>,
1374     ) -> Result<Handle<crate::Expression>, Error<'a>> {
1375         lexer.open_arguments()?;
1376         let pointer = self.parse_general_expression(lexer, ctx.reborrow())?;
1377         lexer.expect(Token::Separator(','))?;
1378         let ctx_span = ctx.reborrow();
1379         let (value, value_span) =
1380             lexer.capture_span(|lexer| self.parse_general_expression(lexer, ctx_span))?;
1381         lexer.close_arguments()?;
1382 
1383         let expression = match *ctx.resolve_type(value)? {
1384             crate::TypeInner::Scalar { kind, width } => crate::Expression::AtomicResult {
1385                 kind,
1386                 width,
1387                 comparison: false,
1388             },
1389             _ => return Err(Error::InvalidAtomicOperandType(value_span)),
1390         };
1391 
1392         let span = NagaSpan::from(value_span);
1393         let result = ctx.interrupt_emitter(expression, span);
1394         ctx.block.push(
1395             crate::Statement::Atomic {
1396                 pointer,
1397                 fun,
1398                 value,
1399                 result,
1400             },
1401             span,
1402         );
1403         Ok(result)
1404     }
1405 
1406     /// Expects [`Scope::PrimaryExpr`] or [`Scope::SingularExpr`] on top; does not pop it.
1407     /// Expects `word` to be peeked (still in lexer), doesn't consume if returning None.
parse_function_call_inner<'a>( &mut self, lexer: &mut Lexer<'a>, name: &'a str, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result<Option<CalledFunction>, Error<'a>>1408     fn parse_function_call_inner<'a>(
1409         &mut self,
1410         lexer: &mut Lexer<'a>,
1411         name: &'a str,
1412         mut ctx: ExpressionContext<'a, '_, '_>,
1413     ) -> Result<Option<CalledFunction>, Error<'a>> {
1414         assert!(self.scopes.last().is_some());
1415         let expr = if let Some(fun) = conv::map_relational_fun(name) {
1416             let _ = lexer.next();
1417             lexer.open_arguments()?;
1418             let argument = self.parse_general_expression(lexer, ctx.reborrow())?;
1419             lexer.close_arguments()?;
1420             crate::Expression::Relational { fun, argument }
1421         } else if let Some(axis) = conv::map_derivative_axis(name) {
1422             let _ = lexer.next();
1423             lexer.open_arguments()?;
1424             let expr = self.parse_general_expression(lexer, ctx.reborrow())?;
1425             lexer.close_arguments()?;
1426             crate::Expression::Derivative { axis, expr }
1427         } else if let Some(fun) = conv::map_standard_fun(name) {
1428             let _ = lexer.next();
1429             lexer.open_arguments()?;
1430             let arg_count = fun.argument_count();
1431             let arg = self.parse_general_expression(lexer, ctx.reborrow())?;
1432             let arg1 = if arg_count > 1 {
1433                 lexer.expect(Token::Separator(','))?;
1434                 Some(self.parse_general_expression(lexer, ctx.reborrow())?)
1435             } else {
1436                 None
1437             };
1438             let arg2 = if arg_count > 2 {
1439                 lexer.expect(Token::Separator(','))?;
1440                 Some(self.parse_general_expression(lexer, ctx.reborrow())?)
1441             } else {
1442                 None
1443             };
1444             let arg3 = if arg_count > 3 {
1445                 lexer.expect(Token::Separator(','))?;
1446                 Some(self.parse_general_expression(lexer, ctx.reborrow())?)
1447             } else {
1448                 None
1449             };
1450             lexer.close_arguments()?;
1451             crate::Expression::Math {
1452                 fun,
1453                 arg,
1454                 arg1,
1455                 arg2,
1456                 arg3,
1457             }
1458         } else {
1459             match name {
1460                 "bitcast" => {
1461                     let _ = lexer.next();
1462                     lexer.expect_generic_paren('<')?;
1463                     let ((ty, _access), type_span) = lexer.capture_span(|lexer| {
1464                         self.parse_type_decl(lexer, None, ctx.types, ctx.constants)
1465                     })?;
1466                     lexer.expect_generic_paren('>')?;
1467 
1468                     lexer.open_arguments()?;
1469                     let expr = self.parse_general_expression(lexer, ctx.reborrow())?;
1470                     lexer.close_arguments()?;
1471 
1472                     let kind = match ctx.types[ty].inner {
1473                         crate::TypeInner::Scalar { kind, .. } => kind,
1474                         crate::TypeInner::Vector { kind, .. } => kind,
1475                         _ => {
1476                             return Err(Error::BadTypeCast {
1477                                 from_type: format!("{:?}", ctx.resolve_type(expr)?),
1478                                 span: type_span,
1479                                 to_type: format!("{:?}", ctx.types[ty].inner),
1480                             })
1481                         }
1482                     };
1483 
1484                     crate::Expression::As {
1485                         expr,
1486                         kind,
1487                         convert: None,
1488                     }
1489                 }
1490                 "select" => {
1491                     let _ = lexer.next();
1492                     lexer.open_arguments()?;
1493                     let reject = self.parse_general_expression(lexer, ctx.reborrow())?;
1494                     lexer.expect(Token::Separator(','))?;
1495                     let accept = self.parse_general_expression(lexer, ctx.reborrow())?;
1496                     lexer.expect(Token::Separator(','))?;
1497                     let condition = self.parse_general_expression(lexer, ctx.reborrow())?;
1498                     lexer.close_arguments()?;
1499                     crate::Expression::Select {
1500                         condition,
1501                         accept,
1502                         reject,
1503                     }
1504                 }
1505                 "arrayLength" => {
1506                     let _ = lexer.next();
1507                     lexer.open_arguments()?;
1508                     let array = self.parse_general_expression(lexer, ctx.reborrow())?;
1509                     lexer.close_arguments()?;
1510                     crate::Expression::ArrayLength(array)
1511                 }
1512                 // atomics
1513                 "atomicLoad" => {
1514                     let _ = lexer.next();
1515                     lexer.open_arguments()?;
1516                     let pointer = self.parse_atomic_pointer(lexer, ctx.reborrow())?;
1517                     lexer.close_arguments()?;
1518                     crate::Expression::Load { pointer }
1519                 }
1520                 "atomicAdd" => {
1521                     let _ = lexer.next();
1522                     let handle = self.parse_atomic_helper(
1523                         lexer,
1524                         crate::AtomicFunction::Add,
1525                         ctx.reborrow(),
1526                     )?;
1527                     return Ok(Some(CalledFunction {
1528                         result: Some(handle),
1529                     }));
1530                 }
1531                 "atomicSub" => {
1532                     let _ = lexer.next();
1533                     let handle = self.parse_atomic_helper(
1534                         lexer,
1535                         crate::AtomicFunction::Subtract,
1536                         ctx.reborrow(),
1537                     )?;
1538                     return Ok(Some(CalledFunction {
1539                         result: Some(handle),
1540                     }));
1541                 }
1542                 "atomicAnd" => {
1543                     let _ = lexer.next();
1544                     let handle = self.parse_atomic_helper(
1545                         lexer,
1546                         crate::AtomicFunction::And,
1547                         ctx.reborrow(),
1548                     )?;
1549                     return Ok(Some(CalledFunction {
1550                         result: Some(handle),
1551                     }));
1552                 }
1553                 "atomicOr" => {
1554                     let _ = lexer.next();
1555                     let handle = self.parse_atomic_helper(
1556                         lexer,
1557                         crate::AtomicFunction::InclusiveOr,
1558                         ctx.reborrow(),
1559                     )?;
1560                     return Ok(Some(CalledFunction {
1561                         result: Some(handle),
1562                     }));
1563                 }
1564                 "atomicXor" => {
1565                     let _ = lexer.next();
1566                     let handle = self.parse_atomic_helper(
1567                         lexer,
1568                         crate::AtomicFunction::ExclusiveOr,
1569                         ctx.reborrow(),
1570                     )?;
1571                     return Ok(Some(CalledFunction {
1572                         result: Some(handle),
1573                     }));
1574                 }
1575                 "atomicMin" => {
1576                     let _ = lexer.next();
1577                     let handle =
1578                         self.parse_atomic_helper(lexer, crate::AtomicFunction::Min, ctx)?;
1579                     return Ok(Some(CalledFunction {
1580                         result: Some(handle),
1581                     }));
1582                 }
1583                 "atomicMax" => {
1584                     let _ = lexer.next();
1585                     let handle =
1586                         self.parse_atomic_helper(lexer, crate::AtomicFunction::Max, ctx)?;
1587                     return Ok(Some(CalledFunction {
1588                         result: Some(handle),
1589                     }));
1590                 }
1591                 "atomicExchange" => {
1592                     let _ = lexer.next();
1593                     let handle = self.parse_atomic_helper(
1594                         lexer,
1595                         crate::AtomicFunction::Exchange { compare: None },
1596                         ctx,
1597                     )?;
1598                     return Ok(Some(CalledFunction {
1599                         result: Some(handle),
1600                     }));
1601                 }
1602                 "atomicCompareExchangeWeak" => {
1603                     let _ = lexer.next();
1604                     lexer.open_arguments()?;
1605                     let pointer = self.parse_general_expression(lexer, ctx.reborrow())?;
1606                     lexer.expect(Token::Separator(','))?;
1607                     let cmp = self.parse_general_expression(lexer, ctx.reborrow())?;
1608                     lexer.expect(Token::Separator(','))?;
1609                     let (value, value_span) = lexer.capture_span(|lexer| {
1610                         self.parse_general_expression(lexer, ctx.reborrow())
1611                     })?;
1612                     lexer.close_arguments()?;
1613 
1614                     let expression = match *ctx.resolve_type(value)? {
1615                         crate::TypeInner::Scalar { kind, width } => {
1616                             crate::Expression::AtomicResult {
1617                                 kind,
1618                                 width,
1619                                 comparison: true,
1620                             }
1621                         }
1622                         _ => return Err(Error::InvalidAtomicOperandType(value_span)),
1623                     };
1624 
1625                     let span = NagaSpan::from(self.peek_scope(lexer));
1626                     let result = ctx.interrupt_emitter(expression, span);
1627                     ctx.block.push(
1628                         crate::Statement::Atomic {
1629                             pointer,
1630                             fun: crate::AtomicFunction::Exchange { compare: Some(cmp) },
1631                             value,
1632                             result,
1633                         },
1634                         span,
1635                     );
1636                     return Ok(Some(CalledFunction {
1637                         result: Some(result),
1638                     }));
1639                 }
1640                 // texture sampling
1641                 "textureSample" => {
1642                     let _ = lexer.next();
1643                     lexer.open_arguments()?;
1644                     let (image_name, image_span) = lexer.next_ident_with_span()?;
1645                     lexer.expect(Token::Separator(','))?;
1646                     let (sampler_name, sampler_span) = lexer.next_ident_with_span()?;
1647                     lexer.expect(Token::Separator(','))?;
1648                     let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
1649                     let sc = ctx.prepare_sampling(image_name, image_span)?;
1650                     let array_index = if sc.arrayed {
1651                         lexer.expect(Token::Separator(','))?;
1652                         Some(self.parse_general_expression(lexer, ctx.reborrow())?)
1653                     } else {
1654                         None
1655                     };
1656                     let offset = if lexer.skip(Token::Separator(',')) {
1657                         Some(self.parse_const_expression(lexer, ctx.types, ctx.constants)?)
1658                     } else {
1659                         None
1660                     };
1661                     lexer.close_arguments()?;
1662                     crate::Expression::ImageSample {
1663                         image: sc.image,
1664                         sampler: ctx.lookup_ident.lookup(sampler_name, sampler_span)?.handle,
1665                         gather: None,
1666                         coordinate,
1667                         array_index,
1668                         offset,
1669                         level: crate::SampleLevel::Auto,
1670                         depth_ref: None,
1671                     }
1672                 }
1673                 "textureSampleLevel" => {
1674                     let _ = lexer.next();
1675                     lexer.open_arguments()?;
1676                     let (image_name, image_span) = lexer.next_ident_with_span()?;
1677                     lexer.expect(Token::Separator(','))?;
1678                     let (sampler_name, sampler_span) = lexer.next_ident_with_span()?;
1679                     lexer.expect(Token::Separator(','))?;
1680                     let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
1681                     let sc = ctx.prepare_sampling(image_name, image_span)?;
1682                     let array_index = if sc.arrayed {
1683                         lexer.expect(Token::Separator(','))?;
1684                         Some(self.parse_general_expression(lexer, ctx.reborrow())?)
1685                     } else {
1686                         None
1687                     };
1688                     lexer.expect(Token::Separator(','))?;
1689                     let level = self.parse_general_expression(lexer, ctx.reborrow())?;
1690                     let offset = if lexer.skip(Token::Separator(',')) {
1691                         Some(self.parse_const_expression(lexer, ctx.types, ctx.constants)?)
1692                     } else {
1693                         None
1694                     };
1695                     lexer.close_arguments()?;
1696                     crate::Expression::ImageSample {
1697                         image: sc.image,
1698                         sampler: ctx.lookup_ident.lookup(sampler_name, sampler_span)?.handle,
1699                         gather: None,
1700                         coordinate,
1701                         array_index,
1702                         offset,
1703                         level: crate::SampleLevel::Exact(level),
1704                         depth_ref: None,
1705                     }
1706                 }
1707                 "textureSampleBias" => {
1708                     let _ = lexer.next();
1709                     lexer.open_arguments()?;
1710                     let (image_name, image_span) = lexer.next_ident_with_span()?;
1711                     lexer.expect(Token::Separator(','))?;
1712                     let (sampler_name, sampler_span) = lexer.next_ident_with_span()?;
1713                     lexer.expect(Token::Separator(','))?;
1714                     let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
1715                     let sc = ctx.prepare_sampling(image_name, image_span)?;
1716                     let array_index = if sc.arrayed {
1717                         lexer.expect(Token::Separator(','))?;
1718                         Some(self.parse_general_expression(lexer, ctx.reborrow())?)
1719                     } else {
1720                         None
1721                     };
1722                     lexer.expect(Token::Separator(','))?;
1723                     let bias = self.parse_general_expression(lexer, ctx.reborrow())?;
1724                     let offset = if lexer.skip(Token::Separator(',')) {
1725                         Some(self.parse_const_expression(lexer, ctx.types, ctx.constants)?)
1726                     } else {
1727                         None
1728                     };
1729                     lexer.close_arguments()?;
1730                     crate::Expression::ImageSample {
1731                         image: sc.image,
1732                         sampler: ctx.lookup_ident.lookup(sampler_name, sampler_span)?.handle,
1733                         gather: None,
1734                         coordinate,
1735                         array_index,
1736                         offset,
1737                         level: crate::SampleLevel::Bias(bias),
1738                         depth_ref: None,
1739                     }
1740                 }
1741                 "textureSampleGrad" => {
1742                     let _ = lexer.next();
1743                     lexer.open_arguments()?;
1744                     let (image_name, image_span) = lexer.next_ident_with_span()?;
1745                     lexer.expect(Token::Separator(','))?;
1746                     let (sampler_name, sampler_span) = lexer.next_ident_with_span()?;
1747                     lexer.expect(Token::Separator(','))?;
1748                     let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
1749                     let sc = ctx.prepare_sampling(image_name, image_span)?;
1750                     let array_index = if sc.arrayed {
1751                         lexer.expect(Token::Separator(','))?;
1752                         Some(self.parse_general_expression(lexer, ctx.reborrow())?)
1753                     } else {
1754                         None
1755                     };
1756                     lexer.expect(Token::Separator(','))?;
1757                     let x = self.parse_general_expression(lexer, ctx.reborrow())?;
1758                     lexer.expect(Token::Separator(','))?;
1759                     let y = self.parse_general_expression(lexer, ctx.reborrow())?;
1760                     let offset = if lexer.skip(Token::Separator(',')) {
1761                         Some(self.parse_const_expression(lexer, ctx.types, ctx.constants)?)
1762                     } else {
1763                         None
1764                     };
1765                     lexer.close_arguments()?;
1766                     crate::Expression::ImageSample {
1767                         image: sc.image,
1768                         sampler: ctx.lookup_ident.lookup(sampler_name, sampler_span)?.handle,
1769                         gather: None,
1770                         coordinate,
1771                         array_index,
1772                         offset,
1773                         level: crate::SampleLevel::Gradient { x, y },
1774                         depth_ref: None,
1775                     }
1776                 }
1777                 "textureSampleCompare" => {
1778                     let _ = lexer.next();
1779                     lexer.open_arguments()?;
1780                     let (image_name, image_span) = lexer.next_ident_with_span()?;
1781                     lexer.expect(Token::Separator(','))?;
1782                     let (sampler_name, sampler_span) = lexer.next_ident_with_span()?;
1783                     lexer.expect(Token::Separator(','))?;
1784                     let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
1785                     let sc = ctx.prepare_sampling(image_name, image_span)?;
1786                     let array_index = if sc.arrayed {
1787                         lexer.expect(Token::Separator(','))?;
1788                         Some(self.parse_general_expression(lexer, ctx.reborrow())?)
1789                     } else {
1790                         None
1791                     };
1792                     lexer.expect(Token::Separator(','))?;
1793                     let reference = self.parse_general_expression(lexer, ctx.reborrow())?;
1794                     let offset = if lexer.skip(Token::Separator(',')) {
1795                         Some(self.parse_const_expression(lexer, ctx.types, ctx.constants)?)
1796                     } else {
1797                         None
1798                     };
1799                     lexer.close_arguments()?;
1800                     crate::Expression::ImageSample {
1801                         image: sc.image,
1802                         sampler: ctx.lookup_ident.lookup(sampler_name, sampler_span)?.handle,
1803                         gather: None,
1804                         coordinate,
1805                         array_index,
1806                         offset,
1807                         level: crate::SampleLevel::Auto,
1808                         depth_ref: Some(reference),
1809                     }
1810                 }
1811                 "textureSampleCompareLevel" => {
1812                     let _ = lexer.next();
1813                     lexer.open_arguments()?;
1814                     let (image_name, image_span) = lexer.next_ident_with_span()?;
1815                     lexer.expect(Token::Separator(','))?;
1816                     let (sampler_name, sampler_span) = lexer.next_ident_with_span()?;
1817                     lexer.expect(Token::Separator(','))?;
1818                     let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
1819                     let sc = ctx.prepare_sampling(image_name, image_span)?;
1820                     let array_index = if sc.arrayed {
1821                         lexer.expect(Token::Separator(','))?;
1822                         Some(self.parse_general_expression(lexer, ctx.reborrow())?)
1823                     } else {
1824                         None
1825                     };
1826                     lexer.expect(Token::Separator(','))?;
1827                     let reference = self.parse_general_expression(lexer, ctx.reborrow())?;
1828                     let offset = if lexer.skip(Token::Separator(',')) {
1829                         Some(self.parse_const_expression(lexer, ctx.types, ctx.constants)?)
1830                     } else {
1831                         None
1832                     };
1833                     lexer.close_arguments()?;
1834                     crate::Expression::ImageSample {
1835                         image: sc.image,
1836                         sampler: ctx.lookup_ident.lookup(sampler_name, sampler_span)?.handle,
1837                         gather: None,
1838                         coordinate,
1839                         array_index,
1840                         offset,
1841                         level: crate::SampleLevel::Zero,
1842                         depth_ref: Some(reference),
1843                     }
1844                 }
1845                 "textureGather" => {
1846                     let _ = lexer.next();
1847                     lexer.open_arguments()?;
1848                     let component = if let (
1849                         Token::Number {
1850                             value,
1851                             ty: NumberType::Sint,
1852                             width: None,
1853                         },
1854                         span,
1855                     ) = lexer.peek()
1856                     {
1857                         let _ = lexer.next();
1858                         lexer.expect(Token::Separator(','))?;
1859                         let index = get_i32_literal(value, span.clone())?;
1860                         *crate::SwizzleComponent::XYZW
1861                             .get(index as usize)
1862                             .ok_or(Error::InvalidGatherComponent(span, index))?
1863                     } else {
1864                         crate::SwizzleComponent::X
1865                     };
1866                     let (image_name, image_span) = lexer.next_ident_with_span()?;
1867                     lexer.expect(Token::Separator(','))?;
1868                     let (sampler_name, sampler_span) = lexer.next_ident_with_span()?;
1869                     lexer.expect(Token::Separator(','))?;
1870                     let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
1871                     let sc = ctx.prepare_sampling(image_name, image_span)?;
1872                     let array_index = if sc.arrayed {
1873                         lexer.expect(Token::Separator(','))?;
1874                         Some(self.parse_general_expression(lexer, ctx.reborrow())?)
1875                     } else {
1876                         None
1877                     };
1878                     let offset = if lexer.skip(Token::Separator(',')) {
1879                         Some(self.parse_const_expression(lexer, ctx.types, ctx.constants)?)
1880                     } else {
1881                         None
1882                     };
1883                     lexer.close_arguments()?;
1884                     crate::Expression::ImageSample {
1885                         image: sc.image,
1886                         sampler: ctx.lookup_ident.lookup(sampler_name, sampler_span)?.handle,
1887                         gather: Some(component),
1888                         coordinate,
1889                         array_index,
1890                         offset,
1891                         level: crate::SampleLevel::Zero,
1892                         depth_ref: None,
1893                     }
1894                 }
1895                 "textureGatherCompare" => {
1896                     let _ = lexer.next();
1897                     lexer.open_arguments()?;
1898                     let (image_name, image_span) = lexer.next_ident_with_span()?;
1899                     lexer.expect(Token::Separator(','))?;
1900                     let (sampler_name, sampler_span) = lexer.next_ident_with_span()?;
1901                     lexer.expect(Token::Separator(','))?;
1902                     let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
1903                     let sc = ctx.prepare_sampling(image_name, image_span)?;
1904                     let array_index = if sc.arrayed {
1905                         lexer.expect(Token::Separator(','))?;
1906                         Some(self.parse_general_expression(lexer, ctx.reborrow())?)
1907                     } else {
1908                         None
1909                     };
1910                     lexer.expect(Token::Separator(','))?;
1911                     let reference = self.parse_general_expression(lexer, ctx.reborrow())?;
1912                     let offset = if lexer.skip(Token::Separator(',')) {
1913                         Some(self.parse_const_expression(lexer, ctx.types, ctx.constants)?)
1914                     } else {
1915                         None
1916                     };
1917                     lexer.close_arguments()?;
1918                     crate::Expression::ImageSample {
1919                         image: sc.image,
1920                         sampler: ctx.lookup_ident.lookup(sampler_name, sampler_span)?.handle,
1921                         gather: Some(crate::SwizzleComponent::X),
1922                         coordinate,
1923                         array_index,
1924                         offset,
1925                         level: crate::SampleLevel::Zero,
1926                         depth_ref: Some(reference),
1927                     }
1928                 }
1929                 "textureLoad" => {
1930                     let _ = lexer.next();
1931                     lexer.open_arguments()?;
1932                     let (image_name, image_span) = lexer.next_ident_with_span()?;
1933                     let image = ctx
1934                         .lookup_ident
1935                         .lookup(image_name, image_span.clone())?
1936                         .handle;
1937                     lexer.expect(Token::Separator(','))?;
1938                     let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
1939                     let (class, arrayed) = match *ctx.resolve_type(image)? {
1940                         crate::TypeInner::Image { class, arrayed, .. } => (class, arrayed),
1941                         _ => return Err(Error::BadTexture(image_span)),
1942                     };
1943                     let array_index = if arrayed {
1944                         lexer.expect(Token::Separator(','))?;
1945                         Some(self.parse_general_expression(lexer, ctx.reborrow())?)
1946                     } else {
1947                         None
1948                     };
1949                     let index = match class {
1950                         crate::ImageClass::Storage { .. } => None,
1951                         // it's the MSAA index for multi-sampled, and LOD for the others
1952                         crate::ImageClass::Sampled { .. } | crate::ImageClass::Depth { .. } => {
1953                             lexer.expect(Token::Separator(','))?;
1954                             Some(self.parse_general_expression(lexer, ctx.reborrow())?)
1955                         }
1956                     };
1957                     lexer.close_arguments()?;
1958                     crate::Expression::ImageLoad {
1959                         image,
1960                         coordinate,
1961                         array_index,
1962                         index,
1963                     }
1964                 }
1965                 "textureDimensions" => {
1966                     let _ = lexer.next();
1967                     lexer.open_arguments()?;
1968                     let (image_name, image_span) = lexer.next_ident_with_span()?;
1969                     let image = ctx.lookup_ident.lookup(image_name, image_span)?.handle;
1970                     let level = if lexer.skip(Token::Separator(',')) {
1971                         let expr = self.parse_general_expression(lexer, ctx.reborrow())?;
1972                         Some(expr)
1973                     } else {
1974                         None
1975                     };
1976                     lexer.close_arguments()?;
1977                     crate::Expression::ImageQuery {
1978                         image,
1979                         query: crate::ImageQuery::Size { level },
1980                     }
1981                 }
1982                 "textureNumLevels" => {
1983                     let _ = lexer.next();
1984                     lexer.open_arguments()?;
1985                     let (image_name, image_span) = lexer.next_ident_with_span()?;
1986                     let image = ctx.lookup_ident.lookup(image_name, image_span)?.handle;
1987                     lexer.close_arguments()?;
1988                     crate::Expression::ImageQuery {
1989                         image,
1990                         query: crate::ImageQuery::NumLevels,
1991                     }
1992                 }
1993                 "textureNumLayers" => {
1994                     let _ = lexer.next();
1995                     lexer.open_arguments()?;
1996                     let (image_name, image_span) = lexer.next_ident_with_span()?;
1997                     let image = ctx.lookup_ident.lookup(image_name, image_span)?.handle;
1998                     lexer.close_arguments()?;
1999                     crate::Expression::ImageQuery {
2000                         image,
2001                         query: crate::ImageQuery::NumLayers,
2002                     }
2003                 }
2004                 "textureNumSamples" => {
2005                     let _ = lexer.next();
2006                     lexer.open_arguments()?;
2007                     let (image_name, image_span) = lexer.next_ident_with_span()?;
2008                     let image = ctx.lookup_ident.lookup(image_name, image_span)?.handle;
2009                     lexer.close_arguments()?;
2010                     crate::Expression::ImageQuery {
2011                         image,
2012                         query: crate::ImageQuery::NumSamples,
2013                     }
2014                 }
2015                 // other
2016                 _ => {
2017                     let result =
2018                         match self.parse_local_function_call(lexer, name, ctx.reborrow())? {
2019                             Some((function, arguments)) => {
2020                                 let span = NagaSpan::from(self.peek_scope(lexer));
2021                                 ctx.block.extend(ctx.emitter.finish(ctx.expressions));
2022                                 let result = ctx.functions[function].result.as_ref().map(|_| {
2023                                     ctx.expressions
2024                                         .append(crate::Expression::CallResult(function), span)
2025                                 });
2026                                 ctx.emitter.start(ctx.expressions);
2027                                 ctx.block.push(
2028                                     crate::Statement::Call {
2029                                         function,
2030                                         arguments,
2031                                         result,
2032                                     },
2033                                     span,
2034                                 );
2035                                 result
2036                             }
2037                             None => return Ok(None),
2038                         };
2039                     return Ok(Some(CalledFunction { result }));
2040                 }
2041             }
2042         };
2043         let span = NagaSpan::from(self.peek_scope(lexer));
2044         let handle = ctx.expressions.append(expr, span);
2045         Ok(Some(CalledFunction {
2046             result: Some(handle),
2047         }))
2048     }
2049 
2050     /// Expects [`Scope::PrimaryExpr`] scope on top; if returning Some(_), pops it.
parse_construction<'a>( &mut self, lexer: &mut Lexer<'a>, type_name: &'a str, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result<Option<Handle<crate::Expression>>, Error<'a>>2051     fn parse_construction<'a>(
2052         &mut self,
2053         lexer: &mut Lexer<'a>,
2054         type_name: &'a str,
2055         mut ctx: ExpressionContext<'a, '_, '_>,
2056     ) -> Result<Option<Handle<crate::Expression>>, Error<'a>> {
2057         assert_eq!(
2058             self.scopes.last().map(|&(ref scope, _)| scope.clone()),
2059             Some(Scope::PrimaryExpr)
2060         );
2061         let ty_resolution = match self.lookup_type.get(type_name) {
2062             Some(&handle) => TypeResolution::Handle(handle),
2063             None => match self.parse_type_decl_impl(
2064                 lexer,
2065                 TypeAttributes::default(),
2066                 type_name,
2067                 ctx.types,
2068                 ctx.constants,
2069             )? {
2070                 Some(inner) => TypeResolution::Value(inner),
2071                 None => return Ok(None),
2072             },
2073         };
2074 
2075         let mut components = Vec::new();
2076         let (last_component, arguments_span) = lexer.capture_span(|lexer| {
2077             lexer.open_arguments()?;
2078             let mut last_component = self.parse_general_expression(lexer, ctx.reborrow())?;
2079 
2080             while lexer.next_argument()? {
2081                 components.push(last_component);
2082                 last_component = self.parse_general_expression(lexer, ctx.reborrow())?;
2083             }
2084 
2085             Ok(last_component)
2086         })?;
2087 
2088         // We can't use the `TypeInner` returned by this because
2089         // `resolve_type` borrows context mutably.
2090         // Use it to insert into the right maps,
2091         // and then grab it again immutably.
2092         ctx.resolve_type(last_component)?;
2093 
2094         let expr = if components.is_empty()
2095             && ty_resolution.inner_with(ctx.types).scalar_kind().is_some()
2096         {
2097             match (
2098                 ty_resolution.inner_with(ctx.types),
2099                 ctx.typifier.get(last_component, ctx.types),
2100             ) {
2101                 (
2102                     &crate::TypeInner::Vector {
2103                         size, kind, width, ..
2104                     },
2105                     &crate::TypeInner::Scalar {
2106                         kind: arg_kind,
2107                         width: arg_width,
2108                         ..
2109                     },
2110                 ) if arg_kind == kind && arg_width == width => crate::Expression::Splat {
2111                     size,
2112                     value: last_component,
2113                 },
2114                 (
2115                     &crate::TypeInner::Scalar { kind, width, .. },
2116                     &crate::TypeInner::Scalar { .. },
2117                 )
2118                 | (
2119                     &crate::TypeInner::Vector { kind, width, .. },
2120                     &crate::TypeInner::Vector { .. },
2121                 ) => crate::Expression::As {
2122                     expr: last_component,
2123                     kind,
2124                     convert: Some(width),
2125                 },
2126                 (&crate::TypeInner::Matrix { width, .. }, &crate::TypeInner::Matrix { .. }) => {
2127                     crate::Expression::As {
2128                         expr: last_component,
2129                         kind: crate::ScalarKind::Float,
2130                         convert: Some(width),
2131                     }
2132                 }
2133                 (to_type, from_type) => {
2134                     return Err(Error::BadTypeCast {
2135                         span: arguments_span,
2136                         from_type: from_type.to_wgsl(ctx.types, ctx.constants),
2137                         to_type: to_type.to_wgsl(ctx.types, ctx.constants),
2138                     });
2139                 }
2140             }
2141         } else {
2142             components.push(last_component);
2143             let mut compose_components = Vec::new();
2144 
2145             if let (
2146                 &crate::TypeInner::Matrix {
2147                     rows,
2148                     width,
2149                     columns,
2150                 },
2151                 &crate::TypeInner::Scalar {
2152                     kind: crate::ScalarKind::Float,
2153                     ..
2154                 },
2155             ) = (
2156                 ty_resolution.inner_with(ctx.types),
2157                 ctx.typifier.get(last_component, ctx.types),
2158             ) {
2159                 let vec_ty = ctx.types.insert(
2160                     crate::Type {
2161                         name: None,
2162                         inner: crate::TypeInner::Vector {
2163                             width,
2164                             kind: crate::ScalarKind::Float,
2165                             size: rows,
2166                         },
2167                     },
2168                     Default::default(),
2169                 );
2170 
2171                 compose_components.reserve(columns as usize);
2172                 for vec_components in components.chunks(rows as usize) {
2173                     let handle = ctx.expressions.append(
2174                         crate::Expression::Compose {
2175                             ty: vec_ty,
2176                             components: Vec::from(vec_components),
2177                         },
2178                         crate::Span::default(),
2179                     );
2180                     compose_components.push(handle);
2181                 }
2182             } else {
2183                 compose_components = components;
2184             }
2185 
2186             let ty = match ty_resolution {
2187                 TypeResolution::Handle(handle) => handle,
2188                 TypeResolution::Value(inner) => ctx
2189                     .types
2190                     .insert(crate::Type { name: None, inner }, Default::default()),
2191             };
2192             crate::Expression::Compose {
2193                 ty,
2194                 components: compose_components,
2195             }
2196         };
2197 
2198         let span = NagaSpan::from(self.pop_scope(lexer));
2199         Ok(Some(ctx.expressions.append(expr, span)))
2200     }
2201 
parse_const_expression_impl<'a>( &mut self, first_token_span: TokenSpan<'a>, lexer: &mut Lexer<'a>, register_name: Option<&'a str>, type_arena: &mut UniqueArena<crate::Type>, const_arena: &mut Arena<crate::Constant>, ) -> Result<Handle<crate::Constant>, Error<'a>>2202     fn parse_const_expression_impl<'a>(
2203         &mut self,
2204         first_token_span: TokenSpan<'a>,
2205         lexer: &mut Lexer<'a>,
2206         register_name: Option<&'a str>,
2207         type_arena: &mut UniqueArena<crate::Type>,
2208         const_arena: &mut Arena<crate::Constant>,
2209     ) -> Result<Handle<crate::Constant>, Error<'a>> {
2210         self.push_scope(Scope::ConstantExpr, lexer);
2211         let inner = match first_token_span {
2212             (Token::Word("true"), _) => crate::ConstantInner::boolean(true),
2213             (Token::Word("false"), _) => crate::ConstantInner::boolean(false),
2214             (Token::Number { value, ty, width }, _) => {
2215                 Self::get_constant_inner(value, ty, width, first_token_span)?
2216             }
2217             (Token::Word(name), name_span) => {
2218                 // look for an existing constant first
2219                 for (handle, var) in const_arena.iter() {
2220                     match var.name {
2221                         Some(ref string) if string == name => {
2222                             self.pop_scope(lexer);
2223                             return Ok(handle);
2224                         }
2225                         _ => {}
2226                     }
2227                 }
2228                 let composite_ty = self.parse_type_decl_name(
2229                     lexer,
2230                     name,
2231                     name_span,
2232                     None,
2233                     TypeAttributes::default(),
2234                     type_arena,
2235                     const_arena,
2236                 )?;
2237 
2238                 lexer.open_arguments()?;
2239                 //Note: this expects at least one argument
2240                 let mut components = Vec::new();
2241                 while components.is_empty() || lexer.next_argument()? {
2242                     let component = self.parse_const_expression(lexer, type_arena, const_arena)?;
2243                     components.push(component);
2244                 }
2245                 crate::ConstantInner::Composite {
2246                     ty: composite_ty,
2247                     components,
2248                 }
2249             }
2250             other => return Err(Error::Unexpected(other, ExpectedToken::Constant)),
2251         };
2252 
2253         // Only set span if it's a named constant. Otherwise, the enclosing Expression should have
2254         // the span.
2255         let span = self.pop_scope(lexer);
2256         let handle = if let Some(name) = register_name {
2257             if crate::keywords::wgsl::RESERVED.contains(&name) {
2258                 return Err(Error::ReservedKeyword(span));
2259             }
2260             const_arena.append(
2261                 crate::Constant {
2262                     name: Some(name.to_string()),
2263                     specialization: None,
2264                     inner,
2265                 },
2266                 NagaSpan::from(span),
2267             )
2268         } else {
2269             const_arena.fetch_or_append(
2270                 crate::Constant {
2271                     name: None,
2272                     specialization: None,
2273                     inner,
2274                 },
2275                 Default::default(),
2276             )
2277         };
2278 
2279         Ok(handle)
2280     }
2281 
parse_const_expression<'a>( &mut self, lexer: &mut Lexer<'a>, type_arena: &mut UniqueArena<crate::Type>, const_arena: &mut Arena<crate::Constant>, ) -> Result<Handle<crate::Constant>, Error<'a>>2282     fn parse_const_expression<'a>(
2283         &mut self,
2284         lexer: &mut Lexer<'a>,
2285         type_arena: &mut UniqueArena<crate::Type>,
2286         const_arena: &mut Arena<crate::Constant>,
2287     ) -> Result<Handle<crate::Constant>, Error<'a>> {
2288         self.parse_const_expression_impl(lexer.next(), lexer, None, type_arena, const_arena)
2289     }
2290 
parse_primary_expression<'a>( &mut self, lexer: &mut Lexer<'a>, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result<TypedExpression, Error<'a>>2291     fn parse_primary_expression<'a>(
2292         &mut self,
2293         lexer: &mut Lexer<'a>,
2294         mut ctx: ExpressionContext<'a, '_, '_>,
2295     ) -> Result<TypedExpression, Error<'a>> {
2296         // Will be popped inside match, possibly inside parse_function_call_inner or parse_construction
2297         self.push_scope(Scope::PrimaryExpr, lexer);
2298         let expr = match lexer.peek() {
2299             (Token::Paren('('), _) => {
2300                 let _ = lexer.next();
2301                 let expr = self.parse_general_expression_for_reference(lexer, ctx.reborrow())?;
2302                 lexer.expect(Token::Paren(')'))?;
2303                 self.pop_scope(lexer);
2304                 expr
2305             }
2306             token @ (Token::Word("true"), _)
2307             | token @ (Token::Word("false"), _)
2308             | token @ (Token::Number { .. }, _) => {
2309                 let _ = lexer.next();
2310                 let const_handle =
2311                     self.parse_const_expression_impl(token, lexer, None, ctx.types, ctx.constants)?;
2312                 let span = NagaSpan::from(self.pop_scope(lexer));
2313                 TypedExpression::non_reference(
2314                     ctx.interrupt_emitter(crate::Expression::Constant(const_handle), span),
2315                 )
2316             }
2317             (Token::Word(word), span) => {
2318                 if let Some(definition) = ctx.lookup_ident.get(word) {
2319                     let _ = lexer.next();
2320                     self.pop_scope(lexer);
2321 
2322                     *definition
2323                 } else if let Some(CalledFunction { result: Some(expr) }) =
2324                     self.parse_function_call_inner(lexer, word, ctx.reborrow())?
2325                 {
2326                     //TODO: resolve the duplicate call in `parse_singular_expression`
2327                     self.pop_scope(lexer);
2328                     TypedExpression::non_reference(expr)
2329                 } else {
2330                     let _ = lexer.next();
2331                     if let Some(expr) = self.parse_construction(lexer, word, ctx.reborrow())? {
2332                         TypedExpression::non_reference(expr)
2333                     } else {
2334                         return Err(Error::UnknownIdent(span, word));
2335                     }
2336                 }
2337             }
2338             other => return Err(Error::Unexpected(other, ExpectedToken::PrimaryExpression)),
2339         };
2340         Ok(expr)
2341     }
2342 
parse_postfix<'a>( &mut self, span_start: usize, lexer: &mut Lexer<'a>, mut ctx: ExpressionContext<'a, '_, '_>, expr: TypedExpression, ) -> Result<TypedExpression, Error<'a>>2343     fn parse_postfix<'a>(
2344         &mut self,
2345         span_start: usize,
2346         lexer: &mut Lexer<'a>,
2347         mut ctx: ExpressionContext<'a, '_, '_>,
2348         expr: TypedExpression,
2349     ) -> Result<TypedExpression, Error<'a>> {
2350         // Parse postfix expressions, adjusting `handle` and `is_reference` along the way.
2351         //
2352         // Most postfix expressions don't affect `is_reference`: for example, `s.x` is a
2353         // reference whenever `s` is a reference. But swizzles (WGSL spec: "multiple
2354         // component selection") apply the load rule, converting references to values, so
2355         // those affect `is_reference` as well as `handle`.
2356         let TypedExpression {
2357             mut handle,
2358             mut is_reference,
2359         } = expr;
2360         let mut prefix_span = lexer.span_from(span_start);
2361 
2362         loop {
2363             // Step lightly around `resolve_type`'s mutable borrow.
2364             ctx.resolve_type(handle)?;
2365 
2366             // Find the type of the composite whose elements, components or members we're
2367             // accessing, skipping through references: except for swizzles, the `Access`
2368             // or `AccessIndex` expressions we'd generate are the same either way.
2369             //
2370             // Pointers, however, are not permitted. For error checks below, note whether
2371             // the base expression is a WGSL pointer.
2372             let temp_inner;
2373             let (composite, wgsl_pointer) = match *ctx.typifier.get(handle, ctx.types) {
2374                 crate::TypeInner::Pointer { base, .. } => (&ctx.types[base].inner, !is_reference),
2375                 crate::TypeInner::ValuePointer {
2376                     size: None,
2377                     kind,
2378                     width,
2379                     ..
2380                 } => {
2381                     temp_inner = crate::TypeInner::Scalar { kind, width };
2382                     (&temp_inner, !is_reference)
2383                 }
2384                 crate::TypeInner::ValuePointer {
2385                     size: Some(size),
2386                     kind,
2387                     width,
2388                     ..
2389                 } => {
2390                     temp_inner = crate::TypeInner::Vector { size, kind, width };
2391                     (&temp_inner, !is_reference)
2392                 }
2393                 ref other => (other, false),
2394             };
2395 
2396             let expression = match lexer.peek().0 {
2397                 Token::Separator('.') => {
2398                     let _ = lexer.next();
2399                     let (name, name_span) = lexer.next_ident_with_span()?;
2400 
2401                     // WGSL doesn't allow accessing members on pointers, or swizzling
2402                     // them. But Naga IR doesn't distinguish pointers and references, so
2403                     // we must check here.
2404                     if wgsl_pointer {
2405                         return Err(Error::Pointer(
2406                             "the value accessed by a `.member` expression",
2407                             prefix_span,
2408                         ));
2409                     }
2410 
2411                     let access = match *composite {
2412                         crate::TypeInner::Struct { ref members, .. } => {
2413                             let index = members
2414                                 .iter()
2415                                 .position(|m| m.name.as_deref() == Some(name))
2416                                 .ok_or(Error::BadAccessor(name_span))?
2417                                 as u32;
2418                             crate::Expression::AccessIndex {
2419                                 base: handle,
2420                                 index,
2421                             }
2422                         }
2423                         crate::TypeInner::Vector { .. } | crate::TypeInner::Matrix { .. } => {
2424                             match Composition::make(name, name_span)? {
2425                                 Composition::Multi(size, pattern) => {
2426                                     // Once you apply the load rule, the expression is no
2427                                     // longer a reference.
2428                                     let current_expr = TypedExpression {
2429                                         handle,
2430                                         is_reference,
2431                                     };
2432                                     let vector = ctx.apply_load_rule(current_expr);
2433                                     is_reference = false;
2434 
2435                                     crate::Expression::Swizzle {
2436                                         size,
2437                                         vector,
2438                                         pattern,
2439                                     }
2440                                 }
2441                                 Composition::Single(index) => crate::Expression::AccessIndex {
2442                                     base: handle,
2443                                     index,
2444                                 },
2445                             }
2446                         }
2447                         _ => return Err(Error::BadAccessor(name_span)),
2448                     };
2449 
2450                     access
2451                 }
2452                 Token::Paren('[') => {
2453                     let (_, open_brace_span) = lexer.next();
2454                     let index = self.parse_general_expression(lexer, ctx.reborrow())?;
2455                     let close_brace_span = lexer.expect_span(Token::Paren(']'))?;
2456 
2457                     // WGSL doesn't allow pointers to be subscripted. But Naga IR doesn't
2458                     // distinguish pointers and references, so we must check here.
2459                     if wgsl_pointer {
2460                         return Err(Error::Pointer(
2461                             "the value indexed by a `[]` subscripting expression",
2462                             prefix_span,
2463                         ));
2464                     }
2465 
2466                     if let crate::Expression::Constant(constant) = ctx.expressions[index] {
2467                         let expr_span = open_brace_span.end..close_brace_span.start;
2468 
2469                         let index = match ctx.constants[constant].inner {
2470                             ConstantInner::Scalar {
2471                                 value: ScalarValue::Uint(int),
2472                                 ..
2473                             } => u32::try_from(int).map_err(|_| Error::BadU32Constant(expr_span)),
2474                             ConstantInner::Scalar {
2475                                 value: ScalarValue::Sint(int),
2476                                 ..
2477                             } => u32::try_from(int).map_err(|_| Error::BadU32Constant(expr_span)),
2478                             _ => Err(Error::BadU32Constant(expr_span)),
2479                         }?;
2480 
2481                         crate::Expression::AccessIndex {
2482                             base: handle,
2483                             index,
2484                         }
2485                     } else {
2486                         crate::Expression::Access {
2487                             base: handle,
2488                             index,
2489                         }
2490                     }
2491                 }
2492                 _ => break,
2493             };
2494 
2495             prefix_span = lexer.span_from(span_start);
2496             handle = ctx
2497                 .expressions
2498                 .append(expression, NagaSpan::from(prefix_span.clone()));
2499         }
2500 
2501         Ok(TypedExpression {
2502             handle,
2503             is_reference,
2504         })
2505     }
2506 
2507     /// Parse a `unary_expression`.
parse_unary_expression<'a>( &mut self, lexer: &mut Lexer<'a>, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result<TypedExpression, Error<'a>>2508     fn parse_unary_expression<'a>(
2509         &mut self,
2510         lexer: &mut Lexer<'a>,
2511         mut ctx: ExpressionContext<'a, '_, '_>,
2512     ) -> Result<TypedExpression, Error<'a>> {
2513         self.push_scope(Scope::UnaryExpr, lexer);
2514         //TODO: refactor this to avoid backing up
2515         let expr = match lexer.peek().0 {
2516             Token::Operation('-') => {
2517                 let _ = lexer.next();
2518                 let unloaded_expr = self.parse_unary_expression(lexer, ctx.reborrow())?;
2519                 let expr = ctx.apply_load_rule(unloaded_expr);
2520                 let expr = crate::Expression::Unary {
2521                     op: crate::UnaryOperator::Negate,
2522                     expr,
2523                 };
2524                 let span = NagaSpan::from(self.peek_scope(lexer));
2525                 TypedExpression::non_reference(ctx.expressions.append(expr, span))
2526             }
2527             Token::Operation('!') | Token::Operation('~') => {
2528                 let _ = lexer.next();
2529                 let unloaded_expr = self.parse_unary_expression(lexer, ctx.reborrow())?;
2530                 let expr = ctx.apply_load_rule(unloaded_expr);
2531                 let expr = crate::Expression::Unary {
2532                     op: crate::UnaryOperator::Not,
2533                     expr,
2534                 };
2535                 let span = NagaSpan::from(self.peek_scope(lexer));
2536                 TypedExpression::non_reference(ctx.expressions.append(expr, span))
2537             }
2538             Token::Operation('*') => {
2539                 let _ = lexer.next();
2540                 // The `*` operator does not accept a reference, so we must apply the Load
2541                 // Rule here. But the operator itself simply changes the type from
2542                 // `ptr<SC, T, A>` to `ref<SC, T, A>`, so we generate no code for the
2543                 // operator itself. We simply return a `TypedExpression` with
2544                 // `is_reference` set to true.
2545                 let unloaded_pointer = self.parse_unary_expression(lexer, ctx.reborrow())?;
2546                 let pointer = ctx.apply_load_rule(unloaded_pointer);
2547 
2548                 // An expression like `&*ptr` may generate no Naga IR at all, but WGSL requires
2549                 // an error if `ptr` is not a pointer. So we have to type-check this ourselves.
2550                 if ctx.resolve_type(pointer)?.pointer_class().is_none() {
2551                     let span = ctx
2552                         .expressions
2553                         .get_span(pointer)
2554                         .to_range()
2555                         .unwrap_or_else(|| self.peek_scope(lexer));
2556                     return Err(Error::NotPointer(span));
2557                 }
2558 
2559                 TypedExpression {
2560                     handle: pointer,
2561                     is_reference: true,
2562                 }
2563             }
2564             Token::Operation('&') => {
2565                 let _ = lexer.next();
2566                 // The `&` operator simply converts a reference to a pointer. And since a
2567                 // reference is required, the Load Rule is not applied.
2568                 let operand = self.parse_unary_expression(lexer, ctx.reborrow())?;
2569                 if !operand.is_reference {
2570                     let span = ctx
2571                         .expressions
2572                         .get_span(operand.handle)
2573                         .to_range()
2574                         .unwrap_or_else(|| self.peek_scope(lexer));
2575                     return Err(Error::NotReference("the operand of the `&` operator", span));
2576                 }
2577 
2578                 // No code is generated. We just declare the pointer a reference now.
2579                 TypedExpression {
2580                     is_reference: false,
2581                     ..operand
2582                 }
2583             }
2584             _ => self.parse_singular_expression(lexer, ctx.reborrow())?,
2585         };
2586 
2587         self.pop_scope(lexer);
2588         Ok(expr)
2589     }
2590 
2591     /// Parse a `singular_expression`.
parse_singular_expression<'a>( &mut self, lexer: &mut Lexer<'a>, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result<TypedExpression, Error<'a>>2592     fn parse_singular_expression<'a>(
2593         &mut self,
2594         lexer: &mut Lexer<'a>,
2595         mut ctx: ExpressionContext<'a, '_, '_>,
2596     ) -> Result<TypedExpression, Error<'a>> {
2597         let start = lexer.current_byte_offset();
2598         self.push_scope(Scope::SingularExpr, lexer);
2599         let primary_expr = self.parse_primary_expression(lexer, ctx.reborrow())?;
2600         let singular_expr = self.parse_postfix(start, lexer, ctx.reborrow(), primary_expr)?;
2601         self.pop_scope(lexer);
2602 
2603         Ok(singular_expr)
2604     }
2605 
parse_equality_expression<'a>( &mut self, lexer: &mut Lexer<'a>, mut context: ExpressionContext<'a, '_, '_>, ) -> Result<TypedExpression, Error<'a>>2606     fn parse_equality_expression<'a>(
2607         &mut self,
2608         lexer: &mut Lexer<'a>,
2609         mut context: ExpressionContext<'a, '_, '_>,
2610     ) -> Result<TypedExpression, Error<'a>> {
2611         // equality_expression
2612         context.parse_binary_op(
2613             lexer,
2614             |token| match token {
2615                 Token::LogicalOperation('=') => Some(crate::BinaryOperator::Equal),
2616                 Token::LogicalOperation('!') => Some(crate::BinaryOperator::NotEqual),
2617                 _ => None,
2618             },
2619             // relational_expression
2620             |lexer, mut context| {
2621                 context.parse_binary_op(
2622                     lexer,
2623                     |token| match token {
2624                         Token::Paren('<') => Some(crate::BinaryOperator::Less),
2625                         Token::Paren('>') => Some(crate::BinaryOperator::Greater),
2626                         Token::LogicalOperation('<') => Some(crate::BinaryOperator::LessEqual),
2627                         Token::LogicalOperation('>') => Some(crate::BinaryOperator::GreaterEqual),
2628                         _ => None,
2629                     },
2630                     // shift_expression
2631                     |lexer, mut context| {
2632                         context.parse_binary_op(
2633                             lexer,
2634                             |token| match token {
2635                                 Token::ShiftOperation('<') => {
2636                                     Some(crate::BinaryOperator::ShiftLeft)
2637                                 }
2638                                 Token::ShiftOperation('>') => {
2639                                     Some(crate::BinaryOperator::ShiftRight)
2640                                 }
2641                                 _ => None,
2642                             },
2643                             // additive_expression
2644                             |lexer, mut context| {
2645                                 context.parse_binary_splat_op(
2646                                     lexer,
2647                                     |token| match token {
2648                                         Token::Operation('+') => Some(crate::BinaryOperator::Add),
2649                                         Token::Operation('-') => {
2650                                             Some(crate::BinaryOperator::Subtract)
2651                                         }
2652                                         _ => None,
2653                                     },
2654                                     // multiplicative_expression
2655                                     |lexer, mut context| {
2656                                         context.parse_binary_splat_op(
2657                                             lexer,
2658                                             |token| match token {
2659                                                 Token::Operation('*') => {
2660                                                     Some(crate::BinaryOperator::Multiply)
2661                                                 }
2662                                                 Token::Operation('/') => {
2663                                                     Some(crate::BinaryOperator::Divide)
2664                                                 }
2665                                                 Token::Operation('%') => {
2666                                                     Some(crate::BinaryOperator::Modulo)
2667                                                 }
2668                                                 _ => None,
2669                                             },
2670                                             |lexer, context| {
2671                                                 self.parse_unary_expression(lexer, context)
2672                                             },
2673                                         )
2674                                     },
2675                                 )
2676                             },
2677                         )
2678                     },
2679                 )
2680             },
2681         )
2682     }
2683 
parse_general_expression<'a>( &mut self, lexer: &mut Lexer<'a>, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result<Handle<crate::Expression>, Error<'a>>2684     fn parse_general_expression<'a>(
2685         &mut self,
2686         lexer: &mut Lexer<'a>,
2687         mut ctx: ExpressionContext<'a, '_, '_>,
2688     ) -> Result<Handle<crate::Expression>, Error<'a>> {
2689         let expr = self.parse_general_expression_for_reference(lexer, ctx.reborrow())?;
2690         Ok(ctx.apply_load_rule(expr))
2691     }
2692 
parse_general_expression_for_reference<'a>( &mut self, lexer: &mut Lexer<'a>, mut context: ExpressionContext<'a, '_, '_>, ) -> Result<TypedExpression, Error<'a>>2693     fn parse_general_expression_for_reference<'a>(
2694         &mut self,
2695         lexer: &mut Lexer<'a>,
2696         mut context: ExpressionContext<'a, '_, '_>,
2697     ) -> Result<TypedExpression, Error<'a>> {
2698         self.push_scope(Scope::GeneralExpr, lexer);
2699         // logical_or_expression
2700         let handle = context.parse_binary_op(
2701             lexer,
2702             |token| match token {
2703                 Token::LogicalOperation('|') => Some(crate::BinaryOperator::LogicalOr),
2704                 _ => None,
2705             },
2706             // logical_and_expression
2707             |lexer, mut context| {
2708                 context.parse_binary_op(
2709                     lexer,
2710                     |token| match token {
2711                         Token::LogicalOperation('&') => Some(crate::BinaryOperator::LogicalAnd),
2712                         _ => None,
2713                     },
2714                     // inclusive_or_expression
2715                     |lexer, mut context| {
2716                         context.parse_binary_op(
2717                             lexer,
2718                             |token| match token {
2719                                 Token::Operation('|') => Some(crate::BinaryOperator::InclusiveOr),
2720                                 _ => None,
2721                             },
2722                             // exclusive_or_expression
2723                             |lexer, mut context| {
2724                                 context.parse_binary_op(
2725                                     lexer,
2726                                     |token| match token {
2727                                         Token::Operation('^') => {
2728                                             Some(crate::BinaryOperator::ExclusiveOr)
2729                                         }
2730                                         _ => None,
2731                                     },
2732                                     // and_expression
2733                                     |lexer, mut context| {
2734                                         context.parse_binary_op(
2735                                             lexer,
2736                                             |token| match token {
2737                                                 Token::Operation('&') => {
2738                                                     Some(crate::BinaryOperator::And)
2739                                                 }
2740                                                 _ => None,
2741                                             },
2742                                             |lexer, context| {
2743                                                 self.parse_equality_expression(lexer, context)
2744                                             },
2745                                         )
2746                                     },
2747                                 )
2748                             },
2749                         )
2750                     },
2751                 )
2752             },
2753         )?;
2754         self.pop_scope(lexer);
2755         Ok(handle)
2756     }
2757 
parse_variable_ident_decl<'a>( &mut self, lexer: &mut Lexer<'a>, type_arena: &mut UniqueArena<crate::Type>, const_arena: &mut Arena<crate::Constant>, ) -> Result<(&'a str, Span, Handle<crate::Type>, crate::StorageAccess), Error<'a>>2758     fn parse_variable_ident_decl<'a>(
2759         &mut self,
2760         lexer: &mut Lexer<'a>,
2761         type_arena: &mut UniqueArena<crate::Type>,
2762         const_arena: &mut Arena<crate::Constant>,
2763     ) -> Result<(&'a str, Span, Handle<crate::Type>, crate::StorageAccess), Error<'a>> {
2764         let (name, name_span) = lexer.next_ident_with_span()?;
2765         lexer.expect(Token::Separator(':'))?;
2766         let (ty, access) = self.parse_type_decl(lexer, None, type_arena, const_arena)?;
2767         Ok((name, name_span, ty, access))
2768     }
2769 
parse_variable_decl<'a>( &mut self, lexer: &mut Lexer<'a>, type_arena: &mut UniqueArena<crate::Type>, const_arena: &mut Arena<crate::Constant>, ) -> Result<ParsedVariable<'a>, Error<'a>>2770     fn parse_variable_decl<'a>(
2771         &mut self,
2772         lexer: &mut Lexer<'a>,
2773         type_arena: &mut UniqueArena<crate::Type>,
2774         const_arena: &mut Arena<crate::Constant>,
2775     ) -> Result<ParsedVariable<'a>, Error<'a>> {
2776         self.push_scope(Scope::VariableDecl, lexer);
2777         let mut class = None;
2778 
2779         if lexer.skip(Token::Paren('<')) {
2780             let (class_str, span) = lexer.next_ident_with_span()?;
2781             class = Some(match class_str {
2782                 "storage" => {
2783                     let access = if lexer.skip(Token::Separator(',')) {
2784                         lexer.next_storage_access()?
2785                     } else {
2786                         // defaulting to `read`
2787                         crate::StorageAccess::LOAD
2788                     };
2789                     crate::StorageClass::Storage { access }
2790                 }
2791                 _ => conv::map_storage_class(class_str, span)?,
2792             });
2793             lexer.expect(Token::Paren('>'))?;
2794         }
2795         let name = lexer.next_ident()?;
2796         lexer.expect(Token::Separator(':'))?;
2797         let (ty, _access) = self.parse_type_decl(lexer, None, type_arena, const_arena)?;
2798 
2799         let init = if lexer.skip(Token::Operation('=')) {
2800             let handle = self.parse_const_expression(lexer, type_arena, const_arena)?;
2801             Some(handle)
2802         } else {
2803             None
2804         };
2805         lexer.expect(Token::Separator(';'))?;
2806         let name_span = self.pop_scope(lexer);
2807         Ok(ParsedVariable {
2808             name,
2809             name_span,
2810             class,
2811             ty,
2812             init,
2813         })
2814     }
2815 
parse_struct_body<'a>( &mut self, lexer: &mut Lexer<'a>, type_arena: &mut UniqueArena<crate::Type>, const_arena: &mut Arena<crate::Constant>, ) -> Result<(Vec<crate::StructMember>, u32), Error<'a>>2816     fn parse_struct_body<'a>(
2817         &mut self,
2818         lexer: &mut Lexer<'a>,
2819         type_arena: &mut UniqueArena<crate::Type>,
2820         const_arena: &mut Arena<crate::Constant>,
2821     ) -> Result<(Vec<crate::StructMember>, u32), Error<'a>> {
2822         let mut offset = 0;
2823         let mut alignment = Alignment::new(1).unwrap();
2824         let mut members = Vec::new();
2825 
2826         lexer.expect(Token::Paren('{'))?;
2827         loop {
2828             let (mut size, mut align) = (None, None);
2829             self.push_scope(Scope::Attribute, lexer);
2830             let mut bind_parser = BindingParser::default();
2831             if lexer.skip(Token::DoubleParen('[')) {
2832                 let mut ready = true;
2833                 loop {
2834                     match lexer.next() {
2835                         (Token::DoubleParen(']'), _) => {
2836                             break;
2837                         }
2838                         (Token::Separator(','), _) if !ready => {
2839                             ready = true;
2840                         }
2841                         (Token::Word(word), word_span) if ready => {
2842                             match word {
2843                                 "size" => {
2844                                     lexer.expect(Token::Paren('('))?;
2845                                     let (value, span) = lexer.capture_span(|lexer| {
2846                                         parse_non_negative_sint_literal(lexer, 4)
2847                                     })?;
2848                                     lexer.expect(Token::Paren(')'))?;
2849                                     size = Some(
2850                                         NonZeroU32::new(value)
2851                                             .ok_or(Error::ZeroSizeOrAlign(span))?,
2852                                     );
2853                                 }
2854                                 "align" => {
2855                                     lexer.expect(Token::Paren('('))?;
2856                                     let (value, span) = lexer.capture_span(|lexer| {
2857                                         parse_non_negative_sint_literal(lexer, 4)
2858                                     })?;
2859                                     lexer.expect(Token::Paren(')'))?;
2860                                     align = Some(
2861                                         NonZeroU32::new(value)
2862                                             .ok_or(Error::ZeroSizeOrAlign(span))?,
2863                                     );
2864                                 }
2865                                 _ => bind_parser.parse(lexer, word, word_span)?,
2866                             }
2867                             ready = false;
2868                         }
2869                         other if ready => {
2870                             return Err(Error::Unexpected(other, ExpectedToken::StructAttribute))
2871                         }
2872                         other => {
2873                             return Err(Error::Unexpected(other, ExpectedToken::AttributeSeparator))
2874                         }
2875                     }
2876                 }
2877             }
2878 
2879             let bind_span = self.pop_scope(lexer);
2880             let (name, span) = match lexer.next() {
2881                 (Token::Word(word), span) => (word, span),
2882                 (Token::Paren('}'), _) => {
2883                     let span = Layouter::round_up(alignment, offset);
2884                     return Ok((members, span));
2885                 }
2886                 other => return Err(Error::Unexpected(other, ExpectedToken::FieldName)),
2887             };
2888             if crate::keywords::wgsl::RESERVED.contains(&name) {
2889                 return Err(Error::ReservedKeyword(span));
2890             }
2891             lexer.expect(Token::Separator(':'))?;
2892             let (ty, _access) = self.parse_type_decl(lexer, None, type_arena, const_arena)?;
2893             lexer.expect(Token::Separator(';'))?;
2894 
2895             self.layouter.update(type_arena, const_arena).unwrap();
2896 
2897             let (range, align) = self.layouter.member_placement(offset, ty, align, size);
2898             alignment = alignment.max(align);
2899             offset = range.end;
2900 
2901             let mut binding = bind_parser.finish(bind_span)?;
2902             if let Some(ref mut binding) = binding {
2903                 binding.apply_default_interpolation(&type_arena[ty].inner);
2904             }
2905             members.push(crate::StructMember {
2906                 name: Some(name.to_owned()),
2907                 ty,
2908                 binding,
2909                 offset: range.start,
2910             });
2911         }
2912     }
2913 
parse_type_decl_impl<'a>( &mut self, lexer: &mut Lexer<'a>, attribute: TypeAttributes, word: &'a str, type_arena: &mut UniqueArena<crate::Type>, const_arena: &mut Arena<crate::Constant>, ) -> Result<Option<crate::TypeInner>, Error<'a>>2914     fn parse_type_decl_impl<'a>(
2915         &mut self,
2916         lexer: &mut Lexer<'a>,
2917         attribute: TypeAttributes,
2918         word: &'a str,
2919         type_arena: &mut UniqueArena<crate::Type>,
2920         const_arena: &mut Arena<crate::Constant>,
2921     ) -> Result<Option<crate::TypeInner>, Error<'a>> {
2922         if let Some((kind, width)) = conv::get_scalar_type(word) {
2923             return Ok(Some(crate::TypeInner::Scalar { kind, width }));
2924         }
2925         Ok(Some(match word {
2926             "vec2" => {
2927                 let (kind, width) = lexer.next_scalar_generic()?;
2928                 crate::TypeInner::Vector {
2929                     size: crate::VectorSize::Bi,
2930                     kind,
2931                     width,
2932                 }
2933             }
2934             "vec3" => {
2935                 let (kind, width) = lexer.next_scalar_generic()?;
2936                 crate::TypeInner::Vector {
2937                     size: crate::VectorSize::Tri,
2938                     kind,
2939                     width,
2940                 }
2941             }
2942             "vec4" => {
2943                 let (kind, width) = lexer.next_scalar_generic()?;
2944                 crate::TypeInner::Vector {
2945                     size: crate::VectorSize::Quad,
2946                     kind,
2947                     width,
2948                 }
2949             }
2950             "mat2x2" => {
2951                 let (_, width) = lexer.next_scalar_generic()?;
2952                 crate::TypeInner::Matrix {
2953                     columns: crate::VectorSize::Bi,
2954                     rows: crate::VectorSize::Bi,
2955                     width,
2956                 }
2957             }
2958             "mat2x3" => {
2959                 let (_, width) = lexer.next_scalar_generic()?;
2960                 crate::TypeInner::Matrix {
2961                     columns: crate::VectorSize::Bi,
2962                     rows: crate::VectorSize::Tri,
2963                     width,
2964                 }
2965             }
2966             "mat2x4" => {
2967                 let (_, width) = lexer.next_scalar_generic()?;
2968                 crate::TypeInner::Matrix {
2969                     columns: crate::VectorSize::Bi,
2970                     rows: crate::VectorSize::Quad,
2971                     width,
2972                 }
2973             }
2974             "mat3x2" => {
2975                 let (_, width) = lexer.next_scalar_generic()?;
2976                 crate::TypeInner::Matrix {
2977                     columns: crate::VectorSize::Tri,
2978                     rows: crate::VectorSize::Bi,
2979                     width,
2980                 }
2981             }
2982             "mat3x3" => {
2983                 let (_, width) = lexer.next_scalar_generic()?;
2984                 crate::TypeInner::Matrix {
2985                     columns: crate::VectorSize::Tri,
2986                     rows: crate::VectorSize::Tri,
2987                     width,
2988                 }
2989             }
2990             "mat3x4" => {
2991                 let (_, width) = lexer.next_scalar_generic()?;
2992                 crate::TypeInner::Matrix {
2993                     columns: crate::VectorSize::Tri,
2994                     rows: crate::VectorSize::Quad,
2995                     width,
2996                 }
2997             }
2998             "mat4x2" => {
2999                 let (_, width) = lexer.next_scalar_generic()?;
3000                 crate::TypeInner::Matrix {
3001                     columns: crate::VectorSize::Quad,
3002                     rows: crate::VectorSize::Bi,
3003                     width,
3004                 }
3005             }
3006             "mat4x3" => {
3007                 let (_, width) = lexer.next_scalar_generic()?;
3008                 crate::TypeInner::Matrix {
3009                     columns: crate::VectorSize::Quad,
3010                     rows: crate::VectorSize::Tri,
3011                     width,
3012                 }
3013             }
3014             "mat4x4" => {
3015                 let (_, width) = lexer.next_scalar_generic()?;
3016                 crate::TypeInner::Matrix {
3017                     columns: crate::VectorSize::Quad,
3018                     rows: crate::VectorSize::Quad,
3019                     width,
3020                 }
3021             }
3022             "atomic" => {
3023                 let (kind, width) = lexer.next_scalar_generic()?;
3024                 crate::TypeInner::Atomic { kind, width }
3025             }
3026             "ptr" => {
3027                 lexer.expect_generic_paren('<')?;
3028                 let (ident, span) = lexer.next_ident_with_span()?;
3029                 let mut class = conv::map_storage_class(ident, span)?;
3030                 lexer.expect(Token::Separator(','))?;
3031                 let (base, _access) = self.parse_type_decl(lexer, None, type_arena, const_arena)?;
3032                 if let crate::StorageClass::Storage { ref mut access } = class {
3033                     *access = if lexer.skip(Token::Separator(',')) {
3034                         lexer.next_storage_access()?
3035                     } else {
3036                         crate::StorageAccess::LOAD
3037                     };
3038                 }
3039                 lexer.expect_generic_paren('>')?;
3040                 crate::TypeInner::Pointer { base, class }
3041             }
3042             "array" => {
3043                 lexer.expect_generic_paren('<')?;
3044                 let (base, _access) = self.parse_type_decl(lexer, None, type_arena, const_arena)?;
3045                 let size = if lexer.skip(Token::Separator(',')) {
3046                     let const_handle =
3047                         self.parse_const_expression(lexer, type_arena, const_arena)?;
3048                     crate::ArraySize::Constant(const_handle)
3049                 } else {
3050                     crate::ArraySize::Dynamic
3051                 };
3052                 lexer.expect_generic_paren('>')?;
3053                 let stride = match attribute.stride {
3054                     Some(stride) => stride.get(),
3055                     None => {
3056                         self.layouter.update(type_arena, const_arena).unwrap();
3057                         let layout = &self.layouter[base];
3058                         Layouter::round_up(layout.alignment, layout.size)
3059                     }
3060                 };
3061 
3062                 crate::TypeInner::Array { base, size, stride }
3063             }
3064             "sampler" => crate::TypeInner::Sampler { comparison: false },
3065             "sampler_comparison" => crate::TypeInner::Sampler { comparison: true },
3066             "texture_1d" => {
3067                 let (kind, width, span) = lexer.next_scalar_generic_with_span()?;
3068                 Self::check_texture_sample_type(kind, width, span)?;
3069                 crate::TypeInner::Image {
3070                     dim: crate::ImageDimension::D1,
3071                     arrayed: false,
3072                     class: crate::ImageClass::Sampled { kind, multi: false },
3073                 }
3074             }
3075             "texture_1d_array" => {
3076                 let (kind, width, span) = lexer.next_scalar_generic_with_span()?;
3077                 Self::check_texture_sample_type(kind, width, span)?;
3078                 crate::TypeInner::Image {
3079                     dim: crate::ImageDimension::D1,
3080                     arrayed: true,
3081                     class: crate::ImageClass::Sampled { kind, multi: false },
3082                 }
3083             }
3084             "texture_2d" => {
3085                 let (kind, width, span) = lexer.next_scalar_generic_with_span()?;
3086                 Self::check_texture_sample_type(kind, width, span)?;
3087                 crate::TypeInner::Image {
3088                     dim: crate::ImageDimension::D2,
3089                     arrayed: false,
3090                     class: crate::ImageClass::Sampled { kind, multi: false },
3091                 }
3092             }
3093             "texture_2d_array" => {
3094                 let (kind, width, span) = lexer.next_scalar_generic_with_span()?;
3095                 Self::check_texture_sample_type(kind, width, span)?;
3096                 crate::TypeInner::Image {
3097                     dim: crate::ImageDimension::D2,
3098                     arrayed: true,
3099                     class: crate::ImageClass::Sampled { kind, multi: false },
3100                 }
3101             }
3102             "texture_3d" => {
3103                 let (kind, width, span) = lexer.next_scalar_generic_with_span()?;
3104                 Self::check_texture_sample_type(kind, width, span)?;
3105                 crate::TypeInner::Image {
3106                     dim: crate::ImageDimension::D3,
3107                     arrayed: false,
3108                     class: crate::ImageClass::Sampled { kind, multi: false },
3109                 }
3110             }
3111             "texture_cube" => {
3112                 let (kind, width, span) = lexer.next_scalar_generic_with_span()?;
3113                 Self::check_texture_sample_type(kind, width, span)?;
3114                 crate::TypeInner::Image {
3115                     dim: crate::ImageDimension::Cube,
3116                     arrayed: false,
3117                     class: crate::ImageClass::Sampled { kind, multi: false },
3118                 }
3119             }
3120             "texture_cube_array" => {
3121                 let (kind, width, span) = lexer.next_scalar_generic_with_span()?;
3122                 Self::check_texture_sample_type(kind, width, span)?;
3123                 crate::TypeInner::Image {
3124                     dim: crate::ImageDimension::Cube,
3125                     arrayed: true,
3126                     class: crate::ImageClass::Sampled { kind, multi: false },
3127                 }
3128             }
3129             "texture_multisampled_2d" => {
3130                 let (kind, width, span) = lexer.next_scalar_generic_with_span()?;
3131                 Self::check_texture_sample_type(kind, width, span)?;
3132                 crate::TypeInner::Image {
3133                     dim: crate::ImageDimension::D2,
3134                     arrayed: false,
3135                     class: crate::ImageClass::Sampled { kind, multi: true },
3136                 }
3137             }
3138             "texture_multisampled_2d_array" => {
3139                 let (kind, width, span) = lexer.next_scalar_generic_with_span()?;
3140                 Self::check_texture_sample_type(kind, width, span)?;
3141                 crate::TypeInner::Image {
3142                     dim: crate::ImageDimension::D2,
3143                     arrayed: true,
3144                     class: crate::ImageClass::Sampled { kind, multi: true },
3145                 }
3146             }
3147             "texture_depth_2d" => crate::TypeInner::Image {
3148                 dim: crate::ImageDimension::D2,
3149                 arrayed: false,
3150                 class: crate::ImageClass::Depth { multi: false },
3151             },
3152             "texture_depth_2d_array" => crate::TypeInner::Image {
3153                 dim: crate::ImageDimension::D2,
3154                 arrayed: true,
3155                 class: crate::ImageClass::Depth { multi: false },
3156             },
3157             "texture_depth_cube" => crate::TypeInner::Image {
3158                 dim: crate::ImageDimension::Cube,
3159                 arrayed: false,
3160                 class: crate::ImageClass::Depth { multi: false },
3161             },
3162             "texture_depth_cube_array" => crate::TypeInner::Image {
3163                 dim: crate::ImageDimension::Cube,
3164                 arrayed: true,
3165                 class: crate::ImageClass::Depth { multi: false },
3166             },
3167             "texture_depth_multisampled_2d" => crate::TypeInner::Image {
3168                 dim: crate::ImageDimension::D2,
3169                 arrayed: false,
3170                 class: crate::ImageClass::Depth { multi: true },
3171             },
3172             "texture_storage_1d" => {
3173                 let (format, access) = lexer.next_format_generic()?;
3174                 crate::TypeInner::Image {
3175                     dim: crate::ImageDimension::D1,
3176                     arrayed: false,
3177                     class: crate::ImageClass::Storage { format, access },
3178                 }
3179             }
3180             "texture_storage_1d_array" => {
3181                 let (format, access) = lexer.next_format_generic()?;
3182                 crate::TypeInner::Image {
3183                     dim: crate::ImageDimension::D1,
3184                     arrayed: true,
3185                     class: crate::ImageClass::Storage { format, access },
3186                 }
3187             }
3188             "texture_storage_2d" => {
3189                 let (format, access) = lexer.next_format_generic()?;
3190                 crate::TypeInner::Image {
3191                     dim: crate::ImageDimension::D2,
3192                     arrayed: false,
3193                     class: crate::ImageClass::Storage { format, access },
3194                 }
3195             }
3196             "texture_storage_2d_array" => {
3197                 let (format, access) = lexer.next_format_generic()?;
3198                 crate::TypeInner::Image {
3199                     dim: crate::ImageDimension::D2,
3200                     arrayed: true,
3201                     class: crate::ImageClass::Storage { format, access },
3202                 }
3203             }
3204             "texture_storage_3d" => {
3205                 let (format, access) = lexer.next_format_generic()?;
3206                 crate::TypeInner::Image {
3207                     dim: crate::ImageDimension::D3,
3208                     arrayed: false,
3209                     class: crate::ImageClass::Storage { format, access },
3210                 }
3211             }
3212             _ => return Ok(None),
3213         }))
3214     }
3215 
check_texture_sample_type( kind: crate::ScalarKind, width: u8, span: Span, ) -> Result<(), Error<'static>>3216     fn check_texture_sample_type(
3217         kind: crate::ScalarKind,
3218         width: u8,
3219         span: Span,
3220     ) -> Result<(), Error<'static>> {
3221         use crate::ScalarKind::*;
3222         // Validate according to https://gpuweb.github.io/gpuweb/wgsl/#sampled-texture-type
3223         match (kind, width) {
3224             (Float, 4) | (Sint, 4) | (Uint, 4) => Ok(()),
3225             _ => Err(Error::BadTextureSampleType { span, kind, width }),
3226         }
3227     }
3228 
3229     /// Parse type declaration of a given name and attribute.
3230     #[allow(clippy::too_many_arguments)]
parse_type_decl_name<'a>( &mut self, lexer: &mut Lexer<'a>, name: &'a str, name_span: Span, debug_name: Option<&'a str>, attribute: TypeAttributes, type_arena: &mut UniqueArena<crate::Type>, const_arena: &mut Arena<crate::Constant>, ) -> Result<Handle<crate::Type>, Error<'a>>3231     fn parse_type_decl_name<'a>(
3232         &mut self,
3233         lexer: &mut Lexer<'a>,
3234         name: &'a str,
3235         name_span: Span,
3236         debug_name: Option<&'a str>,
3237         attribute: TypeAttributes,
3238         type_arena: &mut UniqueArena<crate::Type>,
3239         const_arena: &mut Arena<crate::Constant>,
3240     ) -> Result<Handle<crate::Type>, Error<'a>> {
3241         Ok(match self.lookup_type.get(name) {
3242             Some(&handle) => handle,
3243             None => {
3244                 match self.parse_type_decl_impl(lexer, attribute, name, type_arena, const_arena)? {
3245                     Some(inner) => {
3246                         let span = name_span.start..lexer.current_byte_offset();
3247                         type_arena.insert(
3248                             crate::Type {
3249                                 name: debug_name.map(|s| s.to_string()),
3250                                 inner,
3251                             },
3252                             NagaSpan::from(span),
3253                         )
3254                     }
3255                     None => return Err(Error::UnknownType(name_span)),
3256                 }
3257             }
3258         })
3259     }
3260 
parse_type_decl<'a>( &mut self, lexer: &mut Lexer<'a>, debug_name: Option<&'a str>, type_arena: &mut UniqueArena<crate::Type>, const_arena: &mut Arena<crate::Constant>, ) -> Result<(Handle<crate::Type>, crate::StorageAccess), Error<'a>>3261     fn parse_type_decl<'a>(
3262         &mut self,
3263         lexer: &mut Lexer<'a>,
3264         debug_name: Option<&'a str>,
3265         type_arena: &mut UniqueArena<crate::Type>,
3266         const_arena: &mut Arena<crate::Constant>,
3267     ) -> Result<(Handle<crate::Type>, crate::StorageAccess), Error<'a>> {
3268         self.push_scope(Scope::TypeDecl, lexer);
3269         let mut attribute = TypeAttributes::default();
3270 
3271         if lexer.skip(Token::DoubleParen('[')) {
3272             self.push_scope(Scope::Attribute, lexer);
3273             loop {
3274                 match lexer.next() {
3275                     (Token::Word("stride"), _) => {
3276                         lexer.expect(Token::Paren('('))?;
3277                         let (stride, span) = lexer
3278                             .capture_span(|lexer| parse_non_negative_sint_literal(lexer, 4))?;
3279                         attribute.stride =
3280                             Some(NonZeroU32::new(stride).ok_or(Error::ZeroStride(span))?);
3281                         lexer.expect(Token::Paren(')'))?;
3282                     }
3283                     (Token::DoubleParen(']'), _) => break,
3284                     other => return Err(Error::Unexpected(other, ExpectedToken::TypeAttribute)),
3285                 }
3286             }
3287             self.pop_scope(lexer);
3288         }
3289 
3290         let storage_access = crate::StorageAccess::default();
3291         let (name, name_span) = lexer.next_ident_with_span()?;
3292         let handle = self.parse_type_decl_name(
3293             lexer,
3294             name,
3295             name_span,
3296             debug_name,
3297             attribute,
3298             type_arena,
3299             const_arena,
3300         )?;
3301         self.pop_scope(lexer);
3302         // Only set span if it's the first occurrence of the type.
3303         // Type spans therefore should only be used for errors in type declarations;
3304         // use variable spans/expression spans/etc. otherwise
3305         Ok((handle, storage_access))
3306     }
3307 
3308     /// Parse a assignment statement
parse_assignment_statement<'a, 'out>( &mut self, lexer: &mut Lexer<'a>, mut context: ExpressionContext<'a, '_, 'out>, ) -> Result<(), Error<'a>>3309     fn parse_assignment_statement<'a, 'out>(
3310         &mut self,
3311         lexer: &mut Lexer<'a>,
3312         mut context: ExpressionContext<'a, '_, 'out>,
3313     ) -> Result<(), Error<'a>> {
3314         use crate::BinaryOperator as Bo;
3315 
3316         let span_start = lexer.current_byte_offset();
3317         context.emitter.start(context.expressions);
3318         let reference = self.parse_unary_expression(lexer, context.reborrow())?;
3319         // The left hand side of an assignment must be a reference.
3320         if !reference.is_reference {
3321             let span = span_start..lexer.current_byte_offset();
3322             return Err(Error::NotReference(
3323                 "the left-hand side of an assignment",
3324                 span,
3325             ));
3326         }
3327 
3328         let value = match lexer.next() {
3329             (Token::Operation('='), _) => {
3330                 self.parse_general_expression(lexer, context.reborrow())?
3331             }
3332             (Token::AssignmentOperation(c), span) => {
3333                 let op = match c {
3334                     '<' => Bo::ShiftLeft,
3335                     '>' => Bo::ShiftRight,
3336                     '+' => Bo::Add,
3337                     '-' => Bo::Subtract,
3338                     '*' => Bo::Multiply,
3339                     '/' => Bo::Divide,
3340                     '%' => Bo::Modulo,
3341                     '&' => Bo::And,
3342                     '|' => Bo::InclusiveOr,
3343                     '^' => Bo::ExclusiveOr,
3344                     //Note: `consume_token` shouldn't produce any other assignment ops
3345                     _ => unreachable!(),
3346                 };
3347                 let left = context.expressions.append(
3348                     crate::Expression::Load {
3349                         pointer: reference.handle,
3350                     },
3351                     NagaSpan::from(span_start..lexer.current_byte_offset()),
3352                 );
3353                 let right = self.parse_general_expression(lexer, context.reborrow())?;
3354                 context
3355                     .expressions
3356                     .append(crate::Expression::Binary { op, left, right }, span.into())
3357             }
3358             other => return Err(Error::Unexpected(other, ExpectedToken::SwitchItem)),
3359         };
3360 
3361         let span_end = lexer.current_byte_offset();
3362         context
3363             .block
3364             .extend(context.emitter.finish(context.expressions));
3365         context.block.push(
3366             crate::Statement::Store {
3367                 pointer: reference.handle,
3368                 value,
3369             },
3370             NagaSpan::from(span_start..span_end),
3371         );
3372         Ok(())
3373     }
3374 
3375     /// Parse a function call statement.
parse_function_statement<'a, 'out>( &mut self, lexer: &mut Lexer<'a>, ident: &'a str, mut context: ExpressionContext<'a, '_, 'out>, ) -> Result<(), Error<'a>>3376     fn parse_function_statement<'a, 'out>(
3377         &mut self,
3378         lexer: &mut Lexer<'a>,
3379         ident: &'a str,
3380         mut context: ExpressionContext<'a, '_, 'out>,
3381     ) -> Result<(), Error<'a>> {
3382         self.push_scope(Scope::SingularExpr, lexer);
3383         context.emitter.start(context.expressions);
3384         if self
3385             .parse_function_call_inner(lexer, ident, context.reborrow())?
3386             .is_none()
3387         {
3388             let span = lexer.next().1;
3389             return Err(Error::UnknownLocalFunction(span));
3390         }
3391         context
3392             .block
3393             .extend(context.emitter.finish(context.expressions));
3394         self.pop_scope(lexer);
3395 
3396         Ok(())
3397     }
3398 
parse_switch_case_body<'a, 'out>( &mut self, lexer: &mut Lexer<'a>, mut context: StatementContext<'a, '_, 'out>, ) -> Result<(bool, crate::Block), Error<'a>>3399     fn parse_switch_case_body<'a, 'out>(
3400         &mut self,
3401         lexer: &mut Lexer<'a>,
3402         mut context: StatementContext<'a, '_, 'out>,
3403     ) -> Result<(bool, crate::Block), Error<'a>> {
3404         let mut body = crate::Block::new();
3405         lexer.expect(Token::Paren('{'))?;
3406         let fall_through = loop {
3407             // default statements
3408             if lexer.skip(Token::Word("fallthrough")) {
3409                 lexer.expect(Token::Separator(';'))?;
3410                 lexer.expect(Token::Paren('}'))?;
3411                 break true;
3412             }
3413             if lexer.skip(Token::Paren('}')) {
3414                 break false;
3415             }
3416             self.parse_statement(lexer, context.reborrow(), &mut body, false)?;
3417         };
3418 
3419         Ok((fall_through, body))
3420     }
3421 
parse_statement<'a, 'out>( &mut self, lexer: &mut Lexer<'a>, mut context: StatementContext<'a, '_, 'out>, block: &'out mut crate::Block, is_uniform_control_flow: bool, ) -> Result<(), Error<'a>>3422     fn parse_statement<'a, 'out>(
3423         &mut self,
3424         lexer: &mut Lexer<'a>,
3425         mut context: StatementContext<'a, '_, 'out>,
3426         block: &'out mut crate::Block,
3427         is_uniform_control_flow: bool,
3428     ) -> Result<(), Error<'a>> {
3429         self.push_scope(Scope::Statement, lexer);
3430         match lexer.peek() {
3431             (Token::Separator(';'), _) => {
3432                 let _ = lexer.next();
3433                 self.pop_scope(lexer);
3434                 return Ok(());
3435             }
3436             (Token::Paren('{'), _) => {
3437                 self.push_scope(Scope::Block, lexer);
3438                 let _ = lexer.next();
3439                 let mut statements = crate::Block::new();
3440                 while !lexer.skip(Token::Paren('}')) {
3441                     self.parse_statement(
3442                         lexer,
3443                         context.reborrow(),
3444                         &mut statements,
3445                         is_uniform_control_flow,
3446                     )?;
3447                 }
3448                 self.pop_scope(lexer);
3449                 let span = NagaSpan::from(self.pop_scope(lexer));
3450                 block.push(crate::Statement::Block(statements), span);
3451                 return Ok(());
3452             }
3453             (Token::Word(word), _) => {
3454                 let mut emitter = super::Emitter::default();
3455                 let statement = match word {
3456                     "let" => {
3457                         let _ = lexer.next();
3458                         emitter.start(context.expressions);
3459                         let (name, name_span) = lexer.next_ident_with_span()?;
3460                         if crate::keywords::wgsl::RESERVED.contains(&name) {
3461                             return Err(Error::ReservedKeyword(name_span));
3462                         }
3463                         let given_ty = if lexer.skip(Token::Separator(':')) {
3464                             let (ty, _access) = self.parse_type_decl(
3465                                 lexer,
3466                                 None,
3467                                 context.types,
3468                                 context.constants,
3469                             )?;
3470                             Some(ty)
3471                         } else {
3472                             None
3473                         };
3474                         lexer.expect(Token::Operation('='))?;
3475                         let expr_id = self.parse_general_expression(
3476                             lexer,
3477                             context.as_expression(block, &mut emitter),
3478                         )?;
3479                         lexer.expect(Token::Separator(';'))?;
3480                         if let Some(ty) = given_ty {
3481                             // prepare the typifier, but work around mutable borrowing...
3482                             let _ = context
3483                                 .as_expression(block, &mut emitter)
3484                                 .resolve_type(expr_id)?;
3485                             let expr_inner = context.typifier.get(expr_id, context.types);
3486                             let given_inner = &context.types[ty].inner;
3487                             if !given_inner.equivalent(expr_inner, context.types) {
3488                                 log::error!(
3489                                     "Given type {:?} doesn't match expected {:?}",
3490                                     given_inner,
3491                                     expr_inner
3492                                 );
3493                                 return Err(Error::InitializationTypeMismatch(
3494                                     name_span,
3495                                     expr_inner.to_wgsl(context.types, context.constants),
3496                                 ));
3497                             }
3498                         }
3499                         block.extend(emitter.finish(context.expressions));
3500                         context.lookup_ident.insert(
3501                             name,
3502                             TypedExpression {
3503                                 handle: expr_id,
3504                                 is_reference: false,
3505                             },
3506                         );
3507                         context
3508                             .named_expressions
3509                             .insert(expr_id, String::from(name));
3510                         None
3511                     }
3512                     "var" => {
3513                         let _ = lexer.next();
3514                         enum Init {
3515                             Empty,
3516                             Constant(Handle<crate::Constant>),
3517                             Variable(Handle<crate::Expression>),
3518                         }
3519 
3520                         let (name, name_span) = lexer.next_ident_with_span()?;
3521                         if crate::keywords::wgsl::RESERVED.contains(&name) {
3522                             return Err(Error::ReservedKeyword(name_span));
3523                         }
3524                         let given_ty = if lexer.skip(Token::Separator(':')) {
3525                             let (ty, _access) = self.parse_type_decl(
3526                                 lexer,
3527                                 None,
3528                                 context.types,
3529                                 context.constants,
3530                             )?;
3531                             Some(ty)
3532                         } else {
3533                             None
3534                         };
3535 
3536                         let (init, ty) = if lexer.skip(Token::Operation('=')) {
3537                             emitter.start(context.expressions);
3538                             let value = self.parse_general_expression(
3539                                 lexer,
3540                                 context.as_expression(block, &mut emitter),
3541                             )?;
3542                             block.extend(emitter.finish(context.expressions));
3543 
3544                             // prepare the typifier, but work around mutable borrowing...
3545                             let _ = context
3546                                 .as_expression(block, &mut emitter)
3547                                 .resolve_type(value)?;
3548 
3549                             //TODO: share more of this code with `let` arm
3550                             let ty = match given_ty {
3551                                 Some(ty) => {
3552                                     let expr_inner = context.typifier.get(value, context.types);
3553                                     let given_inner = &context.types[ty].inner;
3554                                     if !given_inner.equivalent(expr_inner, context.types) {
3555                                         log::error!(
3556                                             "Given type {:?} doesn't match expected {:?}",
3557                                             given_inner,
3558                                             expr_inner
3559                                         );
3560                                         return Err(Error::InitializationTypeMismatch(
3561                                             name_span,
3562                                             expr_inner.to_wgsl(context.types, context.constants),
3563                                         ));
3564                                     }
3565                                     ty
3566                                 }
3567                                 None => {
3568                                     // register the type, if needed
3569                                     match context.typifier[value].clone() {
3570                                         TypeResolution::Handle(ty) => ty,
3571                                         TypeResolution::Value(inner) => context.types.insert(
3572                                             crate::Type { name: None, inner },
3573                                             Default::default(),
3574                                         ),
3575                                     }
3576                                 }
3577                             };
3578 
3579                             let init = match context.expressions[value] {
3580                                 crate::Expression::Constant(handle) if is_uniform_control_flow => {
3581                                     Init::Constant(handle)
3582                                 }
3583                                 _ => Init::Variable(value),
3584                             };
3585                             (init, ty)
3586                         } else {
3587                             match given_ty {
3588                                 Some(ty) => (Init::Empty, ty),
3589                                 None => {
3590                                     log::error!(
3591                                         "Variable '{}' without an initializer needs a type",
3592                                         name
3593                                     );
3594                                     return Err(Error::MissingType(name_span));
3595                                 }
3596                             }
3597                         };
3598 
3599                         lexer.expect(Token::Separator(';'))?;
3600                         let var_id = context.variables.append(
3601                             crate::LocalVariable {
3602                                 name: Some(name.to_owned()),
3603                                 ty,
3604                                 init: match init {
3605                                     Init::Constant(value) => Some(value),
3606                                     _ => None,
3607                                 },
3608                             },
3609                             NagaSpan::from(name_span),
3610                         );
3611 
3612                         // Doesn't make sense to assign a span to cached lookup
3613                         let expr_id = context
3614                             .expressions
3615                             .append(crate::Expression::LocalVariable(var_id), Default::default());
3616                         context.lookup_ident.insert(
3617                             name,
3618                             TypedExpression {
3619                                 handle: expr_id,
3620                                 is_reference: true,
3621                             },
3622                         );
3623 
3624                         if let Init::Variable(value) = init {
3625                             Some(crate::Statement::Store {
3626                                 pointer: expr_id,
3627                                 value,
3628                             })
3629                         } else {
3630                             None
3631                         }
3632                     }
3633                     "return" => {
3634                         let _ = lexer.next();
3635                         let value = if lexer.peek().0 != Token::Separator(';') {
3636                             emitter.start(context.expressions);
3637                             let handle = self.parse_general_expression(
3638                                 lexer,
3639                                 context.as_expression(block, &mut emitter),
3640                             )?;
3641                             block.extend(emitter.finish(context.expressions));
3642                             Some(handle)
3643                         } else {
3644                             None
3645                         };
3646                         lexer.expect(Token::Separator(';'))?;
3647                         Some(crate::Statement::Return { value })
3648                     }
3649                     "if" => {
3650                         let _ = lexer.next();
3651                         lexer.expect(Token::Paren('('))?;
3652                         emitter.start(context.expressions);
3653                         let condition = self.parse_general_expression(
3654                             lexer,
3655                             context.as_expression(block, &mut emitter),
3656                         )?;
3657                         block.extend(emitter.finish(context.expressions));
3658                         lexer.expect(Token::Paren(')'))?;
3659 
3660                         let accept = self.parse_block(lexer, context.reborrow(), false)?;
3661 
3662                         let mut elsif_stack = Vec::new();
3663                         let mut elseif_span_start = lexer.current_byte_offset();
3664                         let mut reject = loop {
3665                             if !lexer.skip(Token::Word("else")) {
3666                                 break crate::Block::new();
3667                             }
3668 
3669                             if !lexer.skip(Token::Word("if")) {
3670                                 // ... else { ... }
3671                                 break self.parse_block(lexer, context.reborrow(), false)?;
3672                             }
3673 
3674                             // ... else if (...) { ... }
3675                             let mut sub_emitter = super::Emitter::default();
3676 
3677                             lexer.expect(Token::Paren('('))?;
3678                             sub_emitter.start(context.expressions);
3679                             let other_condition = self.parse_general_expression(
3680                                 lexer,
3681                                 context.as_expression(block, &mut sub_emitter),
3682                             )?;
3683                             let other_emit = sub_emitter.finish(context.expressions);
3684                             lexer.expect(Token::Paren(')'))?;
3685                             let other_block = self.parse_block(lexer, context.reborrow(), false)?;
3686                             elsif_stack.push((
3687                                 elseif_span_start,
3688                                 other_condition,
3689                                 other_emit,
3690                                 other_block,
3691                             ));
3692                             elseif_span_start = lexer.current_byte_offset();
3693                         };
3694 
3695                         let span_end = lexer.current_byte_offset();
3696                         // reverse-fold the else-if blocks
3697                         //Note: we may consider uplifting this to the IR
3698                         for (other_span_start, other_cond, other_emit, other_block) in
3699                             elsif_stack.into_iter().rev()
3700                         {
3701                             let sub_stmt = crate::Statement::If {
3702                                 condition: other_cond,
3703                                 accept: other_block,
3704                                 reject,
3705                             };
3706                             reject = crate::Block::new();
3707                             reject.extend(other_emit);
3708                             reject.push(sub_stmt, NagaSpan::from(other_span_start..span_end))
3709                         }
3710 
3711                         Some(crate::Statement::If {
3712                             condition,
3713                             accept,
3714                             reject,
3715                         })
3716                     }
3717                     "switch" => {
3718                         let _ = lexer.next();
3719                         emitter.start(context.expressions);
3720                         lexer.expect(Token::Paren('('))?;
3721                         let selector = self.parse_general_expression(
3722                             lexer,
3723                             context.as_expression(block, &mut emitter),
3724                         )?;
3725                         let uint = Some(crate::ScalarKind::Uint)
3726                             == context
3727                                 .as_expression(block, &mut emitter)
3728                                 .resolve_type(selector)?
3729                                 .scalar_kind();
3730                         lexer.expect(Token::Paren(')'))?;
3731                         block.extend(emitter.finish(context.expressions));
3732                         lexer.expect(Token::Paren('{'))?;
3733                         let mut cases = Vec::new();
3734 
3735                         loop {
3736                             // cases + default
3737                             match lexer.next() {
3738                                 (Token::Word("case"), _) => {
3739                                     // parse a list of values
3740                                     let value = loop {
3741                                         let value = Self::parse_switch_value(lexer, uint)?;
3742                                         if lexer.skip(Token::Separator(',')) {
3743                                             if lexer.skip(Token::Separator(':')) {
3744                                                 break value;
3745                                             }
3746                                         } else {
3747                                             lexer.expect(Token::Separator(':'))?;
3748                                             break value;
3749                                         }
3750                                         cases.push(crate::SwitchCase {
3751                                             value: crate::SwitchValue::Integer(value),
3752                                             body: crate::Block::new(),
3753                                             fall_through: true,
3754                                         });
3755                                     };
3756 
3757                                     let (fall_through, body) =
3758                                         self.parse_switch_case_body(lexer, context.reborrow())?;
3759 
3760                                     cases.push(crate::SwitchCase {
3761                                         value: crate::SwitchValue::Integer(value),
3762                                         body,
3763                                         fall_through,
3764                                     });
3765                                 }
3766                                 (Token::Word("default"), _) => {
3767                                     lexer.expect(Token::Separator(':'))?;
3768                                     let (fall_through, body) =
3769                                         self.parse_switch_case_body(lexer, context.reborrow())?;
3770                                     cases.push(crate::SwitchCase {
3771                                         value: crate::SwitchValue::Default,
3772                                         body,
3773                                         fall_through,
3774                                     });
3775                                 }
3776                                 (Token::Paren('}'), _) => break,
3777                                 other => {
3778                                     return Err(Error::Unexpected(other, ExpectedToken::SwitchItem))
3779                                 }
3780                             }
3781                         }
3782 
3783                         Some(crate::Statement::Switch { selector, cases })
3784                     }
3785                     "loop" => {
3786                         let _ = lexer.next();
3787                         let mut body = crate::Block::new();
3788                         let mut continuing = crate::Block::new();
3789                         lexer.expect(Token::Paren('{'))?;
3790 
3791                         loop {
3792                             if lexer.skip(Token::Word("continuing")) {
3793                                 continuing = self.parse_block(lexer, context.reborrow(), false)?;
3794                                 lexer.expect(Token::Paren('}'))?;
3795                                 break;
3796                             }
3797                             if lexer.skip(Token::Paren('}')) {
3798                                 break;
3799                             }
3800                             self.parse_statement(lexer, context.reborrow(), &mut body, false)?;
3801                         }
3802 
3803                         Some(crate::Statement::Loop { body, continuing })
3804                     }
3805                     "for" => {
3806                         let _ = lexer.next();
3807                         lexer.expect(Token::Paren('('))?;
3808                         if !lexer.skip(Token::Separator(';')) {
3809                             let num_statements = block.len();
3810                             let (_, span) = lexer.capture_span(|lexer| {
3811                                 self.parse_statement(
3812                                     lexer,
3813                                     context.reborrow(),
3814                                     block,
3815                                     is_uniform_control_flow,
3816                                 )
3817                             })?;
3818 
3819                             if block.len() != num_statements {
3820                                 match *block.last().unwrap() {
3821                                     crate::Statement::Store { .. }
3822                                     | crate::Statement::Call { .. } => {}
3823                                     _ => return Err(Error::InvalidForInitializer(span)),
3824                                 }
3825                             }
3826                         };
3827 
3828                         let mut body = crate::Block::new();
3829                         if !lexer.skip(Token::Separator(';')) {
3830                             let (condition, span) = lexer.capture_span(|lexer| {
3831                                 emitter.start(context.expressions);
3832                                 let condition = self.parse_general_expression(
3833                                     lexer,
3834                                     context.as_expression(&mut body, &mut emitter),
3835                                 )?;
3836                                 lexer.expect(Token::Separator(';'))?;
3837                                 body.extend(emitter.finish(context.expressions));
3838                                 Ok(condition)
3839                             })?;
3840                             let mut reject = crate::Block::new();
3841                             reject.push(crate::Statement::Break, NagaSpan::default());
3842                             body.push(
3843                                 crate::Statement::If {
3844                                     condition,
3845                                     accept: crate::Block::new(),
3846                                     reject,
3847                                 },
3848                                 NagaSpan::from(span),
3849                             );
3850                         };
3851 
3852                         let mut continuing = crate::Block::new();
3853                         if !lexer.skip(Token::Paren(')')) {
3854                             match lexer.peek().0 {
3855                                 Token::Word(ident) if context.lookup_ident.get(ident).is_none() => {
3856                                     self.parse_function_statement(
3857                                         lexer,
3858                                         ident,
3859                                         context.as_expression(&mut continuing, &mut emitter),
3860                                     )?
3861                                 }
3862                                 _ => self.parse_assignment_statement(
3863                                     lexer,
3864                                     context.as_expression(&mut continuing, &mut emitter),
3865                                 )?,
3866                             }
3867                             lexer.expect(Token::Paren(')'))?;
3868                         }
3869                         lexer.expect(Token::Paren('{'))?;
3870 
3871                         while !lexer.skip(Token::Paren('}')) {
3872                             self.parse_statement(lexer, context.reborrow(), &mut body, false)?;
3873                         }
3874 
3875                         Some(crate::Statement::Loop { body, continuing })
3876                     }
3877                     "break" => {
3878                         let _ = lexer.next();
3879                         Some(crate::Statement::Break)
3880                     }
3881                     "continue" => {
3882                         let _ = lexer.next();
3883                         Some(crate::Statement::Continue)
3884                     }
3885                     "discard" => {
3886                         let _ = lexer.next();
3887                         Some(crate::Statement::Kill)
3888                     }
3889                     "storageBarrier" => {
3890                         let _ = lexer.next();
3891                         lexer.expect(Token::Paren('('))?;
3892                         lexer.expect(Token::Paren(')'))?;
3893                         Some(crate::Statement::Barrier(crate::Barrier::STORAGE))
3894                     }
3895                     "workgroupBarrier" => {
3896                         let _ = lexer.next();
3897                         lexer.expect(Token::Paren('('))?;
3898                         lexer.expect(Token::Paren(')'))?;
3899                         Some(crate::Statement::Barrier(crate::Barrier::WORK_GROUP))
3900                     }
3901                     "atomicStore" => {
3902                         let _ = lexer.next();
3903                         emitter.start(context.expressions);
3904                         lexer.open_arguments()?;
3905                         let mut expression_ctx = context.as_expression(block, &mut emitter);
3906                         let pointer =
3907                             self.parse_atomic_pointer(lexer, expression_ctx.reborrow())?;
3908                         lexer.expect(Token::Separator(','))?;
3909                         let value = self.parse_general_expression(lexer, expression_ctx)?;
3910                         lexer.close_arguments()?;
3911                         block.extend(emitter.finish(context.expressions));
3912                         Some(crate::Statement::Store { pointer, value })
3913                     }
3914                     "textureStore" => {
3915                         let _ = lexer.next();
3916                         emitter.start(context.expressions);
3917                         lexer.open_arguments()?;
3918                         let (image_name, image_span) = lexer.next_ident_with_span()?;
3919                         let image = context
3920                             .lookup_ident
3921                             .lookup(image_name, image_span.clone())?
3922                             .handle;
3923                         lexer.expect(Token::Separator(','))?;
3924                         let mut expr_context = context.as_expression(block, &mut emitter);
3925                         let arrayed = match *expr_context.resolve_type(image)? {
3926                             crate::TypeInner::Image { arrayed, .. } => arrayed,
3927                             _ => return Err(Error::BadTexture(image_span)),
3928                         };
3929                         let coordinate = self.parse_general_expression(lexer, expr_context)?;
3930                         let array_index = if arrayed {
3931                             lexer.expect(Token::Separator(','))?;
3932                             Some(self.parse_general_expression(
3933                                 lexer,
3934                                 context.as_expression(block, &mut emitter),
3935                             )?)
3936                         } else {
3937                             None
3938                         };
3939                         lexer.expect(Token::Separator(','))?;
3940                         let value = self.parse_general_expression(
3941                             lexer,
3942                             context.as_expression(block, &mut emitter),
3943                         )?;
3944                         lexer.close_arguments()?;
3945                         block.extend(emitter.finish(context.expressions));
3946                         Some(crate::Statement::ImageStore {
3947                             image,
3948                             coordinate,
3949                             array_index,
3950                             value,
3951                         })
3952                     }
3953                     // assignment or a function call
3954                     ident => {
3955                         match context.lookup_ident.get(ident) {
3956                             Some(_) => self.parse_assignment_statement(
3957                                 lexer,
3958                                 context.as_expression(block, &mut emitter),
3959                             )?,
3960                             None => self.parse_function_statement(
3961                                 lexer,
3962                                 ident,
3963                                 context.as_expression(block, &mut emitter),
3964                             )?,
3965                         }
3966                         lexer.expect(Token::Separator(';'))?;
3967                         None
3968                     }
3969                 };
3970                 let span = NagaSpan::from(self.pop_scope(lexer));
3971                 if let Some(statement) = statement {
3972                     block.push(statement, span);
3973                 }
3974             }
3975             _ => {
3976                 let mut emitter = super::Emitter::default();
3977                 self.parse_assignment_statement(lexer, context.as_expression(block, &mut emitter))?;
3978                 self.pop_scope(lexer);
3979             }
3980         }
3981         Ok(())
3982     }
3983 
parse_block<'a>( &mut self, lexer: &mut Lexer<'a>, mut context: StatementContext<'a, '_, '_>, is_uniform_control_flow: bool, ) -> Result<crate::Block, Error<'a>>3984     fn parse_block<'a>(
3985         &mut self,
3986         lexer: &mut Lexer<'a>,
3987         mut context: StatementContext<'a, '_, '_>,
3988         is_uniform_control_flow: bool,
3989     ) -> Result<crate::Block, Error<'a>> {
3990         self.push_scope(Scope::Block, lexer);
3991         lexer.expect(Token::Paren('{'))?;
3992         let mut block = crate::Block::new();
3993         while !lexer.skip(Token::Paren('}')) {
3994             self.parse_statement(
3995                 lexer,
3996                 context.reborrow(),
3997                 &mut block,
3998                 is_uniform_control_flow,
3999             )?;
4000         }
4001         self.pop_scope(lexer);
4002         Ok(block)
4003     }
4004 
parse_varying_binding<'a>( &mut self, lexer: &mut Lexer<'a>, ) -> Result<Option<crate::Binding>, Error<'a>>4005     fn parse_varying_binding<'a>(
4006         &mut self,
4007         lexer: &mut Lexer<'a>,
4008     ) -> Result<Option<crate::Binding>, Error<'a>> {
4009         self.push_scope(Scope::Attribute, lexer);
4010 
4011         if !lexer.skip(Token::DoubleParen('[')) {
4012             self.pop_scope(lexer);
4013             return Ok(None);
4014         }
4015 
4016         let mut bind_parser = BindingParser::default();
4017         loop {
4018             let (word, span) = lexer.next_ident_with_span()?;
4019             bind_parser.parse(lexer, word, span)?;
4020             match lexer.next() {
4021                 (Token::DoubleParen(']'), _) => {
4022                     break;
4023                 }
4024                 (Token::Separator(','), _) => {}
4025                 other => return Err(Error::Unexpected(other, ExpectedToken::AttributeSeparator)),
4026             }
4027         }
4028 
4029         let span = self.pop_scope(lexer);
4030         bind_parser.finish(span)
4031     }
4032 
parse_function_decl<'a>( &mut self, lexer: &mut Lexer<'a>, module: &mut crate::Module, lookup_global_expression: &FastHashMap<&'a str, crate::Expression>, ) -> Result<(crate::Function, &'a str), Error<'a>>4033     fn parse_function_decl<'a>(
4034         &mut self,
4035         lexer: &mut Lexer<'a>,
4036         module: &mut crate::Module,
4037         lookup_global_expression: &FastHashMap<&'a str, crate::Expression>,
4038     ) -> Result<(crate::Function, &'a str), Error<'a>> {
4039         self.push_scope(Scope::FunctionDecl, lexer);
4040         // read function name
4041         let mut lookup_ident = FastHashMap::default();
4042         let (fun_name, span) = lexer.next_ident_with_span()?;
4043         if crate::keywords::wgsl::RESERVED.contains(&fun_name) {
4044             return Err(Error::ReservedKeyword(span));
4045         }
4046         if let Some(entry) = self
4047             .module_scope_identifiers
4048             .insert(String::from(fun_name), span.clone())
4049         {
4050             return Err(Error::Redefinition {
4051                 previous: entry,
4052                 current: span,
4053             });
4054         }
4055         // populate initial expressions
4056         let mut expressions = Arena::new();
4057         for (&name, expression) in lookup_global_expression.iter() {
4058             let (span, is_reference) = match *expression {
4059                 crate::Expression::GlobalVariable(handle) => (
4060                     module.global_variables.get_span(handle),
4061                     module.global_variables[handle].class != crate::StorageClass::Handle,
4062                 ),
4063                 crate::Expression::Constant(handle) => (module.constants.get_span(handle), false),
4064                 _ => unreachable!(),
4065             };
4066             let expression = expressions.append(expression.clone(), span);
4067             lookup_ident.insert(
4068                 name,
4069                 TypedExpression {
4070                     handle: expression,
4071                     is_reference,
4072                 },
4073             );
4074         }
4075         // read parameter list
4076         let mut arguments = Vec::new();
4077         lexer.expect(Token::Paren('('))?;
4078         let mut ready = true;
4079         while !lexer.skip(Token::Paren(')')) {
4080             if !ready {
4081                 return Err(Error::Unexpected(
4082                     lexer.next(),
4083                     ExpectedToken::Token(Token::Separator(',')),
4084                 ));
4085             }
4086             let mut binding = self.parse_varying_binding(lexer)?;
4087             let (param_name, param_name_span, param_type, _access) =
4088                 self.parse_variable_ident_decl(lexer, &mut module.types, &mut module.constants)?;
4089             if crate::keywords::wgsl::RESERVED.contains(&param_name) {
4090                 return Err(Error::ReservedKeyword(param_name_span));
4091             }
4092             let param_index = arguments.len() as u32;
4093             let expression = expressions.append(
4094                 crate::Expression::FunctionArgument(param_index),
4095                 NagaSpan::from(param_name_span),
4096             );
4097             lookup_ident.insert(
4098                 param_name,
4099                 TypedExpression {
4100                     handle: expression,
4101                     is_reference: false,
4102                 },
4103             );
4104             if let Some(ref mut binding) = binding {
4105                 binding.apply_default_interpolation(&module.types[param_type].inner);
4106             }
4107             arguments.push(crate::FunctionArgument {
4108                 name: Some(param_name.to_string()),
4109                 ty: param_type,
4110                 binding,
4111             });
4112             ready = lexer.skip(Token::Separator(','));
4113         }
4114         // read return type
4115         let result = if lexer.skip(Token::Arrow) && !lexer.skip(Token::Word("void")) {
4116             let mut binding = self.parse_varying_binding(lexer)?;
4117             let (ty, _access) =
4118                 self.parse_type_decl(lexer, None, &mut module.types, &mut module.constants)?;
4119             if let Some(ref mut binding) = binding {
4120                 binding.apply_default_interpolation(&module.types[ty].inner);
4121             }
4122             Some(crate::FunctionResult { ty, binding })
4123         } else {
4124             None
4125         };
4126 
4127         let mut fun = crate::Function {
4128             name: Some(fun_name.to_string()),
4129             arguments,
4130             result,
4131             local_variables: Arena::new(),
4132             expressions,
4133             named_expressions: crate::NamedExpressions::default(),
4134             body: crate::Block::new(),
4135         };
4136 
4137         // read body
4138         let mut typifier = super::Typifier::new();
4139         let mut named_expressions = crate::FastHashMap::default();
4140         fun.body = self.parse_block(
4141             lexer,
4142             StatementContext {
4143                 lookup_ident: &mut lookup_ident,
4144                 typifier: &mut typifier,
4145                 variables: &mut fun.local_variables,
4146                 expressions: &mut fun.expressions,
4147                 named_expressions: &mut named_expressions,
4148                 types: &mut module.types,
4149                 constants: &mut module.constants,
4150                 global_vars: &module.global_variables,
4151                 functions: &module.functions,
4152                 arguments: &fun.arguments,
4153             },
4154             true,
4155         )?;
4156         // fixup the IR
4157         ensure_block_returns(&mut fun.body);
4158         // done
4159         self.pop_scope(lexer);
4160 
4161         // Set named expressions after block parsing ends
4162         fun.named_expressions = named_expressions;
4163 
4164         Ok((fun, fun_name))
4165     }
4166 
parse_global_decl<'a>( &mut self, lexer: &mut Lexer<'a>, module: &mut crate::Module, lookup_global_expression: &mut FastHashMap<&'a str, crate::Expression>, ) -> Result<bool, Error<'a>>4167     fn parse_global_decl<'a>(
4168         &mut self,
4169         lexer: &mut Lexer<'a>,
4170         module: &mut crate::Module,
4171         lookup_global_expression: &mut FastHashMap<&'a str, crate::Expression>,
4172     ) -> Result<bool, Error<'a>> {
4173         // read attributes
4174         let mut binding = None;
4175         // Perspective is the default qualifier.
4176         let mut stage = None;
4177         let mut workgroup_size = [0u32; 3];
4178         let mut early_depth_test = None;
4179 
4180         if lexer.skip(Token::DoubleParen('[')) {
4181             let (mut bind_index, mut bind_group) = (None, None);
4182             self.push_scope(Scope::Attribute, lexer);
4183             loop {
4184                 match lexer.next_ident_with_span()? {
4185                     ("binding", _) => {
4186                         lexer.expect(Token::Paren('('))?;
4187                         bind_index = Some(parse_non_negative_sint_literal(lexer, 4)?);
4188                         lexer.expect(Token::Paren(')'))?;
4189                     }
4190                     ("group", _) => {
4191                         lexer.expect(Token::Paren('('))?;
4192                         bind_group = Some(parse_non_negative_sint_literal(lexer, 4)?);
4193                         lexer.expect(Token::Paren(')'))?;
4194                     }
4195                     ("stage", _) => {
4196                         lexer.expect(Token::Paren('('))?;
4197                         let (ident, ident_span) = lexer.next_ident_with_span()?;
4198                         stage = Some(conv::map_shader_stage(ident, ident_span)?);
4199                         lexer.expect(Token::Paren(')'))?;
4200                     }
4201                     ("workgroup_size", _) => {
4202                         lexer.expect(Token::Paren('('))?;
4203                         for (i, size) in workgroup_size.iter_mut().enumerate() {
4204                             *size = parse_generic_non_negative_int_literal(lexer, 4)?;
4205                             match lexer.next() {
4206                                 (Token::Paren(')'), _) => break,
4207                                 (Token::Separator(','), _) if i != 2 => (),
4208                                 other => {
4209                                     return Err(Error::Unexpected(
4210                                         other,
4211                                         ExpectedToken::WorkgroupSizeSeparator,
4212                                     ))
4213                                 }
4214                             }
4215                         }
4216                         for size in workgroup_size.iter_mut() {
4217                             if *size == 0 {
4218                                 *size = 1;
4219                             }
4220                         }
4221                     }
4222                     ("early_depth_test", _) => {
4223                         let conservative = if lexer.skip(Token::Paren('(')) {
4224                             let (ident, ident_span) = lexer.next_ident_with_span()?;
4225                             let value = conv::map_conservative_depth(ident, ident_span)?;
4226                             lexer.expect(Token::Paren(')'))?;
4227                             Some(value)
4228                         } else {
4229                             None
4230                         };
4231                         early_depth_test = Some(crate::EarlyDepthTest { conservative });
4232                     }
4233                     (_, word_span) => return Err(Error::UnknownAttribute(word_span)),
4234                 }
4235                 match lexer.next() {
4236                     (Token::DoubleParen(']'), _) => {
4237                         break;
4238                     }
4239                     (Token::Separator(','), _) => {}
4240                     other => {
4241                         return Err(Error::Unexpected(other, ExpectedToken::AttributeSeparator))
4242                     }
4243                 }
4244             }
4245             if let (Some(group), Some(index)) = (bind_group, bind_index) {
4246                 binding = Some(crate::ResourceBinding {
4247                     group,
4248                     binding: index,
4249                 });
4250             }
4251             self.pop_scope(lexer);
4252         }
4253 
4254         // read items
4255         let start = lexer.current_byte_offset();
4256         match lexer.next() {
4257             (Token::Separator(';'), _) => {}
4258             (Token::Word("struct"), _) => {
4259                 let (name, span) = lexer.next_ident_with_span()?;
4260                 if crate::keywords::wgsl::RESERVED.contains(&name) {
4261                     return Err(Error::ReservedKeyword(span));
4262                 }
4263                 let (members, span) =
4264                     self.parse_struct_body(lexer, &mut module.types, &mut module.constants)?;
4265                 let type_span = NagaSpan::from(lexer.span_from(start));
4266                 let ty = module.types.insert(
4267                     crate::Type {
4268                         name: Some(name.to_string()),
4269                         inner: crate::TypeInner::Struct { members, span },
4270                     },
4271                     type_span,
4272                 );
4273                 self.lookup_type.insert(name.to_owned(), ty);
4274                 lexer.expect(Token::Separator(';'))?;
4275             }
4276             (Token::Word("type"), _) => {
4277                 let name = lexer.next_ident()?;
4278                 lexer.expect(Token::Operation('='))?;
4279                 let (ty, _access) = self.parse_type_decl(
4280                     lexer,
4281                     Some(name),
4282                     &mut module.types,
4283                     &mut module.constants,
4284                 )?;
4285                 self.lookup_type.insert(name.to_owned(), ty);
4286                 lexer.expect(Token::Separator(';'))?;
4287             }
4288             (Token::Word("let"), _) => {
4289                 let (name, name_span) = lexer.next_ident_with_span()?;
4290                 if crate::keywords::wgsl::RESERVED.contains(&name) {
4291                     return Err(Error::ReservedKeyword(name_span));
4292                 }
4293                 if let Some(entry) = self
4294                     .module_scope_identifiers
4295                     .insert(String::from(name), name_span.clone())
4296                 {
4297                     return Err(Error::Redefinition {
4298                         previous: entry,
4299                         current: name_span,
4300                     });
4301                 }
4302                 let given_ty = if lexer.skip(Token::Separator(':')) {
4303                     let (ty, _access) = self.parse_type_decl(
4304                         lexer,
4305                         None,
4306                         &mut module.types,
4307                         &mut module.constants,
4308                     )?;
4309                     Some(ty)
4310                 } else {
4311                     None
4312                 };
4313 
4314                 lexer.expect(Token::Operation('='))?;
4315                 let first_token_span = lexer.next();
4316                 let const_handle = self.parse_const_expression_impl(
4317                     first_token_span,
4318                     lexer,
4319                     Some(name),
4320                     &mut module.types,
4321                     &mut module.constants,
4322                 )?;
4323 
4324                 if let Some(explicit_ty) = given_ty {
4325                     let con = &module.constants[const_handle];
4326                     let type_match = match con.inner {
4327                         crate::ConstantInner::Scalar { width, value } => {
4328                             module.types[explicit_ty].inner
4329                                 == crate::TypeInner::Scalar {
4330                                     kind: value.scalar_kind(),
4331                                     width,
4332                                 }
4333                         }
4334                         crate::ConstantInner::Composite { ty, components: _ } => ty == explicit_ty,
4335                     };
4336                     if !type_match {
4337                         let exptected_inner_str = match con.inner {
4338                             crate::ConstantInner::Scalar { width, value } => {
4339                                 crate::TypeInner::Scalar {
4340                                     kind: value.scalar_kind(),
4341                                     width,
4342                                 }
4343                                 .to_wgsl(&module.types, &module.constants)
4344                             }
4345                             crate::ConstantInner::Composite { .. } => module.types[explicit_ty]
4346                                 .inner
4347                                 .to_wgsl(&module.types, &module.constants),
4348                         };
4349                         return Err(Error::InitializationTypeMismatch(
4350                             name_span,
4351                             exptected_inner_str,
4352                         ));
4353                     }
4354                 }
4355 
4356                 lexer.expect(Token::Separator(';'))?;
4357                 lookup_global_expression.insert(name, crate::Expression::Constant(const_handle));
4358             }
4359             (Token::Word("var"), _) => {
4360                 let pvar =
4361                     self.parse_variable_decl(lexer, &mut module.types, &mut module.constants)?;
4362                 if crate::keywords::wgsl::RESERVED.contains(&pvar.name) {
4363                     return Err(Error::ReservedKeyword(pvar.name_span));
4364                 }
4365                 if let Some(entry) = self
4366                     .module_scope_identifiers
4367                     .insert(String::from(pvar.name), pvar.name_span.clone())
4368                 {
4369                     return Err(Error::Redefinition {
4370                         previous: entry,
4371                         current: pvar.name_span,
4372                     });
4373                 }
4374                 let var_handle = module.global_variables.append(
4375                     crate::GlobalVariable {
4376                         name: Some(pvar.name.to_owned()),
4377                         class: pvar.class.unwrap_or(crate::StorageClass::Handle),
4378                         binding: binding.take(),
4379                         ty: pvar.ty,
4380                         init: pvar.init,
4381                     },
4382                     NagaSpan::from(pvar.name_span),
4383                 );
4384                 lookup_global_expression
4385                     .insert(pvar.name, crate::Expression::GlobalVariable(var_handle));
4386             }
4387             (Token::Word("fn"), _) => {
4388                 let (function, name) =
4389                     self.parse_function_decl(lexer, module, lookup_global_expression)?;
4390                 match stage {
4391                     Some(stage) => module.entry_points.push(crate::EntryPoint {
4392                         name: name.to_string(),
4393                         stage,
4394                         early_depth_test,
4395                         workgroup_size,
4396                         function,
4397                     }),
4398                     None => {
4399                         module
4400                             .functions
4401                             .append(function, NagaSpan::from(lexer.span_from(start)));
4402                     }
4403                 }
4404             }
4405             (Token::End, _) => return Ok(false),
4406             other => return Err(Error::Unexpected(other, ExpectedToken::GlobalItem)),
4407         }
4408 
4409         match binding {
4410             None => Ok(true),
4411             // we had the attribute but no var?
4412             Some(_) => Err(Error::Other),
4413         }
4414     }
4415 
parse(&mut self, source: &str) -> Result<crate::Module, ParseError>4416     pub fn parse(&mut self, source: &str) -> Result<crate::Module, ParseError> {
4417         self.scopes.clear();
4418         self.lookup_type.clear();
4419         self.layouter.clear();
4420 
4421         let mut module = crate::Module::default();
4422         let mut lexer = Lexer::new(source);
4423         let mut lookup_global_expression = FastHashMap::default();
4424         loop {
4425             match self.parse_global_decl(&mut lexer, &mut module, &mut lookup_global_expression) {
4426                 Err(error) => return Err(error.as_parse_error(lexer.source)),
4427                 Ok(true) => {}
4428                 Ok(false) => {
4429                     if !self.scopes.is_empty() {
4430                         log::error!("Reached the end of file, but scopes are not closed");
4431                         return Err(Error::Other.as_parse_error(lexer.source));
4432                     };
4433                     return Ok(module);
4434                 }
4435             }
4436         }
4437     }
4438 }
4439 
parse_str(source: &str) -> Result<crate::Module, ParseError>4440 pub fn parse_str(source: &str) -> Result<crate::Module, ParseError> {
4441     Parser::new().parse(source)
4442 }
4443 
4444 pub struct StringErrorBuffer {
4445     buf: Vec<u8>,
4446 }
4447 
4448 impl StringErrorBuffer {
new() -> Self4449     pub fn new() -> Self {
4450         Self { buf: Vec::new() }
4451     }
4452 
into_string(self) -> String4453     pub fn into_string(self) -> String {
4454         String::from_utf8(self.buf).unwrap()
4455     }
4456 }
4457 
4458 impl Write for StringErrorBuffer {
write(&mut self, buf: &[u8]) -> io::Result<usize>4459     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4460         self.buf.extend(buf);
4461         Ok(buf.len())
4462     }
4463 
flush(&mut self) -> io::Result<()>4464     fn flush(&mut self) -> io::Result<()> {
4465         Ok(())
4466     }
4467 }
4468 
4469 impl WriteColor for StringErrorBuffer {
supports_color(&self) -> bool4470     fn supports_color(&self) -> bool {
4471         false
4472     }
4473 
set_color(&mut self, _spec: &ColorSpec) -> io::Result<()>4474     fn set_color(&mut self, _spec: &ColorSpec) -> io::Result<()> {
4475         Ok(())
4476     }
4477 
reset(&mut self) -> io::Result<()>4478     fn reset(&mut self) -> io::Result<()> {
4479         Ok(())
4480     }
4481 }
4482