Skip to content

Commit

Permalink
Optimizer
Browse files Browse the repository at this point in the history
  • Loading branch information
Sellig6792 committed Dec 27, 2022
1 parent 63f8653 commit 3da4546
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 16 deletions.
35 changes: 30 additions & 5 deletions src/ast/instructions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::fmt;

#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub enum InstructionType {
Increment,
Decrement,
Expand All @@ -22,16 +22,41 @@ pub enum InstructionType {
Random,
}

impl fmt::Display for InstructionType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
InstructionType::Increment => write!(f, "Increment"),
InstructionType::Decrement => write!(f, "Decrement"),

InstructionType::MoveLeft => write!(f, "MoveLeft"),
InstructionType::MoveRight => write!(f, "MoveRight"),

InstructionType::Input => write!(f, "Input"),
InstructionType::Output => write!(f, "Output"),

InstructionType::Loop => write!(f, "Loop"),

InstructionType::Function => write!(f, "Function"),
InstructionType::CallFunction => write!(f, "CallFunction"),

InstructionType::MoveLeftScope => write!(f, "MoveLeftScope"),
InstructionType::MoveRightScope => write!(f, "MoveRightScope"),

InstructionType::Random => write!(f, "Random"),
}
}
}
#[derive(Clone)]
pub struct Instruction {
pub instruction: InstructionType,
pub instruction_type: InstructionType,
content: Option<Vec<Instruction>>,
}


