From dc98305bb8cc3d326dbb08f861ed7678433b36fe Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 27 Jan 2021 10:51:12 -0500 Subject: [PATCH] Print out detailed WGSL errors --- Cargo.toml | 5 ++++- examples/convert.rs | 39 ++++++++++++++++++++++++++++----------- src/front/wgsl/mod.rs | 26 ++++++++++++++++++++++---- 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8db6230008..0d0b4859c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,9 +33,12 @@ spv-in = ["petgraph", "spirv"] spv-out = ["spirv"] wgsl-in = [] +#Note: it would be nice to do `cargo run` for conversion. +# Blocked on https://github.com/rust-lang/cargo/issues/4663 + [dev-dependencies] difference = "2.0" -env_logger = "0.6" +env_logger = "0.8" ron = "0.6" serde = { version = "1.0", features = ["derive"] } spirv = { package = "spirv_headers", version = "1.5", features = ["deserialize"] } diff --git a/examples/convert.rs b/examples/convert.rs index b77da388a3..82c03a7349 100644 --- a/examples/convert.rs +++ b/examples/convert.rs @@ -1,4 +1,4 @@ -use std::{env, fs, path::Path}; +use std::{env, fmt, fs, path::Path}; #[derive(Hash, PartialEq, Eq, serde::Deserialize)] enum Stage { @@ -41,6 +41,21 @@ struct Parameters { mtl_bindings: naga::FastHashMap, } +trait PrettyResult { + type Target; + fn unwrap_pretty(self) -> Self::Target; +} + +impl PrettyResult for Result { + type Target = T; + fn unwrap_pretty(self) -> T { + match self { + Result::Ok(value) => value, + Result::Err(e) => panic!("{}", e), + } + } +} + fn main() { env_logger::init(); @@ -52,7 +67,7 @@ fn main() { let param_path = std::path::PathBuf::from(&args[1]).with_extension("param.ron"); let params = match fs::read_to_string(param_path) { - Ok(string) => ron::de::from_str(&string).unwrap(), + Ok(string) => ron::de::from_str(&string).unwrap_pretty(), Err(_) => { let mut param = Parameters::default(); // very useful to have this by default @@ -82,7 +97,7 @@ fn main() { #[cfg(feature = "wgsl-in")] "wgsl" => { let input = fs::read_to_string(&args[1]).unwrap(); - naga::front::wgsl::parse_str(&input).unwrap() + naga::front::wgsl::parse_str(&input).unwrap_pretty() } #[cfg(feature = "glsl-in")] "vert" => { @@ -93,7 +108,7 @@ fn main() { naga::ShaderStage::Vertex, Default::default(), ) - .unwrap() + .unwrap_pretty() } #[cfg(feature = "glsl-in")] "frag" => { @@ -104,7 +119,7 @@ fn main() { naga::ShaderStage::Fragment, Default::default(), ) - .unwrap() + .unwrap_pretty() } #[cfg(feature = "glsl-in")] "comp" => { @@ -115,12 +130,12 @@ fn main() { naga::ShaderStage::Compute, Default::default(), ) - .unwrap() + .unwrap_pretty() } #[cfg(feature = "deserialize")] "ron" => { let mut input = fs::File::open(&args[1]).unwrap(); - ron::de::from_reader(&mut input).unwrap() + ron::de::from_reader(&mut input).unwrap_pretty() } other => { if true { @@ -132,7 +147,9 @@ fn main() { }; // validate the IR - naga::proc::Validator::new().validate(&module).unwrap(); + naga::proc::Validator::new() + .validate(&module) + .unwrap_pretty(); if args.len() <= 2 { println!("{:#?}", module); @@ -188,7 +205,7 @@ fn main() { } }); - let spv = spv::write_vec(&module, debug_flag, params.spv_capabilities).unwrap(); + let spv = spv::write_vec(&module, debug_flag, params.spv_capabilities).unwrap_pretty(); let bytes = spv .iter() @@ -234,7 +251,7 @@ fn main() { .open(&args[2]) .unwrap(); - let mut writer = glsl::Writer::new(file, &module, &options).unwrap(); + let mut writer = glsl::Writer::new(file, &module, &options).unwrap_pretty(); writer .write() @@ -250,7 +267,7 @@ fn main() { .with_enumerate_arrays(true) .with_decimal_floats(true); - let output = ron::ser::to_string_pretty(&module, config).unwrap(); + let output = ron::ser::to_string_pretty(&module, config).unwrap_pretty(); fs::write(&args[2], output).unwrap(); } other => { diff --git a/src/front/wgsl/mod.rs b/src/front/wgsl/mod.rs index b1914dca42..d9b68c5bc9 100644 --- a/src/front/wgsl/mod.rs +++ b/src/front/wgsl/mod.rs @@ -17,6 +17,8 @@ use self::lexer::Lexer; use std::num::NonZeroU32; use thiserror::Error; +const SPACE: &str = " "; + #[derive(Copy, Clone, Debug, PartialEq)] pub enum Token<'a> { Separator(char), @@ -336,11 +338,12 @@ struct ParsedVariable<'a> { } #[derive(Clone, Debug, Error)] -#[error("error while parsing WGSL in scopes {scopes:?} at position {pos:?}: {error}")] +#[error("error while parsing WGSL in scopes {scopes:?} at line {line} pos {pos}: {error}")] pub struct ParseError<'a> { pub error: Error<'a>, pub scopes: Vec, - pub pos: (usize, usize), + pub line: usize, + pub pos: usize, } pub struct Parser { @@ -2085,23 +2088,38 @@ impl Parser { Err(error) => { let pos = lexer.offset_from(source); let (mut rows, mut cols) = (0, 1); + let (mut prev_line, mut cur_line) = ("", ""); for line in source[..pos].lines() { rows += 1; cols = line.len(); + prev_line = cur_line; + cur_line = line; + } + log::error!("|\t{}", prev_line); + log::error!( + ">\t{}{}", + cur_line, + source[pos..].lines().next().unwrap_or_default() + ); + if cols <= SPACE.len() { + log::error!("|\t{}^", &SPACE[..cols]); } return Err(ParseError { error, scopes: std::mem::replace(&mut self.scopes, Vec::new()), - pos: (rows, cols), + line: rows, + pos: cols, }); } Ok(true) => {} Ok(false) => { if !self.scopes.is_empty() { + log::error!("Reached the end of file, but scopes are not closed"); return Err(ParseError { error: Error::Other, scopes: std::mem::replace(&mut self.scopes, Vec::new()), - pos: (0, 0), + line: 0, + pos: 0, }); }; return Ok(module);