Added a fmt file and formatted the whole project

master
Wynd 2024-10-22 16:14:15 +03:00
parent 659f9fbe65
commit f39dde9c64
6 changed files with 233 additions and 222 deletions

8
rustfmt.toml 100644
View File

@ -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"

View File

@ -3,88 +3,88 @@ use std::collections::VecDeque;
use crate::tokenizer::{Token, TokenType}; use crate::tokenizer::{Token, TokenType};
pub fn generate(tokens: Vec<Token>) -> String { pub fn generate(tokens: Vec<Token>) -> String {
let mut output = String::new(); let mut output = String::new();
// reserving mem // reserving mem
output.push_str( output.push_str(
"section .bss\n\ "section .bss\n\
data: resb 65536\n", data: resb 65536\n",
); );
// global start label // global start label
output.push_str( output.push_str(
"global _start\n\ "global _start\n\
section .text\n\ section .text\n\
_start:\n", _start:\n",
); );
// create the pointer for our data // create the pointer for our data
output.push_str("mov rdx, data\n"); output.push_str("mov rdx, data\n");
let mut loops = 0; let mut loops = 0;
let mut stack: VecDeque<usize> = VecDeque::new(); let mut stack: VecDeque<usize> = VecDeque::new();
for token in tokens { for token in tokens {
match token.r#type { match token.r#type {
TokenType::Plus(x) => { TokenType::Plus(x) => {
output.push_str(&format!("add byte[rdx], {x}\n")); output.push_str(&format!("add byte[rdx], {x}\n"));
} }
TokenType::Minus(x) => { TokenType::Minus(x) => {
output.push_str(&format!("sub byte[rdx], {x}\n")); output.push_str(&format!("sub byte[rdx], {x}\n"));
} }
TokenType::MoveRight(x) => { TokenType::MoveRight(x) => {
output.push_str(&format!("add rdx, {x}\n")); output.push_str(&format!("add rdx, {x}\n"));
} }
TokenType::MoveLeft(x) => { TokenType::MoveLeft(x) => {
output.push_str(&format!("sub rdx, {x}\n")); output.push_str(&format!("sub rdx, {x}\n"));
} }
TokenType::Output => { TokenType::Output => {
output.push_str( output.push_str(
"push rdx\n\ "push rdx\n\
mov rax, 1\n\ mov rax, 1\n\
mov rdi, 1\n\ mov rdi, 1\n\
mov rsi, rdx\n\ mov rsi, rdx\n\
mov rdx, 1\n\ mov rdx, 1\n\
syscall\n\ syscall\n\
pop rdx\n", pop rdx\n",
); );
} }
TokenType::Input => { TokenType::Input => {
output.push_str( output.push_str(
"push rdx\n\ "push rdx\n\
mov rax, 0\n\ mov rax, 0\n\
mov rdi, 0\n\ mov rdi, 0\n\
mov rsi, rdx\n\ mov rsi, rdx\n\
mov rdx, 1\n\ mov rdx, 1\n\
syscall\n\ syscall\n\
pop rdx\n", pop rdx\n",
); );
} }
TokenType::BracketOpen => { TokenType::BracketOpen => {
output.push_str(&format!( output.push_str(&format!(
".loop_{loops}_start:\n\ ".loop_{loops}_start:\n\
cmp byte[rdx], 0\n\ cmp byte[rdx], 0\n\
je .loop_{loops}_end\n" je .loop_{loops}_end\n"
)); ));
stack.push_back(loops); stack.push_back(loops);
loops += 1; loops += 1;
} }
TokenType::BracketClose => { TokenType::BracketClose => {
let current_loop = stack.pop_back().unwrap(); let current_loop = stack.pop_back().unwrap();
output.push_str(&format!( output.push_str(&format!(
"cmp byte[rdx], 0\n\ "cmp byte[rdx], 0\n\
jne .loop_{current_loop}_start\n\ jne .loop_{current_loop}_start\n\
.loop_{current_loop}_end:\n", .loop_{current_loop}_end:\n",
)); ));
} }
} }
} }
// exit syscall // exit syscall
output.push_str( output.push_str(
"mov rax, 60\n\ "mov rax, 60\n\
mov rdi, 0\n\ mov rdi, 0\n\
syscall\n", syscall\n",
); );
output output
} }

View File

