diff --git a/rust2/.rustfmt.toml b/rust2/.rustfmt.toml new file mode 100644 index 0000000..4d7dd9e --- /dev/null +++ b/rust2/.rustfmt.toml @@ -0,0 +1,3 @@ +imports_granularity = "Crate" +newline_style = "Unix" +group_imports = "StdExternalCrate" \ No newline at end of file diff --git a/rust2/benches/opts.rs b/rust2/benches/opts.rs index 6d9dfc4..d8727c3 100644 --- a/rust2/benches/opts.rs +++ b/rust2/benches/opts.rs @@ -1,6 +1,7 @@ +use std::io::{Read, Write}; + use bumpalo::Bump; use criterion::{black_box, criterion_main, Criterion}; -use std::io::{Read, Write}; struct MockReadWrite; @@ -24,9 +25,9 @@ impl Write for MockReadWrite { fn run_bf(bf: &str) { let bump = Bump::new(); let ast = brainfuck::parse::parse(&bump, bf.bytes().enumerate()).unwrap(); - let ir = brainfuck::opts::optimize(&bump, &ast); - let code = brainfuck::codegen::generate(&bump, &ir); - brainfuck::codegen_interpreter::run(&code, MockReadWrite, MockReadWrite, |_| {}); + let hir = brainfuck::hir::optimized_hir(&bump, &ast); + let lir = brainfuck::lir::generate(&bump, &hir); + brainfuck::lir::interpreter::run(&lir, MockReadWrite, MockReadWrite, |_| {}); } fn optimized(c: &mut Criterion) { diff --git a/rust2/src/hir/mod.rs b/rust2/src/hir/mod.rs new file mode 100644 index 0000000..a2df1a6 --- /dev/null +++ b/rust2/src/hir/mod.rs @@ -0,0 +1,89 @@ +use std::fmt::{Debug, Formatter}; + +use bumpalo::Bump; + +use crate::{ + parse::{Ast, Instr, Span}, + BumpVec, +}; + +pub mod opts; + +#[derive(Clone)] +pub struct Hir<'hir> { + pub stmts: BumpVec<'hir, Stmt<'hir>>, +} + +impl Debug for Hir<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + self.stmts.fmt(f) + } +} + +#[derive(Clone)] +pub struct Stmt<'hir> { + pub kind: StmtKind<'hir>, + pub span: Span, +} + +impl<'hir> Stmt<'hir> { + fn new(kind: StmtKind<'hir>, span: Span) -> Stmt<'hir> { + Self { kind, span } + } + + fn kind(&self) -> &StmtKind<'hir> { + &self.kind + } +} + +impl Debug for Stmt<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + self.kind.fmt(f) + } +} + +#[derive(Debug, Clone)] +pub enum StmtKind<'hir> { + Add(i32, u8), + Sub(i32, u8), + /// Sets the current cell to 0 and adds that value of the cell to another cell at `offset` + MoveAddTo { + offset: i32, + }, + Right(usize), + Left(usize), + Loop(Hir<'hir>), + Out, + In, + SetN(u8), +} + +fn ast_to_ir<'hir>(alloc: &'hir Bump, ast: &Ast<'_>) -> Hir<'hir> { + let mut stmts = Vec::new_in(alloc); + + let stmts_iter = ast.iter().map(|(instr, span)| { + let kind = match instr { + Instr::Add => StmtKind::Add(0, 1), + Instr::Sub => StmtKind::Sub(0, 1), + Instr::Right => StmtKind::Right(1), + Instr::Left => StmtKind::Left(1), + Instr::Out => StmtKind::Out, + Instr::In => StmtKind::In, + Instr::Loop(body) => { + let ir_body = ast_to_ir(alloc, body); + StmtKind::Loop(ir_body) + } + }; + Stmt::new(kind, *span) + }); + + stmts.extend(stmts_iter); + + Hir { stmts } +} + +pub fn optimized_hir<'hir>(alloc: &'hir Bump, ast: &Ast<'_>) -> Hir<'hir> { + let mut hir = ast_to_ir(alloc, ast); + opts::optimize(alloc, &mut hir); + hir +} diff --git a/rust2/src/opts.rs b/rust2/src/hir/opts.rs similarity index 60% rename from rust2/src/opts.rs rename to rust2/src/hir/opts.rs index 7e7d24b..cb03e7b 100644 --- a/rust2/src/opts.rs +++ b/rust2/src/hir/opts.rs @@ -1,111 +1,38 @@ -use crate::parse::{Instr, Span}; -use crate::BumpVec; -use bumpalo::Bump; use std::cmp::Ordering; -use std::fmt::{Debug, Formatter}; + +use bumpalo::Bump; use tracing::trace; -#[derive(Clone)] -pub struct Ir<'ir> { - pub stmts: BumpVec<'ir, Stmt<'ir>>, -} +use crate::{ + hir::{Hir, Stmt, StmtKind}, + BumpVec, +}; -impl Debug for Ir<'_> { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - self.stmts.fmt(f) - } -} - -#[derive(Clone)] -pub struct Stmt<'ir> { - pub kind: StmtKind<'ir>, - pub span: Span, -} - -impl<'ir> Stmt<'ir> { - fn new(kind: StmtKind<'ir>, span: Span) -> Stmt<'ir> { - Self { kind, span } - } - - fn kind(&self) -> &StmtKind<'ir> { - &self.kind - } -} - -impl Debug for Stmt<'_> { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - self.kind.fmt(f) - } -} - -#[derive(Debug, Clone)] -pub enum StmtKind<'ir> { - Add(i32, u8), - Sub(i32, u8), - /// Sets the current cell to 0 and adds that value of the cell to another cell at `offset` - MoveAddTo { - offset: i32, - }, - Right(usize), - Left(usize), - Loop(Ir<'ir>), - Out, - In, - SetN(u8), -} - -pub fn optimize<'ir>(alloc: &'ir Bump, instrs: &[(Instr<'_>, Span)]) -> Ir<'ir> { - let mut ir = ast_to_ir(alloc, instrs); - pass_group(alloc, &mut ir); - pass_find_set_null(&mut ir); - pass_set_n(&mut ir); - pass_cancel_left_right_add_sub(&mut ir); - pass_add_sub_offset(&mut ir); - pass_move_add_to(&mut ir); - - ir -} - -fn ast_to_ir<'ir>(alloc: &'ir Bump, ast: &[(Instr<'_>, Span)]) -> Ir<'ir> { - let mut stmts = Vec::new_in(alloc); - - let stmts_iter = ast.iter().map(|(instr, span)| { - let kind = match instr { - Instr::Add => StmtKind::Add(0, 1), - Instr::Sub => StmtKind::Sub(0, 1), - Instr::Right => StmtKind::Right(1), - Instr::Left => StmtKind::Left(1), - Instr::Out => StmtKind::Out, - Instr::In => StmtKind::In, - Instr::Loop(body) => { - let ir_body = ast_to_ir(alloc, body); - StmtKind::Loop(ir_body) - } - }; - Stmt::new(kind, *span) - }); - - stmts.extend(stmts_iter); - - Ir { stmts } +pub fn optimize<'hir>(alloc: &'hir Bump, hir: &mut Hir<'hir>) { + pass_group(alloc, hir); + pass_find_set_null(hir); + pass_set_n(hir); + pass_cancel_left_right_add_sub(hir); + pass_add_sub_offset(hir); + pass_move_add_to(hir); } /// pass that replaces things like `Sub(1) Sub(1)` with `Sub(2)` // TODO: This pass is really slow, speed it up please #[tracing::instrument] -fn pass_group<'ir>(alloc: &'ir Bump, ir_param: &mut Ir<'ir>) { - let empty_ir = Ir { +fn pass_group<'hir>(alloc: &'hir Bump, ir_param: &mut Hir<'hir>) { + let empty_ir = Hir { stmts: Vec::new_in(alloc), }; let ir = std::mem::replace(ir_param, empty_ir); let new_stmts = Vec::new_in(alloc); - let stmts = ir - .stmts - .into_iter() - .fold(new_stmts, |mut stmts: BumpVec<'ir, Stmt<'ir>>, next| { - let Some(old) = stmts.last_mut() else { + let stmts = + ir.stmts + .into_iter() + .fold(new_stmts, |mut stmts: BumpVec<'hir, Stmt<'hir>>, next| { + let Some(old) = stmts.last_mut() else { if let StmtKind::Loop(mut body) = next.kind { pass_group(alloc, &mut body); stmts.push(Stmt::new( @@ -118,48 +45,48 @@ fn pass_group<'ir>(alloc: &'ir Bump, ir_param: &mut Ir<'ir>) { return stmts; }; - match (&mut old.kind, next.kind) { - (StmtKind::Add(offset_a, a), StmtKind::Add(offset_b, b)) - if *a < 255 && *offset_a == offset_b => - { - old.span = old.span.merge(next.span); - *a += b; + match (&mut old.kind, next.kind) { + (StmtKind::Add(offset_a, a), StmtKind::Add(offset_b, b)) + if *a < 255 && *offset_a == offset_b => + { + old.span = old.span.merge(next.span); + *a += b; + } + (StmtKind::Sub(offset_a, a), StmtKind::Sub(offset_b, b)) + if *a < 255 && *offset_a == offset_b => + { + old.span = old.span.merge(next.span); + *a += b; + } + (StmtKind::Right(a), StmtKind::Right(b)) if *a < 255 => { + old.span = old.span.merge(next.span); + *a += b; + } + (StmtKind::Left(a), StmtKind::Left(b)) if *a < 255 => { + old.span = old.span.merge(next.span); + *a += b; + } + (_, StmtKind::Loop(mut body)) => { + pass_group(alloc, &mut body); + stmts.push(Stmt { + span: next.span, + kind: StmtKind::Loop(body), + }); + } + (_, kind) => { + stmts.push(Stmt::new(kind, next.span)); + } } - (StmtKind::Sub(offset_a, a), StmtKind::Sub(offset_b, b)) - if *a < 255 && *offset_a == offset_b => - { - old.span = old.span.merge(next.span); - *a += b; - } - (StmtKind::Right(a), StmtKind::Right(b)) if *a < 255 => { - old.span = old.span.merge(next.span); - *a += b; - } - (StmtKind::Left(a), StmtKind::Left(b)) if *a < 255 => { - old.span = old.span.merge(next.span); - *a += b; - } - (_, StmtKind::Loop(mut body)) => { - pass_group(alloc, &mut body); - stmts.push(Stmt { - span: next.span, - kind: StmtKind::Loop(body), - }); - } - (_, kind) => { - stmts.push(Stmt::new(kind, next.span)); - } - } - stmts - }); + stmts + }); - *ir_param = Ir { stmts }; + *ir_param = Hir { stmts }; } /// pass that replaces `Loop([Sub(_)])` to `SetNull` #[tracing::instrument] -fn pass_find_set_null(ir: &mut Ir<'_>) { +fn pass_find_set_null(ir: &mut Hir<'_>) { for stmt in &mut ir.stmts { if let Stmt { kind: StmtKind::Loop(body), @@ -182,7 +109,7 @@ fn pass_find_set_null(ir: &mut Ir<'_>) { /// pass that replaces `SetN(n) Add(m)` with `SetN(n + m)` #[tracing::instrument] -fn pass_set_n(ir: &mut Ir<'_>) { +fn pass_set_n(ir: &mut Hir<'_>) { window_pass(ir, pass_set_n, |[a, b]| { if let StmtKind::SetN(before) = a.kind() { let new = match b.kind() { @@ -200,7 +127,7 @@ fn pass_set_n(ir: &mut Ir<'_>) { /// pass that replaces `Left(5) Right(3)` with `Left(2)` #[tracing::instrument] -fn pass_cancel_left_right_add_sub(ir: &mut Ir<'_>) { +fn pass_cancel_left_right_add_sub(ir: &mut Hir<'_>) { 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)) => { @@ -233,7 +160,7 @@ fn pass_cancel_left_right_add_sub(ir: &mut Ir<'_>) { /// pass that replaces `Right(9) Add(5) Left(9)` with `AddOffset(9, 5)` #[tracing::instrument] -fn pass_add_sub_offset(ir: &mut Ir<'_>) { +fn pass_add_sub_offset(ir: &mut Hir<'_>) { window_pass(ir, pass_add_sub_offset, |[a, b, c]| { match (a.kind(), b.kind(), c.kind()) { (StmtKind::Right(r), StmtKind::Add(0, n), StmtKind::Left(l)) if r == l => { @@ -255,7 +182,7 @@ fn pass_add_sub_offset(ir: &mut Ir<'_>) { /// pass that replaces `Loop([Sub(1) AddOffset(o, 1)])` with `MoveAddTo(o)` #[tracing::instrument] -fn pass_move_add_to(ir: &mut Ir<'_>) { +fn pass_move_add_to(ir: &mut Hir<'_>) { for stmt in &mut ir.stmts { if let Stmt { kind: StmtKind::Loop(body), @@ -286,16 +213,16 @@ fn pass_move_add_to(ir: &mut Ir<'_>) { } } -enum WindowPassAction<'ir> { +enum WindowPassAction<'hir> { None, - Merge(StmtKind<'ir>), + Merge(StmtKind<'hir>), RemoveAll, } -fn window_pass<'ir, P, F, const N: usize>(ir: &mut Ir<'ir>, pass_recur: P, action: F) +fn window_pass<'hir, P, F, const N: usize>(ir: &mut Hir<'hir>, pass_recur: P, action: F) where - P: Fn(&mut Ir<'ir>), - F: Fn([&Stmt<'ir>; N]) -> WindowPassAction<'ir>, + P: Fn(&mut Hir<'hir>), + F: Fn([&Stmt<'hir>; N]) -> WindowPassAction<'hir>, { assert!(N > 0); diff --git a/rust2/src/lib.rs b/rust2/src/lib.rs index 9a059fd..b1b72ad 100644 --- a/rust2/src/lib.rs +++ b/rust2/src/lib.rs @@ -2,17 +2,20 @@ #![deny(unsafe_op_in_unsafe_fn)] #![warn(rust_2018_idioms)] -use crate::parse::ParseError; +use std::{ + fmt::Display, + io::{Read, Write}, + path::PathBuf, + str::FromStr, +}; + use bumpalo::Bump; use owo_colors::OwoColorize; -use std::fmt::Display; -use std::io::{Read, Write}; -use std::path::PathBuf; -use std::str::FromStr; -pub mod codegen; -pub mod codegen_interpreter; -pub mod opts; +use crate::parse::ParseError; + +pub mod hir; +pub mod lir; pub mod parse; #[derive(clap::Parser, Default)] @@ -27,8 +30,8 @@ pub struct Args { pub enum DumpKind { Ast, - Ir, - Code, + Hir, + Lir, } impl FromStr for DumpKind { @@ -37,8 +40,8 @@ impl FromStr for DumpKind { fn from_str(s: &str) -> Result { match s { "ast" => Ok(Self::Ast), - "ir" => Ok(Self::Ir), - "code" => Ok(Self::Code), + "hir" => Ok(Self::Hir), + "lir" => Ok(Self::Lir), other => Err(format!("Invalid IR level: '{other}'")), } } @@ -65,12 +68,12 @@ where return Ok(()); } - let ir_alloc = Bump::new(); + let hir_alloc = Bump::new(); - let optimized_ir = opts::optimize(&ir_alloc, &parsed); + let optimized_hir = hir::optimized_hir(&hir_alloc, &parsed); - if let Some(DumpKind::Ir) = config.dump { - println!("{optimized_ir:#?}"); + if let Some(DumpKind::Hir) = config.dump { + println!("{optimized_hir:#?}"); return Ok(()); } @@ -79,27 +82,27 @@ where let cg_alloc = Bump::new(); - let code = codegen::generate(&cg_alloc, &optimized_ir); + let lir = lir::generate(&cg_alloc, &optimized_hir); - if let Some(DumpKind::Code) = config.dump { - println!("{code:#?}"); + if let Some(DumpKind::Lir) = config.dump { + println!("{lir:#?}"); return Ok(()); } - drop(optimized_ir); - drop(ir_alloc); + drop(optimized_hir); + drop(hir_alloc); match config.profile { true => { - let mut code_profile_count = vec![0; code.debug().len()]; + let mut code_profile_count = vec![0; lir.debug().len()]; - codegen_interpreter::run(&code, stdout, stdin, |ip| unsafe { + lir::interpreter::run(&lir, stdout, stdin, |ip| unsafe { *code_profile_count.get_unchecked_mut(ip) += 1; }); let mut src_profile_count = vec![0u64; src.len()]; - for (stmt_span, stmt_count) in code.debug().iter().zip(&code_profile_count) { + for (stmt_span, stmt_count) in lir.debug().iter().zip(&code_profile_count) { for i in &mut src_profile_count[stmt_span.start()..stmt_span.end()] { *i += stmt_count; } @@ -112,7 +115,7 @@ where } } false => { - codegen_interpreter::run(&code, stdout, stdin, |_| {}); + lir::interpreter::run(&lir, stdout, stdin, |_| {}); } } diff --git a/rust2/src/codegen_interpreter.rs b/rust2/src/lir/interpreter.rs similarity index 93% rename from rust2/src/codegen_interpreter.rs rename to rust2/src/lir/interpreter.rs index a7f2f6e..046a918 100644 --- a/rust2/src/codegen_interpreter.rs +++ b/rust2/src/lir/interpreter.rs @@ -1,6 +1,9 @@ -use crate::codegen::{Code, Stmt}; -use std::io::{Read, Write}; -use std::num::Wrapping; +use std::{ + io::{Read, Write}, + num::Wrapping, +}; + +use crate::lir::{Lir, Stmt}; const MEM_SIZE: usize = 32_000; @@ -10,7 +13,7 @@ type Memory = [Wrapping; MEM_SIZE]; // maybe useless, but seems to give tiny wins #[repr(C)] struct Interpreter<'c, W, R, P> { - code: &'c Code<'c>, + code: &'c Lir<'c>, profile_collector: P, ip: usize, ptr: usize, @@ -19,7 +22,7 @@ struct Interpreter<'c, W, R, P> { stdin: R, } -pub fn run(code: &Code<'_>, stdout: W, stdin: R, profile_collector: P) +pub fn run(code: &Lir<'_>, stdout: W, stdin: R, profile_collector: P) where W: Write, R: Read, @@ -35,7 +38,7 @@ where profile_collector, }; - // SAFETY: `Code` can only be produced by the `crate::codegen` module, which is trusted to not + // SAFETY: `Lir` can only be produced by the `crate::lir` module, which is trusted to not // produce out of bounds jumps and put the `End` at the end unsafe { interpreter.execute(); diff --git a/rust2/src/codegen.rs b/rust2/src/lir/mod.rs similarity index 53% rename from rust2/src/codegen.rs rename to rust2/src/lir/mod.rs index ac47e95..30ed996 100644 --- a/rust2/src/codegen.rs +++ b/rust2/src/lir/mod.rs @@ -17,12 +17,18 @@ //! this module must not produce out of bounds jumps and always put the `End` instruction at the //! end -use crate::opts::{Ir, Stmt as IrStmt, StmtKind}; -use crate::parse::Span; -use crate::BumpVec; -use bumpalo::Bump; +pub mod interpreter; + use std::fmt::{Debug, Formatter}; +use bumpalo::Bump; + +use crate::{ + hir::{Hir, Stmt as HirStmt, StmtKind as HirStmtKind}, + parse::Span, + BumpVec, +}; + #[derive(Debug, Clone, Copy)] pub enum Stmt { Add(u8), @@ -43,18 +49,18 @@ pub enum Stmt { const _: [(); 8] = [(); std::mem::size_of::()]; #[derive(Clone)] -pub struct Code<'c> { +pub struct Lir<'c> { stmts: BumpVec<'c, Stmt>, debug: BumpVec<'c, Span>, } -impl Debug for Code<'_> { +impl Debug for Lir<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { self.stmts.fmt(f) } } -impl Code<'_> { +impl Lir<'_> { pub fn stmts(&self) -> &[Stmt] { &self.stmts } @@ -64,68 +70,68 @@ impl Code<'_> { } } -pub fn generate<'c>(alloc: &'c Bump, ir: &Ir<'_>) -> Code<'c> { +pub fn generate<'c>(alloc: &'c Bump, ir: &Hir<'_>) -> Lir<'c> { let stmts = Vec::new_in(alloc); let debug = Vec::new_in(alloc); - let mut code = Code { stmts, debug }; + let mut lir = Lir { stmts, debug }; - generate_stmts(&mut code, &ir.stmts); - code.stmts.push(Stmt::End); - code.debug.push(Span::default()); + generate_stmts(&mut lir, &ir.stmts); + lir.stmts.push(Stmt::End); + lir.debug.push(Span::default()); - assert_eq!(code.stmts.len(), code.debug.len()); + assert_eq!(lir.stmts.len(), lir.debug.len()); - code + lir } -fn generate_stmts<'c>(code: &mut Code<'c>, ir: &[IrStmt<'_>]) { +fn generate_stmts<'c>(lir: &mut Lir<'c>, ir: &[HirStmt<'_>]) { for ir_stmt in ir { - ir_to_stmt(code, ir_stmt); + ir_to_stmt(lir, ir_stmt); } - debug_assert_eq!(code.stmts.len(), code.debug.len()); + debug_assert_eq!(lir.stmts.len(), lir.debug.len()); } -fn ir_to_stmt<'c>(code: &mut Code<'c>, ir_stmt: &IrStmt<'_>) { +fn ir_to_stmt<'c>(lir: &mut Lir<'c>, ir_stmt: &HirStmt<'_>) { let stmt = match &ir_stmt.kind { - StmtKind::Add(0, n) => Stmt::Add(*n), - StmtKind::Sub(0, n) => Stmt::Sub(*n), - StmtKind::Add(offset, n) => Stmt::AddOffset { + HirStmtKind::Add(0, n) => Stmt::Add(*n), + HirStmtKind::Sub(0, n) => Stmt::Sub(*n), + HirStmtKind::Add(offset, n) => Stmt::AddOffset { offset: *offset, n: *n, }, - StmtKind::Sub(offset, n) => Stmt::SubOffset { + HirStmtKind::Sub(offset, n) => Stmt::SubOffset { offset: *offset, n: *n, }, - StmtKind::MoveAddTo { offset } => Stmt::MoveAddTo { offset: *offset }, - StmtKind::Right(n) => Stmt::Right(u32::try_from(*n).unwrap()), - StmtKind::Left(n) => Stmt::Left(u32::try_from(*n).unwrap()), - StmtKind::Out => Stmt::Out, - StmtKind::In => Stmt::In, - StmtKind::SetN(n) => Stmt::SetN(*n), - StmtKind::Loop(instr) => { - let skip_jmp_idx = code.stmts.len(); - code.stmts.push(Stmt::JmpIfZero(0)); // placeholder - code.debug.push(ir_stmt.span); + HirStmtKind::MoveAddTo { offset } => Stmt::MoveAddTo { offset: *offset }, + HirStmtKind::Right(n) => Stmt::Right(u32::try_from(*n).unwrap()), + HirStmtKind::Left(n) => Stmt::Left(u32::try_from(*n).unwrap()), + HirStmtKind::Out => Stmt::Out, + HirStmtKind::In => Stmt::In, + HirStmtKind::SetN(n) => Stmt::SetN(*n), + HirStmtKind::Loop(instr) => { + let skip_jmp_idx = lir.stmts.len(); + lir.stmts.push(Stmt::JmpIfZero(0)); // placeholder + lir.debug.push(ir_stmt.span); // compile the loop body now - generate_stmts(code, &instr.stmts); + generate_stmts(lir, &instr.stmts); // if the loop body is empty, we jmp to ourselves, which is an infinite loop - as expected let first_loop_body_idx = skip_jmp_idx + 1; - code.stmts + lir.stmts .push(Stmt::JmpIfNonZero(first_loop_body_idx.try_into().unwrap())); - code.debug.push(ir_stmt.span); + lir.debug.push(ir_stmt.span); // there will always at least be an `End` instruction after the loop - let after_loop_idx = code.stmts.len(); + let after_loop_idx = lir.stmts.len(); // fix the placeholder with the actual index - code.stmts[skip_jmp_idx] = Stmt::JmpIfZero(after_loop_idx.try_into().unwrap()); + lir.stmts[skip_jmp_idx] = Stmt::JmpIfZero(after_loop_idx.try_into().unwrap()); return; } }; - code.stmts.push(stmt); - code.debug.push(ir_stmt.span); + lir.stmts.push(stmt); + lir.debug.push(ir_stmt.span); } diff --git a/rust2/src/main.rs b/rust2/src/main.rs index 72a798d..d7220d2 100644 --- a/rust2/src/main.rs +++ b/rust2/src/main.rs @@ -1,9 +1,10 @@ #![feature(allocator_api, let_else)] #![warn(rust_2018_idioms)] +use std::{fs, io, process}; + use brainfuck::Args; use clap::Parser; -use std::{fs, io, process}; fn main() { let stdout = io::stdout(); diff --git a/rust2/src/parse.rs b/rust2/src/parse.rs index 895952f..8aa1fff 100644 --- a/rust2/src/parse.rs +++ b/rust2/src/parse.rs @@ -1,6 +1,6 @@ +use std::{cmp, fmt::Debug}; + use bumpalo::Bump; -use std::cmp; -use std::fmt::Debug; #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub struct Span { diff --git a/rust2/test.bf b/rust2/test.bf index 7ad68db..5a2c354 100644 --- a/rust2/test.bf +++ b/rust2/test.bf @@ -1 +1,5 @@ -[->>>>>>>>>+<<<<<<<<<] \ No newline at end of file +[<+++>- + >>>>> + +++[->+++++<]>[-]< + <<<<< + ] \ No newline at end of file