From b8abbfd02fc4b7c372e68f06c92da80688b5a4a8 Mon Sep 17 00:00:00 2001 From: zxq5 Date: Thu, 5 Feb 2026 01:11:38 +0000 Subject: [PATCH] added a brainf&&k module to the compiler (specialised module so no frontend/backend distinction or use of standard model) --- compiler/src/specialised/brainf.rs | 135 +++++++++++++++++++++++++++++ compiler/src/specialised/mod.rs | 13 +++ 2 files changed, 148 insertions(+) create mode 100644 compiler/src/specialised/brainf.rs create mode 100644 compiler/src/specialised/mod.rs diff --git a/compiler/src/specialised/brainf.rs b/compiler/src/specialised/brainf.rs new file mode 100644 index 0000000..fe7a2a9 --- /dev/null +++ b/compiler/src/specialised/brainf.rs @@ -0,0 +1,135 @@ +#[must_use] +pub fn build(src: &str) -> String { + parse(src).join("\n") +} + +#[must_use] +#[expect(clippy::too_many_lines)] +pub fn parse(src: &str) -> Vec { + let stack = "0x10000"; + let acc = "acc"; + let rga = "rga"; + + let bpr = "bpr"; + let spr = "spr"; + let mut instrs = Vec::::new(); + + // Define symbols + let print_start = "print"; + + let tokens = lex(src); + + let mut idstack = Vec::::new(); + + // set up a stack + instrs.push(format!("\tlwi {}, {}", stack, bpr)); + instrs.push(format!("\tmov {}, {}", bpr, spr)); + // set up the data pointer + instrs.push(format!("{}: \t lwi 0x30000, {}", "main", rga)); + + for (id, tok) in tokens.iter().enumerate() { + match tok { + BfToken::Inc => { + instrs.push(format!("\tinc {}", acc)); + } + BfToken::Dec => { + instrs.push(format!("\tdec {}", acc)); + } + BfToken::IncPtr => { + instrs.push(format!("\tstw {}, {}, 0", acc, rga)); + instrs.push(format!("\taddi {}, 4, {}", rga, rga)); + instrs.push(format!("\tlwd {}, {}, 0", rga, acc)); + } + BfToken::DecPtr => { + instrs.push(format!("\tstw {}, {}, 0", acc, rga)); + instrs.push(format!("\tsubi {}, 4, {}", rga, rga)); + instrs.push(format!("\tlwd {}, {}, 0", rga, acc)); + } + BfToken::Out => { + instrs.push(format!("\tpush {}", acc)); + instrs.push(format!("\tcall {}", print_start)); + instrs.push(format!("\tpop zero")); + } + BfToken::In => { + instrs.push(format!("\tlwd 0x40000, {}, 0", acc)); + } + BfToken::Forward => { + let loop_start = format!("loop_start_{}", id); + let loop_end = format!("loop_end_{}", id); + idstack.push(id as u32); + instrs.push(format!("\tcmp {}, zero", acc)); + instrs.push(format!("\tjeq {}, zero", loop_end)); + instrs.push(format!("{}: \tnop", loop_start)); + } + BfToken::Back => { + if let Some(start_id) = idstack.pop() { + let loop_start = format!("loop_start_{}", start_id); + let loop_end = format!("loop_end_{}", start_id); + instrs.push(format!("\tcmp {}, zero", acc)); + instrs.push(format!("\tjne {}, zero", loop_start)); + instrs.push(format!("{}: \tnop", loop_end)); + } else { + eprintln!("Warning: Unmatched ']' at position {}", id); + } + } + } + } + + instrs.push("\thlt".to_string()); + + insert_lib(&mut instrs); + + instrs +} + +fn insert_lib(instrs: &mut Vec) { + let bpr = "bpr"; + let spr = "spr"; + let rg0 = "rg0"; + let rg1 = "rg1"; + + let print_start = "print"; + let current = "current"; + instrs.push(format!("\tdw {}, 0x20000", current)); + instrs.push(format!("{}: \tpush {}", print_start, bpr)); + instrs.push(format!("\tmov {}, {}", spr, bpr)); + instrs.push(format!("\tlwd {}, {}, 8", bpr, rg0)); + instrs.push(format!("\tlwd {}, {}, 0", current, rg1)); + instrs.push(format!("\tstb {}, {}, 0", rg0, rg1)); + instrs.push(format!("\taddi {}, 1, {}", rg1, rg1)); + instrs.push(format!("\tstw {}, {}, 0", rg1, current)); + instrs.push(format!("\tmov {}, {}", bpr, spr)); + instrs.push(format!("\tpop {}", bpr)); + instrs.push("\treturn".to_string()); +} + +enum BfToken { + Inc, + Dec, + IncPtr, + DecPtr, + Out, + In, + Forward, + Back, +} + +fn lex(src: &str) -> Vec { + src.chars() + .filter_map(|c| match c { + '+' => Some(BfToken::Inc), + '-' => Some(BfToken::Dec), + '>' => Some(BfToken::IncPtr), + '<' => Some(BfToken::DecPtr), + '.' => Some(BfToken::Out), + ',' => Some(BfToken::In), + '[' => Some(BfToken::Forward), + ']' => Some(BfToken::Back), + _ => None, + }) + .collect() +} + +fn _create_symbol(id: u32) -> String { + format!("label_{}", id) +} diff --git a/compiler/src/specialised/mod.rs b/compiler/src/specialised/mod.rs new file mode 100644 index 0000000..2ff89ed --- /dev/null +++ b/compiler/src/specialised/mod.rs @@ -0,0 +1,13 @@ +use crate::model::CompilerError; + +pub mod brainf; + +pub fn build_specialised(ext: &str, data: &str) -> Option> { + match ext { + "bf" => { + let res = brainf::build(data); + Some(Ok(res)) + } + _ => None, + } +}