#[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 more