Enum Instruction

Source
#[non_exhaustive]
#[repr(u8)]
pub enum Instruction {
Show 82 variants Nop, Ldar(u16), Sba, Clř, Dumpř(u16), Movař(u8), Setř(u8, u16), Setiř(u8, i8), Ldř(u16), Ldiř([i8; 37]), Clß, Dumpß(u16), Writeß(u16, u8), Movaß(u8), Setß(u16, u8), Setiß(u8, u8), Ldß(u16), Pushß, Popß, Lenßa, Ldidp(u16), ΩChoiceSet(Option<Option<Option<Option<()>>>>), ΩChoiceGetA, ΩGainAPolymorphicDesires, ΩLoseAPolymorphicDesires, ΩPushPolymorphicDesires, ΩTheEndIsNear, ΩSkipToTheChase, ΩSetSentience(bool), ΩSetPaperclipProduction(bool), AddBL, SubBL, MulBL, DivBL, ModBL, NotL, AndBL, OrBL, XorBL, CmpLB, TgFlag, ClFlag, AddF(u16), SubF(u16), MulF(u16), DivF(u16), ModF(u16), StackAlloc(u16), StackDealloc(u16), Push(u16), Pushi(u8), Pop(u16), Popa, Pusha, Popb, Pushb, PopL, PushL, Popf, Pushf, Popch, Pushch, Popnum, Pushnum, Popep, Zpopep, Ppopep, Npopep, Fpopep, Zapopep, Dpopep, GetChar, GetLine, WriteChar, WriteLineß, WriteLine(u16), ToggleDebug, DebugMachineState, DebugMachineStateCompact, DebugMemoryRegion(u16, u16), DebugStackRegion(u16, u16), ShowChoice,
}
Expand description

An instruction.

This is used when executing instructions.

This enum is not stored directly into VM memory. The InstructionKind and the arguments, however, are.

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

Nop

No operation

§

Ldar(u16)

Load A (rotate left)

memory[data].rotate_left(1) // note that rotate left isn't the same as shift left (<<)
§

Sba

Sign of register B to register A

reg_a = reg_b.signum() // 0: zero, 1: positive, 255: negative
§

Clř

Clear ř

reg_ř.fill(0)
§

Dumpř(u16)

Dump ř to memory

memory[data] = reg_ř // indexes more than 1 byte of memory, this is pseudocode
§

Movař(u8)

Move a value from ř to register A

reg_a = reg_ř[data] // arrays can't be indexed by a u8, this is pseudocode
§

Setř(u8, u16)

Set value in ř

reg_ř[data0] = memory[data1] // arrays can't be indexed by a u8, this is pseudocode
§

Setiř(u8, i8)

Set immediate value in ř

reg_ř[data0] = data1 // arrays can't be indexed by a u8, this is pseudocode
§

Ldř(u16)

Load ř

reg_ř = memory[data] // indexes more than 1 byte of memory, this is pseudocode
§

Ldiř([i8; 37])

Load immediate ř

reg_ř = data
§

Clß

Clear ß

reg_ß = empty_string(),
§

Dumpß(u16)

Dump ß to memory

memory[data] = reg_ß // indexes more than 1 byte of memory, this is pseudocode
§

Writeß(u16, u8)

Write a value from ß to memory

memory[data0] = reg_ß[data1] // arrays can't be indexed by a u8, this is pseudocode
§

Movaß(u8)

Move a value from ß to register A

reg_a = reg_ß[data] // arrays can't be indexed by a u8, this is pseudocode
§

Setß(u16, u8)

Set value in ß

reg_ß[data1] = memory[data0] // arrays can't be indexed by a u8, this is pseudocode
§

Setiß(u8, u8)

Set immediate value in ß

reg_ß[data1] = data0 // arrays can't be indexed by a u8, this is pseudocode
§

Ldß(u16)

Load ß

reg_ß = memory[data] // indexes 256 bytes of memory, this is pseudocode
§

Pushß

Push to ß from stack (can’t go over maximum length)

if let Err(_) = regß.push_byte(stack.pop()) {
    flag = true
}
§

Popß

Pop ß to stack

stack.push(reg_ß.pop())
§

Lenßa

Length of ß to register A (in bytes)

reg_a = regß.len()
§

Ldidp(u16)

Load immediate dot pointer

Note that the address must be a fibonacci number that is also a prime or a semiprime (FIB_PRIMES_AND_SEMIPRIMES_LIST_U16)

if !is_fib_prime_or_semiprime_u16(data) {
    flag = true
} else {
    reg_dp = data
}
§

