1use std::fs;
2use std::path::Path;
3use uxn_tal::{Assembler, AssemblerError};
4
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 println!("šØ UXN TAL Batch Assembler Test");
7 println!("Testing all TAL files in the project");
8 println!("====================================");
9
10 let tal_files = find_tal_files(".")?;
11 let mut successful = 0;
12 let mut failed = 0;
13 let mut total_size = 0;
14
15 for file_path in &tal_files {
16 print!("Assembling {}... ", file_path);
17
18 match assemble_file(file_path) {
19 Ok(size) => {
20 println!("ā
Success ({} bytes)", size);
21 successful += 1;
22 total_size += size;
23 }
24 Err(e) => {
25 println!("ā Failed: {}", e);
26 failed += 1;
27 }
28 }
29 }
30
31 println!("\nš Summary:");
32 println!("===========");
33 println!("Total files: {}", tal_files.len());
34 println!(
35 "Successful: {} ({:.1}%)",
36 successful,
37 (successful as f64 / tal_files.len() as f64) * 100.0
38 );
39 println!(
40 "Failed: {} ({:.1}%)",
41 failed,
42 (failed as f64 / tal_files.len() as f64) * 100.0
43 );
44 println!("Total ROM size: {} bytes", total_size);
45
46 if failed > 0 {
47 println!("\nā ļø Failed files may need additional TAL features or contain syntax errors.");
48 } else {
49 println!("\nš All TAL files assembled successfully!");
50 }
51
52 Ok(())
53}
54
55fn find_tal_files(dir: &str) -> Result<Vec<String>, Box<dyn std::error::Error>> {
56 let mut tal_files = Vec::new();
57 find_tal_files_recursive(Path::new(dir), &mut tal_files)?;
58 tal_files.sort();
59 Ok(tal_files)
60}
61
62fn find_tal_files_recursive(
63 dir: &Path,
64 tal_files: &mut Vec<String>,
65) -> Result<(), Box<dyn std::error::Error>> {
66 if dir.is_dir() {
67 for entry in fs::read_dir(dir)? {
68 let entry = entry?;
69 let path = entry.path();
70
71 if path.is_dir() {
72 if let Some(dir_name) = path.file_name().and_then(|n| n.to_str()) {
74 if dir_name.starts_with('.') || dir_name == "target" {
75 continue;
76 }
77 }
78 find_tal_files_recursive(&path, tal_files)?;
79 } else if let Some(extension) = path.extension() {
80 if extension == "tal" {
81 if let Some(path_str) = path.to_str() {
82 tal_files.push(path_str.to_string());
83 }
84 }
85 }
86 }
87 }
88 Ok(())
89}
90
91fn assemble_file(file_path: &str) -> Result<usize, String> {
92 let source =
93 fs::read_to_string(file_path).map_err(|e| format!("Failed to read file: {}", e))?;
94
95 let mut assembler = Assembler::new();
96 match assembler.assemble(&source, Some(file_path.to_string())) {
97 Ok(rom) => {
98 let rom_path = file_path.replace(".tal", ".rom");
100 if let Err(e) = fs::write(&rom_path, &rom) {
101 return Err(format!("Failed to write ROM: {}", e));
102 }
103 Ok(rom.len())
104 }
105 Err(e) => {
106 let error_msg = match &e {
108 AssemblerError::SyntaxError {
109 line,
110 message,
111 path,
112 position,
113 source_line,
114 } => {
115 format!(
116 "{}:{}:{}: {}\n {}",
117 path, line, position, message, source_line
118 )
119 }
120 _ => {
121 format!("{}: {}", file_path, e)
122 }
123 };
124 Err(error_msg)
125 }
126 }
127}