1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
/// This enum represents a single opcode. /// Under the hood, it's just a byte. /// This allows non opcode bytes to be inserted in bytecode streams. /// | Opcode | operands, top first | byte-streams | Does | /// | ------ | ------------------- | ------------ | ---------------------------------------------- | /// | Con | | Const Index | Pushes value from constant table onto stack | /// | Save | Data | | Stores Data in Symbol | /// | Load | | Local Index | Replaces symbol on top of stack with its value | /// | Clear | | | Clears stack to last frame/local | /// | Call | Fun, Data | | Calls the function passing Data as arg | /// | Return | Data | | Clears the frame, leaving value on the stack | #[repr(u8)] #[derive(Debug)] pub enum Opcode { Con = 0, Save = 1, Load = 2, Call = 3, Return = 4, Clear = 5, // probably unneeded } impl Opcode { /// Convert a raw byte to an opcode. /// Note that non-opcode bytes should never be interpreted as an opcode. /// Under the hood, this is just a transmute, so the regular cautions apply. /// This *should* never cause a crash /// and if it does, the vm's designed to crash hard /// so it'll be pretty obvious. pub fn from_byte(byte: u8) -> Opcode { let e: Opcode = unsafe { std::mem::transmute(byte) }; // *chuckles in undefined behavior* return e; // "I'm in danger" } }