bit a dis, bit a dat
This commit is contained in:
parent
a66580e7fe
commit
aaec6375eb
|
|
@ -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 },
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue