#include "lexeme-list.h"

#include <string.h>

#include "scm-mem.h"

// -------------------------------------------------------------------------------------------- //
// * Implementation *
// -------------------------------------------------------------------------------------------- //

scm::LexemeList::LexemeList()
{
	size = 0;
	nalloc = 0;
}

scm::LexemeList::~LexemeList()
{
	clear();
}

scm::LexemeList::LexemeList(const LexemeList& list)
{
	size = list.size;
	
	if (size > 0) {
		lexeme = new Lexeme[size];
		for (int k = 0; k < size; k++)
			lexeme[k] = list.lexeme[k];
	}

	nalloc = size;
}
// -------------------------------------------------------------------------------------------- //

// * swap & assignment * //
// -------------------------------------------------------------------------------------------- //
const scm::LexemeList& scm::LexemeList::operator=(LexemeList list)
{
	swap(list);
	return (*this);
}

void scm::LexemeList::swap(LexemeList& list)
{
	scm::swap(lexeme, list.lexeme);
	scm::swap(size, list.size);
	scm::swap(nalloc, list.nalloc);
}
// -------------------------------------------------------------------------------------------- //

// * add calls * //
// -------------------------------------------------------------------------------------------- //
void scm::LexemeList::add(const char* token, const Lexeme::TYPE type, const int tag)
{
	if (size == nalloc) 
	{
		Lexeme *cp_list;
		cp_list = new Lexeme[nalloc + c_nalloc_inc];

		for (int k = 0; k < size; k++)
			cp_list[k].swap(lexeme[k]);

		if (nalloc > 0) delete[] lexeme;
		lexeme = cp_list;

		nalloc += c_nalloc_inc;
	}

	lexeme[size].set(token, type, tag);
	size++;
}

void scm::LexemeList::add(const char* token, const Lexeme::TYPE type)
{
	add(token, type, 0);
}
// -------------------------------------------------------------------------------------------- //

// * get calls * //
// -------------------------------------------------------------------------------------------- //
int scm::LexemeList::get_size() const
{
	return size;
}

const scm::Lexeme scm::LexemeList::get_lexeme(const int idx) const
{
	if ((idx < 0) || (idx >= size)) return Lexeme();

	return lexeme[idx];
}

const char* scm::LexemeList::get_token(const int idx) const
{
	if ((idx < 0) || (idx >= size)) return NULL;

	return lexeme[idx].get_token();
}

scm::Lexeme::TYPE scm::LexemeList::get_type(const int idx) const
{
	if ((idx < 0) || (idx >= size)) return Lexeme::IS_INVALID;

	return lexeme[idx].get_type();
}

int scm::LexemeList::get_tag(const int idx) const
{
	if ((idx < 0) || (idx >= size)) return 0;

	return lexeme[idx].get_tag();
}
// -------------------------------------------------------------------------------------------- //

// * check lexeme type * //
// -------------------------------------------------------------------------------------------- //
bool scm::LexemeList::is_operator(const int idx) const
{
	if ((idx < 0) || (idx >= size)) return false;

	return lexeme[idx].is_operator();
}
bool scm::LexemeList::is_function(const int idx) const
{
	if ((idx < 0) || (idx >= size)) return false;

	return lexeme[idx].is_function();
}
bool scm::LexemeList::is_ctor(const int idx) const
{
	if ((idx < 0) || (idx >= size)) return false;

	return lexeme[idx].is_ctor();
}
bool scm::LexemeList::is_value(const int idx) const
{
	if ((idx < 0) || (idx >= size)) return false;

	return lexeme[idx].is_value();
}
// -------------------------------------------------------------------------------------------- //

// * clear & reset * //
// -------------------------------------------------------------------------------------------- //
void scm::LexemeList::clear()
{
	if (nalloc > 0)
		delete[] lexeme;

	size = 0;
	nalloc = 0;
}

void scm::LexemeList::reset()
{
	size = 0;
}
// -------------------------------------------------------------------------------------------- //