mirror of
https://github.com/Noratrieb/brainfuck.git
synced 2026-01-14 13:35:00 +01:00
add pass_add_sub_offset
This commit is contained in:
parent
4490d49d35
commit
014770b6fe
4 changed files with 51 additions and 15 deletions
|
|
@ -27,6 +27,8 @@ use std::fmt::{Debug, Formatter};
|
||||||
pub enum Stmt {
|
pub enum Stmt {
|
||||||
Add(u8),
|
Add(u8),
|
||||||
Sub(u8),
|
Sub(u8),
|
||||||
|
AddOffset(i32, u8),
|
||||||
|
SubOffset(i32, u8),
|
||||||
Right(u32),
|
Right(u32),
|
||||||
Left(u32),
|
Left(u32),
|
||||||
Out,
|
Out,
|
||||||
|
|
@ -86,6 +88,8 @@ fn ir_to_stmt<'c>(code: &mut Code<'c>, ir_stmt: &IrStmt<'_>) {
|
||||||
let stmt = match &ir_stmt.kind {
|
let stmt = match &ir_stmt.kind {
|
||||||
StmtKind::Add(n) => Stmt::Add(*n),
|
StmtKind::Add(n) => Stmt::Add(*n),
|
||||||
StmtKind::Sub(n) => Stmt::Sub(*n),
|
StmtKind::Sub(n) => Stmt::Sub(*n),
|
||||||
|
StmtKind::AddOffset(o, n) => Stmt::AddOffset(*o, *n),
|
||||||
|
StmtKind::SubOffset(o, n) => Stmt::SubOffset(*o, *n),
|
||||||
StmtKind::Right(n) => Stmt::Right(u32::try_from(*n).unwrap()),
|
StmtKind::Right(n) => Stmt::Right(u32::try_from(*n).unwrap()),
|
||||||
StmtKind::Left(n) => Stmt::Left(u32::try_from(*n).unwrap()),
|
StmtKind::Left(n) => Stmt::Left(u32::try_from(*n).unwrap()),
|
||||||
StmtKind::Out => Stmt::Out,
|
StmtKind::Out => Stmt::Out,
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,17 @@ const MEM_SIZE: usize = 32_000;
|
||||||
|
|
||||||
type Memory = [Wrapping<u8>; MEM_SIZE];
|
type Memory = [Wrapping<u8>; MEM_SIZE];
|
||||||
|
|
||||||
// TODO maybe repr(C) to prevent field reordering?
|
// `repr(C)` to make sure rustc never reorders the fields weirdly
|
||||||
|
// maybe useless, but seems to give tiny wins
|
||||||
|
#[repr(C)]
|
||||||
struct Interpreter<'c, W, R, P> {
|
struct Interpreter<'c, W, R, P> {
|
||||||
code: &'c Code<'c>,
|
code: &'c Code<'c>,
|
||||||
|
profile_collector: P,
|
||||||
ip: usize,
|
ip: usize,
|
||||||
ptr: usize,
|
ptr: usize,
|
||||||
|
mem: Memory,
|
||||||
stdout: W,
|
stdout: W,
|
||||||
stdin: R,
|
stdin: R,
|
||||||
mem: Memory,
|
|
||||||
profile_collector: P,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run<W, R, P>(code: &Code<'_>, stdout: W, stdin: R, profile_collector: P)
|
pub fn run<W, R, P>(code: &Code<'_>, stdout: W, stdin: R, profile_collector: P)
|
||||||
|
|
@ -60,6 +62,16 @@ where
|
||||||
Stmt::Sub(n) => {
|
Stmt::Sub(n) => {
|
||||||
*self.elem_mut() -= n;
|
*self.elem_mut() -= n;
|
||||||
}
|
}
|
||||||
|
Stmt::AddOffset(o, n) => unsafe {
|
||||||
|
*self
|
||||||
|
.mem
|
||||||
|
.get_unchecked_mut((self.ptr as isize + (o as isize)) as usize) += n;
|
||||||
|
},
|
||||||
|
Stmt::SubOffset(o, n) => unsafe {
|
||||||
|
*self
|
||||||
|
.mem
|
||||||
|
.get_unchecked_mut((self.ptr as isize + (o as isize)) as usize) -= n;
|
||||||
|
},
|
||||||
Stmt::Right(n) => {
|
Stmt::Right(n) => {
|
||||||
self.ptr += n as usize;
|
self.ptr += n as usize;
|
||||||
if self.ptr >= MEM_SIZE {
|
if self.ptr >= MEM_SIZE {
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ impl Debug for Stmt<'_> {
|
||||||
pub enum StmtKind<'ir> {
|
pub enum StmtKind<'ir> {
|
||||||
Add(u8),
|
Add(u8),
|
||||||
Sub(u8),
|
Sub(u8),
|
||||||
|
AddOffset(i32, u8),
|
||||||
|
SubOffset(i32, u8),
|
||||||
Right(usize),
|
Right(usize),
|
||||||
Left(usize),
|
Left(usize),
|
||||||
Loop(Ir<'ir>),
|
Loop(Ir<'ir>),
|
||||||
|
|
@ -211,9 +213,27 @@ fn pass_cancel_left_right_add_sub(ir: &mut Ir<'_>) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// pass that replaces `Right(9) Add(5) Left(9)` with `AddOffset(9)`
|
/// pass that replaces `Right(9) Add(5) Left(9)` with `AddOffset(9, 5)`
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
fn pass_add_sub_offset(ir: &mut Ir<'_>) {}
|
fn pass_add_sub_offset(ir: &mut Ir<'_>) {
|
||||||
|
window_pass(ir, pass_add_sub_offset, |[a, b, c]| {
|
||||||
|
match (a.kind(), b.kind(), c.kind()) {
|
||||||
|
(StmtKind::Right(r), StmtKind::Add(n), StmtKind::Left(l)) if r == l => {
|
||||||
|
WindowPassAction::Merge(StmtKind::AddOffset(i32::try_from(*r).unwrap(), *n))
|
||||||
|
}
|
||||||
|
(StmtKind::Left(l), StmtKind::Add(n), StmtKind::Right(r)) if r == l => {
|
||||||
|
WindowPassAction::Merge(StmtKind::AddOffset(-i32::try_from(*r).unwrap(), *n))
|
||||||
|
}
|
||||||
|
(StmtKind::Right(r), StmtKind::Sub(n), StmtKind::Left(l)) if r == l => {
|
||||||
|
WindowPassAction::Merge(StmtKind::SubOffset(i32::try_from(*r).unwrap(), *n))
|
||||||
|
}
|
||||||
|
(StmtKind::Left(l), StmtKind::Sub(n), StmtKind::Right(r)) if r == l => {
|
||||||
|
WindowPassAction::Merge(StmtKind::SubOffset(-i32::try_from(*r).unwrap(), *n))
|
||||||
|
}
|
||||||
|
_ => WindowPassAction::None,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
enum WindowPassAction<'ir> {
|
enum WindowPassAction<'ir> {
|
||||||
None,
|
None,
|
||||||
|
|
@ -236,13 +256,10 @@ where
|
||||||
pass_recur(body);
|
pass_recur(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
if i >= stmts.len() - (N - 1) {
|
if i + N > stmts.len() {
|
||||||
break; // there aren't N elements left
|
break; // there aren't N elements left
|
||||||
}
|
}
|
||||||
|
|
||||||
let a = &stmts[i];
|
|
||||||
let b = &stmts[i + 1];
|
|
||||||
|
|
||||||
let mut elements = stmts[i..][..N].iter();
|
let mut elements = stmts[i..][..N].iter();
|
||||||
let elements = [(); N].map(|()| elements.next().unwrap());
|
let elements = [(); N].map(|()| elements.next().unwrap());
|
||||||
|
|
||||||
|
|
@ -255,13 +272,16 @@ where
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
WindowPassAction::RemoveAll => {
|
WindowPassAction::RemoveAll => {
|
||||||
trace!(?a, ?b, "Removing both statements");
|
trace!(?elements, "Removing all statements");
|
||||||
stmts.remove(i);
|
for _ in 0..N {
|
||||||
stmts.remove(i);
|
stmts.remove(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
WindowPassAction::Merge(new) => {
|
WindowPassAction::Merge(new) => {
|
||||||
trace!(?a, ?b, ?new, "Merging statements");
|
trace!(?elements, ?new, "Merging statements");
|
||||||
stmts.remove(i + 1);
|
for _ in 1..N {
|
||||||
|
stmts.remove(i);
|
||||||
|
}
|
||||||
stmts[i] = Stmt::new(new, merged_span);
|
stmts[i] = Stmt::new(new, merged_span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>
|
<<<<->>>>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue