//#![feature(plugin)] //#![plugin(dynasm)] //#![feature(proc_macro_hygiene)] #[macro_use] extern crate dynasm; //extern crate winapi; extern crate typed_arena; use std::io::{self, Read}; use std::fs::File; use clap::{Arg, App}; use std::str::FromStr; use std::process::exit; pub mod options; pub mod ir; pub mod parser; pub mod interpret; pub mod optimize; pub mod compile; pub mod formatter; pub mod trans; use crate::ir::MutVisitor; use typed_arena::Arena; fn main() -> io::Result<()> { let matches = App::new("Zombie") .version("0.1.0") .author("Nicolas Winkler <nicolas.winkler@gmx.ch>") .about("Brainfuck interpreter and transpiler") .arg(Arg::with_name("input") .takes_value(true) .help("Input file")) .arg(Arg::with_name("interpret") .long("interpret") .short("i") .help("No JIT, run only simple interpreter")) .arg(Arg::with_name("transpile") .long("transpile") .short("t") .takes_value(true) .help("Transpile to language")) .arg(Arg::with_name("cell size") .long("cell-size") .short("c") .takes_value(true) .help("defines the cell size in bits")) .arg(Arg::with_name("cell modulus") .long("cell-modulus") .short("m") .takes_value(true) .help("defines the cell modulus")) .get_matches(); let mut buffer = String::new(); if let Some(input) = matches.value_of("input") { File::open(&input)?.read_to_string(&mut buffer)?; } else { io::stdin().read_to_string(&mut buffer)?; } let mut options = options::Options::default(); if let Some(cell_size) = matches.value_of("cell size") { match options::CellSize::from_str(cell_size) { Ok(cs) => options.cell_size = cs, Err(_e) => { eprintln!("invalid cell size '{}'", cell_size); exit(1); } } } else if let Some(cell_modulus) = matches.value_of("cell modulus") { match u64::from_str(cell_modulus) { Ok(cs) => options.cell_size = options::CellSize::Modular(cs), Err(_e) => { eprintln!("invalid cell modulus '{}'", cell_modulus); exit(1); } } } let insts = parser::parse(&buffer); if let Ok(mut insts) = insts { let mut lin_loop_optimizer = optimize::LinOptimizer::new(); lin_loop_optimizer.visit_instructions(&mut insts); let _ = std::mem::replace(&mut insts, lin_loop_optimizer.instructions); if matches.is_present("interpret") { interpret::run(&insts, &options); } else { //for ref inst in &insts { //println!("{}\n", inst.to_string()); //} //println!("{}", trans::java::transpile(&insts)); //let c = trans::c::transpile_dfg(&dfg); //println!("{}", c); //println!("{}", trans::java::transpile(&insts)); match matches.value_of("transpile") { Some(lang) => { //let arena = Arena::new(); //let dfg = optimize::create_dfg(&mut insts, &arena); let code = if lang == "c" { //trans::c::transpile_dfg(&dfg) trans::c::transpile(&options, &insts) } else if lang == "java" { trans::java::transpile(&options, &insts) } else if lang == "python" { trans::python::transpile(&options, &insts) } else if lang == "zombie_ir" { trans::zombie_ir::transpile(&insts) } else { eprintln!("invalid transpiler lang '{}'", lang); "".to_owned() }; println!("{}", code); }, None => { let _code = compile::compile_and_run(&insts, &options); } } } } else if let Err(msg) = insts { println!("error parsing: {}", msg); } Ok(()) }