qamp/Qrakhen.Qamp.Core/Execution/OpCode.cs

131 lines
4.0 KiB
C#

namespace Qrakhen.Qamp.Core.Execution;
public class SerializedEnumAttribute(Type serializedType) : Attribute
{
public Type SerializedType { get; } = serializedType;
}
/// <summary>
///
/// </summary>
/// <remarks>
/// 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
/// </remarks>
[SerializedEnum(typeof(byte))]
public enum OpCode
{
/// <summary>
/// Mask bits, to be used like <c>opCode &amp; F_Mask == F_Operation</c>, for example.
/// </summary>
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,
Divide = F_Arithmetic | 4,
Modulo = F_Arithmetic | 5,
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})";
}