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;
/// <summary>
/// Dynamic Pointer able to point to any object implementing the <see cref="IGetSet{long, TValue}"/> interface.
/// </summary>
public class Pointer<T>
{
public IGetSet<long, T> Target;
protected IGetSet<long, T> Target;
public long Ptr;
public Pointer(IGetSet<long, T> target, long pointer = 0)
@ -21,17 +24,30 @@ public class Pointer<T>
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 void Set(long position, T value)
{
Target.Set(position, value);
}
/// <summary>
/// Sets the value of <see cref="Target"/> at <paramref name="position"/>.
/// </summary>
public void Set(long position, T value) => Target.Set(position, value);
public T Get(long position)
{
return Target.Get(position);
}
/// <summary>
/// Sets the value of <see cref="Target"/> at the current <see cref="Ptr"/> location.
/// </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
@ -94,13 +110,13 @@ public class InstructionPtr : Pointer<Instruction>
public class Call
{
public Closure Closure;
public InstructionPtr Ptr;
public InstructionPtr Instruction;
public Pointer<Value> StackPtr;
public Call(Closure closure, StackLike<Value> stack, long stackOffset)
{
Closure = closure;
Ptr = new InstructionPtr(Closure.Function.Segment);
Instruction = new InstructionPtr(Closure.Function.Segment);
StackPtr = new Pointer<Value>(stack, stackOffset);
}
}
@ -152,10 +168,10 @@ public class Runner : IDisposable
_logger.Method();
Call call = Calls.Peek(-1);
do {
Op opCode = call.Ptr.Next();
Op opCode = call.Instruction.Next();
_logger.Verbose($"OpCode: {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.Not: OpNot(); break;
@ -173,21 +189,21 @@ public class Runner : IDisposable
case Op.BitwiseRight: OpBitwiseRight(); break;
case Op.GetLocal: {
long slot = call.Ptr.NextDynamic();
long slot = call.Instruction.NextDynamic();
_logger.Verbose($"getting slot {slot} which is {call.StackPtr.Get(slot)}");
Push(call.StackPtr.Get(slot));
break;
}
case Op.SetLocal: {
long slot = call.Ptr.NextDynamic();
long slot = call.Instruction.NextDynamic();
_logger.Verbose($"setting stackptr {slot} to {Peek()}");
call.StackPtr.Set(slot, Peek());
break;
}
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))
throw new ExecutionException($"tried to define global variable with empty name");
Globals[name] = Pop();
@ -196,7 +212,7 @@ public class Runner : IDisposable
}
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))
throw new ExecutionException($"tried to set global variable with empty name");
if (!Globals.Has(name))
@ -206,10 +222,8 @@ public class Runner : IDisposable
break;
}
// todo: add closure
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))
throw new ExecutionException($"tried to set global variable with empty name");
if (!Globals.Has(name))
@ -246,7 +260,7 @@ public class Runner : IDisposable
break;
}
} while (call.Ptr.Segment.Instructions.Length > call.Ptr.Ptr);
} while (call.Instruction.Segment.Instructions.Length > call.Instruction.Ptr);
return ExecutionResult.OK;
}