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(¶m_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