1//! WGSL directives. The focal point of this API is [`DirectiveKind`].
2//!
3//! See also <https://www.w3.org/TR/WGSL/#directives>.
45pub mod enable_extension;
6pub(crate) mod language_extension;
78use alloc::boxed::Box;
910/// A parsed sentinel word indicating the type of directive to be parsed next.
11#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
12#[cfg_attr(test, derive(strum::EnumIter))]
13pub(crate) enum DirectiveKind {
14/// A [`crate::diagnostic_filter`].
15Diagnostic,
16/// An [`enable_extension`].
17Enable,
18/// A [`language_extension`].
19Requires,
20}
2122impl DirectiveKind {
23const DIAGNOSTIC: &'static str = "diagnostic";
24const ENABLE: &'static str = "enable";
25const REQUIRES: &'static str = "requires";
2627/// Convert from a sentinel word in WGSL into its associated [`DirectiveKind`], if possible.
28pub fn from_ident(s: &str) -> Option<Self> {
29Some(match s {
30Self::DIAGNOSTIC => Self::Diagnostic,
31Self::ENABLE => Self::Enable,
32Self::REQUIRES => Self::Requires,
33_ => return None,
34 })
35 }
36}
3738impl crate::diagnostic_filter::Severity {
39#[cfg(feature = "wgsl-in")]
40pub(crate) fn report_wgsl_parse_diag<'a>(
41self,
42 err: Box<crate::front::wgsl::error::Error<'a>>,
43 source: &str,
44 ) -> crate::front::wgsl::Result<'a, ()> {
45self.report_diag(err, |e, level| {
46let e = e.as_parse_error(source);
47log::log!(level, "{}", e.emit_to_string(source));
48 })
49 }
50}
5152#[cfg(test)]
53mod test {
54use alloc::format;
5556use strum::IntoEnumIterator;
5758use super::DirectiveKind;
59use crate::front::wgsl::assert_parse_err;
6061#[test]
62fn directive_after_global_decl() {
63for unsupported_shader in DirectiveKind::iter() {
64let directive;
65let expected_msg;
66match unsupported_shader {
67 DirectiveKind::Diagnostic => {
68 directive = "diagnostic(off,derivative_uniformity)";
69 expected_msg = "\
70error: expected global declaration, but found a global directive
71 ┌─ wgsl:2:1
72 │
732 │ diagnostic(off,derivative_uniformity);
74 │ ^^^^^^^^^^ written after first global declaration
75 │
76 = note: global directives are only allowed before global declarations; maybe hoist this closer to the top of the shader module?
7778";
79 }
80 DirectiveKind::Enable => {
81 directive = "enable f16";
82 expected_msg = "\
83error: expected global declaration, but found a global directive
84 ┌─ wgsl:2:1
85 │
862 │ enable f16;
87 │ ^^^^^^ written after first global declaration
88 │
89 = note: global directives are only allowed before global declarations; maybe hoist this closer to the top of the shader module?
9091";
92 }
93 DirectiveKind::Requires => {
94 directive = "requires readonly_and_readwrite_storage_textures";
95 expected_msg = "\
96error: expected global declaration, but found a global directive
97 ┌─ wgsl:2:1
98 │
992 │ requires readonly_and_readwrite_storage_textures;
100 │ ^^^^^^^^ written after first global declaration
101 │
102 = note: global directives are only allowed before global declarations; maybe hoist this closer to the top of the shader module?
103104";
105 }
106 }
107108let shader = format!(
109"\
110@group(0) @binding(0) var<storage> thing: i32;
111{directive};
112"
113);
114 assert_parse_err(&shader, expected_msg);
115 }
116 }
117}