/* SymbolTableEntry.c */
/*****************************************************************************/
/*                                                                           */
/*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
/*    Copyright (C) 1994  Thomas R. Lawrence                                 */
/*                                                                           */
/*    This program is free software; you can redistribute it and/or modify   */
/*    it under the terms of the GNU General Public License as published by   */
/*    the Free Software Foundation; either version 2 of the License, or      */
/*    (at your option) any later version.                                    */
/*                                                                           */
/*    This program is distributed in the hope that it will be useful,        */
/*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
/*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
/*    GNU General Public License for more details.                           */
/*                                                                           */
/*    You should have received a copy of the GNU General Public License      */
/*    along with this program; if not, write to the Free Software            */
/*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
/*                                                                           */
/*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
/*                                                                           */
/*****************************************************************************/

#include "MiscInfo.h"
#include "Audit.h"
#include "Debug.h"
#include "Definitions.h"

#include "SymbolTableEntry.h"
#include "CRC32.h"
#include "TrashTracker.h"
#include "Memory.h"
#include "SymbolList.h"


struct SymbolRec
	{
		SymbolType				Type;
		char*							SymbolName;
		unsigned long			HashValue;
		DataTypes					ObjectDataType;
		SymbolListRec*		FunctionArgList;
		long							VariableStackAddress;
	};


/* create a new symbol table entry for a variable */
SymbolRec*				NewSymbol(struct TrashTrackRec* Trash, char* String, long StringLength)
	{
		SymbolRec*			Symbol;

		Symbol = (SymbolRec*)AllocTrackedBlock(sizeof(SymbolRec),Trash);
		if (Symbol == NIL)
			{
				return NIL;
			}
		SetTag(Symbol,"SymbolRec: NewVariableSymbol");

		Symbol->SymbolName = AllocTrackedBlock(StringLength,Trash);
		if (Symbol->SymbolName == NIL)
			{
				return NIL;
			}
		SetTag(Symbol->SymbolName,"NewVariableSymbol:  name string");

		EXECUTE(Symbol->VariableStackAddress = -1;)

		Symbol->Type = eSymbolUndefined;
		CopyData(String,Symbol->SymbolName,StringLength);
		Symbol->HashValue = CalculateCRC32(Symbol->SymbolName,StringLength);
		return Symbol;
	}


/* find out what the symbol is a symbol of */
SymbolType				WhatIsThisSymbol(SymbolRec* Symbol)
	{
		CheckPtrExistence(Symbol);
		return Symbol->Type;
	}


/* get the hash value for the string */
unsigned long			GetSymbolHashValue(SymbolRec* Symbol)
	{
		CheckPtrExistence(Symbol);
		return Symbol->HashValue;
	}


/* get a pointer to the actual string name of the variable */
char*							GetSymbolName(SymbolRec* Symbol)
	{
		CheckPtrExistence(Symbol);
		return Symbol->SymbolName;
	}


/* make symbol into a variable symbol */
void							SymbolBecomeVariable(SymbolRec* Symbol, DataTypes VarType)
	{
		CheckPtrExistence(Symbol);
		ERROR(Symbol->Type != eSymbolUndefined,PRERR(ForceAbort,
			"GetSymbolVariableDataType:  symbol has already been defined"));
		Symbol->Type = eSymbolVariable;
		Symbol->ObjectDataType = VarType;
	}


/* make variable know where on the stack it lives */
void							SetSymbolVariableStackLocation(SymbolRec* Symbol, long StackLoc)
	{
		CheckPtrExistence(Symbol);
		ERROR(StackLoc < 0,PRERR(ForceAbort,"SetSymbolVariableStackLocation:  negative index"));
		ERROR(Symbol->VariableStackAddress >= 0,PRERR(ForceAbort,
			"SetSymbolVariableStackLocation:  location has already been set"));
		Symbol->VariableStackAddress = StackLoc;
	}


/* find out where on the stack a variable lives. */
long							GetSymbolVariableStackLocation(SymbolRec* Symbol)
	{
		CheckPtrExistence(Symbol);
		ERROR(Symbol->VariableStackAddress < 0,PRERR(ForceAbort,
			"SetSymbolVariableStackLocation:  location has already been set"));
		return Symbol->VariableStackAddress;
	}


/* get the object type for the variable */
DataTypes					GetSymbolVariableDataType(SymbolRec* Symbol)
	{
		CheckPtrExistence(Symbol);
		ERROR(Symbol->Type != eSymbolVariable,PRERR(ForceAbort,
			"GetSymbolVariableDataType:  not a variable"));
		return Symbol->ObjectDataType;
	}


/* make symbol into a function symbol */
void							SymbolBecomeFunction(SymbolRec* Symbol, struct SymbolListRec* ArgList,
										DataTypes ReturnType)
	{
		CheckPtrExistence(Symbol);
		ERROR(Symbol->Type != eSymbolUndefined,PRERR(ForceAbort,
			"GetSymbolVariableDataType:  already defined"));
		Symbol->Type = eSymbolFunction;
		Symbol->ObjectDataType = ReturnType;
		Symbol->FunctionArgList = ArgList;
	}


/* get the return type for the function */
DataTypes					GetSymbolFunctionReturnType(SymbolRec* Symbol)
	{
		CheckPtrExistence(Symbol);
		ERROR(Symbol->Type != eSymbolFunction,PRERR(ForceAbort,
			"GetSymbolVariableDataType:  not a function"));
		return Symbol->ObjectDataType;
	}


/* get the list of symbol table entries from a function call argument list */
struct SymbolListRec*	GetSymbolFunctionArgList(SymbolRec* Symbol)
	{
		CheckPtrExistence(Symbol);
		ERROR(Symbol->Type != eSymbolFunction,PRERR(ForceAbort,
			"GetSymbolFunctionArgList:  symbol table entry is not a function"));
		return Symbol->FunctionArgList;
	}


/* perform a hash on a name */
unsigned long			UseSymbolTableHash(char* String, long Length)
	{
		return CalculateCRC32(String,Length);
	}
