Enum esoteric_vm::instruction::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
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: negativeClř
Clear ř
reg_ř.fill(0)Dumpř(u16)
Dump ř to memory
memory[data] = reg_ř // indexes more than 1 byte of memory, this is pseudocodeMovař(u8)
Move a value from ř to register A
reg_a = reg_ř[data] // arrays can't be indexed by a u8, this is pseudocodeSetř(u8, u16)
Set value in ř
reg_ř[data0] = memory[data1] // arrays can't be indexed by a u8, this is pseudocodeSetiř(u8, i8)
Set immediate value in ř
reg_ř[data0] = data1 // arrays can't be indexed by a u8, this is pseudocodeLdř(u16)
Load ř
reg_ř = memory[data] // indexes more than 1 byte of memory, this is pseudocodeLdiř([i8; 37])
Load immediate ř
reg_ř = dataClß
Clear ß
reg_ß = empty_string(),Dumpß(u16)
Dump ß to memory
memory[data] = reg_ß // indexes more than 1 byte of memory, this is pseudocodeWriteß(u16, u8)
Write a value from ß to memory
memory[data0] = reg_ß[data1] // arrays can't be indexed by a u8, this is pseudocodeMovaß(u8)
Move a value from ß to register A
reg_a = reg_ß[data] // arrays can't be indexed by a u8, this is pseudocodeSetß(u16, u8)
Set value in ß
reg_ß[data1] = memory[data0] // arrays can't be indexed by a u8, this is pseudocodeSetiß(u8, u8)
Set immediate value in ß
reg_ß[data1] = data0 // arrays can't be indexed by a u8, this is pseudocodeLdß(u16)
Load ß
reg_ß = memory[data] // indexes 256 bytes of memory, this is pseudocodePushß
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 = dataAddBL
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 u16ModBL
Modulo register L with register B
reg_L %= transmute(reg_b) // transmute to u16NotL
Bitwise NOT register L
reg_L = !reg_LAndBL
Bitwise AND register B and register L to register L
reg_L &= reg_bOrBL
Bitwise OR register B and register L to register L
reg_L |= reg_bXorBL
Bitwise AND register B and register L to register L
reg_L ^= reg_bCmpLB
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 = !flagClFlag
Clear flag
flag = falseAddF(u16)
Add data in memory to register F
reg_f += transmute(memory[data]) // indexes 8 bytesSubF(u16)
Subtract data in memory from register F
reg_f -= transmute(memory[data]) // indexes 8 bytesMulF(u16)
Multiply data in memory with register F to register F
reg_f *= transmute(memory[data]) // indexes 8 bytesDivF(u16)
Divide register f with data in memory to register F
reg_f /= transmute(memory[data]) // indexes 8 bytesModF(u16)
data in memory to register F
reg_f += transmute(memory[data]) // indexes 8 bytesStackAlloc(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 overflowPush(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 i16Pushb
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_modeDebugMachineState
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
impl Clone for Instruction
source§fn clone(&self) -> Instruction
fn clone(&self) -> Instruction
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moresource§impl Debug for Instruction
impl Debug for Instruction
source§impl Default for Instruction
impl Default for Instruction
source§fn default() -> Instruction
fn default() -> Instruction
source§impl<'_enum> From<&'_enum Instruction> for InstructionKind
impl<'_enum> From<&'_enum Instruction> for InstructionKind
source§fn from(val: &'_enum Instruction) -> InstructionKind
fn from(val: &'_enum Instruction) -> InstructionKind
source§impl From<Instruction> for InstructionKind
impl From<Instruction> for InstructionKind
source§fn from(val: Instruction) -> InstructionKind
fn from(val: Instruction) -> InstructionKind
source§impl Hash for Instruction
impl Hash for Instruction
source§impl Ord for Instruction
impl Ord for Instruction
source§fn cmp(&self, other: &Instruction) -> Ordering
fn cmp(&self, other: &Instruction) -> Ordering
1.21.0 · source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
source§impl PartialEq for Instruction
impl PartialEq for Instruction
source§impl PartialOrd for Instruction
impl PartialOrd for Instruction
impl Copy for Instruction
impl Eq for Instruction
impl StructuralPartialEq for Instruction
Auto Trait Implementations§
impl Freeze for Instruction
impl RefUnwindSafe for Instruction
impl Send for Instruction
impl Sync for Instruction
impl Unpin for Instruction
impl UnwindSafe for Instruction
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§default unsafe fn clone_to_uninit(&self, dst: *mut T)
default unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit)source§impl<T> CloneToUninit for Twhere
T: Copy,
impl<T> CloneToUninit for Twhere
T: Copy,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit)