diff --git a/Qrakhen.Qamp.Core/Collections/Memory.cs b/Qrakhen.Qamp.Core/Collections/Memory.cs
new file mode 100644
index 0000000..2723c79
--- /dev/null
+++ b/Qrakhen.Qamp.Core/Collections/Memory.cs
@@ -0,0 +1,118 @@
+using Qrakhen.Qamp.Core.Collections.Abstractions;
+using Qrakhen.Qamp.Core.Values;
+using System.Collections;
+
+namespace Qrakhen.Qamp.Core.Collections;
+
+///
+/// Similar to a register with the caveat that the memory can free up or reserve blocks within itself, returning the next writeable address when storing data.
+///
+public class Memory :
+ IGetSet,
+ IToArray,
+ IEnumerable>
+{
+ private const int BLOCK_SIZE = sizeof(int);
+ private const uint BLOCK_FULL = (uint)((1UL << 32) - 1);
+
+ private readonly TValue[] _data;
+
+ private readonly uint[] _alloc;
+
+ public int Size { get; }
+
+ public TValue this[Address index]
+ {
+ get => _data[index];
+ set => _data[index] = value;
+ }
+
+ public Memory(int size = 4096)
+ {
+ Size = size;
+ _data = new TValue[size];
+ }
+
+ private int GetBlockIndex(Address address)
+ {
+ return (int)(address / BLOCK_SIZE);
+ }
+
+ private int GetBitIndex(Address address)
+ {
+ return (int)(address % BLOCK_SIZE);
+ }
+
+ private Address SeekFree(Address from = default)
+ {
+ Address cur = from - (from % BLOCK_SIZE);
+ while (cur < Size)
+ {
+ int block = GetBlockIndex(cur);
+ uint mask = _alloc[block];
+ if (mask < BLOCK_FULL)
+ {
+ int index = 0;
+ while ((mask & (1 << index)) > 0)
+ index++;
+
+ return (Address)((long)block * BLOCK_SIZE + index);
+ }
+ cur += BLOCK_SIZE;
+ }
+ return Address.Void;
+ }
+
+ public void Free(Address address, int size = 1)
+ {
+ ArgumentOutOfRangeException.ThrowIfNotEqual(1, size); // only support single address freeing atm
+ int block = GetBlockIndex(address);
+ int index = GetBitIndex(address);
+ uint flags = _alloc[block];
+ _alloc[block] &= ~(1U << index);
+ }
+
+ public void Allocate(int size = 1)
+ {
+ ArgumentOutOfRangeException.ThrowIfNotEqual(1, size); // only support single address allocation atm
+ Address address = SeekFree();
+ int block = GetBlockIndex(address);
+ int index = GetBitIndex(address);
+ _alloc[block] |= (1U << index);
+ }
+
+ public TValue[] ToArray()
+ {
+ return _data.ToArray();
+ }
+
+ public TValue Get(Address index)
+ {
+ return _data[index];
+ }
+
+ public void Set(Address index, TValue value)
+ {
+ _data[index] = value;
+ }
+
+ public Address Add(TValue value)
+ {
+ Address free = SeekFree();
+ if (free == Address.Void)
+ throw new QampException($"Tried to add {value} to a memory block, but no free memory could be allocated.");
+ Set(free, value);
+ return free;
+ }
+
+ public IEnumerator> GetEnumerator()
+ {
+ for (Address addr = 0; addr < Size; addr++)
+ yield return new KeyValuePair(addr, Get(addr));
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+}
diff --git a/Qrakhen.Qamp.Core/Values/Address.cs b/Qrakhen.Qamp.Core/Values/Address.cs
index afb5ff0..a3640bc 100644
--- a/Qrakhen.Qamp.Core/Values/Address.cs
+++ b/Qrakhen.Qamp.Core/Values/Address.cs
@@ -5,7 +5,9 @@ namespace Qrakhen.Qamp.Core.Values;
[StructLayout(LayoutKind.Sequential, Size = sizeof(long))]
public readonly record struct Address(long Value)
{
- public override string ToString() => $"0x{Value:x8}";
+ public static readonly Address Void = new Address(-1);
+
+ public override string ToString() => $"&{Value:x8}";
public static implicit operator long(Address address) => address.Value;
public static implicit operator Address(long value) => new(value);
diff --git a/Qrakhen.Qamp.Core/Values/Ptr.cs b/Qrakhen.Qamp.Core/Values/Ptr.cs
index 13ad90c..f22fca0 100644
--- a/Qrakhen.Qamp.Core/Values/Ptr.cs
+++ b/Qrakhen.Qamp.Core/Values/Ptr.cs
@@ -9,6 +9,8 @@ public readonly struct Ptr
{
private static readonly PushStack _register = new();
+ private static readonly Collections.Memory _memory = [];
+
[Serialized] public readonly Address Address;
//private readonly IntPtr _pointer;
@@ -27,6 +29,7 @@ public readonly struct Ptr
private Ptr(Address address)
{
+
//_pointer = GCHandle.ToIntPtr(GCHandle.Alloc(obj, GCHandleType.Normal));
Address = address;
}
diff --git a/Qrakhen.Qamp.Core/Values/Value.cs b/Qrakhen.Qamp.Core/Values/Value.cs
index 2e9899d..c50155f 100644
--- a/Qrakhen.Qamp.Core/Values/Value.cs
+++ b/Qrakhen.Qamp.Core/Values/Value.cs
@@ -1,5 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
+using System.Security.AccessControl;
using Qrakhen.Qamp.Core.Abstractions;
using Qrakhen.Qamp.Core.Values.Objects;
using String = Qrakhen.Qamp.Core.Values.Objects.String;
@@ -7,6 +8,27 @@ using T = Qrakhen.Qamp.Core.Values.ValueType;
namespace Qrakhen.Qamp.Core.Values;
+
+
+// HEY. IDEA.
+// have custom structs for types. this way we can handle many more thing and also more clean no????
+
+public interface IPrimitive
+{
+ public static abstract string Name { get; }
+ public static abstract int SizeOf { get; }
+
+ public ulong Raw { get; }
+
+ public string Print();
+}
+
+public readonly record struct Signed(long Value)// : IPrimitive
+{
+
+}
+
+
public interface IValue
{
T Data { get; }
diff --git a/Qrakhen.Qamp.Core/Values/ValueType.cs b/Qrakhen.Qamp.Core/Values/ValueType.cs
index 00e6d8e..fe7a8c9 100644
--- a/Qrakhen.Qamp.Core/Values/ValueType.cs
+++ b/Qrakhen.Qamp.Core/Values/ValueType.cs
@@ -19,7 +19,7 @@ public enum ValueType
Integer = Unsigned | Signed | Char,
Primitive = Integer | Decimal | Bool,
- Address = 0x0020, // coded with : symbol
+ Address = 0x0020,
// classes etc. here?