diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..3116f8a --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,8 @@ +unstable_features = true +reorder_imports = true +hard_tabs = true +control_brace_style = "ClosingNextLine" +imports_granularity = "Crate" +group_imports = "StdExternalCrate" +edition = "2021" +newline_style = "Unix" \ No newline at end of file diff --git a/src/asm_gen.rs b/src/asm_gen.rs index ca6b710..f2a7280 100644 --- a/src/asm_gen.rs +++ b/src/asm_gen.rs @@ -3,88 +3,88 @@ use std::collections::VecDeque; use crate::tokenizer::{Token, TokenType}; pub fn generate(tokens: Vec) -> String { - let mut output = String::new(); + let mut output = String::new(); - // reserving mem - output.push_str( - "section .bss\n\ + // reserving mem + output.push_str( + "section .bss\n\ data: resb 65536\n", - ); + ); - // global start label - output.push_str( - "global _start\n\ + // global start label + output.push_str( + "global _start\n\ section .text\n\ _start:\n", - ); + ); - // create the pointer for our data - output.push_str("mov rdx, data\n"); + // create the pointer for our data + output.push_str("mov rdx, data\n"); - let mut loops = 0; - let mut stack: VecDeque = VecDeque::new(); - for token in tokens { - match token.r#type { - TokenType::Plus(x) => { - output.push_str(&format!("add byte[rdx], {x}\n")); - } - TokenType::Minus(x) => { - output.push_str(&format!("sub byte[rdx], {x}\n")); - } - TokenType::MoveRight(x) => { - output.push_str(&format!("add rdx, {x}\n")); - } - TokenType::MoveLeft(x) => { - output.push_str(&format!("sub rdx, {x}\n")); - } - TokenType::Output => { - output.push_str( - "push rdx\n\ + let mut loops = 0; + let mut stack: VecDeque = VecDeque::new(); + for token in tokens { + match token.r#type { + TokenType::Plus(x) => { + output.push_str(&format!("add byte[rdx], {x}\n")); + } + TokenType::Minus(x) => { + output.push_str(&format!("sub byte[rdx], {x}\n")); + } + TokenType::MoveRight(x) => { + output.push_str(&format!("add rdx, {x}\n")); + } + TokenType::MoveLeft(x) => { + output.push_str(&format!("sub rdx, {x}\n")); + } + TokenType::Output => { + output.push_str( + "push rdx\n\ mov rax, 1\n\ mov rdi, 1\n\ mov rsi, rdx\n\ mov rdx, 1\n\ syscall\n\ pop rdx\n", - ); - } - TokenType::Input => { - output.push_str( - "push rdx\n\ + ); + } + TokenType::Input => { + output.push_str( + "push rdx\n\ mov rax, 0\n\ mov rdi, 0\n\ mov rsi, rdx\n\ mov rdx, 1\n\ syscall\n\ pop rdx\n", - ); - } - TokenType::BracketOpen => { - output.push_str(&format!( - ".loop_{loops}_start:\n\ + ); + } + TokenType::BracketOpen => { + output.push_str(&format!( + ".loop_{loops}_start:\n\ cmp byte[rdx], 0\n\ je .loop_{loops}_end\n" - )); - stack.push_back(loops); - loops += 1; - } - TokenType::BracketClose => { - let current_loop = stack.pop_back().unwrap(); - output.push_str(&format!( - "cmp byte[rdx], 0\n\ + )); + stack.push_back(loops); + loops += 1; + } + TokenType::BracketClose => { + let current_loop = stack.pop_back().unwrap(); + output.push_str(&format!( + "cmp byte[rdx], 0\n\ jne .loop_{current_loop}_start\n\ .loop_{current_loop}_end:\n", - )); - } - } - } + )); + } + } + } - // exit syscall - output.push_str( - "mov rax, 60\n\ + // exit syscall + output.push_str( + "mov rax, 60\n\ mov rdi, 0\n\ syscall\n", - ); + ); - output + output } diff --git a/src/compiler.rs b/src/compiler.rs index dc5433e..15f832b 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -3,10 +3,10 @@ use std::{fs, io::Write, path::PathBuf}; use crate::{asm_gen, tokenizer}; pub fn compile(program: Vec, name: String) { - let tokens = tokenizer::tokenize(program); - let asm = asm_gen::generate(tokens); + let tokens = tokenizer::tokenize(program); + let asm = asm_gen::generate(tokens); - let path: PathBuf = [".", &format!("./{name}.asm")].iter().collect(); - let mut file = fs::File::create(path).unwrap(); - file.write_all(asm.as_bytes()).unwrap(); + let path: PathBuf = [".", &format!("./{name}.asm")].iter().collect(); + let mut file = fs::File::create(path).unwrap(); + file.write_all(asm.as_bytes()).unwrap(); } diff --git a/src/interpreter.rs b/src/interpreter.rs index 1d71e09..46e2fdf 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -1,93 +1,95 @@ use std::{ - collections::{HashMap, VecDeque}, - io::{self, Write}, + collections::{HashMap, VecDeque}, + io::{self, Write}, }; pub fn run(program: Vec) { - let mut tape: Vec = vec![0]; - let mut cell_index: usize = 0; + let mut tape: Vec = vec![0]; + let mut cell_index: usize = 0; - let mut ip: usize = 0; - let mut icount: usize = 0; - let mut user_input: Vec = vec![]; + let mut ip: usize = 0; + let mut icount: usize = 0; + let mut user_input: Vec = vec![]; - let mut table: HashMap = HashMap::new(); - let mut stack: VecDeque = VecDeque::new(); - for (ip, instruction) in program.iter().enumerate() { - if *instruction == b'[' { - stack.push_back(ip); - } else if *instruction == b']' { - let begin_index = stack.pop_back().unwrap(); - table.insert(begin_index, ip); - table.insert(ip, begin_index); - } - } + let mut table: HashMap = HashMap::new(); + let mut stack: VecDeque = VecDeque::new(); + for (ip, instruction) in program.iter().enumerate() { + if *instruction == b'[' { + stack.push_back(ip); + } + else if *instruction == b']' { + let begin_index = stack.pop_back().unwrap(); + table.insert(begin_index, ip); + table.insert(ip, begin_index); + } + } - while ip < program.len() { - let Some(instruction) = program.get(ip) else { - break; - }; + while ip < program.len() { + let Some(instruction) = program.get(ip) + else { + break; + }; - match instruction { - b'+' => { - tape[cell_index] = tape[cell_index].wrapping_add(1); - icount += 1; - } - b'-' => { - tape[cell_index] = tape[cell_index].wrapping_sub(1); - icount += 1; - } - b'>' => { - cell_index = cell_index.wrapping_add(1); - if tape.len() <= cell_index { - tape.push(0); - } - icount += 1; - } - b'<' => { - cell_index = cell_index.wrapping_sub(1); - icount += 1; - } - b'.' => { - print!("{}", tape[cell_index] as char); - icount += 1; - } - b',' => { - if user_input.is_empty() { - user_input = input(); - } - tape[cell_index] = user_input.remove(0); - icount += 1; - } - b'[' => { - if tape[cell_index] == 0 { - ip = *table.get(&ip).unwrap(); - } - icount += 1; - } - b']' => { - if tape[cell_index] != 0 { - ip = *table.get(&ip).unwrap(); - } - icount += 1; - } - _ => {} - } + match instruction { + b'+' => { + tape[cell_index] = tape[cell_index].wrapping_add(1); + icount += 1; + } + b'-' => { + tape[cell_index] = tape[cell_index].wrapping_sub(1); + icount += 1; + } + b'>' => { + cell_index = cell_index.wrapping_add(1); + if tape.len() <= cell_index { + tape.push(0); + } + icount += 1; + } + b'<' => { + cell_index = cell_index.wrapping_sub(1); + icount += 1; + } + b'.' => { + print!("{}", tape[cell_index] as char); + icount += 1; + } + b',' => { + if user_input.is_empty() { + user_input = input(); + } + tape[cell_index] = user_input.remove(0); + icount += 1; + } + b'[' => { + if tape[cell_index] == 0 { + ip = *table.get(&ip).unwrap(); + } + icount += 1; + } + b']' => { + if tape[cell_index] != 0 { + ip = *table.get(&ip).unwrap(); + } + icount += 1; + } + _ => {} + } - ip += 1; - } + ip += 1; + } - println!(); - println!("Instructions ran: {icount}"); - // println!("{tape:?}"); + println!(); + println!("Instructions ran: {icount}"); + // println!("{tape:?}"); } fn input() -> Vec { - let mut input = String::new(); + let mut input = String::new(); - print!("Input: "); - let _ = io::stdout().flush(); - let _ = io::stdin().read_line(&mut input); + print!("Input: "); + let _ = io::stdout().flush(); + let _ = io::stdin().read_line(&mut input); - input.as_bytes().to_vec() + input.as_bytes().to_vec() } diff --git a/src/main.rs b/src/main.rs index c8bad90..d777444 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,28 +8,28 @@ mod interpreter; mod tokenizer; fn main() { - let args: Vec = env::args().collect(); - let mode = args.get(1).expect("mode expected"); - let input = args.get(2).expect("malformed arguments"); - let program: Vec = load_program(input); - let name = args - .get(3) - .map(|s| s.to_string()) - .unwrap_or_else(|| "program".to_string()); + let args: Vec = env::args().collect(); + let mode = args.get(1).expect("mode expected"); + let input = args.get(2).expect("malformed arguments"); + let program: Vec = load_program(input); + let name = args + .get(3) + .map(|s| s.to_string()) + .unwrap_or_else(|| "program".to_string()); - match mode { - x if x == "c" => { - compiler::compile(program, name); - } - x if x == "i" => { - interpreter::run(program); - } - _ => {} - } + match mode { + x if x == "c" => { + compiler::compile(program, name); + } + x if x == "i" => { + interpreter::run(program); + } + _ => {} + } } fn load_program(input: &str) -> Vec { - let path: PathBuf = input.into(); - let input = fs::read_to_string(path).expect("failed to read the program file"); - input.as_bytes().to_vec() + let path: PathBuf = input.into(); + let input = fs::read_to_string(path).expect("failed to read the program file"); + input.as_bytes().to_vec() } diff --git a/src/tokenizer.rs b/src/tokenizer.rs index eed8ce3..0ffd47c 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -1,85 +1,86 @@ #[derive(Debug)] pub enum TokenType { - Plus(u32), - Minus(u32), - MoveRight(u32), - MoveLeft(u32), - Output, - Input, - BracketOpen, - BracketClose, + Plus(u32), + Minus(u32), + MoveRight(u32), + MoveLeft(u32), + Output, + Input, + BracketOpen, + BracketClose, } #[derive(Debug)] pub struct Token { - pub r#type: TokenType, + pub r#type: TokenType, } impl Token { - fn new(r#type: TokenType) -> Self { - Self { r#type } - } + fn new(r#type: TokenType) -> Self { + Self { r#type } + } } pub fn tokenize(program: Vec) -> Vec { - let mut tokens = vec![]; + let mut tokens = vec![]; - let mut ip = 0; - while ip < program.len() { - let Some(instruction) = program.get(ip) else { - break; - }; + let mut ip = 0; + while ip < program.len() { + let Some(instruction) = program.get(ip) + else { + break; + }; - ip += 1; + ip += 1; - match instruction { - b'+' => { - let count = check_next(&program, &mut ip, instruction); - tokens.push(Token::new(TokenType::Plus(count))); - } - b'-' => { - let count = check_next(&program, &mut ip, instruction); - tokens.push(Token::new(TokenType::Minus(count))); - } - b'>' => { - let count = check_next(&program, &mut ip, instruction); - tokens.push(Token::new(TokenType::MoveRight(count))); - } - b'<' => { - let count = check_next(&program, &mut ip, instruction); - tokens.push(Token::new(TokenType::MoveLeft(count))); - } - b'.' => { - tokens.push(Token::new(TokenType::Output)); - } - b',' => { - tokens.push(Token::new(TokenType::Input)); - } - b'[' => { - tokens.push(Token::new(TokenType::BracketOpen)); - } - b']' => { - tokens.push(Token::new(TokenType::BracketClose)); - } - _ => {} - } - } + match instruction { + b'+' => { + let count = check_next(&program, &mut ip, instruction); + tokens.push(Token::new(TokenType::Plus(count))); + } + b'-' => { + let count = check_next(&program, &mut ip, instruction); + tokens.push(Token::new(TokenType::Minus(count))); + } + b'>' => { + let count = check_next(&program, &mut ip, instruction); + tokens.push(Token::new(TokenType::MoveRight(count))); + } + b'<' => { + let count = check_next(&program, &mut ip, instruction); + tokens.push(Token::new(TokenType::MoveLeft(count))); + } + b'.' => { + tokens.push(Token::new(TokenType::Output)); + } + b',' => { + tokens.push(Token::new(TokenType::Input)); + } + b'[' => { + tokens.push(Token::new(TokenType::BracketOpen)); + } + b']' => { + tokens.push(Token::new(TokenType::BracketClose)); + } + _ => {} + } + } - // dbg!(&tokens); + // dbg!(&tokens); - tokens + tokens } fn check_next(program: &[u8], ip: &mut usize, instruction: &u8) -> u32 { - let mut icount = 1; - let mut next_instruction = program.get(*ip); - while let Some(next) = next_instruction - && *next == *instruction - { - icount += 1; - *ip += 1; - next_instruction = program.get(*ip); - } + let mut icount = 1; + let mut next_instruction = program.get(*ip); + while let Some(next) = next_instruction + && *next == *instruction + { + icount += 1; + *ip += 1; + next_instruction = program.get(*ip); + } - icount + icount }