/*____________________________________________________________________________
memory pool, emulate simple version of dynamic allocation
time sharing paradigm require that many interpreter share the same memory
why not simply use new and delete... because it is supposed to be an emulator
____________________________________________________________________________*/

#pragma once
#ifndef _MEM
#define _MEM

#include "word.h"
#include "node.hpp"

/*____________________________________________________________________________
class
____________________________________________________________________________*/

class memory{
    //property
    node * _pool,       //all préallocated memory
         * _head;       //first node
    int _size;          //number of cell left
public:
    //constructor
    memory(int);        //init with the specified size
    ~memory();
    //mutator
    node * alloc();     //return one cell
    void free(node *);  //take back one cell
    //getter
    int size()const;    //return number of cell left
    bool empty()const;  //return true if no more memory left
    //debug
    node at(int)const;  //return desired node in pool
};

/*____________________________________________________________________________
method
____________________________________________________________________________*/

memory::memory(int size)
{
    _pool = new node[size];
    _head = 0;
    _size = size;
    for (int i=size-1;i>=0;i--)
    {
        _pool[i].next = _head;
        _head = &_pool[i];
    }
}

memory::~memory()
{
    delete [] _pool;
}

node * memory::alloc()
{
    if (!_size)
        return 0;
    node * tmp = _head;
    _head = _head->next;
    return tmp;
}

void memory::free(node * nud)
{
    if (!nud)
        return;
    nud->next = _head;
    _head = nud;
}

int memory::size()const
{
    return _size;
}

bool memory::empty()const
{
    return _size==0;
}

node memory::at(int index)const
{
    node tmp;
    if (index < _size)
    {
        tmp.data = _pool[index].data;
        tmp.next = _pool[index].next = _pool;
    }
    else
    {
        tmp.data = 0;
        tmp.next = 0;
    }
    return tmp;
}

#endif
