Skip to main content

Effect

Enum Effect 

Source
pub enum Effect {
    AssertionFailed,
    DivisionByZero,
    IntegerOverflow,
    InvalidAddress,
    InvalidOperandStackIndex,
    InvalidReference,
    OperandStackUnderflow,
    OutOfOperators,
    Return,
    UnknownIdentifier,
    Yield,
}
Expand description

§An event triggered by scripts, to signal a specific condition

Effects moderate the communication between script and host. The effect itself only relays which effect has triggered, but that may signal to the host that a different communication channel (like operand stack or memory) is ready to be accessed.

§Handling Effects

The host may handle effects however it wishes. But since most effects signal error conditions that the script would not expect to recover from, a well-behaving host must be careful not to handle effects in a way that make reasoning about the script’s behavior difficult.

Abandoning the evaluation and reporting an error in the appropriate manner, is the only reasonable way to handle most effects. The exception to that is Effect::Yield, which does not signal an error condition. A script would expect to continue afterwards.

To make that possible, the host must clear the effect by calling Eval::clear_effect.

§Example

use stack_assembly::{Effect, Eval, Script};

// This script increments a number in a loop, yielding control to the
// host every time it did so.
let script = Script::compile("
    0

    increment:
        1 +
        yield
        @increment jump
");

let mut eval = Eval::new();

// When running the script for the first time, we expect that it has
// incremented the number once, before yielding.
let (effect, _) = eval.run(&script);
assert_eq!(effect, Effect::Yield);
assert_eq!(eval.operand_stack.to_u32_slice(), &[1]);

// To allow the script to continue, we must clear the effect.
eval.clear_effect();

// Since we handled the effect correctly, we can now assume that the
// script has incremented the number a second time, before yielding
// again.
let (effect, _) = eval.run(&script);
assert_eq!(effect, Effect::Yield);
assert_eq!(eval.operand_stack.to_u32_slice(), &[2]);

Variants§

§

AssertionFailed

§An assertion failed

Can trigger when evaluating assert, if its input is zero.

§

DivisionByZero

§Tried to divide by zero

Can trigger when evaluating the / operator, if its second input is 0.

§

IntegerOverflow

§Division resulted in integer overflow

Can only trigger when evaluating the / operator, if its first input is the lowest signed (two’s complement) 32-bit integer, and its second input is -1.

All other arithmetic operators wrap on overflow and don’t trigger this effect.

§

InvalidAddress

§A memory address is out of bounds

Can trigger when evaluating the read or write operators, if their address input (when interpreted as an unsigned 32-bit integer) does not refer to an address that is within the bounds of the memory.

§

InvalidOperandStackIndex

§Index doesn’t refer to valid value on the operand stack

Can trigger when evaluating the copy or drop operators, if their index input is too large to refer to a value on the operand stack.

§

InvalidReference

§Evaluated a reference that is not paired with a matching label

Can trigger when evaluating a reference, if that reference does not refer to a label.

§

OperandStackUnderflow

§Tried popping a value from an empty operand stack

Can trigger when evaluating any operator that has more inputs than the number of values currently on the operand stack.

§

OutOfOperators

§Ran out of operators to evaluate

Triggers when evaluation reaches the end of the script, where no more operators are available. This is not an error, which makes it one of the ways to signal the regular end of evaluation, alongside Effect::Return.

§

Return

§Evaluated return while call stack was empty

This is not an error, which makes it one of the ways to signal the regular end of evaluation, alongside Effect::OutOfOperators.

§

UnknownIdentifier

§Evaluated an identifier that the language does not recognize

Can trigger when evaluating an identifier, if that identifier does not refer to a known operation.

§

Yield

§The evaluating script yields control to the host

Triggers when evaluating the yield operator.

Trait Implementations§

Source§

impl Clone for Effect

Source§

fn clone(&self) -> Effect

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Effect

Source§

impl Debug for Effect

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Eq for Effect

Source§

impl From<OperandStackUnderflow> for Effect

Source§

fn from(OperandStackUnderflow: OperandStackUnderflow) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for Effect

Source§

fn eq(&self, other: &Effect) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl StructuralPartialEq for Effect

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
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.