From aaec6375ebbd1a736969da69cf5509a40d86f81d Mon Sep 17 00:00:00 2001 From: Qrakhen Date: Thu, 8 Jan 2026 09:29:20 +0100 Subject: [PATCH] bit a dis, bit a dat --- ...ithmicHandler.cs => ArithmeticResolver.cs} | 34 +++++-- Qrakhen.Qamp.Core/Execution/Runner.cs | 99 ++++++++++--------- 2 files changed, 78 insertions(+), 55 deletions(-) rename Qrakhen.Qamp.Core/Execution/{AlgorithmicHandler.cs => ArithmeticResolver.cs} (87%) diff --git a/Qrakhen.Qamp.Core/Execution/AlgorithmicHandler.cs b/Qrakhen.Qamp.Core/Execution/ArithmeticResolver.cs similarity index 87% rename from Qrakhen.Qamp.Core/Execution/AlgorithmicHandler.cs rename to Qrakhen.Qamp.Core/Execution/ArithmeticResolver.cs index da8c933..fd9838b 100644 --- a/Qrakhen.Qamp.Core/Execution/AlgorithmicHandler.cs +++ b/Qrakhen.Qamp.Core/Execution/ArithmeticResolver.cs @@ -8,21 +8,36 @@ public readonly record struct Operation(OpCode OpCode, Value Left, Value Right); public delegate Value OperationHandler(Operation operation); -public class AlgorithmicHandler : IOperationResolver +public class ArithmeticResolver : IOperationResolver { - private readonly ILogger _logger = LoggerService.Get(nameof(AlgorithmicHandler)); + private readonly ILogger _logger = LoggerService.Get(nameof(ArithmeticResolver)); private readonly Register _operations; - public bool CanResolve(OpCode opCode) => (opCode & OpCode.F_Operation) > 0; + public bool CanResolve(OpCode opCode) => (opCode & (OpCode.F_Operation | OpCode.F_Compare)) > 0; - public static Value Resolve(Operation operation) + private Operation PopOperation(Runner runner, OpCode code) { +#if LOG + _logger.Method(code); +#endif + if ((code & OpCode.F_Unary) == OpCode.F_Unary) + return new Operation(code, runner.Pop(), default); + Value right = runner.Pop(); + Value left = runner.Pop(); + return new Operation(code, left, right); + } + + public OperationResult Resolve(Runner runner, OpCode opCode) + { + Operation operation = PopOperation(runner, opCode); + #if LOG _logger.Method($"{operation.Left} {operation.OpCode} {operation.Right}"); #endif + // p sure switch is faster here (as opposed to dict lookup) - return operation.OpCode switch { + Value result = operation.OpCode switch { OpCode.Equal => Equal(operation), OpCode.Greater => Greater(operation), OpCode.Less => Less(operation), @@ -41,9 +56,16 @@ public class AlgorithmicHandler : IOperationResolver OpCode.BitwiseXor => BitwiseXor(operation), _ => throw new NotImplementedException($"Unknown operator {operation.OpCode}.") }; + +#if LOG + _logger.Verbose($"Result: {result}"); +#endif + + runner.Push(result); + return OperationResult.MakeSuccess(result); } - static AlgorithmicHandler() + public ArithmeticResolver() { _operations = new Register { { OpCode.Equal, Equal }, diff --git a/Qrakhen.Qamp.Core/Execution/Runner.cs b/Qrakhen.Qamp.Core/Execution/Runner.cs index 51ffe5d..12428a3 100644 --- a/Qrakhen.Qamp.Core/Execution/Runner.cs +++ b/Qrakhen.Qamp.Core/Execution/Runner.cs @@ -28,7 +28,7 @@ public class Call public interface IOperationResolver { bool CanResolve(OpCode code); - OperationResult Resolve(OpCode code); + OperationResult Resolve(Runner runner, OpCode code); } public struct OperationResult @@ -58,34 +58,33 @@ public class OperationRouter _handlers.Add(resolver); } - public OperationResult Route(OpCode opCode) + public IOperationResolver? Route(Runner runner, OpCode opCode) { if (!_cache.TryGetValue(opCode, out IOperationResolver? resolver)) { resolver = _handlers.FirstOrDefault(h => h.CanResolve(opCode)); if (resolver == null) - return OperationResult.MakeError( - new RuntimeException( - $"Could not find an IOperationHandler for OpCode {opCode}.", - opCode)); + return null; _cache[opCode] = resolver; } - return resolver.Resolve(opCode); + return _cache[opCode]; } } public class Runner : IDisposable { private readonly ILogger _logger = LoggerService.Get(); + private readonly OperationRouter _router = new OperationRouter(); public readonly Options Options; - private StackLike Calls; + private List _resolvers = []; + private StackLike _calls; // todo: maybe have a pointer everywhere to stacks or arrays and use those rather than built-in pointers or cursors... ? - private StackLike Stack; - private long Cursor => Stack.Position; + private StackLike _stack; + private long _cursor => _stack.Position; private List Outers = []; @@ -96,10 +95,12 @@ public class Runner : IDisposable public Runner(Options options) { Options = options; - Calls = new StackLike(options.MaxCalls); - Stack = new StackLike(options.InitialStackSize); + _calls = new StackLike(options.MaxCalls); + _stack = new StackLike(options.InitialStackSize); IO.Console.StdOut ??= options.StdOut; IO.Console.StdIn ??= options.StdIn; + + _router.Register(new ArithmeticResolver()); } public ExecutionResult Run(Stream stream) @@ -107,11 +108,11 @@ public class Runner : IDisposable #if LOG _logger.Method(); #endif - if (Stack.Position != 0) { + if (_stack.Position != 0) { #if LOG - _logger.Warn($"Something went wrong, stack cursor is at {Stack.Position}. Resetting Stack."); + _logger.Warn($"Something went wrong, stack cursor is at {_stack.Position}. Resetting Stack."); #endif - Stack = new StackLike(Options.InitialStackSize); + _stack = new StackLike(Options.InitialStackSize); } Benchmark.Start($"Compile Start"); using Reader reader = new Reader(stream); @@ -136,7 +137,7 @@ public class Runner : IDisposable #if LOG _logger.Method(); #endif - Call call = Calls.Peek(-1); + Call call = _calls.Peek(-1); do { Op opCode = call.Instruction.Next(); #if LOG @@ -145,15 +146,15 @@ public class Runner : IDisposable //IO.Console.Write($"{opCode}: \n - {string.Join("\n - ", Stack.ToArray().Subset(0, Stack.Count))}"); - if (TestFlag(opCode, Op.F_Operation)) { - Value result = AlgorithmicHandler.Resolve(PopOperation(opCode)); - Push(result); - continue; - } + IOperationResolver? resolver = _router.Route(this, opCode); - if (TestFlag(opCode, Op.F_Compare)) { - Value result = AlgorithmicHandler.Resolve(PopOperation(opCode)); - Push(result); + if (resolver != null) + { + OperationResult result = resolver.Resolve(this, opCode); + if (!result.Success) + { + _logger.Error(result.Error?.Message); + } continue; } @@ -367,7 +368,7 @@ public class Runner : IDisposable byte count = call.Instruction.Next(); if (!Invoke(Peek(-(count + 1)), count)) return Error($"Could not invoke function."); - call = Calls.Peek(); + call = _calls.Peek(); break; } @@ -376,7 +377,7 @@ public class Runner : IDisposable byte argumentCount = call.Instruction.Next(); if (!Invoke(name, argumentCount)) return Error($"Could not invoke member {name}."); - call = Calls.Peek(); + call = _calls.Peek(); break; } @@ -386,7 +387,7 @@ public class Runner : IDisposable Class @class = Pop().Ptr.As()!; if (!Invoke(@class, name, argumentCount)) return Error($"Could not invoke member {name} of base class {@class.Name}!"); - call = Calls.Peek(); + call = _calls.Peek(); break; } @@ -407,7 +408,7 @@ public class Runner : IDisposable } case Op.CloseOuter: { - CloseOuters(new Pointer(Stack, Cursor)); + CloseOuters(new Pointer(_stack, _cursor)); Pop(); break; } @@ -415,9 +416,9 @@ public class Runner : IDisposable case Op.Return: { Value result = Pop(); CloseOuters(call.StackPtr.Branch()); - Calls.Pop(); - if (Calls.Count == 0) { - if (Stack.Count > 0) { + _calls.Pop(); + if (_calls.Count == 0) { + if (_stack.Count > 0) { // todo: very bad fix for our stack problem Pop(); } else { @@ -425,9 +426,9 @@ public class Runner : IDisposable } return ExecutionResult.OK; } - Stack.Decimate(call.StackPtr.Cursor); + _stack.Decimate(call.StackPtr.Cursor); Push(result); - call = Calls.Peek(); + call = _calls.Peek(); break; } @@ -478,8 +479,8 @@ public class Runner : IDisposable } case Op.PrintStack: { - for (int i = 0; i < Cursor; i++) { - IO.Console.Write($"{Stack[i].ToString(true)}"); + for (int i = 0; i < _cursor; i++) { + IO.Console.Write($"{_stack[i].ToString(true)}"); } break; } @@ -542,7 +543,7 @@ public class Runner : IDisposable values[i] = Peek(-i - 1); } - Stack.Decimate(Stack.Position - argumentCount - 1); + _stack.Decimate(_stack.Position - argumentCount - 1); Value result = extension.Call(target, values); Push(result); return true; @@ -558,13 +559,13 @@ public class Runner : IDisposable return false; } - if (Calls.Count > Options.MaxCalls) { - Error($"Stack overflow {Calls.Count}"); + if (_calls.Count > Options.MaxCalls) { + Error($"Stack overflow {_calls.Count}"); return false; } - Call call = new(closure, Stack, Cursor - argumentCount - 1); - Calls.Push(call); + Call call = new(closure, _stack, _cursor - argumentCount - 1); + _calls.Push(call); return true; } @@ -605,7 +606,7 @@ public class Runner : IDisposable if (value.Is(T.Method)) { Method method = value.Ptr.As()!; - Stack.Set(Cursor - method.Function.ArgumentCount - 1, method.Receiver); + _stack.Set(_cursor - method.Function.ArgumentCount - 1, method.Receiver); return Invoke(method, method.Function.ArgumentCount); } else if (value.Is(T.Context)) { Context? context = value.Ptr.As()!; @@ -614,7 +615,7 @@ public class Runner : IDisposable throw new NotImplementedException("i dont really want globals in this language so lets see"); } else if (value.Is(T.Class)) { Class? @class = value.Ptr.As()!; - Stack.Set(Cursor - argumentCount - 1, Instantiate(@class)); + _stack.Set(_cursor - argumentCount - 1, Instantiate(@class)); if (@class.Members.TryGet(@class.Name, out Value ctor)) { Context? context = ctor.Ptr.As()!; return Invoke(context, argumentCount); @@ -657,28 +658,28 @@ public class Runner : IDisposable Pop(); } - private Value Peek(int delta = -1) + public Value Peek(int delta = -1) { #if LOG _logger.Method(); #endif - return Stack.Peek(delta); + return _stack.Peek(delta); } - private Value Pop() + public Value Pop() { #if LOG _logger.Method(); #endif - return Stack.Pop(); + return _stack.Pop(); } - private void Push(Value value) + public void Push(Value value) { #if LOG _logger.Method($"{value}"); #endif - Stack.Push(value); + _stack.Push(value); } private Operation PopOperation(Op code) @@ -712,7 +713,7 @@ public class Runner : IDisposable #if LOG _logger.Method(); #endif - Stack.Decimate(0); + _stack.Decimate(0); } public void Dispose()