' Arena/region-based allocator — linear allocation with rollback / reset
#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN() AS LONG
    LOCAL i  AS LONG
    LOCAL j  AS LONG
    LOCAL arenaSize  AS LONG
    LOCAL offset  AS LONG
    LOCAL prevOffset  AS LONG
    LOCAL alloc1  AS LONG
    LOCAL alloc2  AS LONG
    LOCAL alloc3  AS LONG
    LOCAL alloc4  AS LONG
    LOCAL alloc5  AS LONG
    LOCAL alloc6  AS LONG
    LOCAL bytesLeft  AS LONG
    LOCAL largestFree  AS LONG
    LOCAL totalAlloced  AS LONG
    LOCAL peakUsed  AS LONG
    LOCAL numAllocs  AS LONG
    LOCAL tempMark  AS LONG
    LOCAL snapOffset  AS LONG
    LOCAL rollbackOk  AS LONG
    LOCAL arena(2000) AS LONG
    LOCAL allocSizes(50) AS LONG
    LOCAL allocOffsets(50) AS LONG
    LOCAL allocCount  AS LONG
    LOCAL testVal  AS LONG
    arenaSize = 2000
    offset = 0
    allocCount = 0
    totalAlloced = 0
    peakUsed = 0
    numAllocs = 0

    FOR i = 0 TO 2000
        arena(i) = 0
    NEXT i

    PRINT "=== Arena Allocator ==="
    PRINT "Arena size:" & STR$(arenaSize) & " units"
    PRINT "Initial offset: 0"
    PRINT

    PRINT "--- Allocation Phase ---"
    PRINT

    alloc1 = 200
    IF offset + alloc1 <= arenaSize THEN
        allocOffsets(allocCount) = offset
        allocSizes(allocCount) = alloc1
        totalAlloced = totalAlloced + alloc1
        FOR j = 0 TO alloc1 - 1
            arena(offset + j) = 1
        NEXT j
        PRINT "Alloc 1: offset" & STR$(offset) & ", size" & STR$(alloc1)
        offset = offset + alloc1
        allocCount = allocCount + 1
        numAllocs = numAllocs + 1
    END IF

    alloc2 = 300
    IF offset + alloc2 <= arenaSize THEN
        allocOffsets(allocCount) = offset
        allocSizes(allocCount) = alloc2
        totalAlloced = totalAlloced + alloc2
        FOR j = 0 TO alloc2 - 1
            arena(offset + j) = 2
        NEXT j
        PRINT "Alloc 2: offset" & STR$(offset) & ", size" & STR$(alloc2)
        offset = offset + alloc2
        allocCount = allocCount + 1
        numAllocs = numAllocs + 1
    END IF

    alloc3 = 150
    IF offset + alloc3 <= arenaSize THEN
        allocOffsets(allocCount) = offset
        allocSizes(allocCount) = alloc3
        totalAlloced = totalAlloced + alloc3
        FOR j = 0 TO alloc3 - 1
            arena(offset + j) = 3
        NEXT j
        PRINT "Alloc 3: offset" & STR$(offset) & ", size" & STR$(alloc3)
        offset = offset + alloc3
        allocCount = allocCount + 1
        numAllocs = numAllocs + 1
    END IF

    alloc4 = 400
    IF offset + alloc4 <= arenaSize THEN
        allocOffsets(allocCount) = offset
        allocSizes(allocCount) = alloc4
        totalAlloced = totalAlloced + alloc4
        FOR j = 0 TO alloc4 - 1
            arena(offset + j) = 4
        NEXT j
        PRINT "Alloc 4: offset" & STR$(offset) & ", size" & STR$(alloc4)
        offset = offset + alloc4
        allocCount = allocCount + 1
        numAllocs = numAllocs + 1
    END IF

    alloc5 = 500
    IF offset + alloc5 <= arenaSize THEN
        allocOffsets(allocCount) = offset
        allocSizes(allocCount) = alloc5
        totalAlloced = totalAlloced + alloc5
        FOR j = 0 TO alloc5 - 1
            arena(offset + j) = 5
        NEXT j
        PRINT "Alloc 5: offset" & STR$(offset) & ", size" & STR$(alloc5)
        offset = offset + alloc5
        allocCount = allocCount + 1
        numAllocs = numAllocs + 1
    END IF

    alloc6 = 600
    IF offset + alloc6 <= arenaSize THEN
        allocOffsets(allocCount) = offset
        allocSizes(allocCount) = alloc6
        totalAlloced = totalAlloced + alloc6
        FOR j = 0 TO alloc6 - 1
            arena(offset + j) = 6
        NEXT j
        PRINT "Alloc 6: offset" & STR$(offset) & ", size" & STR$(alloc6)
        offset = offset + alloc6
        allocCount = allocCount + 1
        numAllocs = numAllocs + 1
    ELSE
        PRINT "Alloc 6: FAILED (need" & STR$(alloc6) & ", have" & STR$(arenaSize - offset) & ")"
    END IF

    peakUsed = offset
    PRINT
    PRINT "Total allocated:" & STR$(totalAlloced) & " units, offset:" & STR$(offset) & ", free:" & STR$(arenaSize - offset)
    PRINT

    PRINT "--- Arena Snapshot (region markers) ---"
    FOR i = 0 TO offset - 1
        IF arena(i) > 0 THEN
            IF i = 0 OR arena(i) <> arena(i - 1) THEN
                PRINT "  [" & FORMAT$(i) & "-" & FORMAT$(i + allocSizes(arena(i) - 1) - 1) & "] region" & STR$(arena(i))
            END IF
        END IF
    NEXT i
    PRINT

    snapOffset = offset
    PRINT "Saved mark at offset" & STR$(snapOffset)
    PRINT

    PRINT "--- Second allocation phase (after mark) ---"
    FOR i = 0 TO 4
        IF offset + 50 <= arenaSize THEN
            allocOffsets(allocCount) = offset
            allocSizes(allocCount) = 50
            totalAlloced = totalAlloced + 50
            FOR j = 0 TO 49
                arena(offset + j) = 7 + i
            NEXT j
            PRINT "  Extra alloc" & STR$(i) & ": offset" & STR$(offset) & ", size 50"
            offset = offset + 50
            allocCount = allocCount + 1
            numAllocs = numAllocs + 1
        END IF
    NEXT i
    PRINT "Offset after extra allocs:" & STR$(offset)

    PRINT
    PRINT "--- Reset to mark (offset" & STR$(snapOffset) & ") ---"
    offset = snapOffset
    PRINT "Arena reset. Current offset:" & STR$(offset) & ", free:" & STR$(arenaSize - offset)
    PRINT

    PRINT "--- Third allocation phase (after reset) ---"
    alloc3 = 0
    IF offset + 700 <= arenaSize THEN
        allocOffsets(allocCount) = offset
        allocSizes(allocCount) = 700
        totalAlloced = totalAlloced + 700
        FOR j = 0 TO 699
            arena(offset + j) = 8
        NEXT j
        PRINT "Alloc after reset: offset" & STR$(offset) & ", size 700"
        offset = offset + 700
        allocCount = allocCount + 1
        numAllocs = numAllocs + 1
    END IF

    PRINT
    bytesLeft = arenaSize - offset
    largestFree = bytesLeft
    PRINT "Final state: offset" & STR$(offset) & ", free" & STR$(bytesLeft) & " units"
    PRINT "Peak usage:" & STR$(peakUsed) & " units"
    PRINT "Total allocation operations:" & STR$(numAllocs)
    PRINT "Arena allocator simulation complete."

    FUNCTION = 0
END FUNCTION
