bfmod 0.1.0

Brainfuck lexer and compiler library for Rust.
Documentation
use crate::lexer::Commands;
use crate::lexer::Token;
use std::fs;
use std::process::Command;

/// Compile the lexerized code into the rust code.
///
/// # Arguments
///
/// * `tokens` (`&Vec<Token>`) - The brainfuck code will be compiled.
///
/// # Examples
///
/// ```
/// let bf_rust_code: String = bfmod::compiler::compile(&tokens)
/// ```
pub fn compile(tokens: &Vec<Token>) -> String {
    let mut compiled_code = String::from(r#"fn eb(mem: &mut [u8; 30000],cell: i32, val: i32, et: char){if et=='+'{if (*mem)[cell as usize] as i32+val<256 {(*mem)[cell as usize]+=val as u8;}else{(*mem)[cell as usize]=(val%255) as u8;}}else{if (*mem)[cell as usize] as i32-val>=0{(*mem)[cell as usize]-=val as u8;}else{(*mem)[cell as usize]=(256-(val%255)) as u8;}}}"#);
    compiled_code.push('\n');
    compiled_code.push_str(r#"fn ac(cell: &mut i32, ext: i32, et: char){if et=='+'{if *cell+ext<=30000 {*cell+=ext;}else{*cell=ext%30000;}}else{if *cell-ext>=0 {*cell-=ext;}else{*cell=ext%30000;}}}"#);
    compiled_code.push_str("\n#[allow(unused_assignments)]\nfn main(){let mut mem:[u8; 30000]=[0; 30000];let mut cc=0;");
    
    for token in tokens.iter() {
        match token.value {
            Commands::AddByte => compiled_code = format!("{}eb(&mut mem,cc,{},'+');", compiled_code,token.repeats),
            Commands::RemoveByte => compiled_code = format!("{}eb(&mut mem,cc,{},'-');", compiled_code,token.repeats),
            Commands::GoNext => compiled_code = format!("{}ac(&mut cc,{},'+');", compiled_code,token.repeats),
            Commands::GoLast => compiled_code = format!("{}ac(&mut cc,{},'-');", compiled_code,token.repeats),
            Commands::LoopBegin => compiled_code.push_str("while mem[cc as usize]!=(0 as u8){"),
            Commands::LoopEnd => compiled_code.push_str("};"),
            Commands::WriteByte => compiled_code.push_str(r#"print!("{}",mem[cc as usize] as char);"#),
            Commands::ReadByte => {
                match compiled_code.find("use std::io;") {
                    Some(_) => compiled_code.push_str(r#"let mut input: [u8; 1]=[0; 1];io::stdin().read_exact(&mut input).expect("failed to read byte.");mem[cc as usize] = input[0];"#),
                    None => {
                        compiled_code = compiled_code.replace("fn eb", "use std::io;\nuse std::io::Read;\nfn eb");
                        compiled_code.push_str(r#"let mut input: [u8; 1]=[0; 1];io::stdin().read_exact(&mut input).expect("failed to read byte.");mem[cc as usize] = input[0];"#);
                    }
                }
            }
        }
    };

    compiled_code.push('}');
    compiled_code
}

/// Build the lexerized code into the executable file.
///
/// # Arguments
///
/// * `tokens` (`&Vec<Token>`) - The brainfuck code will be builded.
///
/// # Examples
///
/// ```
/// let tokens: bool = bfmod::compiler::build("
///     >++++++++[<+++++++++>-]<.>++++[<+++++++>-]
///     <+.+++++++..+++.>>++++++[<+++++++>-]<++.--
///     ----------.>++++++[<+++++++++>-]<+.<.+++.-
///     -----.--------.>>>++++[<++++++++>-]<+.");
/// ```
pub fn build(tokens: &Vec<Token>, file_path: &str) -> bool {
    let compiled_code = compile(tokens);

    match fs::write(file_path, compiled_code.to_owned()) {
        Ok(()) => match Command::new("rustc").arg(file_path).output() {
            Ok(_) => return true,
            Err(_) => return false
        },
        Err(_) => return false
    }
}