namespace Qrakhen.Qamp.Core.Execution; public class SerializedEnumAttribute(Type serializedType) : Attribute { public Type SerializedType { get; } = serializedType; } /// /// /// /// /// In order to keep instruction files small, all op codes are crammed into 8 bits, /// and operation flags aren't flags, but rather should be seen as IDs (the first 4 bits) /// and the operation itself is a number made from the last 4 bits. /// & 0b11110000 => Handler /// & 0b00001111 => Operation /// [SerializedEnum(typeof(byte))] public enum OpCode { /// /// Mask bits, to be used like opCode & F_Mask == F_Operation, for example. /// Mask_Handler = 0xF0, Mask_Operation = 0x0F, Error = -1, Void = 0, F_Static = 0x10, None = F_Static | 1, True = F_Static | 2, False = F_Static | 3, Constant = F_Static | 4, Null = F_Static | 5, Cast = F_Static | 6, Pop = F_Static | 7, F_Retrieve = 0x20, Val = F_Retrieve | 1, Ref = F_Retrieve | 2, Addr = F_Retrieve | 3, F_Names = 0x30, SetGlobal = F_Names | 1, GetGlobal = F_Names | 2, GetLocal = F_Names | 3, SetLocal = F_Names | 4, GetOuter = F_Names | 5, SetOuter = F_Names | 6, GetMember = F_Names | 7, SetMember = F_Names | 8, DefineGlobal = F_Names | 9, CloseOuter = F_Names | 10, //AssignValue = 0x0, // unsure //AssignReference = 0x0, // unsure F_Arithmetic = 0x40, Add = F_Arithmetic | 1, Subtract = F_Arithmetic | 2, Multiply = F_Arithmetic | 3, Pow = F_Arithmetic | 4, Divide = F_Arithmetic | 5, Modulo = F_Arithmetic | 6, Negate = F_Arithmetic | 7, F_Bitwise = 0x50, BitwiseAnd = F_Bitwise | 1, BitwiseOr = F_Bitwise | 2, BitwiseXor = F_Bitwise | 3, BitwiseLeft = F_Bitwise | 4, BitwiseRight = F_Bitwise | 5, BitwiseNot = F_Bitwise | 6, F_Boolean = 0x60, Not = F_Boolean | 1, Equal = F_Boolean | 2, Greater = F_Boolean | 3, Less = F_Boolean | 4, F_Collection = 0x70, Array = F_Collection | 1, List = F_Collection | 2, Structure = F_Collection | 3, GetItem = F_Collection | 4, SetItem = F_Collection | 5, AddItem = F_Collection | 6, RemoveItem = F_Collection | 7, F_Control = 0x80, Return = F_Control | 1, Jump = F_Control | 2, JumpIfFalse = F_Control | 3, Loop = F_Control | 4, Invoke = F_Control | 5, InvokeBase = F_Control | 6, InvokeMember = F_Control | 7, Context = F_Control | 8, F_Class = 0x90, Class = F_Class | 1, Member = F_Class | 2, Base = F_Class | 3, Inherit = F_Class | 4, Method = F_Class | 5, Static = F_Class | 6, F_Meta = 0xa0, Print = F_Meta | 1, PrintStack = F_Meta | 2, PrintGlobals = F_Meta | 3, PrintExpr = F_Meta | 4, Typeof = F_Meta | 5, F_Module = 0xf0, Export = F_Module | 1, // probably shouldnt be an op code but rather be done during digestion Import = F_Module | 2, // probably shouldnt be an op code but rather be done during digestion } public static class OpCodeExtensions { public static bool IsUnary(this OpCode op) => op is OpCode.Not or OpCode.Negate or OpCode.BitwiseNot; public static bool IsHandledByAlu(this OpCode op) => (op & OpCode.Mask_Handler) is OpCode.F_Arithmetic or OpCode.F_Bitwise or OpCode.F_Boolean; public static string ToString(this OpCode op) => $"{op & OpCode.Mask_Handler}: {op} ({(byte)op:x2})"; }