//***************************************************************************
//
//								SYMTABLE.H
//
//***************************************************************************

#ifndef ABLSYMT_H
#define ABLSYMT_H

#include "ablgen.h"
#include "ablscan.h"
#include "dablenv.h"

//***************************************************************************
namespace ABL
{

//---------------------
// DEFINITION structure

	typedef int RoutineKey;

	typedef union
	{
		long    integer;
		char    character;
		float   real;
		char*   stringPtr;
	} Value;

	typedef enum
	{
		VAR_TYPE_NORMAL,
		VAR_TYPE_STATIC,
		VAR_TYPE_ETERNAL
	} VariableType;

	typedef enum
	{
		DFN_UNDEFINED,
		DFN_CONST,
		DFN_TYPE,
		DFN_VAR,
		//DFN_FIELD,			// Currently not implementing record structures...
		DFN_VALPARAM,
		DFN_REFPARAM,
		DFN_MODULE,
		DFN_PROCEDURE,
		DFN_FUNCTION,
		DFN_STATE,
		DFN_FSM
	} DefinitionType;

	typedef struct _SymTableNode* SymTableNodePtr;
	typedef struct _Type*     TypePtr;

	typedef struct
	{
		Value         value;
	} Constant;

	typedef struct _Routine
	{
		RoutineKey        key;
		bool          isOrder;
		unsigned char     paramCount;
		unsigned char     totalParamSize;
		unsigned short      totalLocalSize;
		union
		{
			SymTableNodePtr     params;					// for modules
			SymTableNodePtr     state;					// for fsm's
		};
		SymTableNodePtr     locals;
		SymTableNodePtr     localSymTable;
		char*         codeSegment;
		long          codeSegmentSize;
	} Routine;

	typedef struct
	{
		VariableType      varType;
		long          offset;
		SymTableNodePtr     recordIdPtr;		// Currently not implementing record structures...
	} Data;

	typedef union
	{
		Constant        constant;
		Routine         routine;
		Data            data;
	} DefinitionInfo;

	typedef struct
	{
		DefinitionType      key;
		DefinitionInfo      info;
	} Definition;

//***************************************************************************

//------------------
// SYMBOL TABLE node	

	typedef struct _SymTableNode
	{
		SymTableNodePtr   left;
		SymTableNodePtr   parent;
		SymTableNodePtr   right;
		SymTableNodePtr   next;
		char*       name;
		char*       info;
		Definition      defn;
		TypePtr       typePtr;
		ABLModulePtr    library;
		unsigned char   level;
		long        labelIndex;		// really for compiling only...
	} SymTableNode;


//***************************************************************************

//---------------
// TYPE structure

	typedef enum
	{
		FRM_NONE,
		FRM_SCALAR,
		FRM_ENUM,
		FRM_ARRAY
		//FRM_RECORD
	} FormType;

//---------------------------------------------------------------------
// Currently, we are only supporting the basic types: arrays and simple
// variables.

	typedef struct _Type
	{
		long              numInstances;
		FormType            form;
		long              size;
		SymTableNodePtr         typeIdPtr;
		union
		{
			struct
			{
				SymTableNodePtr     constIdPtr;
				long          max;
			} enumeration;
			struct
			{
				TypePtr         indexTypePtr;		// should be Integer
				TypePtr         elementTypePtr;		// should be Real, Integer, Char or array
				long          elementCount;
			} array;
			// Not currently implementing record structures...
			//struct {
			//	SymTableNodePtr		fieldSymTable;
			//} record;
		} info;
	} Type;


//***************************************************************************

	void searchLocalSymTable (SymTableNodePtr& IdPtr);
	void searchThisSymTable (SymTableNodePtr& IdPtr, SymTableNodePtr thisTable);
	void searchAllSymTables (SymTableNodePtr& IdPtr);
	void enterLocalSymTable (SymTableNodePtr& IdPtr);
	void enterNameLocalSymTable (SymTableNodePtr& IdPtr, const char* name);
	void searchAndFindAllSymTables (SymTableNodePtr& IdPtr);
	void searchAndEnterLocalSymTable (SymTableNodePtr& IdPtr);
/*inline*/void searchAndEnterThisTable (SymTableNodePtr& IdPtr, SymTableNodePtr thisTable);
	inline SymTableNodePtr symTableSuccessor (SymTableNodePtr nodeX);

	SymTableNodePtr searchSymTable (const char* name, SymTableNodePtr nodePtr);
	SymTableNodePtr searchSymTableDisplay (const char* name);
	SymTableNodePtr enterSymTable (const char* name, SymTableNodePtr* ptrToNodePtr);
	SymTableNodePtr insertSymTable (SymTableNodePtr* tableRoot, SymTableNodePtr newNode);
	SymTableNodePtr extractSymTable (SymTableNodePtr* tableRoot, SymTableNodePtr nodeKill);
	void enterStandardRoutine (const char* name, RoutineKey routineKey, DefinitionType definitionKey, bool isOrder = false);
	void enterScope (SymTableNodePtr symTableRoot);
	SymTableNodePtr exitScope (void);
	void initSymTable (void);

	TypePtr createType (void);
	TypePtr setType (TypePtr type);
	void clearType (TypePtr& type);

	extern SymTableNodePtr    SymTableDisplay[MAX_NESTING_LEVEL];


//***************************************************************************
}


#endif

