bit a dis, bit a dat

This commit is contained in:
Qrakhen 2026-01-08 09:29:20 +01:00
parent a66580e7fe
commit aaec6375eb
2 changed files with 78 additions and 55 deletions

View File

@ -8,21 +8,36 @@ public readonly record struct Operation(OpCode OpCode, Value Left, Value Right);
public delegate Value OperationHandler(Operation operation); 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<OpCode, OperationHandler> _operations; private readonly Register<OpCode, OperationHandler> _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 #if LOG
_logger.Method($"{operation.Left} {operation.OpCode} {operation.Right}"); _logger.Method($"{operation.Left} {operation.OpCode} {operation.Right}");
#endif #endif
// p sure switch is faster here (as opposed to dict lookup) // 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.Equal => Equal(operation),
OpCode.Greater => Greater(operation), OpCode.Greater => Greater(operation),
OpCode.Less => Less(operation), OpCode.Less => Less(operation),
@ -41,9 +56,16 @@ public class AlgorithmicHandler : IOperationResolver
OpCode.BitwiseXor => BitwiseXor(operation), OpCode.BitwiseXor => BitwiseXor(operation),
_ => throw new NotImplementedException($"Unknown operator {operation.OpCode}.") _ => 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, OperationHandler> { _operations = new Register<OpCode, OperationHandler> {
{ OpCode.Equal, Equal }, { OpCode.Equal, Equal },

View File

@ -28,7 +28,7 @@ public class Call
public interface IOperationResolver public interface IOperationResolver
{ {
bool CanResolve(OpCode code); bool CanResolve(OpCode code);
OperationResult Resolve(OpCode code); OperationResult Resolve(Runner runner, OpCode code);
} }
public struct OperationResult public struct OperationResult
@ -58,34 +58,33 @@ public class OperationRouter
_handlers.Add(resolver); _handlers.Add(resolver);
} }
public OperationResult Route(OpCode opCode) public IOperationResolver? Route(Runner runner, OpCode opCode)
{ {
if (!_cache.TryGetValue(opCode, out IOperationResolver? resolver)) { if (!_cache.TryGetValue(opCode, out IOperationResolver? resolver)) {
resolver = _handlers.FirstOrDefault(h => h.CanResolve(opCode)); resolver = _handlers.FirstOrDefault(h => h.CanResolve(opCode));
if (resolver == null) if (resolver == null)
return OperationResult.MakeError( return null;
new RuntimeException(
$"Could not find an IOperationHandler for OpCode {opCode}.",
opCode));
_cache[opCode] = resolver; _cache[opCode] = resolver;
} }
return resolver.Resolve(opCode); return _cache[opCode];
} }
} }
public class Runner : IDisposable public class Runner : IDisposable
{ {
private readonly ILogger _logger = LoggerService.Get<Runner>(); private readonly ILogger _logger = LoggerService.Get<Runner>();
private readonly OperationRouter _router = new OperationRouter();
public readonly Options Options; public readonly Options Options;
private StackLike<Call> Calls; private List<IOperationResolver> _resolvers = [];
private StackLike<Call> _calls;
// todo: maybe have a pointer everywhere to stacks or arrays and use those rather than built-in pointers or cursors... ? // todo: maybe have a pointer everywhere to stacks or arrays and use those rather than built-in pointers or cursors... ?
private StackLike<Value> Stack; private StackLike<Value> _stack;
private long Cursor => Stack.Position; private long _cursor => _stack.Position;
private List<Outer> Outers = []; private List<Outer> Outers = [];
@ -96,10 +95,12 @@ public class Runner : IDisposable
public Runner(Options options) public Runner(Options options)
{ {
Options = options; Options = options;
Calls = new StackLike<Call>(options.MaxCalls); _calls = new StackLike<Call>(options.MaxCalls);
Stack = new StackLike<Value>(options.InitialStackSize); _stack = new StackLike<Value>(options.InitialStackSize);
IO.Console.StdOut ??= options.StdOut; IO.Console.StdOut ??= options.StdOut;
IO.Console.StdIn ??= options.StdIn; IO.Console.StdIn ??= options.StdIn;
_router.Register(new ArithmeticResolver());
} }
public ExecutionResult Run(Stream stream) public ExecutionResult Run(Stream stream)
@ -107,11 +108,11 @@ public class Runner : IDisposable
#if LOG #if LOG
_logger.Method(); _logger.Method();
#endif #endif
if (Stack.Position != 0) { if (_stack.Position != 0) {
#if LOG #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 #endif
Stack = new StackLike<Value>(Options.InitialStackSize); _stack = new StackLike<Value>(Options.InitialStackSize);
} }
Benchmark.Start($"Compile Start"); Benchmark.Start($"Compile Start");
using Reader reader = new Reader(stream); using Reader reader = new Reader(stream);
@ -136,7 +137,7 @@ public class Runner : IDisposable
#if LOG #if LOG
_logger.Method(); _logger.Method();
#endif #endif
Call call = Calls.Peek(-1); Call call = _calls.Peek(-1);
do { do {
Op opCode = call.Instruction.Next(); Op opCode = call.Instruction.Next();
#if LOG #if LOG
@ -145,15 +146,15 @@ public class Runner : IDisposable
//IO.Console.Write($"{opCode}: \n - {string.Join("\n - ", Stack.ToArray().Subset(0, Stack.Count))}"); //IO.Console.Write($"{opCode}: \n - {string.Join("\n - ", Stack.ToArray().Subset(0, Stack.Count))}");
if (TestFlag(opCode, Op.F_Operation)) { IOperationResolver? resolver = _router.Route(this, opCode);
Value result = AlgorithmicHandler.Resolve(PopOperation(opCode));
Push(result);
continue;
}
if (TestFlag(opCode, Op.F_Compare)) { if (resolver != null)
Value result = AlgorithmicHandler.Resolve(PopOperation(opCode)); {
Push(result); OperationResult result = resolver.Resolve(this, opCode);
if (!result.Success)
{
_logger.Error(result.Error?.Message);
}
continue; continue;
} }
@ -367,7 +368,7 @@ public class Runner : IDisposable
byte count = call.Instruction.Next(); byte count = call.Instruction.Next();
if (!Invoke(Peek(-(count + 1)), count)) if (!Invoke(Peek(-(count + 1)), count))
return Error($"Could not invoke function."); return Error($"Could not invoke function.");
call = Calls.Peek(); call = _calls.Peek();
break; break;
} }
@ -376,7 +377,7 @@ public class Runner : IDisposable
byte argumentCount = call.Instruction.Next(); byte argumentCount = call.Instruction.Next();
if (!Invoke(name, argumentCount)) if (!Invoke(name, argumentCount))
return Error($"Could not invoke member {name}."); return Error($"Could not invoke member {name}.");
call = Calls.Peek(); call = _calls.Peek();
break; break;
} }
@ -386,7 +387,7 @@ public class Runner : IDisposable
Class @class = Pop().Ptr.As<Class>()!; Class @class = Pop().Ptr.As<Class>()!;
if (!Invoke(@class, name, argumentCount)) if (!Invoke(@class, name, argumentCount))
return Error($"Could not invoke member {name} of base class {@class.Name}!"); return Error($"Could not invoke member {name} of base class {@class.Name}!");
call = Calls.Peek(); call = _calls.Peek();
break; break;
} }
@ -407,7 +408,7 @@ public class Runner : IDisposable
} }
case Op.CloseOuter: { case Op.CloseOuter: {
CloseOuters(new Pointer<Value>(Stack, Cursor)); CloseOuters(new Pointer<Value>(_stack, _cursor));
Pop(); Pop();
break; break;
} }
@ -415,9 +416,9 @@ public class Runner : IDisposable
case Op.Return: { case Op.Return: {
Value result = Pop(); Value result = Pop();
CloseOuters(call.StackPtr.Branch()); CloseOuters(call.StackPtr.Branch());
Calls.Pop(); _calls.Pop();
if (Calls.Count == 0) { if (_calls.Count == 0) {
if (Stack.Count > 0) { if (_stack.Count > 0) {
// todo: very bad fix for our stack problem // todo: very bad fix for our stack problem
Pop(); Pop();
} else { } else {
@ -425,9 +426,9 @@ public class Runner : IDisposable
} }
return ExecutionResult.OK; return ExecutionResult.OK;
} }
Stack.Decimate(call.StackPtr.Cursor); _stack.Decimate(call.StackPtr.Cursor);
Push(result); Push(result);
call = Calls.Peek(); call = _calls.Peek();
break; break;
} }
@ -478,8 +479,8 @@ public class Runner : IDisposable
} }
case Op.PrintStack: { case Op.PrintStack: {
for (int i = 0; i < Cursor; i++) { for (int i = 0; i < _cursor; i++) {
IO.Console.Write($"{Stack[i].ToString(true)}"); IO.Console.Write($"{_stack[i].ToString(true)}");
} }
break; break;
} }
@ -542,7 +543,7 @@ public class Runner : IDisposable
values[i] = Peek(-i - 1); values[i] = Peek(-i - 1);
} }
Stack.Decimate(Stack.Position - argumentCount - 1); _stack.Decimate(_stack.Position - argumentCount - 1);
Value result = extension.Call(target, values); Value result = extension.Call(target, values);
Push(result); Push(result);
return true; return true;
@ -558,13 +559,13 @@ public class Runner : IDisposable
return false; return false;
} }
if (Calls.Count > Options.MaxCalls) { if (_calls.Count > Options.MaxCalls) {
Error($"Stack overflow {Calls.Count}"); Error($"Stack overflow {_calls.Count}");
return false; return false;
} }
Call call = new(closure, Stack, Cursor - argumentCount - 1); Call call = new(closure, _stack, _cursor - argumentCount - 1);
Calls.Push(call); _calls.Push(call);
return true; return true;
} }
@ -605,7 +606,7 @@ public class Runner : IDisposable
if (value.Is(T.Method)) { if (value.Is(T.Method)) {
Method method = value.Ptr.As<Method>()!; Method method = value.Ptr.As<Method>()!;
Stack.Set(Cursor - method.Function.ArgumentCount - 1, method.Receiver); _stack.Set(_cursor - method.Function.ArgumentCount - 1, method.Receiver);
return Invoke(method, method.Function.ArgumentCount); return Invoke(method, method.Function.ArgumentCount);
} else if (value.Is(T.Context)) { } else if (value.Is(T.Context)) {
Context? context = value.Ptr.As<Context>()!; Context? context = value.Ptr.As<Context>()!;
@ -614,7 +615,7 @@ public class Runner : IDisposable
throw new NotImplementedException("i dont really want globals in this language so lets see"); throw new NotImplementedException("i dont really want globals in this language so lets see");
} else if (value.Is(T.Class)) { } else if (value.Is(T.Class)) {
Class? @class = value.Ptr.As<Class>()!; Class? @class = value.Ptr.As<Class>()!;
Stack.Set(Cursor - argumentCount - 1, Instantiate(@class)); _stack.Set(_cursor - argumentCount - 1, Instantiate(@class));
if (@class.Members.TryGet(@class.Name, out Value ctor)) { if (@class.Members.TryGet(@class.Name, out Value ctor)) {
Context? context = ctor.Ptr.As<Context>()!; Context? context = ctor.Ptr.As<Context>()!;
return Invoke(context, argumentCount); return Invoke(context, argumentCount);
@ -657,28 +658,28 @@ public class Runner : IDisposable
Pop(); Pop();
} }
private Value Peek(int delta = -1) public Value Peek(int delta = -1)
{ {
#if LOG #if LOG
_logger.Method(); _logger.Method();
#endif #endif
return Stack.Peek(delta); return _stack.Peek(delta);
} }
private Value Pop() public Value Pop()
{ {
#if LOG #if LOG
_logger.Method(); _logger.Method();
#endif #endif
return Stack.Pop(); return _stack.Pop();
} }
private void Push(Value value) public void Push(Value value)
{ {
#if LOG #if LOG
_logger.Method($"{value}"); _logger.Method($"{value}");
#endif #endif
Stack.Push(value); _stack.Push(value);
} }
private Operation PopOperation(Op code) private Operation PopOperation(Op code)
@ -712,7 +713,7 @@ public class Runner : IDisposable
#if LOG #if LOG
_logger.Method(); _logger.Method();
#endif #endif
Stack.Decimate(0); _stack.Decimate(0);
} }
public void Dispose() public void Dispose()