From 31d7cb27c6c22e6b160146f6ac1bc426e163577a Mon Sep 17 00:00:00 2001 From: Wynd Date: Tue, 22 Oct 2024 14:12:01 +0300 Subject: [PATCH] Added move and input tokens --- Makefile.toml | 8 ++-- input/move.bf | 1 + src/asm_gen.rs | 42 +++++++++++-------- src/compiler.rs | 13 +++++- src/main.rs | 23 +++++------ src/tokenizer.rs | 102 +++++++++++++++++++++++------------------------ 6 files changed, 103 insertions(+), 86 deletions(-) create mode 100644 input/move.bf diff --git a/Makefile.toml b/Makefile.toml index 565d9f3..03ee6ae 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -8,20 +8,20 @@ args = ["run", "--release", "--", "${@}"] clear = true private = true command = "mv" -args = ["./demo.asm", "./asm/demo.asm"] +args = ["./program.asm", "./asm/program.asm"] dependencies = ["compile-bf"] [tasks.assemble] private = true command = "nasm" -args = ["-felf64", "./asm/demo.asm"] +args = ["-felf64", "./asm/program.asm"] dependencies = ["move"] [tasks.link] clear = true private = true command = "ld.lld" -args = ["./asm/demo.o", "-o", "./asm/demo"] +args = ["./asm/program.o", "-o", "./asm/program"] dependencies = ["assemble"] [tasks.compile] @@ -30,5 +30,5 @@ dependencies = ["link"] [tasks.test] clear = true -command = "./asm/demo" +command = "./asm/program" dependencies = ["link"] diff --git a/input/move.bf b/input/move.bf new file mode 100644 index 0000000..2dbe89e --- /dev/null +++ b/input/move.bf @@ -0,0 +1 @@ +>++++<+.>>+++<--.>. diff --git a/src/asm_gen.rs b/src/asm_gen.rs index 5ca9b69..6fdddc1 100644 --- a/src/asm_gen.rs +++ b/src/asm_gen.rs @@ -5,7 +5,7 @@ pub fn generate(tokens: Vec) -> String { output.push_str( "section .bss\n\ - result: resb 65536\n", + data: resb 65536\n", ); // global start label @@ -15,38 +15,48 @@ pub fn generate(tokens: Vec) -> String { _start:\n", ); + // create the pointer for var + output.push_str("mov rdx, data\n"); + // NOTE: For debugging only - output.push_str("mov dl, 48\n"); + // output.push_str("mov byte[rdx], 48\n"); for token in tokens { match token.r#type { TokenType::Plus(x) => { - output.push_str(&format!( - "add dl, {x}\n\ - mov byte [result], dl\n" - )); + output.push_str(&format!("add byte[rdx], {x}\n")); } TokenType::Minus(x) => { - output.push_str(&format!( - "sub dl, {x}\n\ - mov byte [result], dl\n" - )); + 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::MoveRight(_) => todo!(), - TokenType::MoveLeft(_) => todo!(), TokenType::Output => { output.push_str( "push rdx\n\ - mov byte [result + 1], 10\n\ mov rax, 1\n\ mov rdi, 1\n\ - mov rsi, result\n\ - mov rdx, 4\n\ + mov rsi, rdx\n\ + mov rdx, 1\n\ + syscall\n\ + pop 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::Input => todo!(), TokenType::BracketOpen => todo!(), TokenType::BracketClose => todo!(), } diff --git a/src/compiler.rs b/src/compiler.rs index 19e153d..dc5433e 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,3 +1,12 @@ -pub struct Compiler {} +use std::{fs, io::Write, path::PathBuf}; -impl Compiler {} +use crate::{asm_gen, tokenizer}; + +pub fn compile(program: Vec, name: String) { + 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(); +} diff --git a/src/main.rs b/src/main.rs index 83387ab..285a7c8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ #![feature(let_chains)] -use std::{env, fs, io::Write, path::PathBuf}; +use std::{env, fs, path::PathBuf}; mod asm_gen; mod compiler; @@ -8,22 +8,19 @@ mod interpreter; mod tokenizer; fn main() { - let program: Vec = load_program(); - - let tokens = tokenizer::Tokenizer::default().tokenize(program); - - let asm = asm_gen::generate(tokens); - - let mut file = fs::File::create("./demo.asm").unwrap(); - file.write_all(asm.as_bytes()).unwrap(); + let args: Vec = env::args().collect(); + let input = args.get(1).expect("malformed arguments"); + let program: Vec = load_program(input); + let name = args + .get(2) + .map(|s| s.to_string()) + .unwrap_or_else(|| "program".to_string()); + compiler::compile(program, name); // interpreter::run(program); } -fn load_program() -> Vec { - let args: Vec = env::args().collect(); - let input = args.get(1).expect("malformed arguments"); - +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() diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 059dc66..80028eb 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -21,61 +21,61 @@ impl Token { } } -#[derive(Debug, Default)] -pub struct Tokenizer { - index: u32, -} +pub fn tokenize(program: Vec) -> Vec { + let mut tokens = vec![]; -impl Tokenizer { - pub fn tokenize(&self, program: Vec) -> 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; - let mut icount = 0; - while ip < program.len() { - let Some(instruction) = program.get(ip) else { - break; - }; + ip += 1; - let next_instruction = program.get(&ip + 1); - - ip += 1; - - match instruction { - b'+' => { - icount += 1; - if let Some(next) = next_instruction - && *next == b'+' - { - continue; - } else { - tokens.push(Token::new(TokenType::Plus(icount))); - icount = 0; - } - } - b'-' => { - icount += 1; - if let Some(next) = next_instruction - && *next == b'-' - { - continue; - } else { - tokens.push(Token::new(TokenType::Minus(icount))); - icount = 0; - } - } - b'>' => {} - b'<' => {} - b'.' => { - tokens.push(Token::new(TokenType::Output)); - } - b',' => {} - b'[' => {} - b']' => {} - _ => {} + 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'[' => {} + b']' => {} + _ => {} } - - tokens } + + // dbg!(&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); + } + + icount }