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 layout;
7 mod lexer;
8 #[cfg(test)]
9 mod tests;
10
11 use crate::{
12 arena::{Arena, Handle},
13 proc::{ensure_block_returns, ResolveContext, ResolveError, TypeResolution},
14 FastHashMap,
15 };
16
17 use self::lexer::Lexer;
18 use codespan_reporting::{
19 diagnostic::{Diagnostic, Label},
20 files::{Files, SimpleFile},
21 term::{
22 self,
23 termcolor::{ColorChoice, ColorSpec, StandardStream, WriteColor},
24 },
25 };
26 use std::{
27 io::{self, Write},
28 iter,
29 num::NonZeroU32,
30 ops,
31 };
32 use thiserror::Error;
33
34 type Span = ops::Range<usize>;
35 type TokenSpan<'a> = (Token<'a>, Span);
36
37 #[derive(Copy, Clone, Debug, PartialEq)]
38 pub enum Token<'a> {
39 Separator(char),
40 DoubleColon,
41 Paren(char),
42 DoubleParen(char),
43 Number {
44 value: &'a str,
45 ty: char,
46 width: &'a str,
47 },
48 String(&'a str),
49 Word(&'a str),
50 Operation(char),
51 LogicalOperation(char),
52 ShiftOperation(char),
53 Arrow,
54 Unknown(char),
55 UnterminatedString,
56 Trivia,
57 End,
58 }
59
60 #[derive(Clone, Debug, Error)]
61 pub enum Error<'a> {
62 #[error("")]
63 Unexpected(TokenSpan<'a>, &'a str),
64 #[error("")]
65 BadInteger(Span),
66 #[error("")]
67 BadFloat(Span),
68 #[error("")]
69 BadScalarWidth(Span, &'a str),
70 #[error("")]
71 BadAccessor(Span),
72 #[error("bad texture {0}`")]
73 BadTexture(&'a str),
74 #[error("bad texture coordinate")]
75 BadCoordinate,
76 #[error("invalid type cast to `{0}`")]
77 BadTypeCast(&'a str),
78 #[error(transparent)]
79 InvalidResolve(ResolveError),
80 #[error("for(;;) initializer is not an assignment or a function call")]
81 InvalidForInitializer,
82 #[error("resource type {0:?} is invalid")]
83 InvalidResourceType(Handle<crate::Type>),
84 #[error("unknown import: `{0}`")]
85 UnknownImport(&'a str),
86 #[error("unknown storage class: `{0}`")]
87 UnknownStorageClass(&'a str),
88 #[error("unknown attribute: `{0}`")]
89 UnknownAttribute(&'a str),
90 #[error("unknown scalar kind: `{0}`")]
91 UnknownScalarKind(&'a str),
92 #[error("unknown builtin: `{0}`")]
93 UnknownBuiltin(&'a str),
94 #[error("unknown access: `{0}`")]
95 UnknownAccess(&'a str),
96 #[error("unknown shader stage: `{0}`")]
97 UnknownShaderStage(&'a str),
98 #[error("unknown identifier: `{0}`")]
99 UnknownIdent(&'a str),
100 #[error("unknown scalar type: `{0}`")]
101 UnknownScalarType(&'a str),
102 #[error("unknown type: `{0}`")]
103 UnknownType(&'a str),
104 #[error("unknown function: `{0}`")]
105 UnknownFunction(&'a str),
106 #[error("unknown storage format: `{0}`")]
107 UnknownStorageFormat(&'a str),
108 #[error("unknown conservative depth: `{0}`")]
109 UnknownConservativeDepth(&'a str),
110 #[error("array stride must not be 0")]
111 ZeroStride,
112 #[error("struct member size or array must not be 0")]
113 ZeroSizeOrAlign,
114 #[error("not a composite type: {0:?}")]
115 NotCompositeType(Handle<crate::Type>),
116 #[error("Input/output binding is not consistent: location {0:?}, built-in {1:?}, interpolation {2:?}, and sampling {3:?}")]
117 InconsistentBinding(
118 Option<u32>,
119 Option<crate::BuiltIn>,
120 Option<crate::Interpolation>,
121 Option<crate::Sampling>,
122 ),
123 #[error("call to local `{0}(..)` can't be resolved")]
124 UnknownLocalFunction(&'a str),
125 #[error("builtin {0:?} is not implemented")]
126 UnimplementedBuiltin(crate::BuiltIn),
127 #[error("expression {0} doesn't match its given type {1:?}")]
128 LetTypeMismatch(&'a str, Handle<crate::Type>),
129 #[error("other error")]
130 Other,
131 }
132
133 impl<'a> Error<'a> {
as_parse_error(&self, source: &'a str) -> ParseError134 fn as_parse_error(&self, source: &'a str) -> ParseError {
135 match *self {
136 Error::Unexpected((_, ref unexpected_span), expected) => ParseError {
137 message: format!(
138 "expected {}, found '{}'",
139 expected,
140 &source[unexpected_span.clone()],
141 ),
142 labels: vec![(unexpected_span.clone(), format!("expected {}", expected))],
143 notes: vec![],
144 },
145 Error::BadInteger(ref bad_span) => ParseError {
146 message: format!(
147 "expected integer literal, found `{}`",
148 &source[bad_span.clone()],
149 ),
150 labels: vec![(bad_span.clone(), "expected integer".to_string())],
151 notes: vec![],
152 },
153 Error::BadFloat(ref bad_span) => ParseError {
154 message: format!(
155 "expected floating-point literal, found `{}`",
156 &source[bad_span.clone()],
157 ),
158 labels: vec![(
159 bad_span.clone(),
160 "expected floating-point literal".to_string(),
161 )],
162 notes: vec![],
163 },
164 Error::BadScalarWidth(ref bad_span, width) => ParseError {
165 message: format!("invalid width of `{}` for literal", width,),
166 labels: vec![(bad_span.clone(), "invalid width".to_string())],
167 notes: vec!["valid width is 32".to_string()],
168 },
169 Error::BadAccessor(ref accessor_span) => ParseError {
170 message: format!(
171 "invalid field accessor `{}`",
172 &source[accessor_span.clone()],
173 ),
174 labels: vec![(accessor_span.clone(), "invalid accessor".to_string())],
175 notes: vec![],
176 },
177 ref error => ParseError {
178 message: error.to_string(),
179 labels: vec![],
180 notes: vec![],
181 },
182 }
183 }
184 }
185
186 trait StringValueLookup<'a> {
187 type Value;
lookup(&self, key: &'a str) -> Result<Self::Value, Error<'a>>188 fn lookup(&self, key: &'a str) -> Result<Self::Value, Error<'a>>;
189 }
190 impl<'a> StringValueLookup<'a> for FastHashMap<&'a str, Handle<crate::Expression>> {
191 type Value = Handle<crate::Expression>;
lookup(&self, key: &'a str) -> Result<Self::Value, Error<'a>>192 fn lookup(&self, key: &'a str) -> Result<Self::Value, Error<'a>> {
193 self.get(key).cloned().ok_or(Error::UnknownIdent(key))
194 }
195 }
196
197 struct StatementContext<'input, 'temp, 'out> {
198 lookup_ident: &'temp mut FastHashMap<&'input str, Handle<crate::Expression>>,
199 typifier: &'temp mut super::Typifier,
200 variables: &'out mut Arena<crate::LocalVariable>,
201 expressions: &'out mut Arena<crate::Expression>,
202 types: &'out mut Arena<crate::Type>,
203 constants: &'out mut Arena<crate::Constant>,
204 global_vars: &'out Arena<crate::GlobalVariable>,
205 functions: &'out Arena<crate::Function>,
206 arguments: &'out [crate::FunctionArgument],
207 }
208
209 impl<'a, 'temp> StatementContext<'a, 'temp, '_> {
reborrow(&mut self) -> StatementContext<'a, '_, '_>210 fn reborrow(&mut self) -> StatementContext<'a, '_, '_> {
211 StatementContext {
212 lookup_ident: self.lookup_ident,
213 typifier: self.typifier,
214 variables: self.variables,
215 expressions: self.expressions,
216 types: self.types,
217 constants: self.constants,
218 global_vars: self.global_vars,
219 functions: self.functions,
220 arguments: self.arguments,
221 }
222 }
223
as_expression<'t>( &'t mut self, block: &'t mut crate::Block, emitter: &'t mut super::Emitter, ) -> ExpressionContext<'a, 't, '_> where 'temp: 't,224 fn as_expression<'t>(
225 &'t mut self,
226 block: &'t mut crate::Block,
227 emitter: &'t mut super::Emitter,
228 ) -> ExpressionContext<'a, 't, '_>
229 where
230 'temp: 't,
231 {
232 ExpressionContext {
233 lookup_ident: self.lookup_ident,
234 typifier: self.typifier,
235 expressions: self.expressions,
236 types: self.types,
237 constants: self.constants,
238 global_vars: self.global_vars,
239 local_vars: self.variables,
240 functions: self.functions,
241 arguments: self.arguments,
242 block,
243 emitter,
244 }
245 }
246 }
247
248 struct SamplingContext {
249 image: Handle<crate::Expression>,
250 arrayed: bool,
251 }
252
253 struct ExpressionContext<'input, 'temp, 'out> {
254 lookup_ident: &'temp FastHashMap<&'input str, Handle<crate::Expression>>,
255 typifier: &'temp mut super::Typifier,
256 expressions: &'out mut Arena<crate::Expression>,
257 types: &'out mut Arena<crate::Type>,
258 constants: &'out mut Arena<crate::Constant>,
259 global_vars: &'out Arena<crate::GlobalVariable>,
260 local_vars: &'out Arena<crate::LocalVariable>,
261 arguments: &'out [crate::FunctionArgument],
262 functions: &'out Arena<crate::Function>,
263 block: &'temp mut crate::Block,
264 emitter: &'temp mut super::Emitter,
265 }
266
267 impl<'a> ExpressionContext<'a, '_, '_> {
reborrow(&mut self) -> ExpressionContext<'a, '_, '_>268 fn reborrow(&mut self) -> ExpressionContext<'a, '_, '_> {
269 ExpressionContext {
270 lookup_ident: self.lookup_ident,
271 typifier: self.typifier,
272 expressions: self.expressions,
273 types: self.types,
274 constants: self.constants,
275 global_vars: self.global_vars,
276 local_vars: self.local_vars,
277 functions: self.functions,
278 arguments: self.arguments,
279 block: self.block,
280 emitter: self.emitter,
281 }
282 }
283
resolve_type( &mut self, handle: Handle<crate::Expression>, ) -> Result<&crate::TypeInner, Error<'a>>284 fn resolve_type(
285 &mut self,
286 handle: Handle<crate::Expression>,
287 ) -> Result<&crate::TypeInner, Error<'a>> {
288 let resolve_ctx = ResolveContext {
289 constants: self.constants,
290 global_vars: self.global_vars,
291 local_vars: self.local_vars,
292 functions: self.functions,
293 arguments: self.arguments,
294 };
295 match self
296 .typifier
297 .grow(handle, self.expressions, self.types, &resolve_ctx)
298 {
299 Err(e) => Err(Error::InvalidResolve(e)),
300 Ok(()) => Ok(self.typifier.get(handle, self.types)),
301 }
302 }
303
prepare_sampling(&mut self, image_name: &'a str) -> Result<SamplingContext, Error<'a>>304 fn prepare_sampling(&mut self, image_name: &'a str) -> Result<SamplingContext, Error<'a>> {
305 let image = self.lookup_ident.lookup(image_name)?;
306 Ok(SamplingContext {
307 image,
308 arrayed: match *self.resolve_type(image)? {
309 crate::TypeInner::Image { arrayed, .. } => arrayed,
310 _ => return Err(Error::BadTexture(image_name)),
311 },
312 })
313 }
314
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<Handle<crate::Expression>, Error<'a>>, ) -> Result<Handle<crate::Expression>, Error<'a>>315 fn parse_binary_op(
316 &mut self,
317 lexer: &mut Lexer<'a>,
318 classifier: impl Fn(Token<'a>) -> Option<crate::BinaryOperator>,
319 mut parser: impl FnMut(
320 &mut Lexer<'a>,
321 ExpressionContext<'a, '_, '_>,
322 ) -> Result<Handle<crate::Expression>, Error<'a>>,
323 ) -> Result<Handle<crate::Expression>, Error<'a>> {
324 let mut left = parser(lexer, self.reborrow())?;
325 while let Some(op) = classifier(lexer.peek().0) {
326 let _ = lexer.next();
327 let right = parser(lexer, self.reborrow())?;
328 left = self
329 .expressions
330 .append(crate::Expression::Binary { op, left, right });
331 }
332 Ok(left)
333 }
334
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<Handle<crate::Expression>, Error<'a>>, ) -> Result<Handle<crate::Expression>, Error<'a>>335 fn parse_binary_splat_op(
336 &mut self,
337 lexer: &mut Lexer<'a>,
338 classifier: impl Fn(Token<'a>) -> Option<crate::BinaryOperator>,
339 mut parser: impl FnMut(
340 &mut Lexer<'a>,
341 ExpressionContext<'a, '_, '_>,
342 ) -> Result<Handle<crate::Expression>, Error<'a>>,
343 ) -> Result<Handle<crate::Expression>, Error<'a>> {
344 let mut left = parser(lexer, self.reborrow())?;
345 while let Some(op) = classifier(lexer.peek().0) {
346 let _ = lexer.next();
347 let mut right = parser(lexer, self.reborrow())?;
348 // insert splats, if needed by the non-'*' operations
349 if op != crate::BinaryOperator::Multiply {
350 let left_size = match *self.resolve_type(left)? {
351 crate::TypeInner::Vector { size, .. } => Some(size),
352 _ => None,
353 };
354 match (left_size, self.resolve_type(right)?) {
355 (Some(size), &crate::TypeInner::Scalar { .. }) => {
356 right = self
357 .expressions
358 .append(crate::Expression::Splat { size, value: right });
359 }
360 (None, &crate::TypeInner::Vector { size, .. }) => {
361 left = self
362 .expressions
363 .append(crate::Expression::Splat { size, value: left });
364 }
365 _ => {}
366 }
367 }
368 left = self
369 .expressions
370 .append(crate::Expression::Binary { op, left, right });
371 }
372 Ok(left)
373 }
374 }
375
376 enum Composition {
377 Single(u32),
378 Multi(crate::VectorSize, [crate::SwizzleComponent; 4]),
379 }
380
381 impl Composition {
382 //TODO: could be `const fn` once MSRV allows
letter_component(letter: char) -> Option<crate::SwizzleComponent>383 fn letter_component(letter: char) -> Option<crate::SwizzleComponent> {
384 use crate::SwizzleComponent as Sc;
385 match letter {
386 'x' | 'r' => Some(Sc::X),
387 'y' | 'g' => Some(Sc::Y),
388 'z' | 'b' => Some(Sc::Z),
389 'w' | 'a' => Some(Sc::W),
390 _ => None,
391 }
392 }
393
extract_impl(name: &str, name_span: Span) -> Result<u32, Error>394 fn extract_impl(name: &str, name_span: Span) -> Result<u32, Error> {
395 let ch = name
396 .chars()
397 .next()
398 .ok_or_else(|| Error::BadAccessor(name_span.clone()))?;
399 match Self::letter_component(ch) {
400 Some(sc) => Ok(sc as u32),
401 None => Err(Error::BadAccessor(name_span)),
402 }
403 }
404
extract( base: Handle<crate::Expression>, name: &str, name_span: Span, ) -> Result<crate::Expression, Error>405 fn extract(
406 base: Handle<crate::Expression>,
407 name: &str,
408 name_span: Span,
409 ) -> Result<crate::Expression, Error> {
410 Self::extract_impl(name, name_span)
411 .map(|index| crate::Expression::AccessIndex { base, index })
412 }
413
make(name: &str, name_span: Span) -> Result<Self, Error>414 fn make(name: &str, name_span: Span) -> Result<Self, Error> {
415 if name.len() > 1 {
416 let mut components = [crate::SwizzleComponent::X; 4];
417 for (comp, ch) in components.iter_mut().zip(name.chars()) {
418 *comp = Self::letter_component(ch)
419 .ok_or_else(|| Error::BadAccessor(name_span.clone()))?;
420 }
421
422 let size = match name.len() {
423 2 => crate::VectorSize::Bi,
424 3 => crate::VectorSize::Tri,
425 4 => crate::VectorSize::Quad,
426 _ => return Err(Error::BadAccessor(name_span)),
427 };
428 Ok(Composition::Multi(size, components))
429 } else {
430 Self::extract_impl(name, name_span).map(Composition::Single)
431 }
432 }
433 }
434
435 #[derive(Default)]
436 struct TypeAttributes {
437 stride: Option<NonZeroU32>,
438 access: crate::StorageAccess,
439 }
440
441 #[derive(Clone, Debug, PartialEq)]
442 pub enum Scope {
443 Attribute,
444 ImportDecl,
445 VariableDecl,
446 TypeDecl,
447 FunctionDecl,
448 Block,
449 Statement,
450 ConstantExpr,
451 PrimaryExpr,
452 SingularExpr,
453 GeneralExpr,
454 }
455
456 type LocalFunctionCall = (Handle<crate::Function>, Vec<Handle<crate::Expression>>);
457
458 #[derive(Default)]
459 struct BindingParser {
460 location: Option<u32>,
461 built_in: Option<crate::BuiltIn>,
462 interpolation: Option<crate::Interpolation>,
463 sampling: Option<crate::Sampling>,
464 }
465
466 impl BindingParser {
parse<'a>(&mut self, lexer: &mut Lexer<'a>, name: &'a str) -> Result<(), Error<'a>>467 fn parse<'a>(&mut self, lexer: &mut Lexer<'a>, name: &'a str) -> Result<(), Error<'a>> {
468 match name {
469 "location" => {
470 lexer.expect(Token::Paren('('))?;
471 self.location = Some(lexer.next_uint_literal()?);
472 lexer.expect(Token::Paren(')'))?;
473 }
474 "builtin" => {
475 lexer.expect(Token::Paren('('))?;
476 let raw = lexer.next_ident()?;
477 self.built_in = Some(conv::map_built_in(raw)?);
478 lexer.expect(Token::Paren(')'))?;
479 }
480 "interpolate" => {
481 lexer.expect(Token::Paren('('))?;
482 let raw = lexer.next_ident()?;
483 self.interpolation = Some(conv::map_interpolation(raw)?);
484 if lexer.skip(Token::Separator(',')) {
485 let raw = lexer.next_ident()?;
486 self.sampling = Some(conv::map_sampling(raw)?);
487 }
488 lexer.expect(Token::Paren(')'))?;
489 }
490 _ => return Err(Error::UnknownAttribute(name)),
491 }
492 Ok(())
493 }
494
finish<'a>(self) -> Result<Option<crate::Binding>, Error<'a>>495 fn finish<'a>(self) -> Result<Option<crate::Binding>, Error<'a>> {
496 match (
497 self.location,
498 self.built_in,
499 self.interpolation,
500 self.sampling,
501 ) {
502 (None, None, None, None) => Ok(None),
503 (Some(location), None, interpolation, sampling) => {
504 // Before handing over the completed `Module`, we call
505 // `apply_common_default_interpolation` to ensure that the interpolation and
506 // sampling have been explicitly specified on all vertex shader output and fragment
507 // shader input user bindings, so leaving them potentially `None` here is fine.
508 Ok(Some(crate::Binding::Location {
509 location,
510 interpolation,
511 sampling,
512 }))
513 }
514 (None, Some(bi), None, None) => Ok(Some(crate::Binding::BuiltIn(bi))),
515 (location, built_in, interpolation, sampling) => Err(Error::InconsistentBinding(
516 location,
517 built_in,
518 interpolation,
519 sampling,
520 )),
521 }
522 }
523 }
524
525 struct ParsedVariable<'a> {
526 name: &'a str,
527 class: Option<crate::StorageClass>,
528 ty: Handle<crate::Type>,
529 access: crate::StorageAccess,
530 init: Option<Handle<crate::Constant>>,
531 }
532
533 #[derive(Clone, Debug)]
534 pub struct ParseError {
535 message: String,
536 labels: Vec<(Span, String)>,
537 notes: Vec<String>,
538 }
539
540 impl ParseError {
diagnostic(&self) -> Diagnostic<()>541 fn diagnostic(&self) -> Diagnostic<()> {
542 let diagnostic = Diagnostic::error()
543 .with_message(self.message.to_string())
544 .with_labels(
545 self.labels
546 .iter()
547 .map(|label| {
548 Label::primary((), label.0.clone()).with_message(label.1.to_string())
549 })
550 .collect(),
551 )
552 .with_notes(
553 self.notes
554 .iter()
555 .map(|note| format!("note: {}", note))
556 .collect(),
557 );
558 diagnostic
559 }
560
561 /// Emits a summary of the error to standard error stream.
emit_to_stderr(&self, source: &str)562 pub fn emit_to_stderr(&self, source: &str) {
563 let files = SimpleFile::new("wgsl", source);
564 let config = codespan_reporting::term::Config::default();
565 let writer = StandardStream::stderr(ColorChoice::Always);
566 term::emit(&mut writer.lock(), &config, &files, &self.diagnostic())
567 .expect("cannot write error");
568 }
569
570 /// Emits a summary of the error to a string.
emit_to_string(&self, source: &str) -> String571 pub fn emit_to_string(&self, source: &str) -> String {
572 let files = SimpleFile::new("wgsl", source);
573 let config = codespan_reporting::term::Config::default();
574 let mut writer = StringErrorBuffer::new();
575 term::emit(&mut writer, &config, &files, &self.diagnostic()).expect("cannot write error");
576 writer.into_string()
577 }
578
579 /// Returns the 1-based line number and column of the first label in the
580 /// error message.
location(&self, source: &str) -> (usize, usize)581 pub fn location(&self, source: &str) -> (usize, usize) {
582 let files = SimpleFile::new("wgsl", source);
583 match self.labels.get(0) {
584 Some(label) => {
585 let location = files
586 .location((), label.0.start)
587 .expect("invalid span location");
588 (location.line_number, location.column_number)
589 }
590 None => (1, 1),
591 }
592 }
593 }
594
595 impl std::fmt::Display for ParseError {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result596 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
597 write!(f, "{}", self.message)
598 }
599 }
600
601 impl std::error::Error for ParseError {
source(&self) -> Option<&(dyn std::error::Error + 'static)>602 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
603 None
604 }
605 }
606
607 pub struct Parser {
608 scopes: Vec<Scope>,
609 lookup_type: FastHashMap<String, Handle<crate::Type>>,
610 layouter: layout::Layouter,
611 }
612
613 impl Parser {
new() -> Self614 pub fn new() -> Self {
615 Parser {
616 scopes: Vec::new(),
617 lookup_type: FastHashMap::default(),
618 layouter: Default::default(),
619 }
620 }
621
get_constant_inner<'a>( word: &'a str, ty: char, width: &'a str, token: TokenSpan<'a>, ) -> Result<crate::ConstantInner, Error<'a>>622 fn get_constant_inner<'a>(
623 word: &'a str,
624 ty: char,
625 width: &'a str,
626 token: TokenSpan<'a>,
627 ) -> Result<crate::ConstantInner, Error<'a>> {
628 let span = token.1;
629 let value = match ty {
630 'i' => word
631 .parse()
632 .map(crate::ScalarValue::Sint)
633 .map_err(|_| Error::BadInteger(span.clone()))?,
634 'u' => word
635 .parse()
636 .map(crate::ScalarValue::Uint)
637 .map_err(|_| Error::BadInteger(span.clone()))?,
638 'f' => word
639 .parse()
640 .map(crate::ScalarValue::Float)
641 .map_err(|_| Error::BadFloat(span.clone()))?,
642 _ => unreachable!(),
643 };
644 Ok(crate::ConstantInner::Scalar {
645 value,
646 width: if width.is_empty() {
647 4
648 } else {
649 match width.parse::<crate::Bytes>() {
650 Ok(bits) => bits / 8,
651 Err(_) => return Err(Error::BadScalarWidth(span, width)),
652 }
653 },
654 })
655 }
656
parse_local_function_call<'a>( &mut self, lexer: &mut Lexer<'a>, name: &'a str, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result<Option<LocalFunctionCall>, Error<'a>>657 fn parse_local_function_call<'a>(
658 &mut self,
659 lexer: &mut Lexer<'a>,
660 name: &'a str,
661 mut ctx: ExpressionContext<'a, '_, '_>,
662 ) -> Result<Option<LocalFunctionCall>, Error<'a>> {
663 let fun_handle = match ctx.functions.iter().find(|&(_, fun)| match fun.name {
664 Some(ref string) => string == name,
665 None => false,
666 }) {
667 Some((fun_handle, _)) => fun_handle,
668 None => return Ok(None),
669 };
670
671 let count = ctx.functions[fun_handle].arguments.len();
672 let mut arguments = Vec::with_capacity(count);
673 lexer.open_arguments()?;
674 while arguments.len() != count {
675 if !arguments.is_empty() {
676 lexer.expect(Token::Separator(','))?;
677 }
678 let arg = self.parse_general_expression(lexer, ctx.reborrow())?;
679 arguments.push(arg);
680 }
681 lexer.close_arguments()?;
682 Ok(Some((fun_handle, arguments)))
683 }
684
parse_function_call_inner<'a>( &mut self, lexer: &mut Lexer<'a>, name: &'a str, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result<Option<Handle<crate::Expression>>, Error<'a>>685 fn parse_function_call_inner<'a>(
686 &mut self,
687 lexer: &mut Lexer<'a>,
688 name: &'a str,
689 mut ctx: ExpressionContext<'a, '_, '_>,
690 ) -> Result<Option<Handle<crate::Expression>>, Error<'a>> {
691 let expr = if let Some(fun) = conv::map_relational_fun(name) {
692 lexer.open_arguments()?;
693 let argument = self.parse_general_expression(lexer, ctx.reborrow())?;
694 lexer.close_arguments()?;
695 crate::Expression::Relational { fun, argument }
696 } else if let Some(axis) = conv::map_derivative_axis(name) {
697 lexer.open_arguments()?;
698 let expr = self.parse_general_expression(lexer, ctx.reborrow())?;
699 lexer.close_arguments()?;
700 crate::Expression::Derivative { axis, expr }
701 } else if let Some(fun) = conv::map_standard_fun(name) {
702 lexer.open_arguments()?;
703 let arg_count = fun.argument_count();
704 let arg = self.parse_general_expression(lexer, ctx.reborrow())?;
705 let arg1 = if arg_count > 1 {
706 lexer.expect(Token::Separator(','))?;
707 Some(self.parse_general_expression(lexer, ctx.reborrow())?)
708 } else {
709 None
710 };
711 let arg2 = if arg_count > 2 {
712 lexer.expect(Token::Separator(','))?;
713 Some(self.parse_general_expression(lexer, ctx.reborrow())?)
714 } else {
715 None
716 };
717 lexer.close_arguments()?;
718 crate::Expression::Math {
719 fun,
720 arg,
721 arg1,
722 arg2,
723 }
724 } else if name == "select" {
725 lexer.open_arguments()?;
726 let accept = self.parse_general_expression(lexer, ctx.reborrow())?;
727 lexer.expect(Token::Separator(','))?;
728 let reject = self.parse_general_expression(lexer, ctx.reborrow())?;
729 lexer.expect(Token::Separator(','))?;
730 let condition = self.parse_general_expression(lexer, ctx.reborrow())?;
731 lexer.close_arguments()?;
732 crate::Expression::Select {
733 condition,
734 accept,
735 reject,
736 }
737 } else if name == "arrayLength" {
738 lexer.open_arguments()?;
739 let array = self.parse_singular_expression(lexer, ctx.reborrow())?;
740 lexer.close_arguments()?;
741 crate::Expression::ArrayLength(array)
742 } else {
743 // texture sampling
744 match name {
745 "textureSample" => {
746 lexer.open_arguments()?;
747 let image_name = lexer.next_ident()?;
748 lexer.expect(Token::Separator(','))?;
749 let sampler_name = lexer.next_ident()?;
750 lexer.expect(Token::Separator(','))?;
751 let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
752 let sc = ctx.prepare_sampling(image_name)?;
753 let array_index = if sc.arrayed {
754 lexer.expect(Token::Separator(','))?;
755 Some(self.parse_general_expression(lexer, ctx.reborrow())?)
756 } else {
757 None
758 };
759 let offset = if lexer.skip(Token::Separator(',')) {
760 Some(self.parse_const_expression(lexer, ctx.types, ctx.constants)?)
761 } else {
762 None
763 };
764 lexer.close_arguments()?;
765 crate::Expression::ImageSample {
766 image: sc.image,
767 sampler: ctx.lookup_ident.lookup(sampler_name)?,
768 coordinate,
769 array_index,
770 offset,
771 level: crate::SampleLevel::Auto,
772 depth_ref: None,
773 }
774 }
775 "textureSampleLevel" => {
776 lexer.open_arguments()?;
777 let image_name = lexer.next_ident()?;
778 lexer.expect(Token::Separator(','))?;
779 let sampler_name = lexer.next_ident()?;
780 lexer.expect(Token::Separator(','))?;
781 let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
782 let sc = ctx.prepare_sampling(image_name)?;
783 let array_index = if sc.arrayed {
784 lexer.expect(Token::Separator(','))?;
785 Some(self.parse_general_expression(lexer, ctx.reborrow())?)
786 } else {
787 None
788 };
789 lexer.expect(Token::Separator(','))?;
790 let level = self.parse_general_expression(lexer, ctx.reborrow())?;
791 let offset = if lexer.skip(Token::Separator(',')) {
792 Some(self.parse_const_expression(lexer, ctx.types, ctx.constants)?)
793 } else {
794 None
795 };
796 lexer.close_arguments()?;
797 crate::Expression::ImageSample {
798 image: sc.image,
799 sampler: ctx.lookup_ident.lookup(sampler_name)?,
800 coordinate,
801 array_index,
802 offset,
803 level: crate::SampleLevel::Exact(level),
804 depth_ref: None,
805 }
806 }
807 "textureSampleBias" => {
808 lexer.open_arguments()?;
809 let image_name = lexer.next_ident()?;
810 lexer.expect(Token::Separator(','))?;
811 let sampler_name = lexer.next_ident()?;
812 lexer.expect(Token::Separator(','))?;
813 let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
814 let sc = ctx.prepare_sampling(image_name)?;
815 let array_index = if sc.arrayed {
816 lexer.expect(Token::Separator(','))?;
817 Some(self.parse_general_expression(lexer, ctx.reborrow())?)
818 } else {
819 None
820 };
821 lexer.expect(Token::Separator(','))?;
822 let bias = self.parse_general_expression(lexer, ctx.reborrow())?;
823 let offset = if lexer.skip(Token::Separator(',')) {
824 Some(self.parse_const_expression(lexer, ctx.types, ctx.constants)?)
825 } else {
826 None
827 };
828 lexer.close_arguments()?;
829 crate::Expression::ImageSample {
830 image: sc.image,
831 sampler: ctx.lookup_ident.lookup(sampler_name)?,
832 coordinate,
833 array_index,
834 offset,
835 level: crate::SampleLevel::Bias(bias),
836 depth_ref: None,
837 }
838 }
839 "textureSampleGrad" => {
840 lexer.open_arguments()?;
841 let image_name = lexer.next_ident()?;
842 lexer.expect(Token::Separator(','))?;
843 let sampler_name = lexer.next_ident()?;
844 lexer.expect(Token::Separator(','))?;
845 let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
846 let sc = ctx.prepare_sampling(image_name)?;
847 let array_index = if sc.arrayed {
848 lexer.expect(Token::Separator(','))?;
849 Some(self.parse_general_expression(lexer, ctx.reborrow())?)
850 } else {
851 None
852 };
853 lexer.expect(Token::Separator(','))?;
854 let x = self.parse_general_expression(lexer, ctx.reborrow())?;
855 lexer.expect(Token::Separator(','))?;
856 let y = self.parse_general_expression(lexer, ctx.reborrow())?;
857 let offset = if lexer.skip(Token::Separator(',')) {
858 Some(self.parse_const_expression(lexer, ctx.types, ctx.constants)?)
859 } else {
860 None
861 };
862 lexer.close_arguments()?;
863 crate::Expression::ImageSample {
864 image: sc.image,
865 sampler: ctx.lookup_ident.lookup(sampler_name)?,
866 coordinate,
867 array_index,
868 offset,
869 level: crate::SampleLevel::Gradient { x, y },
870 depth_ref: None,
871 }
872 }
873 "textureSampleCompare" => {
874 lexer.open_arguments()?;
875 let image_name = lexer.next_ident()?;
876 lexer.expect(Token::Separator(','))?;
877 let sampler_name = lexer.next_ident()?;
878 lexer.expect(Token::Separator(','))?;
879 let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
880 let sc = ctx.prepare_sampling(image_name)?;
881 let array_index = if sc.arrayed {
882 lexer.expect(Token::Separator(','))?;
883 Some(self.parse_general_expression(lexer, ctx.reborrow())?)
884 } else {
885 None
886 };
887 lexer.expect(Token::Separator(','))?;
888 let reference = self.parse_general_expression(lexer, ctx.reborrow())?;
889 let offset = if lexer.skip(Token::Separator(',')) {
890 Some(self.parse_const_expression(lexer, ctx.types, ctx.constants)?)
891 } else {
892 None
893 };
894 lexer.close_arguments()?;
895 crate::Expression::ImageSample {
896 image: sc.image,
897 sampler: ctx.lookup_ident.lookup(sampler_name)?,
898 coordinate,
899 array_index,
900 offset,
901 level: crate::SampleLevel::Zero,
902 depth_ref: Some(reference),
903 }
904 }
905 "textureLoad" => {
906 lexer.open_arguments()?;
907 let image_name = lexer.next_ident()?;
908 let image = ctx.lookup_ident.lookup(image_name)?;
909 lexer.expect(Token::Separator(','))?;
910 let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
911 let (class, arrayed) = match *ctx.resolve_type(image)? {
912 crate::TypeInner::Image { class, arrayed, .. } => (class, arrayed),
913 _ => return Err(Error::BadTexture(image_name)),
914 };
915 let array_index = if arrayed {
916 lexer.expect(Token::Separator(','))?;
917 Some(self.parse_general_expression(lexer, ctx.reborrow())?)
918 } else {
919 None
920 };
921 let index = match class {
922 crate::ImageClass::Storage(_) => None,
923 // it's the MSAA index for multi-sampled, and LOD for the others
924 crate::ImageClass::Sampled { .. } | crate::ImageClass::Depth => {
925 lexer.expect(Token::Separator(','))?;
926 Some(self.parse_general_expression(lexer, ctx.reborrow())?)
927 }
928 };
929 lexer.close_arguments()?;
930 crate::Expression::ImageLoad {
931 image,
932 coordinate,
933 array_index,
934 index,
935 }
936 }
937 "textureDimensions" => {
938 lexer.open_arguments()?;
939 let image_name = lexer.next_ident()?;
940 let image = ctx.lookup_ident.lookup(image_name)?;
941 let level = if lexer.skip(Token::Separator(',')) {
942 let expr = self.parse_general_expression(lexer, ctx.reborrow())?;
943 Some(expr)
944 } else {
945 None
946 };
947 lexer.close_arguments()?;
948 crate::Expression::ImageQuery {
949 image,
950 query: crate::ImageQuery::Size { level },
951 }
952 }
953 "textureNumLevels" => {
954 lexer.open_arguments()?;
955 let image_name = lexer.next_ident()?;
956 let image = ctx.lookup_ident.lookup(image_name)?;
957 lexer.close_arguments()?;
958 crate::Expression::ImageQuery {
959 image,
960 query: crate::ImageQuery::NumLevels,
961 }
962 }
963 "textureNumLayers" => {
964 lexer.open_arguments()?;
965 let image_name = lexer.next_ident()?;
966 let image = ctx.lookup_ident.lookup(image_name)?;
967 lexer.close_arguments()?;
968 crate::Expression::ImageQuery {
969 image,
970 query: crate::ImageQuery::NumLayers,
971 }
972 }
973 "textureNumSamples" => {
974 lexer.open_arguments()?;
975 let image_name = lexer.next_ident()?;
976 let image = ctx.lookup_ident.lookup(image_name)?;
977 lexer.close_arguments()?;
978 crate::Expression::ImageQuery {
979 image,
980 query: crate::ImageQuery::NumSamples,
981 }
982 }
983 // other
984 _ => {
985 let handle =
986 match self.parse_local_function_call(lexer, name, ctx.reborrow())? {
987 Some((function, arguments)) => {
988 ctx.block.extend(ctx.emitter.finish(ctx.expressions));
989 let result =
990 Some(ctx.expressions.append(crate::Expression::Call(function)));
991 ctx.block.push(crate::Statement::Call {
992 function,
993 arguments,
994 result,
995 });
996 // restart the emitter
997 ctx.emitter.start(ctx.expressions);
998 result
999 }
1000 None => None,
1001 };
1002 return Ok(handle);
1003 }
1004 }
1005 };
1006 Ok(Some(ctx.expressions.append(expr)))
1007 }
1008
parse_const_expression_impl<'a>( &mut self, first_token_span: TokenSpan<'a>, lexer: &mut Lexer<'a>, register_name: Option<&'a str>, type_arena: &mut Arena<crate::Type>, const_arena: &mut Arena<crate::Constant>, ) -> Result<Handle<crate::Constant>, Error<'a>>1009 fn parse_const_expression_impl<'a>(
1010 &mut self,
1011 first_token_span: TokenSpan<'a>,
1012 lexer: &mut Lexer<'a>,
1013 register_name: Option<&'a str>,
1014 type_arena: &mut Arena<crate::Type>,
1015 const_arena: &mut Arena<crate::Constant>,
1016 ) -> Result<Handle<crate::Constant>, Error<'a>> {
1017 self.scopes.push(Scope::ConstantExpr);
1018 let inner = match first_token_span {
1019 (Token::Word("true"), _) => crate::ConstantInner::boolean(true),
1020 (Token::Word("false"), _) => crate::ConstantInner::boolean(false),
1021 (
1022 Token::Number {
1023 ref value,
1024 ref ty,
1025 ref width,
1026 },
1027 _,
1028 ) => Self::get_constant_inner(*value, *ty, *width, first_token_span)?,
1029 (Token::Word(name), _) => {
1030 // look for an existing constant first
1031 for (handle, var) in const_arena.iter() {
1032 match var.name {
1033 Some(ref string) if string == name => {
1034 self.scopes.pop();
1035 return Ok(handle);
1036 }
1037 _ => {}
1038 }
1039 }
1040 let composite_ty = self.parse_type_decl_name(
1041 lexer,
1042 name,
1043 None,
1044 TypeAttributes::default(),
1045 type_arena,
1046 const_arena,
1047 )?;
1048
1049 lexer.open_arguments()?;
1050 //Note: this expects at least one argument
1051 let mut components = Vec::new();
1052 while components.is_empty() || lexer.next_argument()? {
1053 let component = self.parse_const_expression(lexer, type_arena, const_arena)?;
1054 components.push(component);
1055 }
1056 crate::ConstantInner::Composite {
1057 ty: composite_ty,
1058 components,
1059 }
1060 }
1061 other => return Err(Error::Unexpected(other, "constant")),
1062 };
1063
1064 let handle = if let Some(name) = register_name {
1065 const_arena.append(crate::Constant {
1066 name: Some(name.to_string()),
1067 specialization: None,
1068 inner,
1069 })
1070 } else {
1071 const_arena.fetch_or_append(crate::Constant {
1072 name: None,
1073 specialization: None,
1074 inner,
1075 })
1076 };
1077
1078 self.scopes.pop();
1079 Ok(handle)
1080 }
1081
parse_const_expression<'a>( &mut self, lexer: &mut Lexer<'a>, type_arena: &mut Arena<crate::Type>, const_arena: &mut Arena<crate::Constant>, ) -> Result<Handle<crate::Constant>, Error<'a>>1082 fn parse_const_expression<'a>(
1083 &mut self,
1084 lexer: &mut Lexer<'a>,
1085 type_arena: &mut Arena<crate::Type>,
1086 const_arena: &mut Arena<crate::Constant>,
1087 ) -> Result<Handle<crate::Constant>, Error<'a>> {
1088 self.parse_const_expression_impl(lexer.next(), lexer, None, type_arena, const_arena)
1089 }
1090
parse_primary_expression<'a>( &mut self, lexer: &mut Lexer<'a>, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result<Handle<crate::Expression>, Error<'a>>1091 fn parse_primary_expression<'a>(
1092 &mut self,
1093 lexer: &mut Lexer<'a>,
1094 mut ctx: ExpressionContext<'a, '_, '_>,
1095 ) -> Result<Handle<crate::Expression>, Error<'a>> {
1096 self.scopes.push(Scope::PrimaryExpr);
1097 let handle = match lexer.next() {
1098 (Token::Paren('('), _) => {
1099 let expr = self.parse_general_expression(lexer, ctx)?;
1100 lexer.expect(Token::Paren(')'))?;
1101 expr
1102 }
1103 token @ (Token::Word("true"), _)
1104 | token @ (Token::Word("false"), _)
1105 | token @ (Token::Number { .. }, _) => {
1106 let const_handle =
1107 self.parse_const_expression_impl(token, lexer, None, ctx.types, ctx.constants)?;
1108 // pause the emitter while generating this expression, since it's pre-emitted
1109 ctx.block.extend(ctx.emitter.finish(ctx.expressions));
1110 let expr = ctx
1111 .expressions
1112 .append(crate::Expression::Constant(const_handle));
1113 ctx.emitter.start(ctx.expressions);
1114 expr
1115 }
1116 (Token::Word(word), _) => {
1117 if let Some(&expr) = ctx.lookup_ident.get(word) {
1118 expr
1119 } else if let Some(expr) =
1120 self.parse_function_call_inner(lexer, word, ctx.reborrow())?
1121 {
1122 //TODO: resolve the duplicate call in `parse_singular_expression`
1123 expr
1124 } else {
1125 let ty_resolution = match self.lookup_type.get(word) {
1126 Some(&handle) => TypeResolution::Handle(handle),
1127 None => {
1128 let inner = self.parse_type_decl_impl(
1129 lexer,
1130 TypeAttributes::default(),
1131 word,
1132 ctx.types,
1133 ctx.constants,
1134 )?;
1135 TypeResolution::Value(inner)
1136 }
1137 };
1138
1139 lexer.open_arguments()?;
1140 let mut components = Vec::new();
1141 let mut last_component =
1142 self.parse_general_expression(lexer, ctx.reborrow())?;
1143 while lexer.next_argument()? {
1144 components.push(last_component);
1145 last_component = self.parse_general_expression(lexer, ctx.reborrow())?;
1146 }
1147
1148 let expr = if components.is_empty()
1149 && ty_resolution.inner_with(ctx.types).scalar_kind().is_some()
1150 {
1151 // We can't use the `TypeInner` returned by this because
1152 // `resolve_type` borrows context mutably.
1153 // Use it to insert into the right maps,
1154 // and then grab it again immutably.
1155 ctx.resolve_type(last_component)?;
1156 match (
1157 ty_resolution.inner_with(ctx.types),
1158 ctx.typifier.get(last_component, ctx.types),
1159 ) {
1160 (
1161 &crate::TypeInner::Vector { size, .. },
1162 &crate::TypeInner::Scalar { .. },
1163 ) => crate::Expression::Splat {
1164 size,
1165 value: last_component,
1166 },
1167 (
1168 &crate::TypeInner::Scalar { kind, width, .. },
1169 &crate::TypeInner::Scalar { .. },
1170 )
1171 | (
1172 &crate::TypeInner::Vector { kind, width, .. },
1173 &crate::TypeInner::Vector { .. },
1174 ) => crate::Expression::As {
1175 expr: last_component,
1176 kind,
1177 convert: Some(width),
1178 },
1179 (
1180 &crate::TypeInner::Matrix { width, .. },
1181 &crate::TypeInner::Matrix { .. },
1182 ) => crate::Expression::As {
1183 expr: last_component,
1184 kind: crate::ScalarKind::Float,
1185 convert: Some(width),
1186 },
1187 _ => {
1188 return Err(Error::BadTypeCast(word));
1189 }
1190 }
1191 } else {
1192 let ty = match ty_resolution {
1193 TypeResolution::Handle(handle) => handle,
1194 TypeResolution::Value(inner) => {
1195 ctx.types.fetch_or_append(crate::Type { name: None, inner })
1196 }
1197 };
1198 components.push(last_component);
1199 crate::Expression::Compose { ty, components }
1200 };
1201 ctx.expressions.append(expr)
1202 }
1203 }
1204 other => return Err(Error::Unexpected(other, "primary expression")),
1205 };
1206 self.scopes.pop();
1207 Ok(handle)
1208 }
1209
parse_postfix<'a>( &mut self, lexer: &mut Lexer<'a>, mut ctx: ExpressionContext<'a, '_, '_>, mut handle: Handle<crate::Expression>, allow_deref: bool, ) -> Result<Handle<crate::Expression>, Error<'a>>1210 fn parse_postfix<'a>(
1211 &mut self,
1212 lexer: &mut Lexer<'a>,
1213 mut ctx: ExpressionContext<'a, '_, '_>,
1214 mut handle: Handle<crate::Expression>,
1215 allow_deref: bool,
1216 ) -> Result<Handle<crate::Expression>, Error<'a>> {
1217 let mut needs_deref = match ctx.expressions[handle] {
1218 crate::Expression::LocalVariable(_) | crate::Expression::GlobalVariable(_) => {
1219 allow_deref
1220 }
1221 _ => false,
1222 };
1223 loop {
1224 // insert the E::Load when we reach a value
1225 if needs_deref {
1226 let now = match *ctx.resolve_type(handle)? {
1227 crate::TypeInner::Pointer { base, class: _ } => match ctx.types[base].inner {
1228 crate::TypeInner::Scalar { .. } | crate::TypeInner::Vector { .. } => true,
1229 _ => false,
1230 },
1231 crate::TypeInner::ValuePointer { .. } => true,
1232 _ => false,
1233 };
1234 if now {
1235 let expression = crate::Expression::Load { pointer: handle };
1236 handle = ctx.expressions.append(expression);
1237 needs_deref = false;
1238 }
1239 }
1240
1241 let expression = match lexer.peek().0 {
1242 Token::Separator('.') => {
1243 let _ = lexer.next();
1244 let (name, name_span) = lexer.next_ident_with_span()?;
1245 match *ctx.resolve_type(handle)? {
1246 crate::TypeInner::Struct { ref members, .. } => {
1247 let index = members
1248 .iter()
1249 .position(|m| m.name.as_deref() == Some(name))
1250 .ok_or(Error::BadAccessor(name_span))?
1251 as u32;
1252 crate::Expression::AccessIndex {
1253 base: handle,
1254 index,
1255 }
1256 }
1257 crate::TypeInner::Vector { .. } | crate::TypeInner::Matrix { .. } => {
1258 match Composition::make(name, name_span)? {
1259 Composition::Multi(dst_size, pattern) => {
1260 crate::Expression::Swizzle {
1261 size: dst_size,
1262 vector: handle,
1263 pattern,
1264 }
1265 }
1266 Composition::Single(index) => crate::Expression::AccessIndex {
1267 base: handle,
1268 index,
1269 },
1270 }
1271 }
1272 crate::TypeInner::ValuePointer { .. } => {
1273 Composition::extract(handle, name, name_span)?
1274 }
1275 crate::TypeInner::Pointer { base, class: _ } => match ctx.types[base].inner
1276 {
1277 crate::TypeInner::Struct { ref members, .. } => {
1278 let index = members
1279 .iter()
1280 .position(|m| m.name.as_deref() == Some(name))
1281 .ok_or(Error::BadAccessor(name_span))?
1282 as u32;
1283 crate::Expression::AccessIndex {
1284 base: handle,
1285 index,
1286 }
1287 }
1288 _ => Composition::extract(handle, name, name_span)?,
1289 },
1290 _ => return Err(Error::BadAccessor(name_span)),
1291 }
1292 }
1293 Token::Paren('[') => {
1294 let _ = lexer.next();
1295 let index = self.parse_general_expression(lexer, ctx.reborrow())?;
1296 lexer.expect(Token::Paren(']'))?;
1297 crate::Expression::Access {
1298 base: handle,
1299 index,
1300 }
1301 }
1302 _ => {
1303 // after we reached for the value, load it
1304 return Ok(if needs_deref {
1305 let expression = crate::Expression::Load { pointer: handle };
1306 ctx.expressions.append(expression)
1307 } else {
1308 handle
1309 });
1310 }
1311 };
1312
1313 handle = ctx.expressions.append(expression);
1314 }
1315 }
1316
parse_singular_expression<'a>( &mut self, lexer: &mut Lexer<'a>, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result<Handle<crate::Expression>, Error<'a>>1317 fn parse_singular_expression<'a>(
1318 &mut self,
1319 lexer: &mut Lexer<'a>,
1320 mut ctx: ExpressionContext<'a, '_, '_>,
1321 ) -> Result<Handle<crate::Expression>, Error<'a>> {
1322 self.scopes.push(Scope::SingularExpr);
1323 //TODO: refactor this to avoid backing up
1324 let backup = lexer.clone();
1325 let (allow_deref, handle) = match lexer.next().0 {
1326 Token::Operation('-') => {
1327 let expr = crate::Expression::Unary {
1328 op: crate::UnaryOperator::Negate,
1329 expr: self.parse_singular_expression(lexer, ctx.reborrow())?,
1330 };
1331 (true, ctx.expressions.append(expr))
1332 }
1333 Token::Operation('!') | Token::Operation('~') => {
1334 let expr = crate::Expression::Unary {
1335 op: crate::UnaryOperator::Not,
1336 expr: self.parse_singular_expression(lexer, ctx.reborrow())?,
1337 };
1338 (true, ctx.expressions.append(expr))
1339 }
1340 Token::Operation('&') => {
1341 let handle = self.parse_primary_expression(lexer, ctx.reborrow())?;
1342 (false, handle)
1343 }
1344 Token::Word(word) => {
1345 let handle = match self.parse_function_call_inner(lexer, word, ctx.reborrow())? {
1346 Some(handle) => handle,
1347 None => {
1348 *lexer = backup;
1349 self.parse_primary_expression(lexer, ctx.reborrow())?
1350 }
1351 };
1352 (true, handle)
1353 }
1354 _ => {
1355 *lexer = backup;
1356 let handle = self.parse_primary_expression(lexer, ctx.reborrow())?;
1357 (true, handle)
1358 }
1359 };
1360
1361 let post_handle = self.parse_postfix(lexer, ctx, handle, allow_deref)?;
1362 self.scopes.pop();
1363 Ok(post_handle)
1364 }
1365
parse_equality_expression<'a>( &mut self, lexer: &mut Lexer<'a>, mut context: ExpressionContext<'a, '_, '_>, ) -> Result<Handle<crate::Expression>, Error<'a>>1366 fn parse_equality_expression<'a>(
1367 &mut self,
1368 lexer: &mut Lexer<'a>,
1369 mut context: ExpressionContext<'a, '_, '_>,
1370 ) -> Result<Handle<crate::Expression>, Error<'a>> {
1371 // equality_expression
1372 context.parse_binary_op(
1373 lexer,
1374 |token| match token {
1375 Token::LogicalOperation('=') => Some(crate::BinaryOperator::Equal),
1376 Token::LogicalOperation('!') => Some(crate::BinaryOperator::NotEqual),
1377 _ => None,
1378 },
1379 // relational_expression
1380 |lexer, mut context| {
1381 context.parse_binary_op(
1382 lexer,
1383 |token| match token {
1384 Token::Paren('<') => Some(crate::BinaryOperator::Less),
1385 Token::Paren('>') => Some(crate::BinaryOperator::Greater),
1386 Token::LogicalOperation('<') => Some(crate::BinaryOperator::LessEqual),
1387 Token::LogicalOperation('>') => Some(crate::BinaryOperator::GreaterEqual),
1388 _ => None,
1389 },
1390 // shift_expression
1391 |lexer, mut context| {
1392 context.parse_binary_op(
1393 lexer,
1394 |token| match token {
1395 Token::ShiftOperation('<') => {
1396 Some(crate::BinaryOperator::ShiftLeft)
1397 }
1398 Token::ShiftOperation('>') => {
1399 Some(crate::BinaryOperator::ShiftRight)
1400 }
1401 _ => None,
1402 },
1403 // additive_expression
1404 |lexer, mut context| {
1405 context.parse_binary_splat_op(
1406 lexer,
1407 |token| match token {
1408 Token::Operation('+') => Some(crate::BinaryOperator::Add),
1409 Token::Operation('-') => {
1410 Some(crate::BinaryOperator::Subtract)
1411 }
1412 _ => None,
1413 },
1414 // multiplicative_expression
1415 |lexer, mut context| {
1416 context.parse_binary_splat_op(
1417 lexer,
1418 |token| match token {
1419 Token::Operation('*') => {
1420 Some(crate::BinaryOperator::Multiply)
1421 }
1422 Token::Operation('/') => {
1423 Some(crate::BinaryOperator::Divide)
1424 }
1425 Token::Operation('%') => {
1426 Some(crate::BinaryOperator::Modulo)
1427 }
1428 _ => None,
1429 },
1430 |lexer, context| {
1431 self.parse_singular_expression(lexer, context)
1432 },
1433 )
1434 },
1435 )
1436 },
1437 )
1438 },
1439 )
1440 },
1441 )
1442 }
1443
parse_general_expression<'a>( &mut self, lexer: &mut Lexer<'a>, mut context: ExpressionContext<'a, '_, '_>, ) -> Result<Handle<crate::Expression>, Error<'a>>1444 fn parse_general_expression<'a>(
1445 &mut self,
1446 lexer: &mut Lexer<'a>,
1447 mut context: ExpressionContext<'a, '_, '_>,
1448 ) -> Result<Handle<crate::Expression>, Error<'a>> {
1449 self.scopes.push(Scope::GeneralExpr);
1450 // logical_or_expression
1451 let handle = context.parse_binary_op(
1452 lexer,
1453 |token| match token {
1454 Token::LogicalOperation('|') => Some(crate::BinaryOperator::LogicalOr),
1455 _ => None,
1456 },
1457 // logical_and_expression
1458 |lexer, mut context| {
1459 context.parse_binary_op(
1460 lexer,
1461 |token| match token {
1462 Token::LogicalOperation('&') => Some(crate::BinaryOperator::LogicalAnd),
1463 _ => None,
1464 },
1465 // inclusive_or_expression
1466 |lexer, mut context| {
1467 context.parse_binary_op(
1468 lexer,
1469 |token| match token {
1470 Token::Operation('|') => Some(crate::BinaryOperator::InclusiveOr),
1471 _ => None,
1472 },
1473 // exclusive_or_expression
1474 |lexer, mut context| {
1475 context.parse_binary_op(
1476 lexer,
1477 |token| match token {
1478 Token::Operation('^') => {
1479 Some(crate::BinaryOperator::ExclusiveOr)
1480 }
1481 _ => None,
1482 },
1483 // and_expression
1484 |lexer, mut context| {
1485 context.parse_binary_op(
1486 lexer,
1487 |token| match token {
1488 Token::Operation('&') => {
1489 Some(crate::BinaryOperator::And)
1490 }
1491 _ => None,
1492 },
1493 |lexer, context| {
1494 self.parse_equality_expression(lexer, context)
1495 },
1496 )
1497 },
1498 )
1499 },
1500 )
1501 },
1502 )
1503 },
1504 )?;
1505 self.scopes.pop();
1506 Ok(handle)
1507 }
1508
parse_variable_ident_decl<'a>( &mut self, lexer: &mut Lexer<'a>, type_arena: &mut Arena<crate::Type>, const_arena: &mut Arena<crate::Constant>, ) -> Result<(&'a str, Handle<crate::Type>, crate::StorageAccess), Error<'a>>1509 fn parse_variable_ident_decl<'a>(
1510 &mut self,
1511 lexer: &mut Lexer<'a>,
1512 type_arena: &mut Arena<crate::Type>,
1513 const_arena: &mut Arena<crate::Constant>,
1514 ) -> Result<(&'a str, Handle<crate::Type>, crate::StorageAccess), Error<'a>> {
1515 let name = lexer.next_ident()?;
1516 lexer.expect(Token::Separator(':'))?;
1517 let (ty, access) = self.parse_type_decl(lexer, None, type_arena, const_arena)?;
1518 Ok((name, ty, access))
1519 }
1520
parse_variable_decl<'a>( &mut self, lexer: &mut Lexer<'a>, type_arena: &mut Arena<crate::Type>, const_arena: &mut Arena<crate::Constant>, ) -> Result<ParsedVariable<'a>, Error<'a>>1521 fn parse_variable_decl<'a>(
1522 &mut self,
1523 lexer: &mut Lexer<'a>,
1524 type_arena: &mut Arena<crate::Type>,
1525 const_arena: &mut Arena<crate::Constant>,
1526 ) -> Result<ParsedVariable<'a>, Error<'a>> {
1527 self.scopes.push(Scope::VariableDecl);
1528 let mut class = None;
1529 if lexer.skip(Token::Paren('<')) {
1530 let class_str = lexer.next_ident()?;
1531 class = Some(conv::map_storage_class(class_str)?);
1532 lexer.expect(Token::Paren('>'))?;
1533 }
1534 let name = lexer.next_ident()?;
1535 lexer.expect(Token::Separator(':'))?;
1536 let (ty, access) = self.parse_type_decl(lexer, None, type_arena, const_arena)?;
1537
1538 let init = if lexer.skip(Token::Operation('=')) {
1539 let handle = self.parse_const_expression(lexer, type_arena, const_arena)?;
1540 Some(handle)
1541 } else {
1542 None
1543 };
1544 lexer.expect(Token::Separator(';'))?;
1545 self.scopes.pop();
1546 Ok(ParsedVariable {
1547 name,
1548 class,
1549 ty,
1550 access,
1551 init,
1552 })
1553 }
1554
parse_struct_body<'a>( &mut self, lexer: &mut Lexer<'a>, type_arena: &mut Arena<crate::Type>, const_arena: &mut Arena<crate::Constant>, ) -> Result<(Vec<crate::StructMember>, u32, crate::Alignment), Error<'a>>1555 fn parse_struct_body<'a>(
1556 &mut self,
1557 lexer: &mut Lexer<'a>,
1558 type_arena: &mut Arena<crate::Type>,
1559 const_arena: &mut Arena<crate::Constant>,
1560 ) -> Result<(Vec<crate::StructMember>, u32, crate::Alignment), Error<'a>> {
1561 let mut offset = 0;
1562 let mut alignment = crate::Alignment::new(1).unwrap();
1563 let mut members = Vec::new();
1564
1565 lexer.expect(Token::Paren('{'))?;
1566 loop {
1567 let (mut size, mut align) = (None, None);
1568 let mut bind_parser = BindingParser::default();
1569 if lexer.skip(Token::DoubleParen('[')) {
1570 self.scopes.push(Scope::Attribute);
1571 let mut ready = true;
1572 loop {
1573 match lexer.next() {
1574 (Token::DoubleParen(']'), _) => {
1575 break;
1576 }
1577 (Token::Separator(','), _) if !ready => {
1578 ready = true;
1579 }
1580 (Token::Word(word), _) if ready => {
1581 match word {
1582 "size" => {
1583 lexer.expect(Token::Paren('('))?;
1584 let value = lexer.next_uint_literal()?;
1585 lexer.expect(Token::Paren(')'))?;
1586 size =
1587 Some(NonZeroU32::new(value).ok_or(Error::ZeroSizeOrAlign)?);
1588 }
1589 "align" => {
1590 lexer.expect(Token::Paren('('))?;
1591 let value = lexer.next_uint_literal()?;
1592 lexer.expect(Token::Paren(')'))?;
1593 align =
1594 Some(NonZeroU32::new(value).ok_or(Error::ZeroSizeOrAlign)?);
1595 }
1596 _ => bind_parser.parse(lexer, word)?,
1597 }
1598 ready = false;
1599 }
1600 other => return Err(Error::Unexpected(other, "attribute separator")),
1601 }
1602 }
1603 self.scopes.pop();
1604 }
1605
1606 let name = match lexer.next() {
1607 (Token::Word(word), _) => word,
1608 (Token::Paren('}'), _) => {
1609 let span = layout::Layouter::round_up(alignment, offset);
1610 return Ok((members, span, alignment));
1611 }
1612 other => return Err(Error::Unexpected(other, "field name")),
1613 };
1614 lexer.expect(Token::Separator(':'))?;
1615 let (ty, _access) = self.parse_type_decl(lexer, None, type_arena, const_arena)?;
1616 lexer.expect(Token::Separator(';'))?;
1617
1618 self.layouter.update(type_arena, const_arena);
1619 let (range, align) = self.layouter.member_placement(offset, ty, align, size);
1620 alignment = alignment.max(align);
1621 offset = range.end;
1622
1623 members.push(crate::StructMember {
1624 name: Some(name.to_owned()),
1625 ty,
1626 binding: bind_parser.finish()?,
1627 offset: range.start,
1628 });
1629 }
1630 }
1631
parse_type_decl_impl<'a>( &mut self, lexer: &mut Lexer<'a>, attribute: TypeAttributes, word: &'a str, type_arena: &mut Arena<crate::Type>, const_arena: &mut Arena<crate::Constant>, ) -> Result<crate::TypeInner, Error<'a>>1632 fn parse_type_decl_impl<'a>(
1633 &mut self,
1634 lexer: &mut Lexer<'a>,
1635 attribute: TypeAttributes,
1636 word: &'a str,
1637 type_arena: &mut Arena<crate::Type>,
1638 const_arena: &mut Arena<crate::Constant>,
1639 ) -> Result<crate::TypeInner, Error<'a>> {
1640 if let Some((kind, width)) = conv::get_scalar_type(word) {
1641 return Ok(crate::TypeInner::Scalar { kind, width });
1642 }
1643 Ok(match word {
1644 "vec2" => {
1645 let (kind, width) = lexer.next_scalar_generic()?;
1646 crate::TypeInner::Vector {
1647 size: crate::VectorSize::Bi,
1648 kind,
1649 width,
1650 }
1651 }
1652 "vec3" => {
1653 let (kind, width) = lexer.next_scalar_generic()?;
1654 crate::TypeInner::Vector {
1655 size: crate::VectorSize::Tri,
1656 kind,
1657 width,
1658 }
1659 }
1660 "vec4" => {
1661 let (kind, width) = lexer.next_scalar_generic()?;
1662 crate::TypeInner::Vector {
1663 size: crate::VectorSize::Quad,
1664 kind,
1665 width,
1666 }
1667 }
1668 "mat2x2" => {
1669 let (_, width) = lexer.next_scalar_generic()?;
1670 crate::TypeInner::Matrix {
1671 columns: crate::VectorSize::Bi,
1672 rows: crate::VectorSize::Bi,
1673 width,
1674 }
1675 }
1676 "mat2x3" => {
1677 let (_, width) = lexer.next_scalar_generic()?;
1678 crate::TypeInner::Matrix {
1679 columns: crate::VectorSize::Bi,
1680 rows: crate::VectorSize::Tri,
1681 width,
1682 }
1683 }
1684 "mat2x4" => {
1685 let (_, width) = lexer.next_scalar_generic()?;
1686 crate::TypeInner::Matrix {
1687 columns: crate::VectorSize::Bi,
1688 rows: crate::VectorSize::Quad,
1689 width,
1690 }
1691 }
1692 "mat3x2" => {
1693 let (_, width) = lexer.next_scalar_generic()?;
1694 crate::TypeInner::Matrix {
1695 columns: crate::VectorSize::Tri,
1696 rows: crate::VectorSize::Bi,
1697 width,
1698 }
1699 }
1700 "mat3x3" => {
1701 let (_, width) = lexer.next_scalar_generic()?;
1702 crate::TypeInner::Matrix {
1703 columns: crate::VectorSize::Tri,
1704 rows: crate::VectorSize::Tri,
1705 width,
1706 }
1707 }
1708 "mat3x4" => {
1709 let (_, width) = lexer.next_scalar_generic()?;
1710 crate::TypeInner::Matrix {
1711 columns: crate::VectorSize::Tri,
1712 rows: crate::VectorSize::Quad,
1713 width,
1714 }
1715 }
1716 "mat4x2" => {
1717 let (_, width) = lexer.next_scalar_generic()?;
1718 crate::TypeInner::Matrix {
1719 columns: crate::VectorSize::Quad,
1720 rows: crate::VectorSize::Bi,
1721 width,
1722 }
1723 }
1724 "mat4x3" => {
1725 let (_, width) = lexer.next_scalar_generic()?;
1726 crate::TypeInner::Matrix {
1727 columns: crate::VectorSize::Quad,
1728 rows: crate::VectorSize::Tri,
1729 width,
1730 }
1731 }
1732 "mat4x4" => {
1733 let (_, width) = lexer.next_scalar_generic()?;
1734 crate::TypeInner::Matrix {
1735 columns: crate::VectorSize::Quad,
1736 rows: crate::VectorSize::Quad,
1737 width,
1738 }
1739 }
1740 "ptr" => {
1741 lexer.expect_generic_paren('<')?;
1742 let class = conv::map_storage_class(lexer.next_ident()?)?;
1743 lexer.expect(Token::Separator(','))?;
1744 let (base, _access) = self.parse_type_decl(lexer, None, type_arena, const_arena)?;
1745 lexer.expect_generic_paren('>')?;
1746 crate::TypeInner::Pointer { base, class }
1747 }
1748 "array" => {
1749 lexer.expect_generic_paren('<')?;
1750 let (base, _access) = self.parse_type_decl(lexer, None, type_arena, const_arena)?;
1751 let size = if lexer.skip(Token::Separator(',')) {
1752 let const_handle =
1753 self.parse_const_expression(lexer, type_arena, const_arena)?;
1754 crate::ArraySize::Constant(const_handle)
1755 } else {
1756 crate::ArraySize::Dynamic
1757 };
1758 lexer.expect_generic_paren('>')?;
1759 let stride = match attribute.stride {
1760 Some(stride) => stride.get(),
1761 None => type_arena[base].inner.span(const_arena),
1762 };
1763
1764 crate::TypeInner::Array { base, size, stride }
1765 }
1766 "sampler" => crate::TypeInner::Sampler { comparison: false },
1767 "sampler_comparison" => crate::TypeInner::Sampler { comparison: true },
1768 "texture_1d" => {
1769 let (kind, _) = lexer.next_scalar_generic()?;
1770 crate::TypeInner::Image {
1771 dim: crate::ImageDimension::D1,
1772 arrayed: false,
1773 class: crate::ImageClass::Sampled { kind, multi: false },
1774 }
1775 }
1776 "texture_1d_array" => {
1777 let (kind, _) = lexer.next_scalar_generic()?;
1778 crate::TypeInner::Image {
1779 dim: crate::ImageDimension::D1,
1780 arrayed: true,
1781 class: crate::ImageClass::Sampled { kind, multi: false },
1782 }
1783 }
1784 "texture_2d" => {
1785 let (kind, _) = lexer.next_scalar_generic()?;
1786 crate::TypeInner::Image {
1787 dim: crate::ImageDimension::D2,
1788 arrayed: false,
1789 class: crate::ImageClass::Sampled { kind, multi: false },
1790 }
1791 }
1792 "texture_2d_array" => {
1793 let (kind, _) = lexer.next_scalar_generic()?;
1794 crate::TypeInner::Image {
1795 dim: crate::ImageDimension::D2,
1796 arrayed: true,
1797 class: crate::ImageClass::Sampled { kind, multi: false },
1798 }
1799 }
1800 "texture_3d" => {
1801 let (kind, _) = lexer.next_scalar_generic()?;
1802 crate::TypeInner::Image {
1803 dim: crate::ImageDimension::D3,
1804 arrayed: false,
1805 class: crate::ImageClass::Sampled { kind, multi: false },
1806 }
1807 }
1808 "texture_cube" => {
1809 let (kind, _) = lexer.next_scalar_generic()?;
1810 crate::TypeInner::Image {
1811 dim: crate::ImageDimension::Cube,
1812 arrayed: false,
1813 class: crate::ImageClass::Sampled { kind, multi: false },
1814 }
1815 }
1816 "texture_cube_array" => {
1817 let (kind, _) = lexer.next_scalar_generic()?;
1818 crate::TypeInner::Image {
1819 dim: crate::ImageDimension::Cube,
1820 arrayed: true,
1821 class: crate::ImageClass::Sampled { kind, multi: false },
1822 }
1823 }
1824 "texture_multisampled_2d" => {
1825 let (kind, _) = lexer.next_scalar_generic()?;
1826 crate::TypeInner::Image {
1827 dim: crate::ImageDimension::D2,
1828 arrayed: false,
1829 class: crate::ImageClass::Sampled { kind, multi: true },
1830 }
1831 }
1832 "texture_multisampled_2d_array" => {
1833 let (kind, _) = lexer.next_scalar_generic()?;
1834 crate::TypeInner::Image {
1835 dim: crate::ImageDimension::D2,
1836 arrayed: true,
1837 class: crate::ImageClass::Sampled { kind, multi: true },
1838 }
1839 }
1840 "texture_depth_2d" => crate::TypeInner::Image {
1841 dim: crate::ImageDimension::D2,
1842 arrayed: false,
1843 class: crate::ImageClass::Depth,
1844 },
1845 "texture_depth_2d_array" => crate::TypeInner::Image {
1846 dim: crate::ImageDimension::D2,
1847 arrayed: true,
1848 class: crate::ImageClass::Depth,
1849 },
1850 "texture_depth_cube" => crate::TypeInner::Image {
1851 dim: crate::ImageDimension::Cube,
1852 arrayed: false,
1853 class: crate::ImageClass::Depth,
1854 },
1855 "texture_depth_cube_array" => crate::TypeInner::Image {
1856 dim: crate::ImageDimension::Cube,
1857 arrayed: true,
1858 class: crate::ImageClass::Depth,
1859 },
1860 "texture_storage_1d" => {
1861 let format = lexer.next_format_generic()?;
1862 crate::TypeInner::Image {
1863 dim: crate::ImageDimension::D1,
1864 arrayed: false,
1865 class: crate::ImageClass::Storage(format),
1866 }
1867 }
1868 "texture_storage_1d_array" => {
1869 let format = lexer.next_format_generic()?;
1870 crate::TypeInner::Image {
1871 dim: crate::ImageDimension::D1,
1872 arrayed: true,
1873 class: crate::ImageClass::Storage(format),
1874 }
1875 }
1876 "texture_storage_2d" => {
1877 let format = lexer.next_format_generic()?;
1878 crate::TypeInner::Image {
1879 dim: crate::ImageDimension::D2,
1880 arrayed: false,
1881 class: crate::ImageClass::Storage(format),
1882 }
1883 }
1884 "texture_storage_2d_array" => {
1885 let format = lexer.next_format_generic()?;
1886 crate::TypeInner::Image {
1887 dim: crate::ImageDimension::D2,
1888 arrayed: true,
1889 class: crate::ImageClass::Storage(format),
1890 }
1891 }
1892 "texture_storage_3d" => {
1893 let format = lexer.next_format_generic()?;
1894 crate::TypeInner::Image {
1895 dim: crate::ImageDimension::D3,
1896 arrayed: false,
1897 class: crate::ImageClass::Storage(format),
1898 }
1899 }
1900 _ => return Err(Error::UnknownType(word)),
1901 })
1902 }
1903
1904 /// Parse type declaration of a given name and attribute.
parse_type_decl_name<'a>( &mut self, lexer: &mut Lexer<'a>, name: &'a str, debug_name: Option<&'a str>, attribute: TypeAttributes, type_arena: &mut Arena<crate::Type>, const_arena: &mut Arena<crate::Constant>, ) -> Result<Handle<crate::Type>, Error<'a>>1905 fn parse_type_decl_name<'a>(
1906 &mut self,
1907 lexer: &mut Lexer<'a>,
1908 name: &'a str,
1909 debug_name: Option<&'a str>,
1910 attribute: TypeAttributes,
1911 type_arena: &mut Arena<crate::Type>,
1912 const_arena: &mut Arena<crate::Constant>,
1913 ) -> Result<Handle<crate::Type>, Error<'a>> {
1914 Ok(match self.lookup_type.get(name) {
1915 Some(&handle) => handle,
1916 None => {
1917 let inner =
1918 self.parse_type_decl_impl(lexer, attribute, name, type_arena, const_arena)?;
1919 type_arena.fetch_or_append(crate::Type {
1920 name: debug_name.map(|s| s.to_string()),
1921 inner,
1922 })
1923 }
1924 })
1925 }
1926
parse_type_decl<'a>( &mut self, lexer: &mut Lexer<'a>, debug_name: Option<&'a str>, type_arena: &mut Arena<crate::Type>, const_arena: &mut Arena<crate::Constant>, ) -> Result<(Handle<crate::Type>, crate::StorageAccess), Error<'a>>1927 fn parse_type_decl<'a>(
1928 &mut self,
1929 lexer: &mut Lexer<'a>,
1930 debug_name: Option<&'a str>,
1931 type_arena: &mut Arena<crate::Type>,
1932 const_arena: &mut Arena<crate::Constant>,
1933 ) -> Result<(Handle<crate::Type>, crate::StorageAccess), Error<'a>> {
1934 self.scopes.push(Scope::TypeDecl);
1935 let mut attribute = TypeAttributes::default();
1936
1937 if lexer.skip(Token::DoubleParen('[')) {
1938 self.scopes.push(Scope::Attribute);
1939 loop {
1940 match lexer.next() {
1941 (Token::Word("access"), _) => {
1942 lexer.expect(Token::Paren('('))?;
1943 attribute.access = match lexer.next_ident()? {
1944 "read" => crate::StorageAccess::LOAD,
1945 "write" => crate::StorageAccess::STORE,
1946 "read_write" => crate::StorageAccess::all(),
1947 other => return Err(Error::UnknownAccess(other)),
1948 };
1949 lexer.expect(Token::Paren(')'))?;
1950 }
1951 (Token::Word("stride"), _) => {
1952 lexer.expect(Token::Paren('('))?;
1953 attribute.stride = Some(
1954 NonZeroU32::new(lexer.next_uint_literal()?).ok_or(Error::ZeroStride)?,
1955 );
1956 lexer.expect(Token::Paren(')'))?;
1957 }
1958 (Token::DoubleParen(']'), _) => break,
1959 other => return Err(Error::Unexpected(other, "type attribute")),
1960 }
1961 }
1962 self.scopes.pop();
1963 }
1964
1965 let storage_access = attribute.access;
1966 let name = lexer.next_ident()?;
1967 let handle =
1968 self.parse_type_decl_name(lexer, name, debug_name, attribute, type_arena, const_arena)?;
1969 self.scopes.pop();
1970 Ok((handle, storage_access))
1971 }
1972
1973 /// Parse a statement that is either an assignment or a function call.
parse_statement_restricted<'a, 'out>( &mut self, lexer: &mut Lexer<'a>, ident: &'a str, mut context: ExpressionContext<'a, '_, 'out>, ) -> Result<(), Error<'a>>1974 fn parse_statement_restricted<'a, 'out>(
1975 &mut self,
1976 lexer: &mut Lexer<'a>,
1977 ident: &'a str,
1978 mut context: ExpressionContext<'a, '_, 'out>,
1979 ) -> Result<(), Error<'a>> {
1980 context.emitter.start(context.expressions);
1981 let stmt = match context.lookup_ident.get(ident) {
1982 Some(&expr) => {
1983 let left = self.parse_postfix(lexer, context.reborrow(), expr, false)?;
1984 lexer.expect(Token::Operation('='))?;
1985 let value = self.parse_general_expression(lexer, context.reborrow())?;
1986 crate::Statement::Store {
1987 pointer: left,
1988 value,
1989 }
1990 }
1991 None => {
1992 let (function, arguments) = self
1993 .parse_local_function_call(lexer, ident, context.reborrow())?
1994 .ok_or(Error::UnknownLocalFunction(ident))?;
1995 crate::Statement::Call {
1996 function,
1997 arguments,
1998 result: None,
1999 }
2000 }
2001 };
2002 context
2003 .block
2004 .extend(context.emitter.finish(context.expressions));
2005 context.block.push(stmt);
2006 Ok(())
2007 }
2008
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>>2009 fn parse_statement<'a, 'out>(
2010 &mut self,
2011 lexer: &mut Lexer<'a>,
2012 mut context: StatementContext<'a, '_, 'out>,
2013 block: &'out mut crate::Block,
2014 is_uniform_control_flow: bool,
2015 ) -> Result<(), Error<'a>> {
2016 let word = match lexer.next() {
2017 (Token::Separator(';'), _) => return Ok(()),
2018 (Token::Paren('{'), _) => {
2019 self.scopes.push(Scope::Block);
2020 let mut statements = Vec::new();
2021 while !lexer.skip(Token::Paren('}')) {
2022 self.parse_statement(
2023 lexer,
2024 context.reborrow(),
2025 &mut statements,
2026 is_uniform_control_flow,
2027 )?;
2028 }
2029 self.scopes.pop();
2030 block.push(crate::Statement::Block(statements));
2031 return Ok(());
2032 }
2033 (Token::Word(word), _) => word,
2034 other => return Err(Error::Unexpected(other, "statement")),
2035 };
2036
2037 self.scopes.push(Scope::Statement);
2038 let mut emitter = super::Emitter::default();
2039 match word {
2040 "let" => {
2041 emitter.start(context.expressions);
2042 let name = lexer.next_ident()?;
2043 let given_ty = if lexer.skip(Token::Separator(':')) {
2044 let (ty, _access) =
2045 self.parse_type_decl(lexer, None, context.types, context.constants)?;
2046 Some(ty)
2047 } else {
2048 None
2049 };
2050 lexer.expect(Token::Operation('='))?;
2051 let expr_id = self
2052 .parse_general_expression(lexer, context.as_expression(block, &mut emitter))?;
2053 lexer.expect(Token::Separator(';'))?;
2054 if let Some(ty) = given_ty {
2055 // prepare the typifier, but work around mutable borrowing...
2056 let _ = context
2057 .as_expression(block, &mut emitter)
2058 .resolve_type(expr_id)?;
2059 let expr_inner = context.typifier.get(expr_id, context.types);
2060 let given_inner = &context.types[ty].inner;
2061 if given_inner != expr_inner {
2062 log::error!(
2063 "Given type {:?} doesn't match expected {:?}",
2064 given_inner,
2065 expr_inner
2066 );
2067 return Err(Error::LetTypeMismatch(name, ty));
2068 }
2069 }
2070 block.extend(emitter.finish(context.expressions));
2071 context.lookup_ident.insert(name, expr_id);
2072 }
2073 "var" => {
2074 enum Init {
2075 Empty,
2076 Constant(Handle<crate::Constant>),
2077 Variable(Handle<crate::Expression>),
2078 }
2079
2080 let (name, ty, _access) =
2081 self.parse_variable_ident_decl(lexer, context.types, context.constants)?;
2082
2083 let init = if lexer.skip(Token::Operation('=')) {
2084 emitter.start(context.expressions);
2085 let value = self.parse_general_expression(
2086 lexer,
2087 context.as_expression(block, &mut emitter),
2088 )?;
2089 block.extend(emitter.finish(context.expressions));
2090 match context.expressions[value] {
2091 crate::Expression::Constant(handle) if is_uniform_control_flow => {
2092 Init::Constant(handle)
2093 }
2094 _ => Init::Variable(value),
2095 }
2096 } else {
2097 Init::Empty
2098 };
2099
2100 lexer.expect(Token::Separator(';'))?;
2101 let var_id = context.variables.append(crate::LocalVariable {
2102 name: Some(name.to_owned()),
2103 ty,
2104 init: match init {
2105 Init::Constant(value) => Some(value),
2106 _ => None,
2107 },
2108 });
2109
2110 let expr_id = context
2111 .expressions
2112 .append(crate::Expression::LocalVariable(var_id));
2113 context.lookup_ident.insert(name, expr_id);
2114
2115 if let Init::Variable(value) = init {
2116 block.push(crate::Statement::Store {
2117 pointer: expr_id,
2118 value,
2119 });
2120 }
2121 }
2122 "return" => {
2123 let value = if lexer.peek().0 != Token::Separator(';') {
2124 emitter.start(context.expressions);
2125 let handle = self.parse_general_expression(
2126 lexer,
2127 context.as_expression(block, &mut emitter),
2128 )?;
2129 block.extend(emitter.finish(context.expressions));
2130 Some(handle)
2131 } else {
2132 None
2133 };
2134 lexer.expect(Token::Separator(';'))?;
2135 block.push(crate::Statement::Return { value });
2136 }
2137 "if" => {
2138 emitter.start(context.expressions);
2139 lexer.expect(Token::Paren('('))?;
2140 let condition = self
2141 .parse_general_expression(lexer, context.as_expression(block, &mut emitter))?;
2142 lexer.expect(Token::Paren(')'))?;
2143 block.extend(emitter.finish(context.expressions));
2144
2145 let accept = self.parse_block(lexer, context.reborrow(), false)?;
2146 let mut elsif_stack = Vec::new();
2147 while lexer.skip(Token::Word("elseif")) {
2148 let mut sub_emitter = super::Emitter::default();
2149 sub_emitter.start(context.expressions);
2150 lexer.expect(Token::Paren('('))?;
2151 let other_condition = self.parse_general_expression(
2152 lexer,
2153 context.as_expression(block, &mut sub_emitter),
2154 )?;
2155 lexer.expect(Token::Paren(')'))?;
2156 let other_emit = sub_emitter.finish(context.expressions);
2157 let other_block = self.parse_block(lexer, context.reborrow(), false)?;
2158 elsif_stack.push((other_condition, other_emit, other_block));
2159 }
2160 let mut reject = if lexer.skip(Token::Word("else")) {
2161 self.parse_block(lexer, context.reborrow(), false)?
2162 } else {
2163 Vec::new()
2164 };
2165 // reverse-fold the else-if blocks
2166 //Note: we may consider uplifting this to the IR
2167 for (other_cond, other_emit, other_block) in elsif_stack.drain(..).rev() {
2168 reject = other_emit
2169 .into_iter()
2170 .chain(iter::once(crate::Statement::If {
2171 condition: other_cond,
2172 accept: other_block,
2173 reject,
2174 }))
2175 .collect();
2176 }
2177
2178 block.push(crate::Statement::If {
2179 condition,
2180 accept,
2181 reject,
2182 });
2183 }
2184 "switch" => {
2185 emitter.start(context.expressions);
2186 lexer.expect(Token::Paren('('))?;
2187 let selector = self
2188 .parse_general_expression(lexer, context.as_expression(block, &mut emitter))?;
2189 lexer.expect(Token::Paren(')'))?;
2190 block.extend(emitter.finish(context.expressions));
2191 lexer.expect(Token::Paren('{'))?;
2192 let mut cases = Vec::new();
2193 let mut default = Vec::new();
2194
2195 loop {
2196 // cases + default
2197 match lexer.next() {
2198 (Token::Word("case"), _) => {
2199 // parse a list of values
2200 let value = loop {
2201 let value = lexer.next_sint_literal()?;
2202 if lexer.skip(Token::Separator(',')) {
2203 if lexer.skip(Token::Separator(':')) {
2204 break value;
2205 }
2206 } else {
2207 lexer.expect(Token::Separator(':'))?;
2208 break value;
2209 }
2210 cases.push(crate::SwitchCase {
2211 value,
2212 body: Vec::new(),
2213 fall_through: true,
2214 });
2215 };
2216
2217 let mut body = Vec::new();
2218 lexer.expect(Token::Paren('{'))?;
2219 let fall_through = loop {
2220 // default statements
2221 if lexer.skip(Token::Word("fallthrough")) {
2222 lexer.expect(Token::Separator(';'))?;
2223 lexer.expect(Token::Paren('}'))?;
2224 break true;
2225 }
2226 if lexer.skip(Token::Paren('}')) {
2227 break false;
2228 }
2229 self.parse_statement(lexer, context.reborrow(), &mut body, false)?;
2230 };
2231
2232 cases.push(crate::SwitchCase {
2233 value,
2234 body,
2235 fall_through,
2236 });
2237 }
2238 (Token::Word("default"), _) => {
2239 lexer.expect(Token::Separator(':'))?;
2240 default = self.parse_block(lexer, context.reborrow(), false)?;
2241 }
2242 (Token::Paren('}'), _) => break,
2243 other => return Err(Error::Unexpected(other, "switch item")),
2244 }
2245 }
2246
2247 block.push(crate::Statement::Switch {
2248 selector,
2249 cases,
2250 default,
2251 });
2252 }
2253 "loop" => {
2254 let mut body = Vec::new();
2255 let mut continuing = Vec::new();
2256 lexer.expect(Token::Paren('{'))?;
2257
2258 loop {
2259 if lexer.skip(Token::Word("continuing")) {
2260 continuing = self.parse_block(lexer, context.reborrow(), false)?;
2261 lexer.expect(Token::Paren('}'))?;
2262 break;
2263 }
2264 if lexer.skip(Token::Paren('}')) {
2265 break;
2266 }
2267 self.parse_statement(lexer, context.reborrow(), &mut body, false)?;
2268 }
2269
2270 block.push(crate::Statement::Loop { body, continuing });
2271 }
2272 "for" => {
2273 lexer.expect(Token::Paren('('))?;
2274 if !lexer.skip(Token::Separator(';')) {
2275 let num_statements = block.len();
2276 self.parse_statement(
2277 lexer,
2278 context.reborrow(),
2279 block,
2280 is_uniform_control_flow,
2281 )?;
2282 if block.len() != num_statements {
2283 match *block.last().unwrap() {
2284 crate::Statement::Store { .. } | crate::Statement::Call { .. } => {}
2285 _ => return Err(Error::InvalidForInitializer),
2286 }
2287 }
2288 };
2289
2290 let mut body = Vec::new();
2291 if !lexer.skip(Token::Separator(';')) {
2292 emitter.start(context.expressions);
2293 let condition = self.parse_general_expression(
2294 lexer,
2295 context.as_expression(&mut body, &mut emitter),
2296 )?;
2297 lexer.expect(Token::Separator(';'))?;
2298 body.extend(emitter.finish(context.expressions));
2299 body.push(crate::Statement::If {
2300 condition,
2301 accept: Vec::new(),
2302 reject: vec![crate::Statement::Break],
2303 });
2304 };
2305
2306 let mut continuing = Vec::new();
2307 if let Token::Word(ident) = lexer.peek().0 {
2308 // manually parse the next statement here instead of calling parse_statement
2309 // because the statement is not terminated with a semicolon
2310 let _ = lexer.next();
2311 self.parse_statement_restricted(
2312 lexer,
2313 ident,
2314 context.as_expression(&mut continuing, &mut emitter),
2315 )?;
2316 }
2317 lexer.expect(Token::Paren(')'))?;
2318 lexer.expect(Token::Paren('{'))?;
2319
2320 while !lexer.skip(Token::Paren('}')) {
2321 self.parse_statement(lexer, context.reborrow(), &mut body, false)?;
2322 }
2323
2324 block.push(crate::Statement::Loop { body, continuing });
2325 }
2326 "break" => block.push(crate::Statement::Break),
2327 "continue" => block.push(crate::Statement::Continue),
2328 "discard" => block.push(crate::Statement::Kill),
2329 "storageBarrier" => {
2330 lexer.expect(Token::Paren('('))?;
2331 lexer.expect(Token::Paren(')'))?;
2332 block.push(crate::Statement::Barrier(crate::Barrier::STORAGE));
2333 }
2334 "workgroupBarrier" => {
2335 lexer.expect(Token::Paren('('))?;
2336 lexer.expect(Token::Paren(')'))?;
2337 block.push(crate::Statement::Barrier(crate::Barrier::WORK_GROUP));
2338 }
2339 "textureStore" => {
2340 emitter.start(context.expressions);
2341 lexer.open_arguments()?;
2342 let image_name = lexer.next_ident()?;
2343 let image = context.lookup_ident.lookup(image_name)?;
2344 lexer.expect(Token::Separator(','))?;
2345 let mut expr_context = context.as_expression(block, &mut emitter);
2346 let arrayed = match *expr_context.resolve_type(image)? {
2347 crate::TypeInner::Image { arrayed, .. } => arrayed,
2348 _ => return Err(Error::BadTexture(image_name)),
2349 };
2350 let coordinate = self.parse_general_expression(lexer, expr_context)?;
2351 let array_index = if arrayed {
2352 lexer.expect(Token::Separator(','))?;
2353 Some(self.parse_general_expression(
2354 lexer,
2355 context.as_expression(block, &mut emitter),
2356 )?)
2357 } else {
2358 None
2359 };
2360 lexer.expect(Token::Separator(','))?;
2361 let value = self
2362 .parse_general_expression(lexer, context.as_expression(block, &mut emitter))?;
2363 lexer.close_arguments()?;
2364 block.extend(emitter.finish(context.expressions));
2365 block.push(crate::Statement::ImageStore {
2366 image,
2367 coordinate,
2368 array_index,
2369 value,
2370 });
2371 }
2372 // assignment or a function call
2373 ident => {
2374 self.parse_statement_restricted(
2375 lexer,
2376 ident,
2377 context.as_expression(block, &mut emitter),
2378 )?;
2379 lexer.expect(Token::Separator(';'))?;
2380 }
2381 }
2382 self.scopes.pop();
2383 Ok(())
2384 }
2385
parse_block<'a>( &mut self, lexer: &mut Lexer<'a>, mut context: StatementContext<'a, '_, '_>, is_uniform_control_flow: bool, ) -> Result<Vec<crate::Statement>, Error<'a>>2386 fn parse_block<'a>(
2387 &mut self,
2388 lexer: &mut Lexer<'a>,
2389 mut context: StatementContext<'a, '_, '_>,
2390 is_uniform_control_flow: bool,
2391 ) -> Result<Vec<crate::Statement>, Error<'a>> {
2392 self.scopes.push(Scope::Block);
2393 lexer.expect(Token::Paren('{'))?;
2394 let mut block = Vec::new();
2395 while !lexer.skip(Token::Paren('}')) {
2396 self.parse_statement(
2397 lexer,
2398 context.reborrow(),
2399 &mut block,
2400 is_uniform_control_flow,
2401 )?;
2402 }
2403 self.scopes.pop();
2404 Ok(block)
2405 }
2406
parse_varying_binding<'a>( &mut self, lexer: &mut Lexer<'a>, ) -> Result<Option<crate::Binding>, Error<'a>>2407 fn parse_varying_binding<'a>(
2408 &mut self,
2409 lexer: &mut Lexer<'a>,
2410 ) -> Result<Option<crate::Binding>, Error<'a>> {
2411 if !lexer.skip(Token::DoubleParen('[')) {
2412 return Ok(None);
2413 }
2414
2415 let mut bind_parser = BindingParser::default();
2416 self.scopes.push(Scope::Attribute);
2417 loop {
2418 let word = lexer.next_ident()?;
2419 bind_parser.parse(lexer, word)?;
2420 match lexer.next() {
2421 (Token::DoubleParen(']'), _) => {
2422 break;
2423 }
2424 (Token::Separator(','), _) => {}
2425 other => return Err(Error::Unexpected(other, "attribute separator")),
2426 }
2427 }
2428 self.scopes.pop();
2429 bind_parser.finish()
2430 }
2431
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>>2432 fn parse_function_decl<'a>(
2433 &mut self,
2434 lexer: &mut Lexer<'a>,
2435 module: &mut crate::Module,
2436 lookup_global_expression: &FastHashMap<&'a str, crate::Expression>,
2437 ) -> Result<(crate::Function, &'a str), Error<'a>> {
2438 self.scopes.push(Scope::FunctionDecl);
2439 // read function name
2440 let mut lookup_ident = FastHashMap::default();
2441 let fun_name = lexer.next_ident()?;
2442 // populate initial expressions
2443 let mut expressions = Arena::new();
2444 for (&name, expression) in lookup_global_expression.iter() {
2445 let expr_handle = expressions.append(expression.clone());
2446 lookup_ident.insert(name, expr_handle);
2447 }
2448 // read parameter list
2449 let mut arguments = Vec::new();
2450 lexer.expect(Token::Paren('('))?;
2451 let mut ready = true;
2452 while !lexer.skip(Token::Paren(')')) {
2453 if !ready {
2454 return Err(Error::Unexpected(lexer.next(), "comma"));
2455 }
2456 let binding = self.parse_varying_binding(lexer)?;
2457 let (param_name, param_type, _access) =
2458 self.parse_variable_ident_decl(lexer, &mut module.types, &mut module.constants)?;
2459 let param_index = arguments.len() as u32;
2460 let expression_token =
2461 expressions.append(crate::Expression::FunctionArgument(param_index));
2462 lookup_ident.insert(param_name, expression_token);
2463 arguments.push(crate::FunctionArgument {
2464 name: Some(param_name.to_string()),
2465 ty: param_type,
2466 binding,
2467 });
2468 ready = lexer.skip(Token::Separator(','));
2469 }
2470 // read return type
2471 let result = if lexer.skip(Token::Arrow) && !lexer.skip(Token::Word("void")) {
2472 let binding = self.parse_varying_binding(lexer)?;
2473 let (ty, _access) =
2474 self.parse_type_decl(lexer, None, &mut module.types, &mut module.constants)?;
2475 Some(crate::FunctionResult { ty, binding })
2476 } else {
2477 None
2478 };
2479
2480 let mut fun = crate::Function {
2481 name: Some(fun_name.to_string()),
2482 arguments,
2483 result,
2484 local_variables: Arena::new(),
2485 expressions,
2486 body: Vec::new(),
2487 };
2488
2489 // read body
2490 let mut typifier = super::Typifier::new();
2491 fun.body = self.parse_block(
2492 lexer,
2493 StatementContext {
2494 lookup_ident: &mut lookup_ident,
2495 typifier: &mut typifier,
2496 variables: &mut fun.local_variables,
2497 expressions: &mut fun.expressions,
2498 types: &mut module.types,
2499 constants: &mut module.constants,
2500 global_vars: &module.global_variables,
2501 functions: &module.functions,
2502 arguments: &fun.arguments,
2503 },
2504 true,
2505 )?;
2506 // fixup the IR
2507 ensure_block_returns(&mut fun.body);
2508 // done
2509 self.scopes.pop();
2510
2511 Ok((fun, fun_name))
2512 }
2513
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>>2514 fn parse_global_decl<'a>(
2515 &mut self,
2516 lexer: &mut Lexer<'a>,
2517 module: &mut crate::Module,
2518 lookup_global_expression: &mut FastHashMap<&'a str, crate::Expression>,
2519 ) -> Result<bool, Error<'a>> {
2520 // read attributes
2521 let mut binding = None;
2522 // Perspective is the default qualifier.
2523 let mut stage = None;
2524 let mut is_block = false;
2525 let mut workgroup_size = [0u32; 3];
2526 let mut early_depth_test = None;
2527
2528 if lexer.skip(Token::DoubleParen('[')) {
2529 let (mut bind_index, mut bind_group) = (None, None);
2530 self.scopes.push(Scope::Attribute);
2531 loop {
2532 match lexer.next_ident()? {
2533 "binding" => {
2534 lexer.expect(Token::Paren('('))?;
2535 bind_index = Some(lexer.next_uint_literal()?);
2536 lexer.expect(Token::Paren(')'))?;
2537 }
2538 "block" => {
2539 is_block = true;
2540 }
2541 "group" => {
2542 lexer.expect(Token::Paren('('))?;
2543 bind_group = Some(lexer.next_uint_literal()?);
2544 lexer.expect(Token::Paren(')'))?;
2545 }
2546 "stage" => {
2547 lexer.expect(Token::Paren('('))?;
2548 stage = Some(conv::map_shader_stage(lexer.next_ident()?)?);
2549 lexer.expect(Token::Paren(')'))?;
2550 }
2551 "workgroup_size" => {
2552 lexer.expect(Token::Paren('('))?;
2553 for (i, size) in workgroup_size.iter_mut().enumerate() {
2554 *size = lexer.next_uint_literal()?;
2555 match lexer.next() {
2556 (Token::Paren(')'), _) => break,
2557 (Token::Separator(','), _) if i != 2 => (),
2558 other => {
2559 return Err(Error::Unexpected(
2560 other,
2561 "workgroup size separator",
2562 ))
2563 }
2564 }
2565 }
2566 for size in workgroup_size.iter_mut() {
2567 if *size == 0 {
2568 *size = 1;
2569 }
2570 }
2571 }
2572 "early_depth_test" => {
2573 let conservative = if lexer.skip(Token::Paren('(')) {
2574 let value = conv::map_conservative_depth(lexer.next_ident()?)?;
2575 lexer.expect(Token::Paren(')'))?;
2576 Some(value)
2577 } else {
2578 None
2579 };
2580 early_depth_test = Some(crate::EarlyDepthTest { conservative });
2581 }
2582 word => return Err(Error::UnknownAttribute(word)),
2583 }
2584 match lexer.next() {
2585 (Token::DoubleParen(']'), _) => {
2586 break;
2587 }
2588 (Token::Separator(','), _) => {}
2589 other => return Err(Error::Unexpected(other, "attribute separator")),
2590 }
2591 }
2592 if let (Some(group), Some(index)) = (bind_group, bind_index) {
2593 binding = Some(crate::ResourceBinding {
2594 group,
2595 binding: index,
2596 });
2597 }
2598 self.scopes.pop();
2599 }
2600
2601 // read items
2602 match lexer.next() {
2603 (Token::Separator(';'), _) => {}
2604 (Token::Word("struct"), _) => {
2605 let name = lexer.next_ident()?;
2606 let (members, span, alignment) =
2607 self.parse_struct_body(lexer, &mut module.types, &mut module.constants)?;
2608 let ty = module.types.fetch_or_append(crate::Type {
2609 name: Some(name.to_string()),
2610 inner: crate::TypeInner::Struct {
2611 level: if is_block {
2612 crate::StructLevel::Root
2613 } else {
2614 crate::StructLevel::Normal { alignment }
2615 },
2616 members,
2617 span,
2618 },
2619 });
2620 self.lookup_type.insert(name.to_owned(), ty);
2621 lexer.expect(Token::Separator(';'))?;
2622 }
2623 (Token::Word("type"), _) => {
2624 let name = lexer.next_ident()?;
2625 lexer.expect(Token::Operation('='))?;
2626 let (ty, _access) = self.parse_type_decl(
2627 lexer,
2628 Some(name),
2629 &mut module.types,
2630 &mut module.constants,
2631 )?;
2632 self.lookup_type.insert(name.to_owned(), ty);
2633 lexer.expect(Token::Separator(';'))?;
2634 }
2635 (Token::Word("let"), _) => {
2636 let (name, explicit_ty, _access) = self.parse_variable_ident_decl(
2637 lexer,
2638 &mut module.types,
2639 &mut module.constants,
2640 )?;
2641 lexer.expect(Token::Operation('='))?;
2642 let first_token_span = lexer.next();
2643 let const_handle = self.parse_const_expression_impl(
2644 first_token_span,
2645 lexer,
2646 Some(name),
2647 &mut module.types,
2648 &mut module.constants,
2649 )?;
2650 let con = &module.constants[const_handle];
2651 let type_match = match con.inner {
2652 crate::ConstantInner::Scalar { width, value } => {
2653 module.types[explicit_ty].inner
2654 == crate::TypeInner::Scalar {
2655 kind: value.scalar_kind(),
2656 width,
2657 }
2658 }
2659 crate::ConstantInner::Composite { ty, components: _ } => ty == explicit_ty,
2660 };
2661 if !type_match {
2662 return Err(Error::LetTypeMismatch(name, explicit_ty));
2663 }
2664 //TODO: check `ty` against `const_handle`.
2665 lexer.expect(Token::Separator(';'))?;
2666 lookup_global_expression.insert(name, crate::Expression::Constant(const_handle));
2667 }
2668 (Token::Word("var"), _) => {
2669 let pvar =
2670 self.parse_variable_decl(lexer, &mut module.types, &mut module.constants)?;
2671 let class = match pvar.class {
2672 Some(c) => c,
2673 None => match module.types[pvar.ty].inner {
2674 crate::TypeInner::Struct { .. } if binding.is_some() => {
2675 if pvar.access.is_empty() {
2676 crate::StorageClass::Uniform
2677 } else {
2678 crate::StorageClass::Storage
2679 }
2680 }
2681 crate::TypeInner::Array { .. } if binding.is_some() => {
2682 crate::StorageClass::Storage
2683 }
2684 crate::TypeInner::Image { .. } | crate::TypeInner::Sampler { .. } => {
2685 crate::StorageClass::Handle
2686 }
2687 _ => crate::StorageClass::Private,
2688 },
2689 };
2690 let var_handle = module.global_variables.append(crate::GlobalVariable {
2691 name: Some(pvar.name.to_owned()),
2692 class,
2693 binding: binding.take(),
2694 ty: pvar.ty,
2695 init: pvar.init,
2696 storage_access: pvar.access,
2697 });
2698 lookup_global_expression
2699 .insert(pvar.name, crate::Expression::GlobalVariable(var_handle));
2700 }
2701 (Token::Word("fn"), _) => {
2702 let (function, name) =
2703 self.parse_function_decl(lexer, module, &lookup_global_expression)?;
2704 match stage {
2705 Some(stage) => module.entry_points.push(crate::EntryPoint {
2706 name: name.to_string(),
2707 stage,
2708 early_depth_test,
2709 workgroup_size,
2710 function,
2711 }),
2712 None => {
2713 module.functions.append(function);
2714 }
2715 }
2716 }
2717 (Token::End, _) => return Ok(false),
2718 other => return Err(Error::Unexpected(other, "global item")),
2719 }
2720
2721 match binding {
2722 None => Ok(true),
2723 // we had the attribute but no var?
2724 Some(_) => Err(Error::Other),
2725 }
2726 }
2727
parse(&mut self, source: &str) -> Result<crate::Module, ParseError>2728 pub fn parse(&mut self, source: &str) -> Result<crate::Module, ParseError> {
2729 self.scopes.clear();
2730 self.lookup_type.clear();
2731 self.layouter.clear();
2732
2733 let mut module = crate::Module::default();
2734 let mut lexer = Lexer::new(source);
2735 let mut lookup_global_expression = FastHashMap::default();
2736 loop {
2737 match self.parse_global_decl(&mut lexer, &mut module, &mut lookup_global_expression) {
2738 Err(error) => return Err(error.as_parse_error(lexer.source)),
2739 Ok(true) => {}
2740 Ok(false) => {
2741 if !self.scopes.is_empty() {
2742 log::error!("Reached the end of file, but scopes are not closed");
2743 return Err(Error::Other.as_parse_error(lexer.source));
2744 };
2745 module.apply_common_default_interpolation();
2746 return Ok(module);
2747 }
2748 }
2749 }
2750 }
2751 }
2752
parse_str(source: &str) -> Result<crate::Module, ParseError>2753 pub fn parse_str(source: &str) -> Result<crate::Module, ParseError> {
2754 Parser::new().parse(source)
2755 }
2756
2757 pub struct StringErrorBuffer {
2758 buf: Vec<u8>,
2759 }
2760
2761 impl StringErrorBuffer {
new() -> Self2762 pub fn new() -> Self {
2763 Self { buf: Vec::new() }
2764 }
2765
into_string(self) -> String2766 pub fn into_string(self) -> String {
2767 String::from_utf8(self.buf).unwrap()
2768 }
2769 }
2770
2771 impl Write for StringErrorBuffer {
write(&mut self, buf: &[u8]) -> io::Result<usize>2772 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
2773 self.buf.extend(buf);
2774 Ok(buf.len())
2775 }
2776
flush(&mut self) -> io::Result<()>2777 fn flush(&mut self) -> io::Result<()> {
2778 Ok(())
2779 }
2780 }
2781
2782 impl WriteColor for StringErrorBuffer {
supports_color(&self) -> bool2783 fn supports_color(&self) -> bool {
2784 false
2785 }
2786
set_color(&mut self, _spec: &ColorSpec) -> io::Result<()>2787 fn set_color(&mut self, _spec: &ColorSpec) -> io::Result<()> {
2788 Ok(())
2789 }
2790
reset(&mut self) -> io::Result<()>2791 fn reset(&mut self) -> io::Result<()> {
2792 Ok(())
2793 }
2794 }
2795