forge_codegen/
compiler.rs1use std::fs;
4use std::path::{Path, PathBuf};
5
6use walkdir::WalkDir;
7
8use crate::lower::lower;
9use crate::parser::tokenize;
10
11pub fn compile_source(source: &str) -> String {
12 let tokens = tokenize(source);
13 lower(&tokens)
14}
15
16pub fn compile_file(input: &Path, output: &Path) -> std::io::Result<()> {
17 let raw = fs::read_to_string(input)?;
18 let lowered = compile_source(&raw);
19 if let Some(parent) = output.parent() {
20 fs::create_dir_all(parent)?;
21 }
22 fs::write(output, lowered)?;
23 Ok(())
24}
25
26pub fn compile_dir(input_dir: &Path, output_dir: &Path) -> std::io::Result<Vec<PathBuf>> {
29 let mut written = Vec::new();
30 if !input_dir.exists() {
31 return Ok(written);
32 }
33 for entry in WalkDir::new(input_dir).into_iter().filter_map(|e| e.ok()) {
34 if !entry.file_type().is_file() {
35 continue;
36 }
37 let path = entry.path();
38 let Some(file_name) = path.file_name().and_then(|n| n.to_str()) else {
39 continue;
40 };
41 if !file_name.ends_with(".forge.html") && !file_name.ends_with(".forge") {
42 continue;
43 }
44 let rel = path.strip_prefix(input_dir).unwrap_or(path);
45 let out_name = file_name
46 .replace(".forge.html", ".html")
47 .replace(".forge", ".html");
48 let mut out_path = output_dir.to_path_buf();
49 if let Some(parent) = rel.parent() {
50 out_path.push(parent);
51 }
52 out_path.push(out_name);
53 compile_file(path, &out_path)?;
54 written.push(out_path);
55 }
56 Ok(written)
57}