use wgslender::{Error, Severity, Strictness, Validation, validate};
const UNREACHABLE: &str = "\
// Every line of this runs except the last one.
@group(0) @binding(0) var<storage, read_write> counters: array<u32>;
@compute @workgroup_size(64)
fn main(@builtin(local_invocation_index) i: u32) {
counters[i] = i;
return;
counters[i] = 0u;
}
";
const UNDECLARED: &str = "\
// Parses fine. The name in it does not resolve to anything.
@compute @workgroup_size(1)
fn main() {
let x = undeclared_variable;
}
";
fn main() -> Result<(), Error> {
report(
"unreachable code, default",
&validate(UNREACHABLE, Strictness::Default)?,
);
report(
"unreachable code, strict",
&validate(UNREACHABLE, Strictness::Strict)?,
);
report(
"an undeclared identifier",
&validate(UNDECLARED, Strictness::Default)?,
);
println!(
"The first two listings hold the same code at the same position.\n\
Strictness grades a finding; it does not change what was found."
);
Ok(())
}
fn report(label: &str, validation: &Validation) {
let verdict = if validation.valid {
"accepted"
} else {
"rejected"
};
println!(
"{label:<28}{verdict:<10}{}, {}",
plural(validation.error_count, "error"),
plural(validation.warning_count, "warning"),
);
for diagnostic in &validation.diagnostics {
let position = format!("{}:{}", diagnostic.line, diagnostic.column);
println!(
" {:<9}{:<7}{position:<7}{}",
grade(diagnostic.severity),
diagnostic.code.as_deref().unwrap_or("-"),
diagnostic.message,
);
}
println!();
}
fn grade(severity: Severity) -> &'static str {
match severity {
Severity::Error => "error",
Severity::Warning => "warning",
Severity::Info => "info",
Severity::Note => "note",
Severity::Hint => "hint",
_ => "unknown",
}
}
fn plural(count: u32, noun: &str) -> String {
if count == 1 {
format!("{count} {noun}")
} else {
format!("{count} {noun}s")
}
}