use std::path::Path;
use uxn_tal::{Assembler, AssemblerError};
fn find_tal_files(root: &str) -> Result<Vec<String>, std::io::Error> {
let mut files = Vec::new();
for entry in walkdir::WalkDir::new(root) {
let entry = entry?;
let path = entry.path();
if path.extension().and_then(|s| s.to_str()) == Some("tal") {
files.push(path.to_string_lossy().to_string());
}
}
Ok(files)
}
fn assemble_file(file_path: &str) -> Result<usize, AssemblerError> {
let source = std::fs::read_to_string(file_path)?;
let mut assembler = Assembler::new();
let path = std::fs::canonicalize(file_path)
.map(|p| p.to_string_lossy().to_string())
.unwrap_or_else(|_| file_path.to_string());
let rom = assembler.assemble(&source, Some(path))?;
Ok(rom.len())
}
fn assemble_file_with_symbols(
path: &Path,
) -> Result<(std::path::PathBuf, std::path::PathBuf, usize), AssemblerError> {
let source = std::fs::read_to_string(path)?;
let mut assembler = Assembler::new();
let canonical = std::fs::canonicalize(path)
.map(|p| p.to_string_lossy().to_string())
.unwrap_or_else(|_| path.to_string_lossy().to_string());
let rom = assembler.assemble(&source, Some(canonical))?;
let rom_path = path.with_extension("rom");
let sym_path = path.with_extension("sym");
std::fs::write(&rom_path, &rom)?;
let sym_txt = assembler.generate_symbol_file();
std::fs::write(&sym_path, sym_txt)?;
Ok((rom_path, sym_path, rom.len()))
}
fn assemble_file_auto(path: &Path) -> Result<(std::path::PathBuf, usize), AssemblerError> {
let source = std::fs::read_to_string(path)?;
let mut assembler = Assembler::new();
let canonical = std::fs::canonicalize(path)
.map(|p| p.to_string_lossy().to_string())
.unwrap_or_else(|_| path.to_string_lossy().to_string());
let rom = assembler.assemble(&source, Some(canonical))?;
let rom_path = path.with_extension("rom");
std::fs::write(&rom_path, &rom)?;
Ok((rom_path, rom.len()))
}
const DEMOS_DIR: &str = "../tal";
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("đ¨ UXN TAL Batch Assembler Test");
println!("Testing all TAL files in the project");
println!("====================================");
let tal_files = find_tal_files(".")?;
let mut successful = 0;
let mut failed = 0;
let mut total_size = 0;
for file_path in &tal_files {
print!("Assembling {}... ", file_path);
match assemble_file(file_path) {
Ok(size) => {
println!("â
Success ({} bytes)", size);
successful += 1;
total_size += size;
}
Err(e) => {
println!("â Failed: {}", e);
failed += 1;
}
}
}
let generate_symbols = std::env::args().any(|arg| arg == "--symbols" || arg == "-s");
if generate_symbols {
println!("đ Symbol file generation enabled\n");
}
if let Ok(entries) = std::fs::read_dir(DEMOS_DIR) {
for entry in entries {
let entry = entry?;
let path = entry.path();
if path.extension().and_then(|s| s.to_str()) != Some("tal") {
continue;
}
let filename = path.file_name().unwrap().to_string_lossy();
print!("đ Assembling {}... ", filename);
if generate_symbols {
match assemble_file_with_symbols(&path) {
Ok((rom_path, sym_path, size)) => {
println!(
"â
{} bytes -> {} + {}",
size,
rom_path.file_name().unwrap().to_string_lossy(),
sym_path.file_name().unwrap().to_string_lossy()
);
successful += 1;
total_size += size;
}
Err(AssemblerError::Io(e)) => {
println!("â IO error: {}", e);
failed += 1;
}
Err(e) => {
println!("â Assembly error: {}", e);
failed += 1;
}
}
} else {
match assemble_file_auto(&path) {
Ok((rom_path, size)) => {
println!(
"â
{} bytes -> {}",
size,
rom_path.file_name().unwrap().to_string_lossy()
);
successful += 1;
total_size += size;
}
Err(AssemblerError::Io(e)) => {
println!("â IO error: {}", e);
failed += 1;
}
Err(e) => {
println!("â Assembly error: {}", e);
failed += 1;
}
}
}
}
} else {
println!(
"âšī¸ DEMOS_DIR '{}' does not exist, skipping demo assembly.",
DEMOS_DIR
);
}
println!("\nđ Results:");
println!(" â
Successfully assembled: {} files", successful);
println!(" â Failed: {} files", failed);
println!(" đĻ Total ROM size: {} bytes", total_size);
if failed > 0 {
println!("\nđĄ Some files may use features not yet implemented in our assembler.");
println!(" This is normal for a TAL assembler implementation.");
}
Ok(())
}