// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/12/Memory.jack

/**
 * This library provides two services: direct access to the computer's main
 * memory (RAM), and allocation and recycling of memory blocks. The Hack RAM
 * consists of 32,768 words, each holding a 16-bit binary number.
 */ 
class Memory {

    static Array memory;
    static Array heap;
    static Array freeList;

    /** Initializes the class. */
    function void init() {
        let memory = 0;
        let heap = 2048;
        let freeList = 2048;
        let heap[0] = 0;
        let heap[1] = 14335;
        return;
    }

    /** Returns the RAM value at the given address. */
    function int peek(int address) {
        return memory[address];
    }

    /** Sets the RAM value at the given address to the given value. */
    function void poke(int address, int value) {
        let memory[address] = value;
        return;
    }

    /** Finds an available RAM block of the given size and returns
     *  a reference to its base address. */
    function int alloc(int size) {
        var Array curList, found;
        let curList = freeList;
        while (curList > 0) {
            if (curList[1] > (size + 1)) {
                do Memory.poke(8010, 1);
                let found = curList + curList[1] - size;
                let curList[1] = curList[1] - size - 2;
                let found[0] = 0;
                let found[1] = size;
                return found;
            } else {
                let curList = curList[0];
            }
        }
        return 0;
    }

    /** De-allocates the given object (cast as an array) by making
     *  it available for future allocations. */
    function void deAlloc(Array o) {
        var Array curList;
        let curList = freeList;
        if(curList = 0) {
            let freeList = o;
            return;
        }
        while (curList[0] > 0) {
            let curList = curList[0];
        }
        let curList = o;
        return;
    }    
}
