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};
pub fn generate(tokens: Vec<Token>) -> 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<usize> = 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<usize> = 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
}

View File

@ -3,10 +3,10 @@ use std::{fs, io::Write, path::PathBuf};
use crate::{asm_gen, tokenizer};
pub fn compile(program: Vec<u8>, 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();
}

View File

@ -1,93 +1,95 @@
use std::{
collections::{HashMap, VecDeque},
io::{self, Write},
collections::{HashMap, VecDeque},
io::{self, Write},
};
pub fn run(program: Vec<u8>) {
let mut tape: Vec<u8> = vec![0];
let mut cell_index: usize = 0;
let mut tape: Vec<u8> = vec![0];
let mut cell_index: usize = 0;
let mut ip: usize = 0;
let mut icount: usize = 0;
let mut user_input: Vec<u8> = vec![];
let mut ip: usize = 0;
let mut icount: usize = 0;
let mut user_input: Vec<u8> = vec![];
let mut table: HashMap<usize, usize> = HashMap::new();
let mut stack: VecDeque<usize> = 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<usize, usize> = HashMap::new();
let mut stack: VecDeque<usize> = 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<u8> {
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()
}

View File

@ -8,28 +8,28 @@ mod interpreter;
mod tokenizer;
fn main() {
let args: Vec<String> = env::args().collect();
let mode = args.get(1).expect("mode expected");
let input = args.get(2).expect("malformed arguments");
let program: Vec<u8> = load_program(input);
let name = args
.get(3)
.map(|s| s.to_string())
.unwrap_or_else(|| "program".to_string());
let args: Vec<String> = env::args().collect();
let mode = args.get(1).expect("mode expected");
let input = args.get(2).expect("malformed arguments");
let program: Vec<u8> = 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<u8> {
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()
}

View File

@ -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<u8>) -> Vec<Token> {
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
}