@ -3,10 +3,10 @@ use std::{fs, io::Write, path::PathBuf};
use crate::{asm_gen, tokenizer}; use crate::{asm_gen, tokenizer};
pub fn compile(program: Vec<u8>, name: String) { pub fn compile(program: Vec<u8>, name: String) {
let tokens = tokenizer::tokenize(program); let tokens = tokenizer::tokenize(program);
let asm = asm_gen::generate(tokens); let asm = asm_gen::generate(tokens);
let path: PathBuf = [".", &format!("./{name}.asm")].iter().collect(); let path: PathBuf = [".", &format!("./{name}.asm")].iter().collect();
let mut file = fs::File::create(path).unwrap(); let mut file = fs::File::create(path).unwrap();
file.write_all(asm.as_bytes()).unwrap(); file.write_all(asm.as_bytes()).unwrap();
} }

View File

@ -1,93 +1,95 @@
use std::{ use std::{
collections::{HashMap, VecDeque}, collections::{HashMap, VecDeque},
io::{self, Write}, io::{self, Write},
}; };
pub fn run(program: Vec<u8>) { pub fn run(program: Vec<u8>) {
let mut tape: Vec<u8> = vec![0]; let mut tape: Vec<u8> = vec![0];
let mut cell_index: usize = 0; let mut cell_index: usize = 0;
let mut ip: usize = 0; let mut ip: usize = 0;
let mut icount: usize = 0; let mut icount: usize = 0;
let mut user_input: Vec<u8> = vec![]; let mut user_input: Vec<u8> = vec![];
let mut table: HashMap<usize, usize> = HashMap::new(); let mut table: HashMap<usize, usize> = HashMap::new();
let mut stack: VecDeque<usize> = VecDeque::new(); let mut stack: VecDeque<usize> = VecDeque::new();
for (ip, instruction) in program.iter().enumerate() { for (ip, instruction) in program.iter().enumerate() {
if *instruction == b'[' { if *instruction == b'[' {
stack.push_back(ip); stack.push_back(ip);
} else if *instruction == b']' { }
let begin_index = stack.pop_back().unwrap(); else if *instruction == b']' {
table.insert(begin_index, ip); let begin_index = stack.pop_back().unwrap();
table.insert(ip, begin_index); table.insert(begin_index, ip);
} table.insert(ip, begin_index);
} }
}
while ip < program.len() { while ip < program.len() {
let Some(instruction) = program.get(ip) else { let Some(instruction) = program.get(ip)
break; else {
}; break;
};
match instruction { match instruction {
b'+' => { b'+' => {
tape[cell_index] = tape[cell_index].wrapping_add(1); tape[cell_index] = tape[cell_index].wrapping_add(1);
icount += 1; icount += 1;
} }
b'-' => { b'-' => {
tape[cell_index] = tape[cell_index].wrapping_sub(1); tape[cell_index] = tape[cell_index].wrapping_sub(1);
icount += 1; icount += 1;
} }
b'>' => { b'>' => {
cell_index = cell_index.wrapping_add(1); cell_index = cell_index.wrapping_add(1);
if tape.len() <= cell_index { if tape.len() <= cell_index {
tape.push(0); tape.push(0);
} }
icount += 1; icount += 1;
} }
b'<' => { b'<' => {
cell_index = cell_index.wrapping_sub(1); cell_index = cell_index.wrapping_sub(1);
icount += 1; icount += 1;
} }
b'.' => { b'.' => {
print!("{}", tape[cell_index] as char); print!("{}", tape[cell_index] as char);
icount += 1; icount += 1;
} }
b',' => { b',' => {
if user_input.is_empty() { if user_input.is_empty() {
user_input = input(); user_input = input();
} }
tape[cell_index] = user_input.remove(0); tape[cell_index] = user_input.remove(0);
icount += 1; icount += 1;
} }
b'[' => { b'[' => {
if tape[cell_index] == 0 { if tape[cell_index] == 0 {
ip = *table.get(&ip).unwrap(); ip = *table.get(&ip).unwrap();
} }
icount += 1; icount += 1;
} }
b']' => { b']' => {
if tape[cell_index] != 0 { if tape[cell_index] != 0 {
ip = *table.get(&ip).unwrap(); ip = *table.get(&ip).unwrap();
} }
icount += 1; icount += 1;
} }
_ => {} _ => {}
} }
ip += 1; ip += 1;
} }
println!(); println!();
println!("Instructions ran: {icount}"); println!("Instructions ran: {icount}");
// println!("{tape:?}"); // println!("{tape:?}");
} }
fn input() -> Vec<u8> { fn input() -> Vec<u8> {
let mut input = String::new(); let mut input = String::new();
print!("Input: "); print!("Input: ");
let _ = io::stdout().flush(); let _ = io::stdout().flush();
let _ = io::stdin().read_line(&mut input); let _ = io::stdin().read_line(&mut input);
input.as_bytes().to_vec() input.as_bytes().to_vec()
} }

View File

