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