#include "Symbol.h"

namespace AScript {

//-----------------------------------------------------------------------------
// Symbol
//-----------------------------------------------------------------------------
Symbol::Symbol(UniqNumber uniqNum, const TCHAR *name) : _uniqNum(uniqNum)
{
	_name = new TCHAR[::_tcslen(name) + 1];
	::_tcscpy(_name, name);
}

Symbol::~Symbol()
{
	delete[] _name;
}

const Symbol *Symbol::Add(const TCHAR *name)
{
	return SymbolPool::GetInstance()->Add(name);
}

bool Symbol::IsFlowControlSymbol() const
{
	return 
		IsIdentical(AScript_Symbol(if_)) ||
		IsIdentical(AScript_Symbol(elsif)) ||
		IsIdentical(AScript_Symbol(repeat)) ||
		IsIdentical(AScript_Symbol(while_)) ||
		IsIdentical(AScript_Symbol(for_));
}

//-----------------------------------------------------------------------------
// SymbolSet
//-----------------------------------------------------------------------------
const SymbolSet SymbolSet::Null;

SymbolSet::SymbolSet(const SymbolSet &symbolSet)
{
	foreach_const (SymbolSet, ppSymbol, symbolSet) Insert(*ppSymbol);
}

void SymbolSet::operator=(const SymbolSet &symbolSet)
{
	foreach_const (SymbolSet, ppSymbol, symbolSet) Insert(*ppSymbol);
}

//-----------------------------------------------------------------------------
// SymbolPool
//-----------------------------------------------------------------------------
SymbolPool *SymbolPool::_pInst = NULL;

SymbolPool::~SymbolPool()
{
	foreach (Content, ppSymbol, _content) {
		Symbol::Delete(*ppSymbol);
	}
}

void SymbolPool::Initialize()
{
	if (_pInst == NULL) {
		_pInst = new SymbolPool();
		_pInst->_Initialize();
	}
}

void SymbolPool::_Initialize()
{
	AScript_RealizeSymbolEx(Str_Empty,		_T(""));
	AScript_RealizeSymbolEx(Char_Plus,		_T("+"));
	AScript_RealizeSymbolEx(Char_Multiply,	_T("*"));
	AScript_RealizeSymbolEx(Char_Question,	_T("?"));
	AScript_RealizeSymbolEx(Char_Modulo,	_T("%"));
	AScript_RealizeSymbolEx(Char_And,		_T("&"));
	AScript_RealizeSymbol(unknown);
	AScript_RealizeSymbol(number);
	AScript_RealizeSymbol(boolean);
	AScript_RealizeSymbol(symbol);
	AScript_RealizeSymbol(string);
	AScript_RealizeSymbol(complex);
	AScript_RealizeSymbol(Module);
	AScript_RealizeSymbol(Class);
	AScript_RealizeSymbol(Object);
	AScript_RealizeSymbol(Function);
	AScript_RealizeSymbol(List);
	AScript_RealizeSymbol(Dict);
	AScript_RealizeSymbol(File);
	AScript_RealizeSymbol(FileStat);
	AScript_RealizeSymbol(DateTime);
	AScript_RealizeSymbol(Expr);
	AScript_RealizeSymbol(Environment);
	AScript_RealizeSymbol(Error);
	AScript_RealizeSymbol(Struct);
	AScript_RealizeSymbol(e);
	AScript_RealizeSymbol(pi);
	AScript_RealizeSymbol(nil);
	AScript_RealizeSymbol(zero);
	AScript_RealizeSymbol(raise);
	AScript_RealizeSymbolEx(true_,			_T("true"));
	AScript_RealizeSymbolEx(false_,			_T("false"));
	AScript_RealizeSymbol(rem);				// dummy for MS-DOS batch
	AScript_RealizeSymbol(j);
	AScript_RealizeSymbolEx(if_,			_T("if"));
	AScript_RealizeSymbol(elsif);
	AScript_RealizeSymbolEx(else_,			_T("else"));
	AScript_RealizeSymbol(repeat);
	AScript_RealizeSymbolEx(while_,			_T("while"));
	AScript_RealizeSymbolEx(for_,			_T("for"));
	AScript_RealizeSymbolEx(break_,			_T("break"));
	AScript_RealizeSymbolEx(continue_,		_T("continue"));
	AScript_RealizeSymbolEx(except_,		_T("except"));
	AScript_RealizeSymbol(__init__);
	AScript_RealizeSymbol(__del__);
	AScript_RealizeSymbol(__str__);
	AScript_RealizeSymbol(super);
	AScript_RealizeSymbol(self);
	AScript_RealizeSymbolEx(static_,		_T("static"));
	AScript_RealizeSymbolEx(const_,			_T("const"));
	AScript_RealizeSymbolEx(_anonymous_,	_T("<>"));
	AScript_RealizeSymbolEx(public_,		_T("public"));
	AScript_RealizeSymbolEx(private_,		_T("private"));
	AScript_RealizeSymbolEx(protected_,		_T("protected"));
	AScript_RealizeSymbol(dynamic_scope);
	AScript_RealizeSymbol(inside_scope);
	AScript_RealizeSymbol(map);
	AScript_RealizeSymbol(nomap);
	AScript_RealizeSymbol(strict);
	AScript_RealizeSymbol(loose);
	AScript_RealizeSymbol(block);
	AScript_RealizeSymbol(list);
	AScript_RealizeSymbol(xlist);
	AScript_RealizeSymbol(set);
	AScript_RealizeSymbol(xset);
	AScript_RealizeSymbol(rev);
	AScript_RealizeSymbol(and);
	AScript_RealizeSymbol(or);
	AScript_RealizeSymbol(xor);
	AScript_RealizeSymbolEx(void_,			_T("void"));
	AScript_RealizeSymbol(icase);
	AScript_RealizeSymbol(index);
	AScript_RealizeSymbol(last_index);
	AScript_RealizeSymbol(indices);
	AScript_RealizeSymbol(ascend);
	AScript_RealizeSymbol(descend);
	AScript_RealizeSymbol(stable);
	AScript_RealizeSymbol(up);
	AScript_RealizeSymbol(down);
	AScript_RealizeSymbol(left);
	AScript_RealizeSymbol(right);
	AScript_RealizeSymbol(prev);
	AScript_RealizeSymbol(next);
	AScript_RealizeSymbol(name);
	AScript_RealizeSymbol(parent);
	AScript_RealizeSymbol(parents);
	AScript_RealizeSymbol(sibling);
	AScript_RealizeSymbol(siblings);
	AScript_RealizeSymbol(child);
	AScript_RealizeSymbol(children);
	AScript_RealizeSymbol(path);
	AScript_RealizeSymbol(x);
	AScript_RealizeSymbol(y);
	AScript_RealizeSymbol(z);
}

const Symbol *SymbolPool::Add(const TCHAR *name)
{
	Symbol *pSymbol = new Symbol(_uniqNum, name);
	std::pair<Content::iterator, bool> rtn = _content.insert(pSymbol);
	if (rtn.second) {
		_uniqNum++;
	} else {
		Symbol::Delete(pSymbol);
	}
	pSymbol = *rtn.first;
	return pSymbol;
}

}
