mirror of
https://github.com/Noratrieb/brainfuck.git
synced 2026-01-14 21:35:02 +01:00
things
This commit is contained in:
parent
539d0e0502
commit
7b88c99039
7 changed files with 576 additions and 29 deletions
|
|
@ -1,4 +1,4 @@
|
|||
use crate::opts::IrInstr;
|
||||
use crate::opts::Stmt;
|
||||
use std::io::{Read, Write};
|
||||
use std::num::Wrapping;
|
||||
|
||||
|
|
@ -6,29 +6,29 @@ const MEM_SIZE: usize = 32_000;
|
|||
|
||||
type Memory = [Wrapping<u8>; MEM_SIZE];
|
||||
|
||||
pub fn run(instrs: &[IrInstr<'_>]) {
|
||||
pub fn run(instrs: &[Stmt<'_>]) {
|
||||
let mut mem = [Wrapping(0u8); MEM_SIZE];
|
||||
let mut ptr = 0;
|
||||
|
||||
execute(&mut mem, &mut ptr, instrs);
|
||||
}
|
||||
|
||||
fn execute(mem: &mut Memory, ptr: &mut usize, instrs: &[IrInstr<'_>]) {
|
||||
fn execute(mem: &mut Memory, ptr: &mut usize, instrs: &[Stmt<'_>]) {
|
||||
for instr in instrs {
|
||||
match instr {
|
||||
IrInstr::Add(n) => {
|
||||
Stmt::Add(n) => {
|
||||
mem[*ptr] += n;
|
||||
}
|
||||
IrInstr::Sub(n) => {
|
||||
Stmt::Sub(n) => {
|
||||
mem[*ptr] -= n;
|
||||
}
|
||||
IrInstr::Right(n) => {
|
||||
Stmt::Right(n) => {
|
||||
*ptr += n;
|
||||
if *ptr >= MEM_SIZE {
|
||||
*ptr = 0;
|
||||
}
|
||||
}
|
||||
IrInstr::Left(n) => {
|
||||
Stmt::Left(n) => {
|
||||
if *ptr < *n {
|
||||
let diff = *n - *ptr;
|
||||
*ptr = MEM_SIZE - 1 - diff;
|
||||
|
|
@ -36,22 +36,22 @@ fn execute(mem: &mut Memory, ptr: &mut usize, instrs: &[IrInstr<'_>]) {
|
|||
*ptr -= n;
|
||||
}
|
||||
}
|
||||
IrInstr::Out => {
|
||||
Stmt::Out => {
|
||||
let char = mem[*ptr].0 as char;
|
||||
print!("{char}");
|
||||
std::io::stdout().flush().unwrap();
|
||||
}
|
||||
IrInstr::In => {
|
||||
Stmt::In => {
|
||||
let mut buf = [0; 1];
|
||||
std::io::stdin().read_exact(&mut buf).unwrap();
|
||||
mem[*ptr] = Wrapping(buf[0]);
|
||||
}
|
||||
IrInstr::Loop(body) => {
|
||||
Stmt::Loop(body) => {
|
||||
while mem[*ptr] != Wrapping(0) {
|
||||
execute(mem, ptr, body);
|
||||
}
|
||||
}
|
||||
IrInstr::SetNull => {
|
||||
Stmt::SetNull => {
|
||||
mem[*ptr] = Wrapping(0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
3
rust2/src/lib.rs
Normal file
3
rust2/src/lib.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
pub mod ir_interpreter;
|
||||
pub mod opts;
|
||||
pub mod parse;
|
||||
|
|
@ -4,9 +4,7 @@
|
|||
use bumpalo::Bump;
|
||||
use std::{env, fs, process};
|
||||
|
||||
mod ir_interpreter;
|
||||
mod opts;
|
||||
mod parse;
|
||||
use brainfuck::{ir_interpreter, opts, parse};
|
||||
|
||||
fn main() {
|
||||
let Some(path) = env::args().nth(1) else {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
use crate::parse::Instr;
|
||||
use bumpalo::Bump;
|
||||
|
||||
pub type Ir<'ir> = Vec<IrInstr<'ir>, &'ir Bump>;
|
||||
pub type Ir<'ir> = Vec<Stmt<'ir>, &'ir Bump>;
|
||||
|
||||
pub enum IrInstr<'ir> {
|
||||
#[derive(Debug)]
|
||||
pub enum Stmt<'ir> {
|
||||
Add(u8),
|
||||
Sub(u8),
|
||||
Right(usize),
|
||||
|
|
@ -15,19 +16,65 @@ pub enum IrInstr<'ir> {
|
|||
}
|
||||
|
||||
pub fn optimize<'ir>(alloc: &'ir Bump, instrs: &[Instr<'_>]) -> Ir<'ir> {
|
||||
ast_to_ir(alloc, instrs)
|
||||
let mut ir = ast_to_ir(alloc, instrs);
|
||||
pass_find_set_null(&mut ir);
|
||||
ir
|
||||
}
|
||||
|
||||
fn ast_to_ir<'ir>(alloc: &'ir Bump, ast: &[Instr<'_>]) -> Ir<'ir> {
|
||||
let mut vec = Vec::new_in(alloc);
|
||||
vec.extend(ast.iter().map(|instr| match instr {
|
||||
Instr::Add => IrInstr::Add(1),
|
||||
Instr::Sub => IrInstr::Sub(1),
|
||||
Instr::Right => IrInstr::Right(1),
|
||||
Instr::Left => IrInstr::Left(1),
|
||||
Instr::Out => IrInstr::Out,
|
||||
Instr::In => IrInstr::In,
|
||||
Instr::Loop(body) => IrInstr::Loop(ast_to_ir(alloc, body)),
|
||||
}));
|
||||
vec
|
||||
let mut ir = Vec::new_in(alloc);
|
||||
|
||||
let mut instr_iter = ast.iter();
|
||||
|
||||
let Some(first) = instr_iter.next() else { return ir; };
|
||||
|
||||
let mut last = first;
|
||||
let mut count = 1;
|
||||
|
||||
for next in instr_iter {
|
||||
match last {
|
||||
Instr::Add | Instr::Sub | Instr::Right | Instr::Left if last == next => {
|
||||
count += 1;
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
let new_last = match last {
|
||||
Instr::Add => Stmt::Add(count),
|
||||
Instr::Sub => Stmt::Sub(count),
|
||||
Instr::Right => Stmt::Right(count.into()),
|
||||
Instr::Left => Stmt::Left(count.into()),
|
||||
Instr::Out => Stmt::Out,
|
||||
Instr::In => Stmt::In,
|
||||
Instr::Loop(body) => Stmt::Loop(ast_to_ir(alloc, body)),
|
||||
};
|
||||
ir.push(new_last);
|
||||
last = next;
|
||||
count = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let new_last = match last {
|
||||
Instr::Add => Stmt::Add(count),
|
||||
Instr::Sub => Stmt::Sub(count),
|
||||
Instr::Right => Stmt::Right(count.into()),
|
||||
Instr::Left => Stmt::Left(count.into()),
|
||||
Instr::Out => Stmt::Out,
|
||||
Instr::In => Stmt::In,
|
||||
Instr::Loop(body) => Stmt::Loop(ast_to_ir(alloc, body)),
|
||||
};
|
||||
ir.push(new_last);
|
||||
|
||||
ir
|
||||
}
|
||||
|
||||
fn pass_find_set_null(ir: &mut Ir<'_>) {
|
||||
for stmt in ir {
|
||||
if let Stmt::Loop(body) = stmt {
|
||||
if let [Stmt::Sub(_)] = body.as_slice() {
|
||||
println!("REPLACE");
|
||||
*stmt = Stmt::SetNull;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue