Skip to main content

JournalEntry

Enum JournalEntry 

Source
pub enum JournalEntry {
Show 19 variants RegOverwrite { slot: usize, old: Value, }, GlobalOverwrite { idx: usize, old: Option<Value>, }, MultiRegOverwrite { slots: Vec<(usize, Value)>, }, ShowLine, NondetRead { dst_slot: usize, dst_old: Value, drawn: Value, }, Branch { taken: bool, }, CollectionMutate { slot: usize, old: Value, }, ListPop { list_slot: usize, list_old: Value, dst_slot: usize, dst_old: Value, }, IterNextUndo { advanced: bool, dst_slot: usize, dst_old: Value, }, IterPopUndo { items: Vec<Value>, idx: usize, }, CrdtInterior { slot: usize, snapshot: Value, }, CrdtFieldInterior { obj_slot: usize, field: String, snapshot: Value, }, DivReconstruct { dst_slot: usize, divisor: Value, remainder: Value, }, ShiftReconstruct { dst_slot: usize, dropped: i64, k: u32, left: bool, }, MaskReconstruct { dst_slot: usize, saved: i64, mask: i64, and: bool, }, ModReconstruct { dst_slot: usize, quotient: i64, divisor: Value, }, CallUndo { restore_len: usize, }, CallValueUndo { restore_len: usize, captures: Vec<(usize, Value)>, }, ReturnUndo { frame_from: usize, frame_vals: Vec<Value>, iter_from: usize, iter_vals: Vec<(Vec<Value>, usize)>, rv_slot: usize, rv_old: Value, arg_lo: usize, arg_old: Vec<Value>, },
}
Expand description

One recorded delta on the HistoryTape. Records only what a forward op DESTROYED, so reverse execution can restore it. Zero-cost/control entries (a shown line, a branch direction) carry no erased data — they are re-derivable — and so contribute nothing to the erased-bit measure.

Variants§

§

RegOverwrite

A register slot (base + r) was overwritten; restore old on reverse.

Fields

§slot: usize
§old: Value
§

GlobalOverwrite

A promoted global was overwritten (or first-defined, old == None); restore it on reverse.

Fields

§idx: usize
§

MultiRegOverwrite

Several register slots were overwritten at once (a tuple destructure). Reverse restores each.

Fields

§slots: Vec<(usize, Value)>
§

ShowLine

A Show appended one output line; reverse truncates the output buffer. The content is re-derivable on a re-forward, so no data is erased.

§

NondetRead

A NONDETERMINISTIC read (clock / random) drew drawn into a register. Reading does not mutate the world, so reverse simply restores the register’s prior value (dst_old). Critically, drawn is RECORDED — the entropy is captured on the tape (a deterministic replay could feed it back), rather than silently discarded, which is what makes reversing a nondeterministic program honest rather than a lie.

Fields

§dst_slot: usize
§dst_old: Value
§drawn: Value
§

Branch

A conditional branch was taken (true) or fell through (false); reverse follows it back. One bit of control flow, not erased data.

Fields

§taken: bool
§

CollectionMutate

An in-place collection mutation (push / index-set / add / remove). old is the register’s pre-mutation value — an Rc bump for a shared List/Map/Set, or a deep copy for a by-value container. Because that bump forces the op’s copy-on-write, the original stays pristine, so reverse restores old exactly (bit-identical, including aliasing). If instead the register still holds the SAME Rc (an in-place mutation — only when value-semantics is off), reverse declines rather than mis-restore.

Fields

§slot: usize
§old: Value
§

ListPop

A ListPop: it both shrinks a list AND overwrites a destination register. Reverse restores the pristine pre-pop list (list_old, which — COW-forced — still holds the popped element) and the destination’s prior value (dst_old), so no push-back or empty-flag is needed.

Fields

§list_slot: usize
§list_old: Value
§dst_slot: usize
§dst_old: Value
§

IterNextUndo

An IterNext. advanced = it yielded an element (idx < len): reverse restores the destination’s prior value and rewinds the top iterator’s index by one. !advanced = it was exhausted (a pure jump to the loop exit): reverse does nothing.

Fields

§advanced: bool
§dst_slot: usize
§dst_old: Value
§

IterPopUndo

An IterPop dropped the top iterator (a snapshot + cursor). Reverse re-pushes it so the loop body’s IterNexts can be rewound.

Fields

§items: Vec<Value>
§idx: usize
§

CrdtInterior

A CRDT interior mutation (CrdtAppend/CrdtResolve on an Rc<RefCell<CrdtValue>>). Unlike a by-value container, the mutation happens IN PLACE through the shared handle, so an Rc-bump snapshot would share the mutated interior, not preserve it. Instead snapshot is a DEEP clone of the pre-mutation CrdtValue (wrapped in a fresh handle); reverse copies it back THROUGH the register’s live handle (*rc.borrow_mut() = …), so every alias observes the restore.

Fields

§slot: usize
§snapshot: Value
§

CrdtFieldInterior

A CrdtResolve onto a nested CRDT-register FIELD (registers[obj_slot]’s field) — the field’s Rc<RefCell<CrdtValue>> interior is resolved in place. Like JournalEntry::CrdtInterior but the handle lives inside a struct field, so snapshot (a deep pre-resolve clone) is copied back through that field’s live handle. (A resolve onto a plain field is a CollectionMutate instead.)

Fields

§obj_slot: usize
§field: String
§snapshot: Value
§

DivReconstruct

An IN-PLACE integer division a = a / b — the quotient is kept in dst_slot, the REMAINDER is the only bit truly discarded. Reverse reconstructs a_old = q·b + r from the kept quotient and the divisor, so the Landauer cost is the remainder’s few bits (< log₂ b), not the whole dividend word. The divisor is a recomputable input (stored here for a self-contained reverse, but it is not erased information, so it costs nothing).

Fields

§dst_slot: usize
§divisor: Value
§remainder: Value
§

ShiftReconstruct

An IN-PLACE bit shift (a = a << k / a = a >> k; Shl/Shr/DivPow2 with dst == lhs). Only the shifted-OUT bits are destroyed — the rest of a_old survives in the kept result — so the tape records just those k bits (dropped: the low k bits for a right shift, the top k bits right-aligned for a left shift). Reverse recombines them with the kept result, so the Landauer cost is k bits, not the whole 64-bit word.

Fields

§dst_slot: usize
§dropped: i64
§left: bool
§

MaskReconstruct

An IN-PLACE bitwise mask (a = a & b / a = a | b; BitAnd/BitOr with dst == lhs). The bits the live mask b cannot recover are saved: for AND the bits where b = 0, for OR the bits where b = 1. Reverse re-merges them under the complementary mask. The Landauer cost is exactly the count of unrecoverable positions (64 − popcount b for AND, popcount b for OR).

Fields

§dst_slot: usize
§saved: i64
§mask: i64
§and: bool
§

ModReconstruct

An IN-PLACE integer modulo (a = a % b; Mod with dst == lhs). The remainder is kept in the destination; the QUOTIENT is the discarded information. Reverse rebuilds a_old = q·b + r from the saved quotient and the live divisor. The Landauer cost is the quotient’s magnitude bits.

Fields

§dst_slot: usize
§quotient: i64
§divisor: Value
§

CallUndo

A Call grew the register file (a callee window). Reverse truncates it back to restore_len after the callee’s body has been reversed.

Fields

§restore_len: usize
§

CallValueUndo

A CallValue (closure invocation): like Call it grew the register file, and it also bound captures into the callee frame. captures are the pre-binding (slot, old_value) pairs (an overlap capture slot survives the truncate, so its prior caller value must be restored). Reverse restores the capture slots, then truncates back to restore_len.

Fields

§restore_len: usize
§captures: Vec<(usize, Value)>
§

ReturnUndo

A Return/ReturnNothing tore down the callee frame. Reverse rebuilds it: regrow the registers to frame_from + frame_vals.len() restoring the callee’s saved window, restore the iterator stack, and undo the return-value write (rv_slot←rv_old) and the argument-window clear (arg_lo..←arg_old) — leaving the machine exactly in the callee’s pre-return state so the callee body can be walked backward.

Fields

§frame_from: usize
§frame_vals: Vec<Value>
§iter_from: usize
§iter_vals: Vec<(Vec<Value>, usize)>
§rv_slot: usize
§rv_old: Value
§arg_lo: usize
§arg_old: Vec<Value>

Trait Implementations§

Source§

impl Debug for JournalEntry

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,