Add //#include macro

You can now include WGSL files in other WGSL files
This commit is contained in:
Matthew Gordon 2024-12-12 10:23:34 -04:00
parent 5c208a73ec
commit 2ce14e25d8
2 changed files with 53 additions and 29 deletions

View File

@ -10,3 +10,4 @@ proc-macro = true
quote = "1.0"
syn = "2.0.90"
naga = { version = "23.0.0", features = ["wgsl-in"] }
regex = "1.11.1"

View File

@ -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<SourceMap>,
pub struct SourceMap {
lines: Vec<String>,
files: Vec<PathBuf>,
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<PathBuf> {
&self.files
}
}
pub fn read_source_file(source_dir: &Path, filename: &Path) -> Result<SourceFile, Error> {
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<SourceMap, Error> {
let mut source_map = SourceMap {
lines: vec![],
files: vec![],
line_map: vec![],
};
ingest_file(source_dir, filename, &mut source_map)?;
Ok(source_map)
}