impl Instruction {
pub fn new(instruction: InstructionType, content: Option<Vec<Instruction>>) -> Instruction {
pub fn new(instruction_type: InstructionType, content: Option<Vec<Instruction>>) -> Instruction {
Instruction {
instruction,
instruction_type,
content,
}
}
Expand All @@ -51,7 +76,7 @@ impl Instruction {

impl fmt::Display for Instruction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.instruction {
match &self.instruction_type {
InstructionType::Increment => write!(f, "Increment"),
InstructionType::Decrement => write!(f, "Decrement"),

Expand Down
38 changes: 28 additions & 10 deletions src/evaluation/evaluator.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use rand::Rng;

use crate::ast::instructions::{Instruction, InstructionType};
use crate::optimization::optimized_instructions::OptimizedInstruction;

use crate::evaluation::Scope;

Expand Down Expand Up @@ -31,14 +32,18 @@ impl Evaluator {
}
}

pub fn evaluate(&mut self, container_to_execute: Option<Instruction>, show_output: Option<bool>) {
pub fn evaluate(
&mut self,
container_to_execute: Option<Instruction>,
show_output: Option<bool>,
) {
let instructions = match container_to_execute {
Some(container) => container.get_content(),
None => self.program.clone(),
};

for instruction in instructions.iter() {
match &instruction.instruction {
match &instruction.instruction_type {
InstructionType::Increment => {
if self.scopes[self.scope_pointer].memory[self.memory_pointer] == 255 {
self.scopes[self.scope_pointer].memory[self.memory_pointer] = 0;
Expand Down Expand Up @@ -84,28 +89,29 @@ impl Evaluator {
.push(self.scopes[self.scope_pointer].memory[self.memory_pointer]);
}

InstructionType::Loop => {
InstructionType::Loop => {
while self.scopes[self.scope_pointer].memory[self.memory_pointer] != 0 {
self.evaluate(
Some(instruction.clone()),
Some(false)
)
self.evaluate(Some(instruction.clone()), Some(false))
}
}
InstructionType::Function => {
self.scopes[self.scope_pointer].function_memory[self.memory_pointer] =
Instruction::new(
InstructionType::Function,
Some(instruction.get_content())
Some(instruction.get_content()),
);
}

InstructionType::CallFunction => {
self.scopes.push(Scope::new());
self.scope_pointer += 1;
self.evaluate(
Some(self.scopes[self.scope_pointer - 1].function_memory[self.memory_pointer].clone()),
Some(false)
Some(
self.scopes[self.scope_pointer - 1].function_memory
[self.memory_pointer]
.clone(),
),
Some(false),
);
self.scopes.pop();
self.scope_pointer -= 1;
Expand Down Expand Up @@ -159,3 +165,15 @@ impl Evaluator {
}
}
}

struct OptimizedEvaluator {
program: Vec<OptimizedInstruction>,

scopes: Vec<Scope>,
scope_pointer: usize,

memory_pointer: usize,
input: Vec<u8>,
output_buffer: Vec<u8>,
}

7 changes: 6 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod ast;
mod evaluation;
mod optimization;

use std::fs;

Expand Down Expand Up @@ -29,7 +30,11 @@ fn main() {
let mut parser = ast::Parser::new(program);
let instructions = parser.parse();

// Optimize the program
let mut optimizer = optimization::Optimizer::new(instructions.clone());
let optimized_instructions = optimizer.optimize();

// Run the program
let mut brainfuck = Evaluator::new(instructions);
let mut brainfuck = Evaluator::new(instructions.clone());
brainfuck.evaluate(None, None);
}
4 changes: 4 additions & 0 deletions src/optimization.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub mod optimized_instructions;
mod optimizer;

pub use optimizer::Optimizer;
116 changes: 116 additions & 0 deletions src/optimization/optimized_instructions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use std::fmt;

use crate::ast::instructions::{Instruction, InstructionType};

#[derive(Clone)]
pub struct OptimizedInstruction {
pub instruction: Instruction,
content: Option<Vec<OptimizedInstruction>>,
pub amount: u32,
}

impl OptimizedInstruction {
pub fn from(
instruction: Instruction,
content: Option<Vec<OptimizedInstruction>>,
) -> OptimizedInstruction {
OptimizedInstruction {
instruction,
content,
amount: 1,
}
}

pub fn get_content(&self) -> Vec<OptimizedInstruction> {
match &self.content {
Some(content) => content.clone(),
None => vec![],
}
}
pub fn get_content_ref(&self) -> &Vec<OptimizedInstruction> {
match &self.content {
Some(content) => content,
None => panic!("Instruction has no content"),
}
}

pub fn add(&mut self, amount: u32) {
self.amount += amount
}

pub fn sub(&mut self, amount: u32) {
self.amount -= amount
}

pub fn get_amount(&self) -> u32 {
self.amount
}

pub fn is_opposed(&self, other: &OptimizedInstruction) -> bool {
match self.instruction.instruction_type {
InstructionType::Increment => {
match other.instruction.instruction_type {
InstructionType::Decrement => true,
_ => false,
}
}
InstructionType::Decrement => {
match other.instruction.instruction_type {
InstructionType::Increment => true,
_ => false,
}
}
InstructionType::MoveLeft => {
match other.instruction.instruction_type {
InstructionType::MoveRight => true,
_ => false,
}
}
InstructionType::MoveRight => {
match other.instruction.instruction_type {
InstructionType::MoveLeft => true,
_ => false,
}
}
InstructionType::MoveLeftScope => {
match other.instruction.instruction_type {
InstructionType::MoveRightScope => true,
_ => false,
}
}
InstructionType::MoveRightScope => {
match other.instruction.instruction_type {
InstructionType::MoveLeftScope => true,
_ => false,
}
}

_ => false
}
}
}

impl fmt::Debug for OptimizedInstruction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.instruction.instruction_type {
InstructionType::Increment => write!(f, "Increment({})", self.amount),
InstructionType::Decrement => write!(f, "Decrement({})", self.amount),

InstructionType::MoveLeft => write!(f, "MoveLeft({})", self.amount),
InstructionType::MoveRight => write!(f, "MoveRight({})", self.amount),

InstructionType::Input => write!(f, "Input"),
InstructionType::Output => write!(f, "Output"),

InstructionType::Loop => write!(f, "Loop{:?}", self.get_content_ref()),

InstructionType::Function => write!(f, "Function{:?}", self.get_content_ref()),
InstructionType::CallFunction => write!(f, "CallFunction"),

InstructionType::MoveLeftScope => write!(f, "MoveLeftScope"),
InstructionType::MoveRightScope => write!(f, "MoveRightScope"),

InstructionType::Random => write!(f, "Random"),
}
}
}
84 changes: 84 additions & 0 deletions src/optimization/optimizer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use crate::ast::instructions::{Instruction, InstructionType};

use crate::optimization::optimized_instructions::OptimizedInstruction;

pub struct Optimizer {
instructions: Vec<Instruction>,
}

impl Optimizer {
pub fn new(instructions: Vec<Instruction>) -> Optimizer {
Optimizer { instructions }
}

pub fn optimize(&mut self) -> Vec<OptimizedInstruction> {
let mut optimized_instructions = vec![];
self.merge_instructions(&mut optimized_instructions);
self.cancel_opposed_instructions(&mut optimized_instructions);
optimized_instructions
}

fn optimize_container(&self, container: Instruction) -> OptimizedInstruction {
let optimized_instructions = Optimizer::new(container.get_content()).optimize();
let mut optimized_container = OptimizedInstruction::from(container, Some(optimized_instructions));

optimized_container
}

fn merge_instructions(&self, optimized_instructions: &mut Vec<OptimizedInstruction>) -> () {
for instruction in self.instructions.iter() {
match optimized_instructions.last_mut() {
Some(last_optimized_instruction) => {
if last_optimized_instruction.instruction.instruction_type
== instruction.instruction_type
{
last_optimized_instruction.add(1);
} else {
match instruction.instruction_type {
InstructionType::Function | InstructionType::Loop => {
optimized_instructions.push(self.optimize_container(instruction.clone()));
}
_ => {
optimized_instructions.push(OptimizedInstruction::from(
instruction.clone(),
None,
));
}
}
}
}
None => match instruction.instruction_type {
InstructionType::Function | InstructionType::Loop => {
optimized_instructions.push(self.optimize_container(instruction.clone()));
}
_ => optimized_instructions.push(OptimizedInstruction::from(instruction.clone(), None)),

},
}
}
}

fn cancel_opposed_instructions(&self, optimized_instructions: &mut Vec<OptimizedInstruction>) -> () {
let mut new_optimized_instructions: Vec<OptimizedInstruction> = vec![];

for optimized_instruction in optimized_instructions.iter() {
let last_optimized_instruction = new_optimized_instructions.last_mut();

match last_optimized_instruction {
Some(last_optimized_instruction) => {
if last_optimized_instruction.is_opposed(optimized_instruction) {
last_optimized_instruction.sub(optimized_instruction.get_amount());
} else if last_optimized_instruction.instruction.instruction_type == optimized_instruction.instruction.instruction_type {
last_optimized_instruction.add(optimized_instruction.get_amount())
} else {
new_optimized_instructions.push(optimized_instruction.clone());
}
},

None => new_optimized_instructions.push(optimized_instruction.clone())
}
}

*optimized_instructions = new_optimized_instructions;
}
}

0 comments on commit 3da4546

Please sign in to comment.