use anyhow::{bail, Result}; use clap::{Parser, Subcommand}; use std::fs; use std::fs::File; use std::io::{BufReader, Read, Write}; use std::path::Path; use hence::*; #[derive(Debug, Parser)] #[clap(author, version, about, long_about = None)] struct Cli { #[clap(subcommand)] commands: Commands, } #[derive(Debug, Subcommand)] enum Commands { #[clap(about = "Lexes source code and outputs tokens")] Lex { #[clap(value_parser)] src: String, }, #[clap(about = "Parses source code and outputs AST")] Parse { #[clap(value_parser)] src: String, }, #[clap(about = "Compiles binary from source code")] Assemble { #[clap(value_parser)] src: String, #[clap(value_parser)] bin: Option, #[clap(long, action)] dump: bool, }, #[clap(about = "Emulates binary")] Run { #[clap(value_parser)] bin: String, }, } fn main() -> Result<()> { let args = Cli::parse(); match args.commands { Commands::Lex { src } => { let assembly = fs::read_to_string(src)?; let tokens = lexer::lex(assembly)?; dbg!(tokens); Ok(()) } Commands::Parse { src } => { let assembly = fs::read_to_string(src)?; let tokens = lexer::lex(assembly)?; let ast = parser::parse(tokens)?; dbg!(ast); Ok(()) } Commands::Assemble { src, bin, dump } => { let assembly = fs::read_to_string(&src)?; let tokens = lexer::lex(assembly)?; let ast = parser::parse(tokens)?; let mut data = assembler::Data::new( match match Path::new(&src).parent() { Some(x) => x.to_str().map(|y| y.to_string()), None => None, } { Some(s) => s, None => bail!("Could not get directory in which source code resides"), }, ast, ); data.assemble()?; if let Some(x) = bin { File::create(x)?.write_all(&data.program)?; } if dump { println!("{}", rhexdump::hexdump(&data.program)); } Ok(()) } Commands::Run { bin } => { let mut program_buf: Vec = vec![]; let file = File::open(bin)?; BufReader::new(file).read_to_end(&mut program_buf)?; if program_buf.len() < (32 * 1024) { program_buf.append(&mut vec![0; 32 * 1024 - program_buf.len()]); } let program: [u8; 32 * 1024] = (&program_buf[0..(32 * 1024)]).try_into()?; let mut data = emulator::Data::new(program); emulator::emulate(&mut data)?; Ok(()) } } } #[cfg(test)] mod tests {}