mirror of
https://github.com/Noratrieb/brainfuck.git
synced 2026-01-16 14:25:03 +01:00
add mir
This commit is contained in:
parent
d0718adf7f
commit
80b1b0e3f6
4 changed files with 341 additions and 0 deletions
149
rust2/src/mir/state.rs
Normal file
149
rust2/src/mir/state.rs
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
use std::{
|
||||
cell::RefCell,
|
||||
fmt::{Debug, Formatter},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
use bumpalo::Bump;
|
||||
|
||||
use crate::BumpVec;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum CellState {
|
||||
Unknown,
|
||||
LoopNull,
|
||||
WrittenToUnknown(Store),
|
||||
WrittenToKnown(Store, u8),
|
||||
}
|
||||
|
||||
/// A change in the known state of the memory caused by a single instruction
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum MemoryStateChange {
|
||||
/// A cell was changed
|
||||
Change { offset: i32, new_state: CellState },
|
||||
/// The pointer was moved
|
||||
Move(i32),
|
||||
/// Forget everything
|
||||
Forget,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MemoryState<'mir>(Rc<RefCell<MemoryStateInner<'mir>>>);
|
||||
|
||||
impl<'mir> MemoryState<'mir> {
|
||||
pub fn empty(alloc: &'mir Bump) -> Self {
|
||||
Self(Rc::new(RefCell::new(MemoryStateInner {
|
||||
prev: None,
|
||||
deltas: Vec::new_in(alloc),
|
||||
})))
|
||||
}
|
||||
|
||||
pub fn state_for_offset(&self, offset: i32) -> &'mir CellState {
|
||||
self.0.borrow().state_for_offset(offset)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for MemoryState<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
self.0
|
||||
.try_borrow()
|
||||
.map(|s| MemoryStateInner::fmt(&*s, f))
|
||||
.unwrap_or_else(|_| f.debug_struct("MemoryState").finish_non_exhaustive())
|
||||
}
|
||||
}
|
||||
|
||||
/// The known state of memory relative to the pointer
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MemoryStateInner<'mir> {
|
||||
prev: Option<MemoryState<'mir>>,
|
||||
deltas: BumpVec<'mir, MemoryStateChange>,
|
||||
}
|
||||
|
||||
impl<'mir> MemoryStateInner<'mir> {
|
||||
pub fn state_for_offset(&self, offset: i32) -> &'mir CellState {
|
||||
let mut offset = offset;
|
||||
for delta in &self.deltas {
|
||||
match delta {
|
||||
MemoryStateChange::Change {
|
||||
offset: write_offset,
|
||||
new_state,
|
||||
} if *write_offset == offset => {
|
||||
return new_state;
|
||||
}
|
||||
MemoryStateChange::Move(change) => offset -= change,
|
||||
// we may not access the forbidden knowledge
|
||||
MemoryStateChange::Forget => return &CellState::Unknown,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
self.prev
|
||||
.map(|state| state.state_for_offset(offset))
|
||||
.unwrap_or(&CellState::Unknown)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'mir> MemoryState<'mir> {
|
||||
pub fn single(
|
||||
alloc: &'mir Bump,
|
||||
prev: MemoryState<'mir>,
|
||||
delta: MemoryStateChange,
|
||||
) -> MemoryState<'mir> {
|
||||
let mut deltas = Vec::new_in(alloc);
|
||||
deltas.push(delta);
|
||||
Self::new(prev, deltas)
|
||||
}
|
||||
|
||||
pub fn double(
|
||||
alloc: &'mir Bump,
|
||||
prev: MemoryState<'mir>,
|
||||
delta1: MemoryStateChange,
|
||||
delta2: MemoryStateChange,
|
||||
) -> MemoryState<'mir> {
|
||||
let mut deltas = Vec::new_in(alloc);
|
||||
deltas.push(delta1);
|
||||
deltas.push(delta2);
|
||||
Self::new(prev, deltas)
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
prev: MemoryState<'mir>,
|
||||
deltas: BumpVec<'mir, MemoryStateChange>,
|
||||
) -> MemoryState<'mir> {
|
||||
Self(Rc::new(RefCell::new(MemoryStateInner {
|
||||
prev: Some(prev),
|
||||
deltas,
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Store(Rc<RefCell<StoreInner>>);
|
||||
|
||||
impl Store {
|
||||
pub fn unknown() -> Self {
|
||||
StoreInner::Unknown.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Store {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
self.0
|
||||
.try_borrow()
|
||||
.map(|s| StoreInner::fmt(&*s, f))
|
||||
.unwrap_or_else(|_| f.debug_struct("Store").finish_non_exhaustive())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum StoreInner {
|
||||
Unknown,
|
||||
Used(usize),
|
||||
Dead,
|
||||
}
|
||||
|
||||
impl From<StoreInner> for Store {
|
||||
fn from(inner: StoreInner) -> Self {
|
||||
Self(Rc::new(RefCell::new(inner)))
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue