aboutsummaryrefslogtreecommitdiff
path: root/projects/12/Memory.jack
blob: b1e67ef73d4e91997c5c717897ea075a4ac38685 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// 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 int first;

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

    /** 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;
    }

    /** Finds an available RAM block of the given size and returns
     *  a reference to its base address. */
    function int alloc(int size) {
        var int current;
        var int size2;
        var int newLast;
        let current = 0;
        let size2 = size + 2;
        while ((current > -1) & (heap[current + 1] < size2)) {
            let current = heap[current];
        }
        if (current = -1) {
            String.println("Insufficient space for allocation!");
            Sys.error(1);
        } else {
            let heap[current + 1] = heap[current + 1] - size2;
            let newLast = current + heap[current + 1] + 2;
            let heap[newLast] = heap[current];
            let heap[current] = newLast;
            let heap[newLast + 1] = size;
            return heap + newLast + 2;
        }
    }

    /** De-allocates the given object (cast as an array) by making
     *  it available for future allocations. */
    function void deAlloc(Array o) {
        var int base;
        var int current;
        var int prev;
        let prev = 0;
        let current = heap[prev];
        let oBase = o - heap - 2;
        while ((current > -1) & (~(current = oBase))){
            let prev = current;
            let current = heap[current];
        }
        if (current = -1) {
            String.println("The impossible happened");
            Sys.error(1);
        } else {
            let heap[prev] = heap[current]
            let heap[prev + 1] = heap[prev] - prev - 2;
            return;
        }
    }    
}