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 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;
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, OperationHandler> {
{ OpCode.Equal, Equal },

View File

@ -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<Runner>();
private readonly OperationRouter _router = new OperationRouter();
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... ?
private StackLike<Value> Stack;
private long Cursor => Stack.Position;
private StackLike<Value> _stack;
private long _cursor => _stack.Position;
private List<Outer> Outers = [];
@ -96,10 +95,12 @@ public class Runner : IDisposable
public Runner(Options options)
{
Options = options;
Calls = new StackLike<Call>(options.MaxCalls);
Stack = new StackLike<Value>(options.InitialStackSize);
_calls = new StackLike<Call>(options.MaxCalls);
_stack = new StackLike<Value>(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<Value>(Options.InitialStackSize);
_stack = new StackLike<Value>(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<Class>()!;
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<Value>(Stack, Cursor));
CloseOuters(new Pointer<Value>(_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<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);
} else if (value.Is(T.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");
} else if (value.Is(T.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)) {
Context? context = ctor.Ptr.As<Context>()!;
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()