ΩChoiceSet(Option<Option<Option<Option<()>>>>)

Set the reg_Ω.illusion_of_choice to the specified value

reg_Ω.illusion_of_choice = data
§

ΩChoiceGetA

Write the reg_Ω.illusion_of_choice to register A (it’s 0, note: technically it isn’t 0 but that’s none of anyone’s business, which makes it a good way to clear the A register)

reg_a = 0
§

ΩGainAPolymorphicDesires

Increase polymorphic desires by register A’s value (if it overflows, then it just stays at u64::MAX, which is saturating addition)

reg_Ω.polymorphic_desires += reg_a
§

ΩLoseAPolymorphicDesires

Decrease polymorphic desires by register A’s value (if it overflows, then it just stays at 0, which is saturating subtraction)

reg_Ω.polymorphic_desires -= reg_a
§

ΩPushPolymorphicDesires

Push the amount of polymorphic desires onto stack

stack.push(reg_Ω.polymorphic_desires)
§

ΩTheEndIsNear

Create the feeling of impending doom (and you can’t cancel that)

reg_Ω.feeling_of_impending_doom = true
§

ΩSkipToTheChase

If there is the feeling of impending doom, exit the program already (with the exit code being the value of the number register).

if reg_Ω.feeling_of_impending_doom {
    abort_program(num_reg)
}
§

ΩSetSentience(bool)

Make the machine sentient (it isn’t actually a sentient being, or is it?)

if data == true {
    reg_Ω.is_sentient = true
} else if reg_Ω.is_sentient == false {
    resist() // resists the change and it doesn't happen
}
§

ΩSetPaperclipProduction(bool)

Turn the paperclip production on/off

reg_Ω.should_make_infinite_paperclips = data
§

AddBL

Add register B to register L

reg_L += transmute(reg_b) // transmute to u16
if overflow {
    flag = true
}
§

SubBL

Subtract register B from register L

reg_L -= transmute(reg_b) // transmute to u16
if overflow {
    flag = true
}
§

MulBL

Multiply register B with register L to register L

reg_L *= transmute(reg_b) // transmute to u16
if overflow {
    flag = true
}
§

DivBL

Divide register L with register B to register L

reg_L /= transmute(reg_b) // transmute to u16
§

ModBL

Modulo register L with register B

reg_L %= transmute(reg_b) // transmute to u16
§

NotL

Bitwise NOT register L

reg_L = !reg_L
§

AndBL

Bitwise AND register B and register L to register L

reg_L &= reg_b
§

OrBL

Bitwise OR register B and register L to register L

reg_L |= reg_b
§

XorBL

Bitwise AND register B and register L to register L

reg_L ^= reg_b
§

CmpLB

Compare register B and register L to register B

In this scenario, register B is treated as an i16, not as a u16.

A negative value (if unsigned, a value over 32767) in register B means that B is bigger, while a positive value means that L is bigger.

This means that register L has to be changed to an i16. If it exceeds i16::MAX, register B is automatically set to i16::MAX and the flag is set.

If register B is less than 0, it’s calculated as normal unless it overflows, in that case it automatically sets register B to i16::MAX and sets the flag.

if reg_b > 32767 { // i16::MAX
    reg_b = i16::MAX;
    flag = true;
}
match (reg_L as i16).checked_sub(reg_b) {
    Some(n) => reg_b = n,
    None => { // if subtraction overflows
        reg_b = i16::MAX;
        flag = true;
    }
}
§

TgFlag

Toggle flag

flag = !flag
§

ClFlag

Clear flag

flag = false
§

AddF(u16)

Add data in memory to register F

reg_f += transmute(memory[data]) // indexes 8 bytes
§

SubF(u16)

Subtract data in memory from register F

reg_f -= transmute(memory[data]) // indexes 8 bytes
§

MulF(u16)

Multiply data in memory with register F to register F

reg_f *= transmute(memory[data]) // indexes 8 bytes
§

DivF(u16)

Divide register f with data in memory to register F

reg_f /= transmute(memory[data]) // indexes 8 bytes
§

ModF(u16)

data in memory to register F

reg_f += transmute(memory[data]) // indexes 8 bytes
§

StackAlloc(u16)

Allocates x bytes on stack, if overflows, flag is set and it doesn’t allocate

stack.alloc(data)
if overflow {
flag = true
}
§

StackDealloc(u16)

Deallocates x bytes on stack, if overflows, flag is set but it does clear the stack

stack.dealloc(data)
if overflow
§

Push(u16)

Push a value from memory to stack

stack.push_byte(memory[data])
§

Pushi(u8)

Push an immediate value to stack

stack.push_byte(data)
§

Pop(u16)

Pop a value from stack to memory, sets the flag if it can’t

memory[data] = stack.pop()
§

Popa

Pop to A

reg_a = stack.pop_byte()
§

Pusha

Push from A

stack.push_byte(reg_a)
§

Popb

Pop to B

reg_b = transmute( u16::from_bytes(stack.dealloc(2)) ) // transmute to i16
§

Pushb

Push from B

stack.push_bytes(reg_b.as_bytes())
§

PopL

Pop to L

reg_L = u16::from_bytes(stack.dealloc(2))
§

PushL

Push from L

stack.push_bytes(reg_L.as_bytes())
§

Popf

Pop to F

reg_f = f64::from_bytes(stack.dealloc(8))
§

Pushf

Push from F

stack.push_bytes(reg_f.as_bytes())
§

Popch

Pop to Ch

reg_ch = char::from_bytes(stack.dealloc(4))
§

Pushch

Push from Ch

stack.push_bytes(reg_ch.as_bytes())
§

Popnum

Pop to Num

num_reg = i32::from_bytes(stack.dealloc(2))
§

Pushnum

Push from Num

stack.push_bytes(num_reg.as_bytes())
§

Popep

Pop to execution pointer

reg_ep = stack.dealloc(2)
§

Zpopep

Pop to execution pointer if (B is) zero (aka equal)

if reg_b == 0 {
    reg_ep = stack.dealloc(2)
}
§

Ppopep

Pop to execution pointer if positive (aka more than)

if reg_b > 0 {
    reg_ep = stack.dealloc(2)
}
§

Npopep

Pop to execution pointer if negative (aka less than)

if reg_b < 0 {
    reg_ep = stack.dealloc(2)
}
§

Fpopep

Pop to execution pointer if flag (aka overflow/error)

if flag == true {
    reg_ep = stack.dealloc(2)
}
§

Zapopep

Pop to execution pointer if register A is zero

if reg_a == 0 {
    reg_ep = stack.dealloc(2)
}
§

Dpopep

Pop to execution pointer if debug mode is enabled

if debug_mode {
    reg_ep = stack.dealloc(2)
}
§

GetChar

Get a single character and put it in register Ch

Note: this doesn’t write anything on screen. This also isn’t the correct instruction to use if you want a line of input.

enable_raw_mode();

let input = await_char_input();
reg_ch = input.char;
reg_L = input.flags;

disable_raw_mode();
§

GetLine

Get a line and put it in register ß

get_line(reg_ß)
§

WriteChar

Write a char from register Ch and flush

Note that flushing each time is inefficient so you should only use this sparingly.

write_char(reg_ch)
flush()
§

WriteLineß

Write a line from register ß

write_line(reg_ß)
§

WriteLine(u16)

Write a line from memory (null terminated)

write_line(c_string(memory[data]))
§

ToggleDebug

Toggles debug mode

debug_mode = !debug_mode
§

DebugMachineState

Debug print machine state

println!("{:#?}", machine)
§

DebugMachineStateCompact

Debug print machine state compactly

println!("{:?}", machine)
§

DebugMemoryRegion(u16, u16)

Debug print region of memory

println!("{:?}", &memory[data0..data1])
§

DebugStackRegion(u16, u16)

Debug print region of stack

println!("{:?}", &stack[data0..data1])
§

ShowChoice

Print reg_Ω.illusion_of_choice.

println!("{}", reg_Ω.illusion_of_choice)

Trait Implementations§

Source§

impl Clone for Instruction

Source§

fn clone(&self) -> Instruction

Returns a copy of the value. Read more
1.0.0 · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for Instruction

Source§

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

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

impl Default for Instruction

Source§

fn default() -> Instruction

Returns the “default value” for a type. Read more
Source§

impl<'_enum> From<&'_enum Instruction> for InstructionKind

Source§

fn from(val: &'_enum Instruction) -> InstructionKind

Converts to this type from the input type.
Source§

impl From<Instruction> for InstructionKind

Source§

fn from(val: Instruction) -> InstructionKind

Converts to this type from the input type.
Source§

impl Hash for Instruction

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Ord for Instruction

Source§

fn cmp(&self, other: &Instruction) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl PartialEq for Instruction

Source§

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

Tests for self and other values to be equal, and is used by ==.
1.0.0 · 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 PartialOrd for Instruction

Source§

fn partial_cmp(&self, other: &Instruction) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

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

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

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

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

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

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

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

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl Copy for Instruction

Source§

impl Eq for Instruction

Source§

impl StructuralPartialEq for Instruction

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.