rewrite Pointer<T>

This commit is contained in:
Qrakhen 2025-11-07 14:49:22 +01:00
parent ada9fc766e
commit 703410b548
1 changed files with 35 additions and 21 deletions

View File

@ -10,9 +10,12 @@ namespace Qrakhen.Qamp.Core.Execution;
using Op = OpCode; using Op = OpCode;
/// <summary>
/// Dynamic Pointer able to point to any object implementing the <see cref="IGetSet{long, TValue}"/> interface.
/// </summary>
public class Pointer<T> public class Pointer<T>
{ {
public IGetSet<long, T> Target; protected IGetSet<long, T> Target;
public long Ptr; public long Ptr;
public Pointer(IGetSet<long, T> target, long pointer = 0) public Pointer(IGetSet<long, T> target, long pointer = 0)
@ -21,17 +24,30 @@ public class Pointer<T>
Ptr = pointer; Ptr = pointer;
} }
/// <summary>
/// Returns the next item from <see cref="Target"/> and increases the pointer by 1.
/// </summary>
public T Next() => Target.Get(Ptr++); public T Next() => Target.Get(Ptr++);
public void Set(long position, T value) /// <summary>
{ /// Sets the value of <see cref="Target"/> at <paramref name="position"/>.
Target.Set(position, value); /// </summary>
} public void Set(long position, T value) => Target.Set(position, value);
public T Get(long position) /// <summary>
{ /// Sets the value of <see cref="Target"/> at the current <see cref="Ptr"/> location.
return Target.Get(position); /// </summary>
} public void Set(T value) => Set(Ptr, value);
/// <summary>
/// Gets the value of <see cref="Target"/> at <paramref name="position"/>.
/// </summary>
public T Get(long position) => Target.Get(position);
/// <summary>
/// Gets the value of <see cref="Target"/> at the current <see cref="Ptr"/> location.
/// </summary>
public T Get() => Get(Ptr);
} }
// this is all a bit cheesy imho // this is all a bit cheesy imho
@ -94,13 +110,13 @@ public class InstructionPtr : Pointer<Instruction>
public class Call public class Call
{ {
public Closure Closure; public Closure Closure;
public InstructionPtr Ptr; public InstructionPtr Instruction;
public Pointer<Value> StackPtr; public Pointer<Value> StackPtr;
public Call(Closure closure, StackLike<Value> stack, long stackOffset) public Call(Closure closure, StackLike<Value> stack, long stackOffset)
{ {
Closure = closure; Closure = closure;
Ptr = new InstructionPtr(Closure.Function.Segment); Instruction = new InstructionPtr(Closure.Function.Segment);
StackPtr = new Pointer<Value>(stack, stackOffset); StackPtr = new Pointer<Value>(stack, stackOffset);
} }
} }
@ -152,10 +168,10 @@ public class Runner : IDisposable
_logger.Method(); _logger.Method();
Call call = Calls.Peek(-1); Call call = Calls.Peek(-1);
do { do {
Op opCode = call.Ptr.Next(); Op opCode = call.Instruction.Next();
_logger.Verbose($"OpCode: {opCode}"); _logger.Verbose($"OpCode: {opCode}");
switch (opCode) { switch (opCode) {
case Op.Constant: Push(call.Ptr.NextConstant()); break; case Op.Constant: Push(call.Instruction.NextConstant()); break;
case Op.Pop: Pop(); break; case Op.Pop: Pop(); break;
case Op.Not: OpNot(); break; case Op.Not: OpNot(); break;
@ -173,21 +189,21 @@ public class Runner : IDisposable
case Op.BitwiseRight: OpBitwiseRight(); break; case Op.BitwiseRight: OpBitwiseRight(); break;
case Op.GetLocal: { case Op.GetLocal: {
long slot = call.Ptr.NextDynamic(); long slot = call.Instruction.NextDynamic();
_logger.Verbose($"getting slot {slot} which is {call.StackPtr.Get(slot)}"); _logger.Verbose($"getting slot {slot} which is {call.StackPtr.Get(slot)}");
Push(call.StackPtr.Get(slot)); Push(call.StackPtr.Get(slot));
break; break;
} }
case Op.SetLocal: { case Op.SetLocal: {
long slot = call.Ptr.NextDynamic(); long slot = call.Instruction.NextDynamic();
_logger.Verbose($"setting stackptr {slot} to {Peek()}"); _logger.Verbose($"setting stackptr {slot} to {Peek()}");
call.StackPtr.Set(slot, Peek()); call.StackPtr.Set(slot, Peek());
break; break;
} }
case Op.DefineGlobal: { case Op.DefineGlobal: {
string? name = call.Ptr.GetString(call.Ptr.NextDynamic())?.Value; string? name = call.Instruction.GetString(call.Instruction.NextDynamic())?.Value;
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
throw new ExecutionException($"tried to define global variable with empty name"); throw new ExecutionException($"tried to define global variable with empty name");
Globals[name] = Pop(); Globals[name] = Pop();
@ -196,7 +212,7 @@ public class Runner : IDisposable
} }
case Op.SetGlobal: { case Op.SetGlobal: {
string? name = call.Ptr.GetString(call.Ptr.NextDynamic())?.Value; string? name = call.Instruction.GetString(call.Instruction.NextDynamic())?.Value;
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
throw new ExecutionException($"tried to set global variable with empty name"); throw new ExecutionException($"tried to set global variable with empty name");
if (!Globals.Has(name)) if (!Globals.Has(name))
@ -206,10 +222,8 @@ public class Runner : IDisposable
break; break;
} }
// todo: add closure
case Op.GetGlobal: { case Op.GetGlobal: {
string? name = call.Ptr.GetString(call.Ptr.NextDynamic())?.Value; string? name = call.Instruction.GetString(call.Instruction.NextDynamic())?.Value;
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
throw new ExecutionException($"tried to set global variable with empty name"); throw new ExecutionException($"tried to set global variable with empty name");
if (!Globals.Has(name)) if (!Globals.Has(name))
@ -246,7 +260,7 @@ public class Runner : IDisposable
break; break;
} }
} while (call.Ptr.Segment.Instructions.Length > call.Ptr.Ptr); } while (call.Instruction.Segment.Instructions.Length > call.Instruction.Ptr);
return ExecutionResult.OK; return ExecutionResult.OK;
} }