Skip to content

Commit

Permalink
Pattern Matching setup and SetToZero already added
Browse files Browse the repository at this point in the history
  • Loading branch information
Sellig6792 committed Dec 27, 2022
1 parent 4d21e3f commit d49c490
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 16 deletions.
8 changes: 5 additions & 3 deletions src/ast.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod instruction_types;
mod instructions;
mod parser;
mod instruction_types;
mod patterns;

pub use parser::Parser;
pub use instructions::{InstructionTrait, Instruction};
pub use instruction_types::InstructionType;
pub use instructions::{Instruction, InstructionTrait};
pub use parser::Parser;
pub use patterns::{Pattern, PatternType};
6 changes: 5 additions & 1 deletion src/ast/instruction_types.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::ast::patterns::PatternType;

#[derive(Debug, Clone, PartialEq)]
pub enum InstructionType {
Increment,
Expand All @@ -18,4 +20,6 @@ pub enum InstructionType {
MoveRightScope,

Random,
}

Pattern(PatternType),
}
36 changes: 36 additions & 0 deletions src/ast/patterns.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
mod set_to_zero;

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

pub trait Pattern<T>
where
T: InstructionTrait<T>,
{
fn match_pattern(&self, instructions: &Vec<T>) -> bool;
fn replace(&self, instructions: Vec<T>) -> Vec<T>;
}

#[derive(Clone, Debug, PartialEq)]
pub enum PatternType {
SetToZero(set_to_zero::SetToZero),
}

impl PatternType {
pub fn iter() -> std::slice::Iter<'static, PatternType> {
static PATTERNS: [PatternType; 1] = [PatternType::SetToZero(set_to_zero::SetToZero {})];
PATTERNS.iter()
}

pub fn get_pattern(&self) -> Box<dyn Pattern<OptimizedInstruction>> {
match self {
PatternType::SetToZero(pattern) => Box::new(pattern.clone()),
}
}

pub fn replace(&self, instructions: Vec<OptimizedInstruction>) -> Vec<OptimizedInstruction> {
self.get_pattern().replace(instructions)
}
}


51 changes: 51 additions & 0 deletions src/ast/patterns/set_to_zero.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use crate::ast::{InstructionTrait, InstructionType, Pattern, PatternType};

#[derive(Clone, Debug, PartialEq)]
pub struct SetToZero {}

impl<T> Pattern<T> for SetToZero
// This pattern is Loop<Decrement(2n+1) or Loop<Increment(2n+1)
where
T: InstructionTrait<T> + Clone,
{
fn match_pattern(&self, instructions: &Vec<T>) -> bool {
if instructions.len() != 1 {
return false;
}

match instructions[0].get_instruction_type() {
InstructionType::Loop => {
let content = instructions[0].get_content_ref();
if content.len() != 1 {
return false;
}
match content[0].get_instruction_type() {
InstructionType::Decrement | InstructionType::Increment => {
let amount = content[0].get_amount();
if amount % 2 != 1 {
return false;
}
}
_ => return false,
}
}
_ => return false,
}

true
}

fn replace(&self, mut instructions: Vec<T>) -> Vec<T> {
// Find in instructions somewhere where the pattern matches
// Replace the pattern with a SetToZero instruction
// Remove the instructions that were replaced
for instruction in &mut instructions {
if self.match_pattern(&vec![instruction.clone()]) {
let new_instruction = T::new(InstructionType::Pattern(PatternType::SetToZero(SetToZero {})), None);
*instruction = new_instruction;
}
}

instructions
}
}
13 changes: 8 additions & 5 deletions src/evaluation/evaluator.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rand::Rng;

use crate::ast::{InstructionTrait, InstructionType};
use crate::ast::{InstructionTrait, InstructionType, PatternType};

use crate::evaluation::{Cell, Scopes};

Expand Down Expand Up @@ -141,6 +141,12 @@ where
}
}
}

InstructionType::Pattern(pattern_type) => match pattern_type {
PatternType::SetToZero(_) => {
self.scopes.get_current_cell_mut().set_value(0);
}
},
}
}

Expand Down Expand Up @@ -182,9 +188,6 @@ mod tests {
let optimized_instructions = optimizer.optimize();
let mut brainfuck = Evaluator::new(optimized_instructions);
brainfuck.evaluate(None, Some(false));
assert_eq!(
String::from_utf8(brainfuck.output_buffer).unwrap(),
"1"
);
assert_eq!(String::from_utf8(brainfuck.output_buffer).unwrap(), "1");
}
}
12 changes: 8 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ struct CLI {
#[arg(required = true, help = "Path to the file to execute")]
path: std::path::PathBuf,

#[arg(short = 'O', long = "optimize", help = "Optimize the code", default_value = "false")]
#[arg(
short = 'O',
long = "optimize",
help = "Optimize the code",
default_value = "false"
)]
optimize: bool,
}


fn main() -> Result<(), Box<dyn std::error::Error>>{
let args= CLI::parse();
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = CLI::parse();
// Read the file and quit if it's not found
let program = fs::read_to_string(&args.path)
.with_context(|| format!("Could not read file `{}`", args.path.to_str().unwrap()))?;
Expand Down
18 changes: 15 additions & 3 deletions src/optimization/optimizer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::ast::{Instruction, InstructionTrait, InstructionType};
use crate::ast::{Instruction, InstructionTrait, InstructionType, Pattern, PatternType};

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

Expand All @@ -15,6 +15,7 @@ impl Optimizer {
let mut optimized_instructions = vec![];
self.merge_instructions(&mut optimized_instructions);
self.cancel_opposed_instructions(&mut optimized_instructions);
self.recognize_patterns(&mut optimized_instructions);
optimized_instructions
}

Expand All @@ -38,9 +39,8 @@ impl Optimizer {
Some(self.optimize_container(instruction.get_content())),
));
}
_ => last_optimized_instruction.add(1)
_ => last_optimized_instruction.add(1),
}

} else {
match instruction.get_instruction_type() {
InstructionType::Function | InstructionType::Loop => {
Expand Down Expand Up @@ -128,4 +128,16 @@ impl Optimizer {

*optimized_instructions = new_optimized_instructions;
}

fn recognize_patterns(&self, optimized_instructions: &mut Vec<OptimizedInstruction>) -> () {
let mut new_optimized_instructions: Vec<OptimizedInstruction> = optimized_instructions.clone();

let patterns = PatternType::iter();

for pattern in patterns {
new_optimized_instructions = pattern.replace(optimized_instructions.clone());
}

*optimized_instructions = new_optimized_instructions;
}
}

0 comments on commit d49c490

Please sign in to comment.