Added move and input tokens

master
Wynd 2024-10-22 14:12:01 +03:00
parent fdefd706a9
commit 31d7cb27c6
6 changed files with 103 additions and 86 deletions

View File

@ -8,20 +8,20 @@ args = ["run", "--release", "--", "${@}"]
clear = true clear = true
private = true private = true
command = "mv" command = "mv"
args = ["./demo.asm", "./asm/demo.asm"] args = ["./program.asm", "./asm/program.asm"]
dependencies = ["compile-bf"] dependencies = ["compile-bf"]
[tasks.assemble] [tasks.assemble]
private = true private = true
command = "nasm" command = "nasm"
args = ["-felf64", "./asm/demo.asm"] args = ["-felf64", "./asm/program.asm"]
dependencies = ["move"] dependencies = ["move"]
[tasks.link] [tasks.link]
clear = true clear = true
private = true private = true
command = "ld.lld" command = "ld.lld"
args = ["./asm/demo.o", "-o", "./asm/demo"] args = ["./asm/program.o", "-o", "./asm/program"]
dependencies = ["assemble"] dependencies = ["assemble"]
[tasks.compile] [tasks.compile]
@ -30,5 +30,5 @@ dependencies = ["link"]
[tasks.test] [tasks.test]
clear = true clear = true
command = "./asm/demo" command = "./asm/program"
dependencies = ["link"] dependencies = ["link"]

1
input/move.bf 100644
View File

@ -0,0 +1 @@
>++++<+.>>+++<--.>.

View File

@ -5,7 +5,7 @@ pub fn generate(tokens: Vec<Token>) -> String {
output.push_str( output.push_str(
"section .bss\n\ "section .bss\n\
result: resb 65536\n", data: resb 65536\n",
); );
// global start label // global start label
@ -15,38 +15,48 @@ pub fn generate(tokens: Vec<Token>) -> String {
_start:\n", _start:\n",
); );
// create the pointer for var
output.push_str("mov rdx, data\n");
// NOTE: For debugging only // NOTE: For debugging only
output.push_str("mov dl, 48\n"); // output.push_str("mov byte[rdx], 48\n");
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!( output.push_str(&format!("add byte[rdx], {x}\n"));
"add dl, {x}\n\
mov byte [result], dl\n"
));
} }
TokenType::Minus(x) => { TokenType::Minus(x) => {
output.push_str(&format!( output.push_str(&format!("sub byte[rdx], {x}\n"));
"sub dl, {x}\n\ }
mov byte [result], dl\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 => { TokenType::Output => {
output.push_str( output.push_str(
"push rdx\n\ "push rdx\n\
mov byte [result + 1], 10\n\
mov rax, 1\n\ mov rax, 1\n\
mov rdi, 1\n\ mov rdi, 1\n\
mov rsi, result\n\ mov rsi, rdx\n\
mov rdx, 4\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\ syscall\n\
pop rdx\n", pop rdx\n",
); );
} }
TokenType::Input => todo!(),
TokenType::BracketOpen => todo!(), TokenType::BracketOpen => todo!(),
TokenType::BracketClose => todo!(), TokenType::BracketClose => todo!(),
} }

View File

@ -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<u8>, 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();
}

View File

@ -1,6 +1,6 @@
#![feature(let_chains)] #![feature(let_chains)]
use std::{env, fs, io::Write, path::PathBuf}; use std::{env, fs, path::PathBuf};
mod asm_gen; mod asm_gen;
mod compiler; mod compiler;
@ -8,22 +8,19 @@ mod interpreter;
mod tokenizer; mod tokenizer;
fn main() { fn main() {
let program: Vec<u8> = load_program(); let args: Vec<String> = env::args().collect();
let input = args.get(1).expect("malformed arguments");
let tokens = tokenizer::Tokenizer::default().tokenize(program); let program: Vec<u8> = load_program(input);
let name = args
let asm = asm_gen::generate(tokens); .get(2)
.map(|s| s.to_string())
let mut file = fs::File::create("./demo.asm").unwrap(); .unwrap_or_else(|| "program".to_string());
file.write_all(asm.as_bytes()).unwrap();
compiler::compile(program, name);
// interpreter::run(program); // interpreter::run(program);
} }
fn load_program() -> Vec<u8> { fn load_program(input: &str) -> Vec<u8> {
let args: Vec<String> = env::args().collect();
let input = args.get(1).expect("malformed arguments");
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

@ -21,61 +21,61 @@ impl Token {
} }
} }
#[derive(Debug, Default)] pub fn tokenize(program: Vec<u8>) -> Vec<Token> {
pub struct Tokenizer {
index: u32,
}
impl Tokenizer {
pub fn tokenize(&self, program: Vec<u8>) -> Vec<Token> {
let mut tokens = vec![]; let mut tokens = vec![];
let mut ip = 0; let mut ip = 0;
let mut icount = 0;
while ip < program.len() { while ip < program.len() {
let Some(instruction) = program.get(ip) else { let Some(instruction) = program.get(ip) else {
break; break;
}; };
let next_instruction = program.get(&ip + 1);
ip += 1; ip += 1;
match instruction { match instruction {
b'+' => { b'+' => {
icount += 1; let count = check_next(&program, &mut ip, instruction);
if let Some(next) = next_instruction tokens.push(Token::new(TokenType::Plus(count)));
&& *next == b'+'
{
continue;
} else {
tokens.push(Token::new(TokenType::Plus(icount)));
icount = 0;
}
} }
b'-' => { b'-' => {
icount += 1; let count = check_next(&program, &mut ip, instruction);
if let Some(next) = next_instruction tokens.push(Token::new(TokenType::Minus(count)));
&& *next == b'-'
{
continue;
} else {
tokens.push(Token::new(TokenType::Minus(icount)));
icount = 0;
} }
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'>' => {}
b'<' => {}
b'.' => { b'.' => {
tokens.push(Token::new(TokenType::Output)); tokens.push(Token::new(TokenType::Output));
} }
b',' => {} b',' => {
tokens.push(Token::new(TokenType::Input));
}
b'[' => {} b'[' => {}
b']' => {} b']' => {}
_ => {} _ => {}
} }
} }
// 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);
}
icount
} }