// Copyright (C) 2025 Thom Hayward. // // This program is free software: you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free Software // Foundation, version 3. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more // details. // // You should have received a copy of the GNU General Public License along with // this program. If not, see . // #[cfg(feature = "asm")] mod asm; mod conv; mod ops; mod reg; mod universal_machine; use std::{path::Path, time::Instant}; use universal_machine::Um; fn main() { let mut program = Vec::new(); let mut time = false; for arg in std::env::args().skip(1) { if arg == "--time" { time = true; continue; } let path = Path::new(&arg); program.extend_from_slice(&match load_program(path) { Ok(p) => p, Err(error) => { eprintln!("{error}"); std::process::exit(1); } }); } let start = Instant::now(); Um::new(program) .stdout(&mut std::io::stdout()) .stdin(&mut std::io::stdin()) .run(); if time { eprintln!("{:?}", start.elapsed()); } } #[cfg(feature = "asm")] fn load_program(path: &Path) -> std::io::Result> { match path.extension().map(|ext| ext.as_encoded_bytes()) { // In an ideal world we would just add `#[cfg(feature = "asm")]` here. // Unfortunately this leads some wierd code generation fuckery which // makes the version without the 'asm' feature ~1-2 seconds slower // when running the sandmark program. Some(b"uasm" | b"asm") => { let source = std::fs::read_to_string(path)?; Ok(asm::assemble(&source)) } _ => { let program = std::fs::read(path)?; Ok(conv::bytes_to_program(&program).unwrap()) } } } #[cfg(not(feature = "asm"))] fn load_program(path: &Path) -> std::io::Result> { let program = std::fs::read(path)?; Ok(conv::bytes_to_program(&program).unwrap()) }