Skip to content

Commit

Permalink
Very basic match
Browse files Browse the repository at this point in the history
  • Loading branch information
3top1a committed Feb 8, 2025
1 parent 552af25 commit c424964
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 95 deletions.
64 changes: 35 additions & 29 deletions src/lir/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ impl Codegen {
self.code += "\n";
self.ptr = number_left;

self.parse_instructions(instructions);

self.code
}

fn parse_instructions(&mut self, instructions: Instructions) {
for instr in instructions.0 {
self.code += format!("{} ", instr.debug()).as_str();

Expand All @@ -51,20 +57,12 @@ impl Codegen {
Read(loc) => self.read(loc),
Print(val) => self.print(val),

Match(loc) => self.startmatch(loc),
EndCaseDefault => self.endcasedefault(),
CaseDefault => self.casedefault(),
Case(n) => self.case(n),
EndCase => self.endcase(),
EndMatch => self.endmatch(),

Match { source, cases } => self.startmatch(source, cases),
// _ => unimplemented!("Instruction not implemented: {:?}", instr),
}

self.code += "\n";
}

self.code
}

fn goto_stack(&mut self) {
Expand Down Expand Up @@ -217,7 +215,7 @@ impl Codegen {
}
}

fn startmatch(&mut self, loc: Location) {
fn startmatch(&mut self, loc: Location, cases: Vec<(u8, Instructions)>) {
/*
For example:
Expand All @@ -235,30 +233,38 @@ impl Codegen {
match loc {
Location::Stack => {
self.goto_stack();
self.code += ">+<[";
self.code += ">+<";
self.ptr += 1;
}
_ => unimplemented!(),
}
}

fn endmatch(&mut self) {
// TODO
}
// Sort cases by number, n .. 0
let mut cases = cases;
cases.sort_by(|a, b| b.0.cmp(&a.0));

fn case(&mut self, n: u8) {
// TODO
}
let mut highest_num = 0;
for c in cases.iter().rev() {
self.code += &"-".repeat((c.0 as usize - highest_num));
self.code += "[";
highest_num = c.0 as usize;
}

fn endcase(&mut self) {
// TODO
}
// Default case
self.code += "[-]>-default#<";

fn casedefault(&mut self) {
// TODO
}
let mut prev = 255;
for case in cases {
let num = case.0;
debug_assert!(num < prev);
self.code += "]>[-";

fn endcasedefault(&mut self) {
// TODO
// Code
self.parse_instructions(case.1);

self.code += "]<";

prev = num;
}
}
_ => unimplemented!(),
}
}
}
31 changes: 2 additions & 29 deletions src/lir/instructions.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,11 @@
use crate::lir::lir::{Instruction, Location, Value};

#[derive(Debug, Clone)]
pub struct Instructions(pub Vec<Instruction>);

impl Instructions {
/// Validates instructions and panics if invalid.
pub fn validate(&self) -> bool {
// Check for equal match and unmatch
let mut match_count = 0;
for instr in &self.0 {
match instr {
Instruction::Match(_) => match_count += 1,
Instruction::EndMatch => match_count -= 1,
_ => (),
}
}
if match_count != 0 {
panic!("Unmatched match");
}

// Check that case (x) are ordered from n to 0
let mut highest_case = 255;
for instr in &self.0 {
match instr {
Instruction::Case(x) => {
if *x < highest_case {
highest_case = *x;
} else {
panic!("Case not ordered");
}
}
Instruction::Match(_) => highest_case = 255,
_ => (),
}
}

// Check that all variables are declared before use
let variables = self.get_variable_indexes();
for instr in &self.0 {
Expand Down
21 changes: 9 additions & 12 deletions src/lir/lir.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::lir::instructions::Instructions;

type Immediate = u8;

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -38,12 +40,10 @@ pub enum Instruction {
Print(Value),

// Control flow
Match(Location),
Case(Immediate),
EndCase,
CaseDefault,
EndCaseDefault,
EndMatch,
Match {
source: Location,
cases: Vec<(Immediate, Instructions)>,
},
}

#[derive(Debug, Clone)]
Expand All @@ -70,12 +70,9 @@ impl Instruction {
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),
Instruction::Case(n) => format!("Case {}", n),
Instruction::CaseDefault => "CaseDefault".to_string(),
Instruction::EndMatch => "EndMatch".to_string(),
Instruction::EndCase => "EndCase".to_string(),
Instruction::EndCaseDefault => "EndCaseDefault".to_string(),
Instruction::Match { source, cases } => {
format!("Match")
}
}
}
}
45 changes: 20 additions & 25 deletions src/lir/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ mod tests {

fn eq(code: String, b: &str) {
println!("{}", code);
assert_eq!(remove_nonbf(code), b);
assert_eq!(remove_nonbf(code), remove_nonbf(b.to_string()));
}

fn gen(instructions: Vec<Instruction>) -> String {
Expand Down Expand Up @@ -134,35 +134,30 @@ mod tests {

#[test]
fn test_match() {
// test(
// vec![
// Push(1),
// Match(Location::Stack),
// Case(0),
// Print(Value::Immediate(b'0')),
// Case(1),
// Print(Value::Immediate(b'1')),
// Case(2),
// Print(Value::Immediate(b'2')),
// CaseDefault,
// Print(Value::Immediate(b'D')),
// EndMatch,
// ],
// "",
// );



test(
vec![
Push(4),
Match(Location::Stack),
CaseDefault,
Case(1),
Case(0),
EndMatch,
Match {
source: Location::Stack,
cases: vec![(0, vec![].into()), (1, vec![].into())],
},
],
">++++>+<[-[[-]>-default#<]>[-1#]<]>[-0#]<",
);

test(
vec![
Push(1),
Match {
source: Location::Stack,
cases: vec![
(0, vec![Print(Value::Immediate(b'0'))].into()),
(1, vec![Print(Value::Immediate(b'1'))].into()),
(2, vec![Print(Value::Immediate(b'2'))].into()),
]
}
],
"",
);
}
}

0 comments on commit c424964

Please sign in to comment.