@ -8,28 +8,28 @@ mod interpreter;
mod tokenizer; mod tokenizer;
fn main() { fn main() {
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
let mode = args.get(1).expect("mode expected"); let mode = args.get(1).expect("mode expected");
let input = args.get(2).expect("malformed arguments"); let input = args.get(2).expect("malformed arguments");
let program: Vec<u8> = load_program(input); let program: Vec<u8> = load_program(input);
let name = args let name = args
.get(3) .get(3)
.map(|s| s.to_string()) .map(|s| s.to_string())
.unwrap_or_else(|| "program".to_string()); .unwrap_or_else(|| "program".to_string());
match mode { match mode {
x if x == "c" => { x if x == "c" => {
compiler::compile(program, name); compiler::compile(program, name);
} }
x if x == "i" => { x if x == "i" => {
interpreter::run(program); interpreter::run(program);
} }
_ => {} _ => {}
} }
} }
fn load_program(input: &str) -> Vec<u8> { fn load_program(input: &str) -> Vec<u8> {
let path: PathBuf = input.into(); let path: PathBuf = input.into();
let input = fs::read_to_string(path).expect("failed to read the program file"); let input = fs::read_to_string(path).expect("failed to read the program file");
input.as_bytes().to_vec() input.as_bytes().to_vec()
} }

View File

@ -1,85 +1,86 @@
#[derive(Debug)] #[derive(Debug)]
pub enum TokenType { pub enum TokenType {
Plus(u32), Plus(u32),
Minus(u32), Minus(u32),
MoveRight(u32), MoveRight(u32),
MoveLeft(u32), MoveLeft(u32),
Output, Output,
Input, Input,
BracketOpen, BracketOpen,
BracketClose, BracketClose,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Token { pub struct Token {
pub r#type: TokenType, pub r#type: TokenType,
} }
impl Token { impl Token {
fn new(r#type: TokenType) -> Self { fn new(r#type: TokenType) -> Self {
Self { r#type } Self { r#type }
} }
} }
pub fn tokenize(program: Vec<u8>) -> Vec<Token> { pub fn tokenize(program: Vec<u8>) -> Vec<Token> {
let mut tokens = vec![]; let mut tokens = vec![];
let mut ip = 0; let mut ip = 0;
while ip < program.len() { while ip < program.len() {
let Some(instruction) = program.get(ip) else { let Some(instruction) = program.get(ip)
break; else {
}; break;
};
ip += 1; ip += 1;
match instruction { match instruction {
b'+' => { b'+' => {
let count = check_next(&program, &mut ip, instruction); let count = check_next(&program, &mut ip, instruction);
tokens.push(Token::new(TokenType::Plus(count))); tokens.push(Token::new(TokenType::Plus(count)));
} }
b'-' => { b'-' => {
let count = check_next(&program, &mut ip, instruction); let count = check_next(&program, &mut ip, instruction);
tokens.push(Token::new(TokenType::Minus(count))); tokens.push(Token::new(TokenType::Minus(count)));
} }
b'>' => { b'>' => {
let count = check_next(&program, &mut ip, instruction); let count = check_next(&program, &mut ip, instruction);
tokens.push(Token::new(TokenType::MoveRight(count))); tokens.push(Token::new(TokenType::MoveRight(count)));
} }
b'<' => { b'<' => {
let count = check_next(&program, &mut ip, instruction); let count = check_next(&program, &mut ip, instruction);
tokens.push(Token::new(TokenType::MoveLeft(count))); tokens.push(Token::new(TokenType::MoveLeft(count)));
} }
b'.' => { b'.' => {
tokens.push(Token::new(TokenType::Output)); tokens.push(Token::new(TokenType::Output));
} }
b',' => { b',' => {
tokens.push(Token::new(TokenType::Input)); tokens.push(Token::new(TokenType::Input));
} }
b'[' => { b'[' => {
tokens.push(Token::new(TokenType::BracketOpen)); tokens.push(Token::new(TokenType::BracketOpen));
} }
b']' => { b']' => {
tokens.push(Token::new(TokenType::BracketClose)); tokens.push(Token::new(TokenType::BracketClose));
} }
_ => {} _ => {}
} }
} }
// dbg!(&tokens); // dbg!(&tokens);
tokens tokens
} }
fn check_next(program: &[u8], ip: &mut usize, instruction: &u8) -> u32 { fn check_next(program: &[u8], ip: &mut usize, instruction: &u8) -> u32 {
let mut icount = 1; let mut icount = 1;
let mut next_instruction = program.get(*ip); let mut next_instruction = program.get(*ip);
while let Some(next) = next_instruction while let Some(next) = next_instruction
&& *next == *instruction && *next == *instruction
{ {
icount += 1; icount += 1;
*ip += 1; *ip += 1;
next_instruction = program.get(*ip); next_instruction = program.get(*ip);
} }
icount icount
} }