Added move and input tokens
parent
fdefd706a9
commit
31d7cb27c6
|
@ -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"]
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
>++++<+.>>+++<--.>.
|
|
@ -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!(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
23
src/main.rs
23
src/main.rs
|
@ -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()
|
||||||
|
|
102
src/tokenizer.rs
102
src/tokenizer.rs
|
@ -21,61 +21,61 @@ impl Token {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
pub fn tokenize(program: Vec<u8>) -> Vec<Token> {
|
||||||
pub struct Tokenizer {
|
let mut tokens = vec![];
|
||||||
index: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Tokenizer {
|
let mut ip = 0;
|
||||||
pub fn tokenize(&self, program: Vec<u8>) -> Vec<Token> {
|
while ip < program.len() {
|
||||||
let mut tokens = vec![];
|
let Some(instruction) = program.get(ip) else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
let mut ip = 0;
|
ip += 1;
|
||||||
let mut icount = 0;
|
|
||||||
while ip < program.len() {
|
|
||||||
let Some(instruction) = program.get(ip) else {
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
let next_instruction = program.get(&ip + 1);
|
match instruction {
|
||||||
|
b'+' => {
|
||||||
ip += 1;
|
let count = check_next(&program, &mut ip, instruction);
|
||||||
|
tokens.push(Token::new(TokenType::Plus(count)));
|
||||||
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']' => {}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue