Skip to content

Commit

Permalink
more instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
3top1a committed Feb 8, 2025
1 parent 2ee36a5 commit 3c3e2f9
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 11 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ version = "0.1.0"
edition = "2021"

[dependencies]
logos = { version = "0.15.0", features = [] }
#logos = { version = "0.15.0", features = [] }
6 changes: 5 additions & 1 deletion src/bf/optim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@ pub fn optimize_no_effect() {}

/// Removes all non-brainfuck characters from the input
pub fn remove_nonbf(bf: String) -> String {
bf.chars().filter(|&c| "+-><[].,".contains(c)).collect::<String>().trim().to_string()
bf.chars()
.filter(|&c| "+-><[].,".contains(c))
.collect::<String>()
.trim()
.to_string()
}
97 changes: 93 additions & 4 deletions src/lir/codegen.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::lir::instructions::Instructions;
use crate::lir::lir::Instruction::*;
use crate::lir::lir::{Location, Value};
use crate::lir::lir::{BinaryOp, Location, Value};

#[derive(Debug, Clone)]
pub struct Codegen {
Expand All @@ -26,21 +26,32 @@ impl Codegen {

// Allocate memory for variables
// One less because stack ops go right once
let number_left = (self.variables - 1).min(0);
let number_left = self.variables.checked_sub(1).unwrap_or(0);
self.code += format!("Variables: {} ", number_left).as_str();
self.code += ">".repeat(number_left).as_str();
self.code += "\n";
self.ptr = number_left;

for instr in instructions.0 {
self.code += format!("{}", instr.debug()).as_str();
self.code += format!("{} ", instr.debug()).as_str();

match instr {
Push(n) => self.push(n),
Pop => self.pop(),
Dup => self.dup(),

Binary {
op,
modified,
consumed,
} => self.binary(op, modified, consumed),

Copy { from, to } => self.copy(from, to),

Read(loc) => self.read(loc),

Print(val) => self.print(val),

_ => unimplemented!(),
}

Expand All @@ -51,6 +62,8 @@ impl Codegen {
}

fn goto_stack(&mut self) {
// Ensure we're at the top of the stack
// That means pointer at the last populated cell (my drunk future self)
// TODO
}

Expand All @@ -74,6 +87,7 @@ impl Codegen {
}

fn copy(&mut self, from: Value, to: Location) {
// TODO Refactor > Extract Method
match from {
Value::Immediate(n) => {
match to {
Expand All @@ -85,7 +99,7 @@ impl Codegen {
self.code += "<".repeat(self.ptr - var).as_str();
// Add n
// TODO Optim for n = 0
self.code += "[-]+".repeat(n as usize).as_str();
self.code += "+".repeat(n as usize).as_str();
// Go back
self.code += ">".repeat(self.ptr - var).as_str();
}
Expand Down Expand Up @@ -116,4 +130,79 @@ impl Codegen {
}
}
}

fn binary(&mut self, operation: BinaryOp, modified: Location, consumed: Value) {
let ops = (modified, consumed);
match operation {
BinaryOp::Add => match ops {
(Location::Stack, Value::Immediate(n)) => {
self.goto_stack();
self.code += "+".repeat(n as usize).as_str();
}
(Location::Stack, Value::Location(Location::Stack)) => {
self.goto_stack();
self.code += "[-<+>]<";
}
_ => unimplemented!(),
},
BinaryOp::Sub => match ops {
(Location::Stack, Value::Immediate(n)) => {
self.goto_stack();
self.code += "-".repeat(n as usize).as_str();
}
(Location::Stack, Value::Location(Location::Stack)) => {
self.goto_stack();
self.code += "[-<->]<";
}
_ => unimplemented!(),
},
BinaryOp::Mul => {}
BinaryOp::Div => {}
BinaryOp::Eq => {}
}
}

fn read(&mut self, loc: Location) {
match loc {
Location::Stack => {
self.goto_stack();
self.code += ">,";
}
Location::Variable(var) => {
self.goto_stack(); // So that the math works out
// Goto var
self.code += "<".repeat(self.ptr - var).as_str();
// Read
self.code += ",";
// Go back
self.code += ">".repeat(self.ptr - var).as_str();
}
}
}

fn print(&mut self, val: Value) {
match val {
Value::Immediate(n) => {
self.goto_stack();
self.push(n);
self.code += ".[-]<";
}
Value::Location(loc) => {
match loc {
Location::Stack => {
self.goto_stack();
self.code += ".[-]<";
}
Location::Variable(var) => {
// Goto var
self.code += "<".repeat(self.ptr - var).as_str();
// Print
self.code += ".";
// Go back
self.code += ">".repeat(self.ptr - var).as_str();
}
}
}
}
}
}
2 changes: 1 addition & 1 deletion src/lir/lir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl Instruction {
modified,
consumed,
} => format!("{:?}", op),
Instruction::Copy { from, to } => format!("C{:?}{:?}", from, to),
Instruction::Copy { from, to } => format!("Copy {:?} to {:?}", from, to),
Instruction::Read(loc) => format!("Read {:?}", loc),
Instruction::Print(val) => format!("Print {:?}", val),
Instruction::Match(loc) => format!("Match {:?}", loc),
Expand Down
104 changes: 100 additions & 4 deletions src/lir/tests.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
mod tests {
use crate::bf::optim::remove_nonbf;
use crate::lir::codegen::Codegen;
use crate::lir::lir::{Instruction, Location, Value};
use crate::lir::lir::Instruction::*;
use crate::lir::lir::Location::Variable;
use crate::lir::lir::{BinaryOp, Instruction, Location, Value};

fn eq(code: String, b: &str) {
println!("{}", code);
Expand All @@ -13,17 +14,112 @@ mod tests {
Codegen::new().codegen(instructions.into())
}

fn test(instruction: Vec<Instruction>, expected: &str) {
eq(gen(instruction), expected);
}

#[test]
fn test() {
fn test_copy() {
let c = gen(vec![
Push(4),
Push(9),
Copy {
from: Value::Location(Location::Stack),
to: Location::Variable(0),
to: Variable(0),
},
]);
eq(c, ">++++>+++++++++[-<<+>>]<");
// The stack should be [9] [4]
// The stack should be [9] [4] [0]

// Copy immidiate to variable
let c = gen(vec![
Push(2),
Copy {
from: Value::Immediate(4),
to: Variable(0),
},
]);
eq(c, ">++<++++>");
// The stack should be [4] [2]
}

#[test]
fn test_dup() {
test(vec![Push(4), Dup], ">++++[->+>+<<]>>[-<<+>>]<");
// The stack should be [0] [4] [4]
}

#[test]
fn test_pop() {
test(vec![Push(4), Pop], ">++++[-]<");
// The stack should be [0]
}

#[test]
fn test_binary() {
// Add stack to stack
test(
vec![
Push(4),
Push(9),
Binary {
op: BinaryOp::Add,
modified: Location::Stack,
consumed: Value::Location(Location::Stack),
},
],
">++++>+++++++++[-<+>]<",
);
// The stack should be [0] [13]

// Subtract stack from stack
test(
vec![
Push(9),
Push(4),
Binary {
op: BinaryOp::Sub,
modified: Location::Stack,
consumed: Value::Location(Location::Stack),
},
],
">+++++++++>++++[-<->]<",
);
// The stack should be [0] [5]
}

#[test]
fn test_read() {
// Test read to stack
test(vec![Read(Location::Stack)], ">,");

// Test read to variable
test(vec![Read(Variable(0)), Read(Variable(1))], "><,>,");
}

#[test]
fn test_print() {
// Test print stack
test(
vec![Push(4), Print(Value::Location(Location::Stack))],
">++++.[-]<",
);

// Test print variable
test(
vec![
Copy {
from: Value::Immediate(4),
to: Variable(0),
},
Print(Value::Location(Variable(0))),
],
"++++.",
);

test(
vec![Print(Value::Immediate(72))],
">++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.[-]<",
)
}
}

0 comments on commit 3c3e2f9

Please sign in to comment.