mirror of
https://github.com/Noratrieb/brainfuck.git
synced 2026-01-14 13:35:00 +01:00
simplify window passes
This commit is contained in:
parent
3eb9486a8c
commit
31f2304a30
1 changed files with 55 additions and 53 deletions
|
|
@ -160,42 +160,65 @@ fn pass_find_set_null(ir: &mut Ir<'_>) {
|
||||||
|
|
||||||
/// pass that replaces `SetN(n) Add(m)` with `SetN(n + m)`
|
/// pass that replaces `SetN(n) Add(m)` with `SetN(n + m)`
|
||||||
fn pass_set_n(ir: &mut Ir<'_>) {
|
fn pass_set_n(ir: &mut Ir<'_>) {
|
||||||
let stmts = &mut ir.stmts;
|
two_window_pass(ir, pass_set_n, |a, b| {
|
||||||
for i in 0..stmts.len() {
|
|
||||||
let a = &mut stmts[i];
|
|
||||||
if let StmtKind::Loop(body) = &mut a.kind {
|
|
||||||
pass_set_n(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
if i >= stmts.len() - 1 {
|
|
||||||
break; // we are the last element
|
|
||||||
}
|
|
||||||
|
|
||||||
let a = &stmts[i];
|
|
||||||
if let StmtKind::SetN(before) = a.kind() {
|
if let StmtKind::SetN(before) = a.kind() {
|
||||||
let b = &stmts[i + 1];
|
|
||||||
let new = match b.kind() {
|
let new = match b.kind() {
|
||||||
StmtKind::Add(n) => StmtKind::SetN(before.wrapping_add(*n)),
|
StmtKind::Add(n) => StmtKind::SetN(before.wrapping_add(*n)),
|
||||||
StmtKind::Sub(n) => StmtKind::SetN(before.wrapping_sub(*n)),
|
StmtKind::Sub(n) => StmtKind::SetN(before.wrapping_sub(*n)),
|
||||||
_ => {
|
_ => {
|
||||||
continue;
|
return WindowPassAction::None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let span = a.span.merge(b.span);
|
return WindowPassAction::Merge(new);
|
||||||
stmts.remove(i + 1);
|
|
||||||
stmts[i] = Stmt::new(new, span);
|
|
||||||
}
|
}
|
||||||
}
|
WindowPassAction::None
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// pass that replaces `Left(5) Right(3)` with `Left(2)`
|
/// pass that replaces `Left(5) Right(3)` with `Left(2)`
|
||||||
fn pass_cancel_left_right_add_sub(ir: &mut Ir<'_>) {
|
fn pass_cancel_left_right_add_sub(ir: &mut Ir<'_>) {
|
||||||
|
two_window_pass(ir, pass_cancel_left_right_add_sub, |a, b| {
|
||||||
|
match (a.kind(), b.kind()) {
|
||||||
|
(StmtKind::Right(r), StmtKind::Left(l)) | (StmtKind::Left(l), StmtKind::Right(r)) => {
|
||||||
|
let new = match r.cmp(l) {
|
||||||
|
Ordering::Equal => return WindowPassAction::RemoveBoth,
|
||||||
|
Ordering::Less => StmtKind::Left(l - r),
|
||||||
|
Ordering::Greater => StmtKind::Right(r - l),
|
||||||
|
};
|
||||||
|
|
||||||
|
WindowPassAction::Merge(new)
|
||||||
|
}
|
||||||
|
(StmtKind::Add(r), StmtKind::Sub(l)) | (StmtKind::Sub(l), StmtKind::Add(r)) => {
|
||||||
|
let new = match r.cmp(l) {
|
||||||
|
Ordering::Equal => return WindowPassAction::RemoveBoth,
|
||||||
|
Ordering::Less => StmtKind::Sub(l - r),
|
||||||
|
Ordering::Greater => StmtKind::Add(r - l),
|
||||||
|
};
|
||||||
|
|
||||||
|
WindowPassAction::Merge(new)
|
||||||
|
}
|
||||||
|
_ => WindowPassAction::None,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
enum WindowPassAction<'ir> {
|
||||||
|
None,
|
||||||
|
Merge(StmtKind<'ir>),
|
||||||
|
RemoveBoth,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn two_window_pass<'ir, P, F>(ir: &mut Ir<'ir>, pass_recur: P, action: F)
|
||||||
|
where
|
||||||
|
P: Fn(&mut Ir<'ir>),
|
||||||
|
F: Fn(&Stmt<'ir>, &Stmt<'ir>) -> WindowPassAction<'ir>,
|
||||||
|
{
|
||||||
let stmts = &mut ir.stmts;
|
let stmts = &mut ir.stmts;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < stmts.len() {
|
while i < stmts.len() {
|
||||||
let a = &mut stmts[i];
|
let a = &mut stmts[i];
|
||||||
if let StmtKind::Loop(body) = &mut a.kind {
|
if let StmtKind::Loop(body) = &mut a.kind {
|
||||||
pass_cancel_left_right_add_sub(body);
|
pass_recur(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
if i >= stmts.len() - 1 {
|
if i >= stmts.len() - 1 {
|
||||||
|
|
@ -205,44 +228,23 @@ fn pass_cancel_left_right_add_sub(ir: &mut Ir<'_>) {
|
||||||
let a = &stmts[i];
|
let a = &stmts[i];
|
||||||
let b = &stmts[i + 1];
|
let b = &stmts[i + 1];
|
||||||
|
|
||||||
match (a.kind(), b.kind()) {
|
let merged_span = a.span.merge(b.span);
|
||||||
(StmtKind::Right(r), StmtKind::Left(l)) | (StmtKind::Left(l), StmtKind::Right(r)) => {
|
|
||||||
let new = match r.cmp(l) {
|
|
||||||
Ordering::Equal => {
|
|
||||||
// remove both
|
|
||||||
stmts.remove(i + 1);
|
|
||||||
stmts.remove(i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Ordering::Less => StmtKind::Left(l - r),
|
|
||||||
Ordering::Greater => StmtKind::Right(r - l),
|
|
||||||
};
|
|
||||||
|
|
||||||
let span = a.span.merge(b.span);
|
let result = action(a, b);
|
||||||
stmts.remove(i + 1);
|
|
||||||
stmts[i] = Stmt::new(new, span);
|
|
||||||
// don't increment i, maybe the next one matches as well (<><)
|
|
||||||
}
|
|
||||||
(StmtKind::Add(r), StmtKind::Sub(l)) | (StmtKind::Sub(l), StmtKind::Add(r)) => {
|
|
||||||
let new = match r.cmp(l) {
|
|
||||||
Ordering::Equal => {
|
|
||||||
// remove both
|
|
||||||
stmts.remove(i + 1);
|
|
||||||
stmts.remove(i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Ordering::Less => StmtKind::Sub(l - r),
|
|
||||||
Ordering::Greater => StmtKind::Add(r - l),
|
|
||||||
};
|
|
||||||
|
|
||||||
let span = a.span.merge(b.span);
|
match result {
|
||||||
stmts.remove(i + 1);
|
WindowPassAction::None => {
|
||||||
stmts[i] = Stmt::new(new, span);
|
// only increment i if we haven't removed anything
|
||||||
// don't increment i, maybe the next one matches as well (<><)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
WindowPassAction::RemoveBoth => {
|
||||||
|
stmts.remove(i);
|
||||||
|
stmts.remove(i + 1);
|
||||||
|
}
|
||||||
|
WindowPassAction::Merge(new) => {
|
||||||
|
stmts.remove(i + 1);
|
||||||
|
stmts[i] = Stmt::new(new, merged_span);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue