move places of casts

This commit is contained in:
nora 2022-04-15 19:27:48 +02:00
parent 7dd2c82fa4
commit b535178cb8

View file

@ -2,15 +2,15 @@ use crate::codegen::{Code, Stmt};
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::num::Wrapping; use std::num::Wrapping;
const MEM_SIZE: u32 = 32_000; const MEM_SIZE: usize = 32_000;
type Memory = [Wrapping<u8>; MEM_SIZE as usize]; type Memory = [Wrapping<u8>; MEM_SIZE];
// TODO maybe repr(C) to prevent field reordering? // TODO maybe repr(C) to prevent field reordering?
struct Interpreter<'c, W, R> { struct Interpreter<'c, W, R> {
code: &'c Code<'c>, code: &'c Code<'c>,
ip: u32, ip: usize,
ptr: u32, ptr: usize,
stdout: W, stdout: W,
stdin: R, stdin: R,
mem: Memory, mem: Memory,
@ -27,7 +27,7 @@ where
ptr: 0, ptr: 0,
stdout, stdout,
stdin, stdin,
mem: [Wrapping(0u8); MEM_SIZE as usize], mem: [Wrapping(0u8); MEM_SIZE],
}; };
// SAFETY: `Code` can only be produced by the `crate::codegen` module, which is trusted to not // SAFETY: `Code` can only be produced by the `crate::codegen` module, which is trusted to not
@ -44,8 +44,8 @@ impl<'c, W: Write, R: Read> Interpreter<'c, W, R> {
// SAFETY: If the code ends with an `End` and there are no out of bounds jumps, // SAFETY: If the code ends with an `End` and there are no out of bounds jumps,
// `self.ip` will never be out of bounds // `self.ip` will never be out of bounds
// Removing this bounds check speeds up execution by about 40% // Removing this bounds check speeds up execution by about 40%
debug_assert!((self.ip as usize) < stmts.len()); debug_assert!(self.ip < stmts.len());
let instr = unsafe { *stmts.get_unchecked(self.ip as usize) }; let instr = unsafe { *stmts.get_unchecked(self.ip) };
self.ip += 1; self.ip += 1;
match instr { match instr {
Stmt::Add(n) => { Stmt::Add(n) => {
@ -55,17 +55,17 @@ impl<'c, W: Write, R: Read> Interpreter<'c, W, R> {
*self.elem_mut() -= n; *self.elem_mut() -= n;
} }
Stmt::Right(n) => { Stmt::Right(n) => {
self.ptr += n; self.ptr += n as usize;
if self.ptr >= MEM_SIZE { if self.ptr >= MEM_SIZE {
self.ptr = 0; self.ptr = 0;
} }
} }
Stmt::Left(n) => { Stmt::Left(n) => {
if self.ptr < n { if self.ptr < n as usize {
let diff = n - self.ptr; let diff = n as usize - self.ptr;
self.ptr = MEM_SIZE - 1 - diff; self.ptr = MEM_SIZE - 1 - diff;
} else { } else {
self.ptr -= n; self.ptr -= n as usize;
} }
} }
Stmt::Out => { Stmt::Out => {
@ -83,24 +83,27 @@ impl<'c, W: Write, R: Read> Interpreter<'c, W, R> {
} }
Stmt::JmpIfZero(pos) => { Stmt::JmpIfZero(pos) => {
if self.elem() == 0 { if self.elem() == 0 {
self.ip = pos; self.ip = pos as usize;
} }
} }
Stmt::JmpIfNonZero(pos) => { Stmt::JmpIfNonZero(pos) => {
if self.elem() != 0 { if self.elem() != 0 {
self.ip = pos; self.ip = pos as usize;
} }
} }
Stmt::End => break, Stmt::End => break,
} }
} }
} }
fn elem_mut(&mut self) -> &mut Wrapping<u8> { fn elem_mut(&mut self) -> &mut Wrapping<u8> {
&mut self.mem[self.ptr as usize] // SAFETY: `self.ptr` is never out of bounds
//debug_assert!(self.ptr < self.mem.len());
unsafe { self.mem.get_unchecked_mut(self.ptr) }
} }
fn elem(&self) -> u8 { fn elem(&self) -> u8 {
self.mem[self.ptr as usize].0 // SAFETY: `self.ptr` is never out of bounds
//debug_assert!(self.ptr < self.mem.len());
unsafe { self.mem.get_unchecked(self.ptr).0 }
} }
} }