use plotnik_bytecode::Nav;
use super::collapse_up::collapse_up;
use super::CompileResult;
use crate::bytecode::{InstructionIR, Label, MatchIR};
#[test]
fn collapse_up_single_mode() {
let mut result = CompileResult {
instructions: vec![
MatchIR::at(Label(0)).nav(Nav::Up(1)).next(Label(1)).into(),
MatchIR::at(Label(1)).nav(Nav::Up(1)).next(Label(2)).into(),
MatchIR::terminal(Label(2)).into(),
],
def_entries: Default::default(),
preamble_entry: Label(0),
};
collapse_up(&mut result);
assert_eq!(result.instructions.len(), 2);
let InstructionIR::Match(m) = &result.instructions[0] else {
panic!("expected Match");
};
assert_eq!(m.nav, Nav::Up(2));
assert_eq!(m.successors, vec![Label(2)]);
}
#[test]
fn collapse_up_chain_of_three() {
let mut result = CompileResult {
instructions: vec![
MatchIR::at(Label(0)).nav(Nav::Up(1)).next(Label(1)).into(),
MatchIR::at(Label(1)).nav(Nav::Up(2)).next(Label(2)).into(),
MatchIR::at(Label(2)).nav(Nav::Up(3)).next(Label(3)).into(),
MatchIR::terminal(Label(3)).into(),
],
def_entries: Default::default(),
preamble_entry: Label(0),
};
collapse_up(&mut result);
assert_eq!(result.instructions.len(), 2);
let InstructionIR::Match(m) = &result.instructions[0] else {
panic!("expected Match");
};
assert_eq!(m.nav, Nav::Up(6));
}
#[test]
fn collapse_up_mixed_modes_no_merge() {
let mut result = CompileResult {
instructions: vec![
MatchIR::at(Label(0)).nav(Nav::Up(1)).next(Label(1)).into(),
MatchIR::at(Label(1))
.nav(Nav::UpSkipTrivia(1))
.next(Label(2))
.into(),
MatchIR::terminal(Label(2)).into(),
],
def_entries: Default::default(),
preamble_entry: Label(0),
};
collapse_up(&mut result);
assert_eq!(result.instructions.len(), 3);
}
#[test]
fn collapse_up_skip_trivia_same_mode() {
let mut result = CompileResult {
instructions: vec![
MatchIR::at(Label(0))
.nav(Nav::UpSkipTrivia(1))
.next(Label(1))
.into(),
MatchIR::at(Label(1))
.nav(Nav::UpSkipTrivia(1))
.next(Label(2))
.into(),
MatchIR::terminal(Label(2)).into(),
],
def_entries: Default::default(),
preamble_entry: Label(0),
};
collapse_up(&mut result);
assert_eq!(result.instructions.len(), 2);
let InstructionIR::Match(m) = &result.instructions[0] else {
panic!("expected Match");
};
assert_eq!(m.nav, Nav::UpSkipTrivia(2));
}
#[test]
fn collapse_up_exact_same_mode() {
let mut result = CompileResult {
instructions: vec![
MatchIR::at(Label(0))
.nav(Nav::UpExact(1))
.next(Label(1))
.into(),
MatchIR::at(Label(1))
.nav(Nav::UpExact(1))
.next(Label(2))
.into(),
MatchIR::terminal(Label(2)).into(),
],
def_entries: Default::default(),
preamble_entry: Label(0),
};
collapse_up(&mut result);
assert_eq!(result.instructions.len(), 2);
let InstructionIR::Match(m) = &result.instructions[0] else {
panic!("expected Match");
};
assert_eq!(m.nav, Nav::UpExact(2));
}
#[test]
fn collapse_up_with_effects_no_merge() {
use crate::bytecode::EffectIR;
use plotnik_bytecode::EffectOpcode;
let mut result = CompileResult {
instructions: vec![
MatchIR::at(Label(0)).nav(Nav::Up(1)).next(Label(1)).into(),
MatchIR::at(Label(1))
.nav(Nav::Up(1))
.post_effects(vec![EffectIR::simple(EffectOpcode::Null, 0)])
.next(Label(2))
.into(),
MatchIR::terminal(Label(2)).into(),
],
def_entries: Default::default(),
preamble_entry: Label(0),
};
collapse_up(&mut result);
assert_eq!(result.instructions.len(), 3);
}
#[test]
fn collapse_up_max_63() {
let mut result = CompileResult {
instructions: vec![
MatchIR::at(Label(0)).nav(Nav::Up(60)).next(Label(1)).into(),
MatchIR::at(Label(1)).nav(Nav::Up(10)).next(Label(2)).into(),
MatchIR::terminal(Label(2)).into(),
],
def_entries: Default::default(),
preamble_entry: Label(0),
};
collapse_up(&mut result);
assert_eq!(result.instructions.len(), 2);
let InstructionIR::Match(m) = &result.instructions[0] else {
panic!("expected Match");
};
assert_eq!(m.nav, Nav::Up(63));
}
#[test]
fn collapse_up_branching_no_merge() {
let mut result = CompileResult {
instructions: vec![
MatchIR::at(Label(0))
.nav(Nav::Up(1))
.next_many(vec![Label(1), Label(2)])
.into(),
MatchIR::at(Label(1)).nav(Nav::Up(1)).next(Label(3)).into(),
MatchIR::at(Label(2)).nav(Nav::Up(1)).next(Label(3)).into(),
MatchIR::terminal(Label(3)).into(),
],
def_entries: Default::default(),
preamble_entry: Label(0),
};
collapse_up(&mut result);
let InstructionIR::Match(m) = &result.instructions[0] else {
panic!("expected Match");
};
assert_eq!(m.nav, Nav::Up(1));
}
#[test]
fn collapse_up_no_up_unchanged() {
let mut result = CompileResult {
instructions: vec![
MatchIR::at(Label(0)).nav(Nav::Down).next(Label(1)).into(),
MatchIR::at(Label(1)).nav(Nav::Next).next(Label(2)).into(),
MatchIR::terminal(Label(2)).into(),
],
def_entries: Default::default(),
preamble_entry: Label(0),
};
collapse_up(&mut result);
assert_eq!(result.instructions.len(), 3);
}