109 lines
2.9 KiB
Rust
109 lines
2.9 KiB
Rust
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<String>,
|
|
#[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<u8> = 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 {}
|