glsl/
syntax.rs

1//! GLSL abstract syntax tree and grammar.
2//!
3//! This module exports all the grammar syntax that defines GLSL. You’ll be handling ASTs
4//! representing your GLSL source.
5//!
6//! The most external form of a GLSL parsed AST is [`TranslationUnit`] (a shader). Some parts of the
7//! tree are *boxed*. This is due to two facts:
8//!
9//! - Recursion is used, hence we need a way to give our types a static size.
10//! - Because of some very deep variants, runtime size would explode if no indirection weren’t
11//!   in place.
12//!
13//! The types are commented so feel free to inspect each of theme. As a starter, you should read
14//! the documentation of [`Expr`], [`FunctionDefinition`], [`Statement`] and [`TranslationUnit`].
15//!
16//! [`Statement`]: crate::syntax::Statement
17//! [`TranslationUnit`]: crate::syntax::TranslationUnit
18//! [`Expr`]: crate::syntax::Expr
19//! [`FunctionDefinition`]: crate::syntax::FunctionDefinition
20
21use std::fmt;
22use std::iter::{once, FromIterator};
23use std::ops::{Deref, DerefMut};
24
25/// A non-empty [`Vec`]. It has at least one element.
26#[derive(Clone, Debug, PartialEq)]
27pub struct NonEmpty<T>(pub Vec<T>);
28
29impl<T> NonEmpty<T> {
30  /// Construct a non-empty from an iterator.
31  ///
32  /// # Errors
33  ///
34  /// `None` if the iterator yields no value.
35  pub fn from_non_empty_iter<I>(iter: I) -> Option<Self>
36  where
37    I: IntoIterator<Item = T>,
38  {
39    let vec: Vec<_> = iter.into_iter().collect();
40
41    if vec.is_empty() {
42      None
43    } else {
44      Some(NonEmpty(vec))
45    }
46  }
47
48  /// Move a new item at the end of the non-empty.
49  pub fn push(&mut self, item: T) {
50    self.0.push(item);
51  }
52
53  /// Move out the last element of the non-empty.
54  ///
55  /// # Errors
56  ///
57  /// This function returns `None` if called on a non-empty that contains a single element.
58  pub fn pop(&mut self) -> Option<T> {
59    if self.0.len() == 1 {
60      None
61    } else {
62      self.0.pop()
63    }
64  }
65}
66
67impl<T> IntoIterator for NonEmpty<T> {
68  type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
69  type Item = T;
70
71  fn into_iter(self) -> Self::IntoIter {
72    self.0.into_iter()
73  }
74}
75
76impl<'a, T> IntoIterator for &'a NonEmpty<T> {
77  type IntoIter = <&'a Vec<T> as IntoIterator>::IntoIter;
78  type Item = &'a T;
79
80  fn into_iter(self) -> Self::IntoIter {
81    self.0.iter()
82  }
83}
84
85impl<'a, T> IntoIterator for &'a mut NonEmpty<T> {
86  type IntoIter = <&'a mut Vec<T> as IntoIterator>::IntoIter;
87  type Item = &'a mut T;
88
89  fn into_iter(self) -> Self::IntoIter {
90    self.0.iter_mut()
91  }
92}
93
94impl<T> Extend<T> for NonEmpty<T> {
95  fn extend<I>(&mut self, iter: I)
96  where
97    I: IntoIterator<Item = T>,
98  {
99    self.0.extend(iter);
100  }
101}
102
103/// A path literal.
104#[derive(Clone, Debug, PartialEq)]
105pub enum Path {
106  /// Specified with angle brackets.
107  Absolute(String),
108  /// Specified with double quotes.
109  Relative(String),
110}
111
112/// Error that might occur when creating a new [`Identifier`].
113#[derive(Debug)]
114pub enum IdentifierError {
115  StartsWithDigit,
116  ContainsNonASCIIAlphaNum,
117}
118
119impl std::error::Error for IdentifierError {}
120
121impl fmt::Display for IdentifierError {
122  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
123    match *self {
124      IdentifierError::StartsWithDigit => f.write_str("starts starts with a digit"),
125
126      IdentifierError::ContainsNonASCIIAlphaNum => {
127        f.write_str("contains at least one non-alphanumeric ASCII character")
128      }
129    }
130  }
131}
132
133/// A generic identifier.
134#[derive(Clone, Debug, PartialEq)]
135pub struct Identifier(pub String);
136
137impl Identifier {
138  /// Create a new [`Identifier`].
139  ///
140  /// # Errors
141  ///
142  /// This function will fail if the identifier starts with a digit or contains non-alphanumeric
143  /// ASCII characters.
144  pub fn new<N>(name: N) -> Result<Self, IdentifierError>
145  where
146    N: Into<String>,
147  {
148    let name = name.into();
149
150    if name
151      .chars()
152      .next()
153      .map(|c| c.is_ascii_alphabetic() || c == '_')
154      == Some(false)
155    {
156      // check the first letter is not a digit
157      Err(IdentifierError::StartsWithDigit)
158    } else if name.contains(|c: char| !(c.is_ascii_alphanumeric() || c == '_')) {
159      // check we only have ASCII alphanumeric characters
160      Err(IdentifierError::ContainsNonASCIIAlphaNum)
161    } else {
162      Ok(Identifier(name))
163    }
164  }
165
166  /// Get the string representation of the identifier.
167  pub fn as_str(&self) -> &str {
168    &self.0
169  }
170}
171
172impl<'a> From<&'a str> for Identifier {
173  fn from(s: &str) -> Self {
174    Identifier(s.to_owned())
175  }
176}
177
178impl From<String> for Identifier {
179  fn from(s: String) -> Self {
180    Identifier(s)
181  }
182}
183
184impl fmt::Display for Identifier {
185  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
186    self.0.fmt(f)
187  }
188}
189
190/// Any type name.
191#[derive(Clone, Debug, PartialEq)]
192pub struct TypeName(pub String);
193
194impl TypeName {
195  /// Create a new [`TypeName`].
196  ///
197  /// # Errors
198  ///
199  /// This function will fail if the type name starts with a digit or contains non-alphanumeric
200  /// ASCII characters.
201  pub fn new<N>(name: N) -> Result<Self, IdentifierError>
202  where
203    N: Into<String>,
204  {
205    // build as identifier and unwrap into type name
206    let Identifier(tn) = Identifier::new(name)?;
207    Ok(TypeName(tn))
208  }
209
210  /// Get the string representation of the type name.
211  pub fn as_str(&self) -> &str {
212    &self.0
213  }
214}
215
216impl<'a> From<&'a str> for TypeName {
217  fn from(s: &str) -> Self {
218    TypeName(s.to_owned())
219  }
220}
221
222impl From<String> for TypeName {
223  fn from(s: String) -> Self {
224    TypeName(s)
225  }
226}
227
228impl fmt::Display for TypeName {
229  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
230    self.0.fmt(f)
231  }
232}
233
234/// Type specifier (non-array).
235#[derive(Clone, Debug, PartialEq)]
236pub enum TypeSpecifierNonArray {
237  // transparent types
238  Void,
239  Bool,
240  Int,
241  UInt,
242  Float,
243  Double,
244  Vec2,
245  Vec3,
246  Vec4,
247  DVec2,
248  DVec3,
249  DVec4,
250  BVec2,
251  BVec3,
252  BVec4,
253  IVec2,
254  IVec3,
255  IVec4,
256  UVec2,
257  UVec3,
258  UVec4,
259  Mat2,
260  Mat3,
261  Mat4,
262  Mat23,
263  Mat24,
264  Mat32,
265  Mat34,
266  Mat42,
267  Mat43,
268  DMat2,
269  DMat3,
270  DMat4,
271  DMat23,
272  DMat24,
273  DMat32,
274  DMat34,
275  DMat42,
276  DMat43,
277  // floating point opaque types
278  Sampler1D,
279  Image1D,
280  Sampler2D,
281  Image2D,
282  Sampler3D,
283  Image3D,
284  SamplerCube,
285  ImageCube,
286  Sampler2DRect,
287  Image2DRect,
288  Sampler1DArray,
289  Image1DArray,
290  Sampler2DArray,
291  Image2DArray,
292  SamplerBuffer,
293  ImageBuffer,
294  Sampler2DMS,
295  Image2DMS,
296  Sampler2DMSArray,
297  Image2DMSArray,
298  SamplerCubeArray,
299  ImageCubeArray,
300  Sampler1DShadow,
301  Sampler2DShadow,
302  Sampler2DRectShadow,
303  Sampler1DArrayShadow,
304  Sampler2DArrayShadow,
305  SamplerCubeShadow,
306  SamplerCubeArrayShadow,
307  // signed integer opaque types
308  ISampler1D,
309  IImage1D,
310  ISampler2D,
311  IImage2D,
312  ISampler3D,
313  IImage3D,
314  ISamplerCube,
315  IImageCube,
316  ISampler2DRect,
317  IImage2DRect,
318  ISampler1DArray,
319  IImage1DArray,
320  ISampler2DArray,
321  IImage2DArray,
322  ISamplerBuffer,
323  IImageBuffer,
324  ISampler2DMS,
325  IImage2DMS,
326  ISampler2DMSArray,
327  IImage2DMSArray,
328  ISamplerCubeArray,
329  IImageCubeArray,
330  // unsigned integer opaque types
331  AtomicUInt,
332  USampler1D,
333  UImage1D,
334  USampler2D,
335  UImage2D,
336  USampler3D,
337  UImage3D,
338  USamplerCube,
339  UImageCube,
340  USampler2DRect,
341  UImage2DRect,
342  USampler1DArray,
343  UImage1DArray,
344  USampler2DArray,
345  UImage2DArray,
346  USamplerBuffer,
347  UImageBuffer,
348  USampler2DMS,
349  UImage2DMS,
350  USampler2DMSArray,
351  UImage2DMSArray,
352  USamplerCubeArray,
353  UImageCubeArray,
354  Struct(StructSpecifier),
355  TypeName(TypeName),
356}
357
358/// Type specifier.
359#[derive(Clone, Debug, PartialEq)]
360pub struct TypeSpecifier {
361  pub ty: TypeSpecifierNonArray,
362  pub array_specifier: Option<ArraySpecifier>,
363}
364
365impl TypeSpecifier {
366  pub fn new(ty: TypeSpecifierNonArray) -> Self {
367    TypeSpecifier {
368      ty,
369      array_specifier: None,
370    }
371  }
372}
373
374impl From<TypeSpecifierNonArray> for TypeSpecifier {
375  fn from(ty: TypeSpecifierNonArray) -> Self {
376    TypeSpecifier::new(ty)
377  }
378}
379
380/// Struct specifier. Used to create new, user-defined types.
381#[derive(Clone, Debug, PartialEq)]
382pub struct StructSpecifier {
383  pub name: Option<TypeName>,
384  pub fields: NonEmpty<StructFieldSpecifier>,
385}
386
387/// Struct field specifier. Used to add fields to struct specifiers.
388#[derive(Clone, Debug, PartialEq)]
389pub struct StructFieldSpecifier {
390  pub qualifier: Option<TypeQualifier>,
391  pub ty: TypeSpecifier,
392  pub identifiers: NonEmpty<ArrayedIdentifier>, // several identifiers of the same type
393}
394
395impl StructFieldSpecifier {
396  /// Create a struct field.
397  pub fn new<A, T>(identifier: A, ty: T) -> Self
398  where
399    A: Into<ArrayedIdentifier>,
400    T: Into<TypeSpecifier>,
401  {
402    StructFieldSpecifier {
403      qualifier: None,
404      ty: ty.into(),
405      identifiers: NonEmpty(vec![identifier.into()]),
406    }
407  }
408
409  /// Create a list of struct fields that all have the same type.
410  pub fn new_many<I>(identifiers: I, ty: TypeSpecifier) -> Self
411  where
412    I: IntoIterator<Item = ArrayedIdentifier>,
413  {
414    StructFieldSpecifier {
415      qualifier: None,
416      ty,
417      identifiers: NonEmpty(identifiers.into_iter().collect()),
418    }
419  }
420}
421
422/// An identifier with an optional array specifier.
423#[derive(Clone, Debug, PartialEq)]
424pub struct ArrayedIdentifier {
425  pub ident: Identifier,
426  pub array_spec: Option<ArraySpecifier>,
427}
428
429impl ArrayedIdentifier {
430  pub fn new<I, AS>(ident: I, array_spec: AS) -> Self
431  where
432    I: Into<Identifier>,
433    AS: Into<Option<ArraySpecifier>>,
434  {
435    ArrayedIdentifier {
436      ident: ident.into(),
437      array_spec: array_spec.into(),
438    }
439  }
440}
441
442impl<'a> From<&'a str> for ArrayedIdentifier {
443  fn from(ident: &str) -> Self {
444    ArrayedIdentifier {
445      ident: Identifier(ident.to_owned()),
446      array_spec: None,
447    }
448  }
449}
450
451impl From<Identifier> for ArrayedIdentifier {
452  fn from(ident: Identifier) -> Self {
453    ArrayedIdentifier {
454      ident,
455      array_spec: None,
456    }
457  }
458}
459
460/// Type qualifier.
461#[derive(Clone, Debug, PartialEq)]
462pub struct TypeQualifier {
463  pub qualifiers: NonEmpty<TypeQualifierSpec>,
464}
465
466/// Type qualifier spec.
467#[derive(Clone, Debug, PartialEq)]
468pub enum TypeQualifierSpec {
469  Storage(StorageQualifier),
470  Layout(LayoutQualifier),
471  Precision(PrecisionQualifier),
472  Interpolation(InterpolationQualifier),
473  Invariant,
474  Precise,
475}
476
477/// Storage qualifier.
478#[derive(Clone, Debug, PartialEq)]
479pub enum StorageQualifier {
480  Const,
481  InOut,
482  In,
483  Out,
484  Centroid,
485  Patch,
486  Sample,
487  Uniform,
488  Attribute,
489  Varying,
490  Buffer,
491  Shared,
492  Coherent,
493  Volatile,
494  Restrict,
495  ReadOnly,
496  WriteOnly,
497  Subroutine(Vec<TypeName>),
498}
499
500/// Layout qualifier.
501#[derive(Clone, Debug, PartialEq)]
502pub struct LayoutQualifier {
503  pub ids: NonEmpty<LayoutQualifierSpec>,
504}
505
506/// Layout qualifier spec.
507#[derive(Clone, Debug, PartialEq)]
508pub enum LayoutQualifierSpec {
509  Identifier(Identifier, Option<Box<Expr>>),
510  Shared,
511}
512
513/// Precision qualifier.
514#[derive(Clone, Debug, PartialEq)]
515pub enum PrecisionQualifier {
516  High,
517  Medium,
518  Low,
519}
520
521/// Interpolation qualifier.
522#[derive(Clone, Debug, PartialEq)]
523pub enum InterpolationQualifier {
524  Smooth,
525  Flat,
526  NoPerspective,
527}
528
529/// Fully specified type.
530#[derive(Clone, Debug, PartialEq)]
531pub struct FullySpecifiedType {
532  pub qualifier: Option<TypeQualifier>,
533  pub ty: TypeSpecifier,
534}
535
536impl FullySpecifiedType {
537  pub fn new(ty: TypeSpecifierNonArray) -> Self {
538    FullySpecifiedType {
539      qualifier: None,
540      ty: TypeSpecifier {
541        ty,
542        array_specifier: None,
543      },
544    }
545  }
546}
547
548impl From<TypeSpecifierNonArray> for FullySpecifiedType {
549  fn from(ty: TypeSpecifierNonArray) -> Self {
550    FullySpecifiedType::new(ty)
551  }
552}
553
554/// Dimensionality of an array.
555#[derive(Clone, Debug, PartialEq)]
556pub struct ArraySpecifier {
557  /// List of all the dimensions – possibly unsized or explicitly-sized.
558  pub dimensions: NonEmpty<ArraySpecifierDimension>,
559}
560
561/// One array specifier dimension.
562#[derive(Clone, Debug, PartialEq)]
563pub enum ArraySpecifierDimension {
564  Unsized,
565  ExplicitlySized(Box<Expr>),
566}
567
568/// A declaration.
569#[derive(Clone, Debug, PartialEq)]
570pub enum Declaration {
571  FunctionPrototype(FunctionPrototype),
572  InitDeclaratorList(InitDeclaratorList),
573  Precision(PrecisionQualifier, TypeSpecifier),
574  Block(Block),
575  Global(TypeQualifier, Vec<Identifier>),
576}
577
578/// A general purpose block, containing fields and possibly a list of declared identifiers. Semantic
579/// is given with the storage qualifier.
580#[derive(Clone, Debug, PartialEq)]
581pub struct Block {
582  pub qualifier: TypeQualifier,
583  pub name: Identifier,
584  pub fields: Vec<StructFieldSpecifier>,
585  pub identifier: Option<ArrayedIdentifier>,
586}
587
588/// Function identifier.
589#[derive(Clone, Debug, PartialEq)]
590pub enum FunIdentifier {
591  Identifier(Identifier),
592  Expr(Box<Expr>),
593}
594
595impl FunIdentifier {
596  pub(crate) fn into_expr(self) -> Option<Expr> {
597    match self {
598      FunIdentifier::Identifier(..) => None,
599      FunIdentifier::Expr(expr) => Some(*expr),
600    }
601  }
602}
603
604/// Function prototype.
605#[derive(Clone, Debug, PartialEq)]
606pub struct FunctionPrototype {
607  pub ty: FullySpecifiedType,
608  pub name: Identifier,
609  pub parameters: Vec<FunctionParameterDeclaration>,
610}
611
612/// Function parameter declaration.
613#[derive(Clone, Debug, PartialEq)]
614pub enum FunctionParameterDeclaration {
615  Named(Option<TypeQualifier>, FunctionParameterDeclarator),
616  Unnamed(Option<TypeQualifier>, TypeSpecifier),
617}
618
619impl FunctionParameterDeclaration {
620  /// Create a named function argument.
621  pub fn new_named<I, T>(ident: I, ty: T) -> Self
622  where
623    I: Into<ArrayedIdentifier>,
624    T: Into<TypeSpecifier>,
625  {
626    let declator = FunctionParameterDeclarator {
627      ty: ty.into(),
628      ident: ident.into(),
629    };
630
631    FunctionParameterDeclaration::Named(None, declator)
632  }
633
634  /// Create an unnamed function argument (mostly useful for interfaces / function prototypes).
635  pub fn new_unnamed<T>(ty: T) -> Self
636  where
637    T: Into<TypeSpecifier>,
638  {
639    FunctionParameterDeclaration::Unnamed(None, ty.into())
640  }
641}
642
643/// Function parameter declarator.
644#[derive(Clone, Debug, PartialEq)]
645pub struct FunctionParameterDeclarator {
646  pub ty: TypeSpecifier,
647  pub ident: ArrayedIdentifier,
648}
649
650/// Init declarator list.
651#[derive(Clone, Debug, PartialEq)]
652pub struct InitDeclaratorList {
653  pub head: SingleDeclaration,
654  pub tail: Vec<SingleDeclarationNoType>,
655}
656
657/// Single declaration.
658#[derive(Clone, Debug, PartialEq)]
659pub struct SingleDeclaration {
660  pub ty: FullySpecifiedType,
661  pub name: Option<Identifier>,
662  pub array_specifier: Option<ArraySpecifier>,
663  pub initializer: Option<Initializer>,
664}
665
666/// A single declaration with implicit, already-defined type.
667#[derive(Clone, Debug, PartialEq)]
668pub struct SingleDeclarationNoType {
669  pub ident: ArrayedIdentifier,
670  pub initializer: Option<Initializer>,
671}
672
673/// Initializer.
674#[derive(Clone, Debug, PartialEq)]
675pub enum Initializer {
676  Simple(Box<Expr>),
677  List(NonEmpty<Initializer>),
678}
679
680impl From<Expr> for Initializer {
681  fn from(e: Expr) -> Self {
682    Initializer::Simple(Box::new(e))
683  }
684}
685
686/// The most general form of an expression. As you can see if you read the variant list, in GLSL, an
687/// assignment is an expression. This is a bit silly but think of an assignment as a statement first
688/// then an expression which evaluates to what the statement “returns”.
689///
690/// An expression is either an assignment or a list (comma) of assignments.
691#[derive(Clone, Debug, PartialEq)]
692pub enum Expr {
693  /// A variable expression, using an identifier.
694  Variable(Identifier),
695  /// Integral constant expression.
696  IntConst(i32),
697  /// Unsigned integral constant expression.
698  UIntConst(u32),
699  /// Boolean constant expression.
700  BoolConst(bool),
701  /// Single precision floating expression.
702  FloatConst(f32),
703  /// Double precision floating expression.
704  DoubleConst(f64),
705  /// A unary expression, gathering a single expression and a unary operator.
706  Unary(UnaryOp, Box<Expr>),
707  /// A binary expression, gathering two expressions and a binary operator.
708  Binary(BinaryOp, Box<Expr>, Box<Expr>),
709  /// A ternary conditional expression, gathering three expressions.
710  Ternary(Box<Expr>, Box<Expr>, Box<Expr>),
711  /// An assignment is also an expression. Gathers an expression that defines what to assign to, an
712  /// assignment operator and the value to associate with.
713  Assignment(Box<Expr>, AssignmentOp, Box<Expr>),
714  /// Add an array specifier to an expression.
715  Bracket(Box<Expr>, ArraySpecifier),
716  /// A functional call. It has a function identifier and a list of expressions (arguments).
717  FunCall(FunIdentifier, Vec<Expr>),
718  /// An expression associated with a field selection (struct).
719  Dot(Box<Expr>, Identifier),
720  /// Post-incrementation of an expression.
721  PostInc(Box<Expr>),
722  /// Post-decrementation of an expression.
723  PostDec(Box<Expr>),
724  /// An expression that contains several, separated with comma.
725  Comma(Box<Expr>, Box<Expr>),
726}
727
728impl From<i32> for Expr {
729  fn from(x: i32) -> Expr {
730    Expr::IntConst(x)
731  }
732}
733
734impl From<u32> for Expr {
735  fn from(x: u32) -> Expr {
736    Expr::UIntConst(x)
737  }
738}
739
740impl From<bool> for Expr {
741  fn from(x: bool) -> Expr {
742    Expr::BoolConst(x)
743  }
744}
745
746impl From<f32> for Expr {
747  fn from(x: f32) -> Expr {
748    Expr::FloatConst(x)
749  }
750}
751
752impl From<f64> for Expr {
753  fn from(x: f64) -> Expr {
754    Expr::DoubleConst(x)
755  }
756}
757
758/// All unary operators that exist in GLSL.
759#[derive(Clone, Debug, PartialEq)]
760pub enum UnaryOp {
761  Inc,
762  Dec,
763  Add,
764  Minus,
765  Not,
766  Complement,
767}
768
769/// All binary operators that exist in GLSL.
770#[derive(Clone, Debug, PartialEq)]
771pub enum BinaryOp {
772  Or,
773  Xor,
774  And,
775  BitOr,
776  BitXor,
777  BitAnd,
778  Equal,
779  NonEqual,
780  LT,
781  GT,
782  LTE,
783  GTE,
784  LShift,
785  RShift,
786  Add,
787  Sub,
788  Mult,
789  Div,
790  Mod,
791}
792
793/// All possible operators for assigning expressions.
794#[derive(Clone, Debug, PartialEq)]
795pub enum AssignmentOp {
796  Equal,
797  Mult,
798  Div,
799  Mod,
800  Add,
801  Sub,
802  LShift,
803  RShift,
804  And,
805  Xor,
806  Or,
807}
808
809/// Starting rule.
810#[derive(Clone, Debug, PartialEq)]
811pub struct TranslationUnit(pub NonEmpty<ExternalDeclaration>);
812
813/// A shader stage.
814pub type ShaderStage = TranslationUnit;
815
816impl TranslationUnit {
817  /// Construct a translation unit from an iterator representing a _non-empty_ sequence of
818  /// [`ExternalDeclaration`].
819  ///
820  /// # Errors
821  ///
822  /// `None` if the iterator yields no value.
823  pub fn from_non_empty_iter<I>(iter: I) -> Option<Self>
824  where
825    I: IntoIterator<Item = ExternalDeclaration>,
826  {
827    NonEmpty::from_non_empty_iter(iter).map(TranslationUnit)
828  }
829}
830
831impl Deref for TranslationUnit {
832  type Target = NonEmpty<ExternalDeclaration>;
833
834  fn deref(&self) -> &Self::Target {
835    &self.0
836  }
837}
838
839impl DerefMut for TranslationUnit {
840  fn deref_mut(&mut self) -> &mut Self::Target {
841    &mut self.0
842  }
843}
844
845impl IntoIterator for TranslationUnit {
846  type IntoIter = <NonEmpty<ExternalDeclaration> as IntoIterator>::IntoIter;
847  type Item = ExternalDeclaration;
848
849  fn into_iter(self) -> Self::IntoIter {
850    self.0.into_iter()
851  }
852}
853
854impl<'a> IntoIterator for &'a TranslationUnit {
855  type IntoIter = <&'a NonEmpty<ExternalDeclaration> as IntoIterator>::IntoIter;
856  type Item = &'a ExternalDeclaration;
857
858  fn into_iter(self) -> Self::IntoIter {
859    (&self.0).into_iter()
860  }
861}
862
863impl<'a> IntoIterator for &'a mut TranslationUnit {
864  type IntoIter = <&'a mut NonEmpty<ExternalDeclaration> as IntoIterator>::IntoIter;
865  type Item = &'a mut ExternalDeclaration;
866
867  fn into_iter(self) -> Self::IntoIter {
868    (&mut self.0).into_iter()
869  }
870}
871
872/// External declaration.
873#[derive(Clone, Debug, PartialEq)]
874pub enum ExternalDeclaration {
875  Preprocessor(Preprocessor),
876  FunctionDefinition(FunctionDefinition),
877  Declaration(Declaration),
878}
879
880impl ExternalDeclaration {
881  /// Create a new function.
882  pub fn new_fn<T, N, A, S>(ret_ty: T, name: N, args: A, body: S) -> Self
883  where
884    T: Into<FullySpecifiedType>,
885    N: Into<Identifier>,
886    A: IntoIterator<Item = FunctionParameterDeclaration>,
887    S: IntoIterator<Item = Statement>,
888  {
889    ExternalDeclaration::FunctionDefinition(FunctionDefinition {
890      prototype: FunctionPrototype {
891        ty: ret_ty.into(),
892        name: name.into(),
893        parameters: args.into_iter().collect(),
894      },
895      statement: CompoundStatement {
896        statement_list: body.into_iter().collect(),
897      },
898    })
899  }
900
901  /// Create a new structure.
902  ///
903  /// # Errors
904  ///
905  ///   - [`None`] if no fields are provided. GLSL forbids having empty structs.
906  pub fn new_struct<N, F>(name: N, fields: F) -> Option<Self>
907  where
908    N: Into<TypeName>,
909    F: IntoIterator<Item = StructFieldSpecifier>,
910  {
911    let fields: Vec<_> = fields.into_iter().collect();
912
913    if fields.is_empty() {
914      None
915    } else {
916      Some(ExternalDeclaration::Declaration(
917        Declaration::InitDeclaratorList(InitDeclaratorList {
918          head: SingleDeclaration {
919            ty: FullySpecifiedType {
920              qualifier: None,
921              ty: TypeSpecifier {
922                ty: TypeSpecifierNonArray::Struct(StructSpecifier {
923                  name: Some(name.into()),
924                  fields: NonEmpty(fields.into_iter().collect()),
925                }),
926                array_specifier: None,
927              },
928            },
929            name: None,
930            array_specifier: None,
931            initializer: None,
932          },
933          tail: vec![],
934        }),
935      ))
936    }
937  }
938}
939
940/// Function definition.
941#[derive(Clone, Debug, PartialEq)]
942pub struct FunctionDefinition {
943  pub prototype: FunctionPrototype,
944  pub statement: CompoundStatement,
945}
946
947/// Compound statement (with no new scope).
948#[derive(Clone, Debug, PartialEq)]
949pub struct CompoundStatement {
950  pub statement_list: Vec<Statement>,
951}
952
953impl FromIterator<Statement> for CompoundStatement {
954  fn from_iter<T>(iter: T) -> Self
955  where
956    T: IntoIterator<Item = Statement>,
957  {
958    CompoundStatement {
959      statement_list: iter.into_iter().collect(),
960    }
961  }
962}
963
964/// Statement.
965#[derive(Clone, Debug, PartialEq)]
966pub enum Statement {
967  Compound(Box<CompoundStatement>),
968  Simple(Box<SimpleStatement>),
969}
970
971impl Statement {
972  /// Create a case-label sequence of nested statements.
973  pub fn new_case<C, S>(case: C, statements: S) -> Self
974  where
975    C: Into<CaseLabel>,
976    S: IntoIterator<Item = Statement>,
977  {
978    let case_stmt = Statement::Simple(Box::new(SimpleStatement::CaseLabel(case.into())));
979
980    Statement::Compound(Box::new(CompoundStatement {
981      statement_list: once(case_stmt).chain(statements.into_iter()).collect(),
982    }))
983  }
984
985  /// Declare a new variable.
986  ///
987  /// `ty` is the type of the variable, `name` the name of the binding to create,
988  /// `array_specifier` an optional argument to make your binding an array and
989  /// `initializer`
990  pub fn declare_var<T, N, A, I>(ty: T, name: N, array_specifier: A, initializer: I) -> Self
991  where
992    T: Into<FullySpecifiedType>,
993    N: Into<Identifier>,
994    A: Into<Option<ArraySpecifier>>,
995    I: Into<Option<Initializer>>,
996  {
997    Statement::Simple(Box::new(SimpleStatement::Declaration(
998      Declaration::InitDeclaratorList(InitDeclaratorList {
999        head: SingleDeclaration {
1000          ty: ty.into(),
1001          name: Some(name.into()),
1002          array_specifier: array_specifier.into(),
1003          initializer: initializer.into(),
1004        },
1005        tail: Vec::new(),
1006      }),
1007    )))
1008  }
1009}
1010
1011/// Simple statement.
1012#[derive(Clone, Debug, PartialEq)]
1013pub enum SimpleStatement {
1014  Declaration(Declaration),
1015  Expression(ExprStatement),
1016  Selection(SelectionStatement),
1017  Switch(SwitchStatement),
1018  CaseLabel(CaseLabel),
1019  Iteration(IterationStatement),
1020  Jump(JumpStatement),
1021}
1022
1023impl SimpleStatement {
1024  /// Create a new expression statement.
1025  pub fn new_expr<E>(expr: E) -> Self
1026  where
1027    E: Into<Expr>,
1028  {
1029    SimpleStatement::Expression(Some(expr.into()))
1030  }
1031
1032  /// Create a new selection statement (if / else).
1033  pub fn new_if_else<If, True, False>(ife: If, truee: True, falsee: False) -> Self
1034  where
1035    If: Into<Expr>,
1036    True: Into<Statement>,
1037    False: Into<Statement>,
1038  {
1039    SimpleStatement::Selection(SelectionStatement {
1040      cond: Box::new(ife.into()),
1041      rest: SelectionRestStatement::Else(Box::new(truee.into()), Box::new(falsee.into())),
1042    })
1043  }
1044
1045  /// Create a new switch statement.
1046  ///
1047  /// A switch statement is always composed of a [`SimpleStatement::Switch`] block, that contains it
1048  /// all, and has as body a compound list of case statements.
1049  pub fn new_switch<H, B>(head: H, body: B) -> Self
1050  where
1051    H: Into<Expr>,
1052    B: IntoIterator<Item = Statement>,
1053  {
1054    SimpleStatement::Switch(SwitchStatement {
1055      head: Box::new(head.into()),
1056      body: body.into_iter().collect(),
1057    })
1058  }
1059
1060  /// Create a new while statement.
1061  pub fn new_while<C, S>(cond: C, body: S) -> Self
1062  where
1063    C: Into<Condition>,
1064    S: Into<Statement>,
1065  {
1066    SimpleStatement::Iteration(IterationStatement::While(
1067      cond.into(),
1068      Box::new(body.into()),
1069    ))
1070  }
1071
1072  /// Create a new do-while statement.
1073  pub fn new_do_while<C, S>(body: S, cond: C) -> Self
1074  where
1075    S: Into<Statement>,
1076    C: Into<Expr>,
1077  {
1078    SimpleStatement::Iteration(IterationStatement::DoWhile(
1079      Box::new(body.into()),
1080      Box::new(cond.into()),
1081    ))
1082  }
1083}
1084
1085/// Expression statement.
1086pub type ExprStatement = Option<Expr>;
1087
1088/// Selection statement.
1089#[derive(Clone, Debug, PartialEq)]
1090pub struct SelectionStatement {
1091  pub cond: Box<Expr>,
1092  pub rest: SelectionRestStatement,
1093}
1094
1095/// Condition.
1096#[derive(Clone, Debug, PartialEq)]
1097pub enum Condition {
1098  Expr(Box<Expr>),
1099  Assignment(FullySpecifiedType, Identifier, Initializer),
1100}
1101
1102impl From<Expr> for Condition {
1103  fn from(expr: Expr) -> Self {
1104    Condition::Expr(Box::new(expr))
1105  }
1106}
1107
1108/// Selection rest statement.
1109#[derive(Clone, Debug, PartialEq)]
1110pub enum SelectionRestStatement {
1111  /// Body of the if.
1112  Statement(Box<Statement>),
1113  /// The first argument is the body of the if, the rest is the next statement.
1114  Else(Box<Statement>, Box<Statement>),
1115}
1116
1117/// Switch statement.
1118#[derive(Clone, Debug, PartialEq)]
1119pub struct SwitchStatement {
1120  pub head: Box<Expr>,
1121  pub body: Vec<Statement>,
1122}
1123
1124/// Case label statement.
1125#[derive(Clone, Debug, PartialEq)]
1126pub enum CaseLabel {
1127  Case(Box<Expr>),
1128  Def,
1129}
1130
1131/// Iteration statement.
1132#[derive(Clone, Debug, PartialEq)]
1133pub enum IterationStatement {
1134  While(Condition, Box<Statement>),
1135  DoWhile(Box<Statement>, Box<Expr>),
1136  For(ForInitStatement, ForRestStatement, Box<Statement>),
1137}
1138
1139/// For init statement.
1140#[derive(Clone, Debug, PartialEq)]
1141pub enum ForInitStatement {
1142  Expression(Option<Expr>),
1143  Declaration(Box<Declaration>),
1144}
1145
1146/// For init statement.
1147#[derive(Clone, Debug, PartialEq)]
1148pub struct ForRestStatement {
1149  pub condition: Option<Condition>,
1150  pub post_expr: Option<Box<Expr>>,
1151}
1152
1153/// Jump statement.
1154#[derive(Clone, Debug, PartialEq)]
1155pub enum JumpStatement {
1156  Continue,
1157  Break,
1158  Return(Option<Box<Expr>>),
1159  Discard,
1160}
1161
1162/// Some basic preprocessor directives.
1163///
1164/// As it’s important to carry them around the AST because they cannot be substituted in a normal
1165/// preprocessor (they’re used by GPU’s compilers), those preprocessor directives are available for
1166/// inspection.
1167#[derive(Clone, Debug, PartialEq)]
1168pub enum Preprocessor {
1169  Define(PreprocessorDefine),
1170  Else,
1171  ElIf(PreprocessorElIf),
1172  EndIf,
1173  Error(PreprocessorError),
1174  If(PreprocessorIf),
1175  IfDef(PreprocessorIfDef),
1176  IfNDef(PreprocessorIfNDef),
1177  Include(PreprocessorInclude),
1178  Line(PreprocessorLine),
1179  Pragma(PreprocessorPragma),
1180  Undef(PreprocessorUndef),
1181  Version(PreprocessorVersion),
1182  Extension(PreprocessorExtension),
1183}
1184
1185/// A #define preprocessor directive.
1186///
1187/// Allows any expression but only Integer and Float literals make sense
1188#[derive(Clone, Debug, PartialEq)]
1189pub enum PreprocessorDefine {
1190  ObjectLike {
1191    ident: Identifier,
1192    value: String,
1193  },
1194
1195  FunctionLike {
1196    ident: Identifier,
1197    args: Vec<Identifier>,
1198    value: String,
1199  },
1200}
1201
1202/// An #elif preprocessor directive.
1203#[derive(Clone, Debug, PartialEq)]
1204pub struct PreprocessorElIf {
1205  pub condition: String,
1206}
1207
1208/// An #error preprocessor directive.
1209#[derive(Clone, Debug, PartialEq)]
1210pub struct PreprocessorError {
1211  pub message: String,
1212}
1213
1214/// An #if preprocessor directive.
1215#[derive(Clone, Debug, PartialEq)]
1216pub struct PreprocessorIf {
1217  pub condition: String,
1218}
1219
1220/// An #ifdef preprocessor directive.
1221#[derive(Clone, Debug, PartialEq)]
1222pub struct PreprocessorIfDef {
1223  pub ident: Identifier,
1224}
1225
1226/// A #ifndef preprocessor directive.
1227#[derive(Clone, Debug, PartialEq)]
1228pub struct PreprocessorIfNDef {
1229  pub ident: Identifier,
1230}
1231
1232/// An #include name annotation.
1233#[derive(Clone, Debug, PartialEq)]
1234pub struct PreprocessorInclude {
1235  pub path: Path,
1236}
1237
1238/// A #line preprocessor directive.
1239#[derive(Clone, Debug, PartialEq)]
1240pub struct PreprocessorLine {
1241  pub line: u32,
1242  pub source_string_number: Option<u32>,
1243}
1244
1245/// A #pragma preprocessor directive.
1246/// Holds compiler-specific command.
1247#[derive(Clone, Debug, PartialEq)]
1248pub struct PreprocessorPragma {
1249  pub command: String,
1250}
1251
1252/// A #undef preprocessor directive.
1253#[derive(Clone, Debug, PartialEq)]
1254pub struct PreprocessorUndef {
1255  pub name: Identifier,
1256}
1257
1258/// A #version preprocessor directive.
1259#[derive(Clone, Debug, PartialEq)]
1260pub struct PreprocessorVersion {
1261  pub version: u16,
1262  pub profile: Option<PreprocessorVersionProfile>,
1263}
1264
1265/// A #version profile annotation.
1266#[derive(Clone, Debug, PartialEq)]
1267pub enum PreprocessorVersionProfile {
1268  Core,
1269  Compatibility,
1270  ES,
1271}
1272
1273/// An #extension preprocessor directive.
1274#[derive(Clone, Debug, PartialEq)]
1275pub struct PreprocessorExtension {
1276  pub name: PreprocessorExtensionName,
1277  pub behavior: Option<PreprocessorExtensionBehavior>,
1278}
1279
1280/// An #extension name annotation.
1281#[derive(Clone, Debug, PartialEq)]
1282pub enum PreprocessorExtensionName {
1283  /// All extensions you could ever imagine in your whole lifetime (how crazy is that!).
1284  All,
1285  /// A specific extension.
1286  Specific(String),
1287}
1288
1289/// An #extension behavior annotation.
1290#[derive(Clone, Debug, PartialEq)]
1291pub enum PreprocessorExtensionBehavior {
1292  Require,
1293  Enable,
1294  Warn,
1295  Disable,
1296}
1297
1298#[cfg(test)]
1299mod tests {
1300  use super::*;
1301
1302  #[test]
1303  fn create_new_identifier() {
1304    assert!(Identifier::new("foo_bar").is_ok());
1305    assert!(Identifier::new("3foo_bar").is_err());
1306    assert!(Identifier::new("FooBar").is_ok());
1307    assert!(Identifier::new("_FooBar").is_ok());
1308    assert!(Identifier::new("foo3").is_ok());
1309    assert!(Identifier::new("foo3_").is_ok());
1310    assert!(Identifier::new("fδo3_").is_err());
1311  }
1312
1313  #[test]
1314  fn create_new_type_name() {
1315    assert!(TypeName::new("foo_bar").is_ok());
1316    assert!(TypeName::new("FooBar").is_ok());
1317    assert!(TypeName::new("foo3").is_ok());
1318    assert!(TypeName::new("foo3_").is_ok());
1319
1320    assert!(TypeName::new("_FooBar").is_ok());
1321    assert!(TypeName::new("3foo_bar").is_err());
1322    assert!(TypeName::new("fδo3_").is_err());
1323  }
1324
1325  // bool predicate(float x) {
1326  // }
1327  #[test]
1328  fn declare_new_fn() {
1329    let _ = ExternalDeclaration::new_fn(
1330      TypeSpecifierNonArray::Bool,
1331      "predicate",
1332      vec![FunctionParameterDeclaration::new_named(
1333        "x",
1334        TypeSpecifierNonArray::Float,
1335      )],
1336      vec![],
1337    );
1338  }
1339
1340  // struct Point2D {
1341  //   float x;
1342  //   float y;
1343  // };
1344  #[test]
1345  fn declare_struct() {
1346    let point = ExternalDeclaration::new_struct(
1347      "Point2D",
1348      vec![
1349        StructFieldSpecifier::new("x", TypeSpecifierNonArray::Double),
1350        StructFieldSpecifier::new("y", TypeSpecifierNonArray::Double),
1351      ],
1352    );
1353
1354    assert!(point.is_some());
1355  }
1356
1357  // struct Point2D {};
1358  #[test]
1359  fn declare_bad_struct() {
1360    let point = ExternalDeclaration::new_struct("Point2D", vec![]);
1361    assert!(point.is_none());
1362  }
1363
1364  #[test]
1365  fn initializer_from_expr() {
1366    let _: Initializer = Expr::from(false).into();
1367  }
1368}