#ifndef EXEC_DEF
 #define EXEC_DEF


//------------ EXECUTER & Base Poliz Elem Module  ---------------//
//						  v 15 . 04 .  2007						 //
//																 //
//								MT								 //
//---------------------------------------------------------------//

//--- Classes
class CVar;
class CExecuter;
class PolizElem;
//=== Classes


//---------------------- Incudes 
#include "stdio.h"
#include "ctype.h"
#include "strings.h"
#include "../../ui/onerror.hpp"
#include "stack.hpp"

#include "lex.hpp"
#include "syn.hpp"

#include "../robot/data.hpp"
#include "../robot/robot.hpp"
//====================== Includes


//---------------------- Defines
#define VT_VAR_NOT_FOUND  "Var not found in VarTable."
//====================== Defines

//------------------------------- Base POLIZ --------------------------
//--- Main Poliz Element ---
class PolizElem {
protected:
	CExecuter *exe;
	
	void Push(PolizElem *e);
	PolizElem *Pop();

public:
	PolizElem() { exe=NULL; };
	PolizElem(CExecuter *e) { exe=e; };
	virtual ~PolizElem() {};

	virtual void Evaluate() = 0;
	virtual void Evaluate_main(CExecuter *e)
	{
		exe=e;
		Evaluate();
	};
};


/* Throw */ 
class PolizEx { 
protected:
	PolizElem *addr; 
public:
	PolizEx() { };
	PolizEx(PolizElem *cur) { addr=cur; };
	virtual PolizElem* GetAddr() { return addr; };
};


class PolizExConst : public PolizEx {
public: 	
	PolizExConst(PolizElem *cur) { addr=cur; };
};

class PolizExNotInt : public PolizEx {
public: 	
	PolizExNotInt(PolizElem *cur) { addr=cur; };
};


//=======//

//--- Poliz Item ---
class PolizItem {
	friend class CExecuter;	
protected : 
	PolizItem  *next;
	PolizElem  *p; 
public : 
	inline PolizItem() { next = NULL; p = NULL; };
	inline PolizItem(PolizElem *tmp) {  next=NULL; p=tmp; };
	~PolizItem() { };

	void inline Assign(PolizElem *tmp) { p = tmp; };
};


//------------------------------- Executer ----------------------------
//--- CVar ---
class CVar {
private :
	char *name;
	int value;

public :
	CVar () { name = NULL; value = 0; }; 
	CVar (char *str, int i) { SetName(str); SetValue(i); }; 
	~CVar () { delete[] name; }; 

	//--- Functions
	void inline  SetName(char *str) { name = strdup(str); };
	void inline  SetValue(int i) { value = i; };
	void inline  Set(char *str, int i) { SetName(str); SetValue(i); };
	bool inline  IsNameEq(char *str) { return (strcmp(name, str) == 0); }; 
	int  inline  GetValue() { return value; };
	char inline  *GetName() { return name; };
};


//--- CExecuter ---
class CExecuter {
public : 
	class CVarTable {
	private :
		CVar  *var;
		int  c; 
	public :
		CVarTable() { var=NULL; c=0; };
		~CVarTable() { delete[] var; };

		int inline Add(char *name, int val=0) 
		{
			//--- test: is such var existed?
			for (int i=0; i<c; i++)
				if (var[i].IsNameEq(name))
					return i;

			//--- adding
			c++;
			CVar *v = new CVar[c];
			for (int i=0; i<c-1; i++) 
				v[i] = var[i];
			v[c-1].Set(name, val);
			var = v;

			return -1;
		};

		void inline SetVar(char *name, int val=0)
		{
			int i = Add(name, val);
			if (i == -1) return;
			var[i].SetValue(val); 
		}

		int  inline GetVar(char *name) 
		{
			for (int i=0; i<c; i++)
				if (var[i].IsNameEq(name))
					return var[i].GetValue();

			throw VT_VAR_NOT_FOUND;
			return 0;
		};

		void inline Print()
		{
			printf("\n");	
			for (int i=0; i<c; i++)
				printf(" Var :: %s = %d; \n", var[i].GetName(), var[i].GetValue());
			printf("\n");
		};
	};

//======================
//----------------------
private :
	CError  Error;
	CData  *Data;
	CVarTable  VarTable;

	PolizItem  *begin, *cur;
	CStack <PolizItem>  stack;
	int flag_debug;
public : 
	CRobot  *Robot;
	
public :
	//--- Constructor 
	CExecuter (CData *d, CRobot *r) 
		{ SetData(d); SetRobot(r); begin=NULL; cur=NULL; flag_debug=-1; };
	//--- Debug
	void SetDebugMode(int m) { flag_debug = m; };
	void Debug(char *s1, char *s2=NULL) 
		{ if (flag_debug==1) printf(s1,s2); };
	//--- Show Error
	void ShowError(char *str, char *str2 = NULL);

	//--- Robot Data
	void SetData(CData *d) { Data = d; };
	void SetRobot(CRobot *r) { Robot = r; };
	int inline GetDataInt
		(char *name1, char *name2=NULL, int n=-1, char *name3=NULL)
			{ return Data->Get(name1, name2, n, name3); };

	//--- Variable Table	
	int GetVar(char *str);
	void inline SetVar(char *name, int val=0)
		{ VarTable.SetVar(name, val); };

	//--- Stack <PolizElem>
	void Push(PolizElem *e);
	PolizElem* Pop();

	//--- P.O.L.I.Z.
	//--- Execute
	void Execute ();
	void AddElem (PolizElem *elem);
	
	PolizItem *GetCurCmd() { return cur; };

	//--- Destructor
	~CExecuter();

};



#endif




