From 2ce14e25d8f1685bd3486257cba4025587fd0fb9 Mon Sep 17 00:00:00 2001 From: Matthew Gordon Date: Thu, 12 Dec 2024 10:23:34 -0400 Subject: [PATCH] Add //#include macro You can now include WGSL files in other WGSL files --- Cargo.toml | 3 +- src/source_reader.rs | 79 ++++++++++++++++++++++++++++---------------- 2 files changed, 53 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 496a3c5..fba2f74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,4 +9,5 @@ proc-macro = true [dependencies] quote = "1.0" syn = "2.0.90" -naga = { version = "23.0.0", features = ["wgsl-in"] } \ No newline at end of file +naga = { version = "23.0.0", features = ["wgsl-in"] } +regex = "1.11.1" \ No newline at end of file diff --git a/src/source_reader.rs b/src/source_reader.rs index 74a6fe0..0a142d7 100644 --- a/src/source_reader.rs +++ b/src/source_reader.rs @@ -1,55 +1,78 @@ use { crate::Error, + regex::Regex, std::{ fs, + io::{BufRead, BufReader}, path::{Path, PathBuf}, }, }; -struct SourceMap { - filename: PathBuf, - offset: usize, - total_lines: usize, - insertions: Vec, +pub struct SourceMap { + lines: Vec, + files: Vec, + line_map: Vec<(usize, usize)>, } -pub struct SourceFile { - source_text: String, - source_map: SourceMap, -} - -impl SourceFile { +impl SourceMap { pub fn root_filename(&self) -> &Path { - &self.source_map.filename + &self.files[0] } - pub fn full_text(&self) -> &str { - &self.source_text + pub fn full_text(&self) -> String { + self.lines.join("\n") } pub fn map_source_line_num(&self, line_num: usize) -> (&Path, usize) { - (&self.source_map.filename, line_num) + let (source_file_index, source_file_line_num) = self.line_map[line_num]; + (&self.files[source_file_index], source_file_line_num) } - pub fn all_filenames(&self) -> Vec<&Path> { - vec![&self.source_map.filename] + pub fn all_filenames(&self) -> &Vec { + &self.files } } -pub fn read_source_file(source_dir: &Path, filename: &Path) -> Result { - let source_text = fs::read_to_string(&source_dir.join(filename)).map_err(|err| { +fn ingest_file( + source_dir: &Path, + filename: &Path, + source_map: &mut SourceMap, +) -> Result<(), Error> { + let file = fs::File::open(source_dir.join(filename)).map_err(|err| { Error::from_message(format!( "Could not open \"{}\": {}", &filename.as_os_str().to_string_lossy(), err )) })?; - Ok(SourceFile { - source_text, - source_map: SourceMap { - filename: filename.into(), - offset: 0, - total_lines: 0, - insertions: vec![], - }, - }) + let file_num = source_map.files.len(); + source_map.files.push(filename.to_path_buf()); + let var_name = Regex::new(r"^//\#include\s+(.*)\s*$"); + let include_regex = var_name.unwrap(); + for (line_num, line) in BufReader::new(file).lines().enumerate() { + let line = line.map_err(|err| { + Error::from_message(format!( + "Error reading \"{}\": {}", + &filename.as_os_str().to_string_lossy(), + err + )) + })?; + if let Some(captures) = include_regex.captures(&line) { + let nested_filename = captures.get(1).unwrap().as_str(); + ingest_file(source_dir, Path::new(nested_filename), source_map)?; + } else { + source_map.lines.push(line); + source_map.line_map.push((file_num, line_num)); + } + } + Ok(()) +} + +pub fn read_source_file(source_dir: &Path, filename: &Path) -> Result { + let mut source_map = SourceMap { + lines: vec![], + files: vec![], + line_map: vec![], + }; + ingest_file(source_dir, filename, &mut source_map)?; + Ok(source_map) }