using Qrakhen.Qamp.Core.Collections; using Qrakhen.Qamp.Core.Compilation; using Qrakhen.Qamp.Core.Logging; using Qrakhen.Qamp.Core.Values; namespace Qrakhen.Qamp.Core.Execution; public readonly record struct Operation(OpCode OpCode, Value Left, Value Right); public delegate Value OperationHandler(Operation operation); public static class ValueOperation { private static readonly ILogger _logger = LoggerService.Get(nameof(ValueOperation)); private static readonly Register _operations; public static Value Resolve(Operation operation) { _logger.Method($"{operation.Left} {operation.OpCode} {operation.Right}"); return _operations[operation.OpCode].Invoke(operation); } static ValueOperation() { _operations = new Register(); _operations.Add(OpCode.Equal, Equal); _operations.Add(OpCode.Greater, Greater); _operations.Add(OpCode.Less, Less); _operations.Add(OpCode.Not, Not); _operations.Add(OpCode.Add, Add); _operations.Add(OpCode.Subtract, Subtract); _operations.Add(OpCode.Divide, Divide); _operations.Add(OpCode.Modulo, Modulo); _operations.Add(OpCode.Multiply, Multiply); _operations.Add(OpCode.Negate, Negate); _operations.Add(OpCode.BitwiseOr, BitwiseOr); _operations.Add(OpCode.BitwiseAnd, BitwiseAnd); _operations.Add(OpCode.BitwiseLeft, BitwiseLeft); _operations.Add(OpCode.BitwiseRight, BitwiseRight); _operations.Add(OpCode.BitwiseNot, BitwiseInvert); _operations.Add(OpCode.BitwiseXor, BitwiseXor); } public static Value Equal(Operation operation) { Value a = operation.Left; Value b = operation.Right; Assert.NotVoid(a, b); Assert.IsPrimitive(a, b); return new Value(a.Dynamic == b.Dynamic); } public static Value Greater(Operation operation) { Value a = operation.Left; Value b = operation.Right; Assert.NotVoid(a, b); Assert.IsPrimitive(a, b); return new Value(a.Dynamic > b.Dynamic); } public static Value Less(Operation operation) { Value a = operation.Left; Value b = operation.Right; Assert.NotVoid(a, b); Assert.IsPrimitive(a, b); return new Value(a.Dynamic < b.Dynamic); } public static Value Not(Operation operation) { Value value = operation.Left; _logger.Method($"{value}"); Assert.NotVoid(value); ulong inner = value.Unsigned; return new Value(inner == 0); } public static Value Add(Operation operation) { Value a = operation.Left; Value b = operation.Right; Assert.NotVoid(a, b); if (a.IsString) return Values.Objects.String.Make($"{a}{b}"); Assert.IsPrimitive(a, b); bool convert = a.Type != b.Type; return new Value(a.Dynamic + b.Dynamic); } public static Value Subtract(Operation operation) { Value a = operation.Left; Value b = operation.Right; Assert.NotVoid(a, b); Assert.IsPrimitive(a, b); return new Value(a.Dynamic - b.Dynamic); } public static Value Divide(Operation operation) { Value a = operation.Left; Value b = operation.Right; Assert.NotVoid(a, b); Assert.IsPrimitive(a, b); Assert.NotZero(b); return new Value(a.Dynamic / b.Dynamic); } public static Value Modulo(Operation operation) { Value a = operation.Left; Value b = operation.Right; Assert.NotVoid(a, b); Assert.IsPrimitive(a, b); Assert.NotZero(b); return new Value(a.Dynamic % b.Dynamic); } public static Value Multiply(Operation operation) { Value a = operation.Left; Value b = operation.Right; Assert.NotVoid(a, b); Assert.IsPrimitive(a, b); return new Value(a.Dynamic * b.Dynamic); } public static Value Negate(Operation operation) { Value value = operation.Left; Assert.NotVoid(value); Assert.IsPrimitive(value); return new Value(-value.Dynamic); } public static Value BitwiseOr(Operation operation) { Value a = operation.Left; Value b = operation.Right; Assert.NotVoid(a, b); Assert.IsPrimitive(a, b); Assert.IsInteger(a, b); return new Value(a.Dynamic | b.Dynamic); } public static Value BitwiseAnd(Operation operation) { Value a = operation.Left; Value b = operation.Right; Assert.NotVoid(a, b); Assert.IsPrimitive(a, b); Assert.IsInteger(a, b); return new Value(a.Dynamic & b.Dynamic); } public static Value BitwiseXor(Operation operation) { Value a = operation.Left; Value b = operation.Right; Assert.NotVoid(a, b); Assert.IsPrimitive(a, b); Assert.IsInteger(a, b); return new Value(a.Dynamic ^ b.Dynamic); } public static Value BitwiseLeft(Operation operation) { Value a = operation.Left; Value b = operation.Right; Assert.NotVoid(a, b); Assert.IsPrimitive(a, b); Assert.IsInteger(a, b); return new Value(a.Dynamic << (int)(b.Dynamic ?? 0)); } public static Value BitwiseRight(Operation operation) { Value a = operation.Left; Value b = operation.Right; Assert.NotVoid(a, b); Assert.IsPrimitive(a, b); Assert.IsInteger(a, b); return new Value(a.Dynamic >> (int)(b.Dynamic ?? 0)); } public static Value BitwiseInvert(Operation operation) { Value a = operation.Left; Assert.NotVoid(a); Assert.IsPrimitive(a); Assert.IsInteger(a); return new Value(~a.Dynamic); } }