#ifndef SEM_DEF
 #define SEM_DEF


//-------------------- SEMANTIC ANALYZER Module -----------------//
//						  v 15 . 04 .  2007						 //
//																 //
//								MT								 //
//---------------------------------------------------------------//


//--- Classes
//=== Classes

//---------------------- Incudes 
#include "stdio.h"
#include "ctype.h"
#include "strings.h"

#include "../../ui/onerror.hpp"

#include "../robot/robot.hpp"

#include "lex.hpp"
#include "syn.hpp"
#include "exec.hpp"
//====================== Includes

//---------------------- Defines
//====================== Defines

//--- Classes --- 

//--- Poliz Constants ---
template <class T> 
class PolizConst : public PolizElem {
protected:
	T val;
public:
	PolizConst(T a) { val = a; };
	virtual ~PolizConst() {};

	virtual PolizElem* Clone() const { return new PolizConst(val); };
	T inline Get() const { return val; };

	virtual void  Evaluate()
	{ 
		exe->Debug(" Const pushing -> ");
		Push(Clone());
		exe->Debug(" Const pushed -> ");
	};
};

typedef PolizConst<int> PolizConstInt;
typedef PolizConst<char*> PolizConstStr;
typedef PolizConst<char*> PolizConstVarAddr;
typedef PolizConst<PolizItem*> PolizConstLabel;
/* === */ 

//--- Poliz Functions ---
class PolizFunc : public PolizElem {
protected : 
	virtual PolizElem* PopTest()=0;
	
public :
	virtual PolizElem *EvaluateFunc() = 0;
	virtual void Evaluate()
	{
		PolizElem *res = EvaluateFunc();
		if (res!=NULL) Push(res);
	};
};


//--- Poliz Functions +-*/% --- 
class PolizFuncPlus : public PolizFunc {
protected :
	virtual PolizElem* PopTest() 
	{
		PolizElem *operand = Pop();
		PolizConstInt *i=dynamic_cast<PolizConstInt*>(operand);
		if(i==NULL) { throw PolizExNotInt(operand); } 
		return i;
	}


	virtual int Operate(int o1, int o2) {
		return o1 + o2;
	}
public :
	virtual PolizElem *EvaluateFunc()
	{
		PolizConstInt *i1, *i2;
		exe->Debug(" FuncOper::PopTest operand 1 -> ");
		i1 = (PolizConstInt*) PopTest();
		exe->Debug(" FuncOper::PopTest operand 2 -> ");
		i2 = (PolizConstInt*) PopTest();
		int res = Operate(i1->Get(), i2->Get());
		delete i1;
		delete i2;
		return new PolizConstInt(res);
	};
};

class PolizFuncMinus : public PolizFuncPlus {
protected: 
	virtual int Operate(int o1, int o2) {
		return o1-o2;
	};
};

class PolizFuncMult : public PolizFuncPlus {
protected: 
	virtual int Operate(int o1, int o2) {
		return o1*o2;
	};
};

class PolizFuncDiv : public PolizFuncPlus {
protected: 
	virtual int Operate(int o1, int o2) {
		return o1/o2;
	};
};

class PolizFuncMod : public PolizFuncPlus {
protected: 
	virtual int Operate(int o1, int o2) {
		return o1%o2;
	};
};

//--- Poliz Functions & | < > == ---
class PolizFuncAnd : public PolizFuncPlus {
protected: 
	virtual int Operate(int o1, int o2) {
		return o1 & o2;
	};
};

class PolizFuncOr : public PolizFuncPlus {
protected: 
	virtual int Operate(int o1, int o2) {
		return o1 | o2;
	};
};

class PolizFuncHigher : public PolizFuncPlus {
protected: 
	virtual int Operate(int o1, int o2) {
		return o1 > o2;
	};
};

class PolizFuncLower : public PolizFuncPlus {
protected: 
	virtual int Operate(int o1, int o2) {
		return o1 < o2;
	};
};

class PolizFuncEq : public PolizFuncPlus {
protected: 
	virtual int Operate(int o1, int o2) {
		return o1 == o2;
	};
};


//--- Poliz Function Var Read/Write --- 
class PolizFuncVar : public PolizFunc {
protected: 
	char *s;

protected: 
	virtual PolizElem* PopTest() 
	{
		PolizElem *operand = Pop();
		PolizConstInt *i=dynamic_cast<PolizConstInt*>(operand);
		if(i==NULL) { throw PolizExNotInt(operand); } 
		return i;
	}

	virtual void ReadStack() {
		PolizConstInt *red = (PolizConstInt*) PopTest();
		exe->SetVar(s, red->Get());
	};
};

class PolizFuncVarRead : public PolizFuncVar {
public:
	PolizFuncVarRead(char *str) { s=str; };
	virtual PolizElem *EvaluateFunc() {
		ReadStack();
		return NULL;
	};
	
};

class PolizFuncVarWrite : public PolizFuncVar {
public:
	PolizFuncVarWrite(char *str) { s=str; };
	virtual PolizElem *EvaluateFunc() {
		return new PolizConstInt(exe->GetVar(s));
	};
};
//--- Poliz Function Robot Read/Write --- 
class PolizFuncRoboWrite : public PolizFunc {
protected: 
	char *s1, *s2, *s3;
	int n;

protected: 
	virtual PolizElem* PopTest() {return NULL;};
	
public:
	PolizFuncRoboWrite
		(char *n1, char *n2=NULL, int num=-1, char *n3=NULL)
			{ s1=n1; s2=n2; s3=n3; n=num; };

	virtual PolizElem *EvaluateFunc() {
		return new PolizConstInt(exe->GetDataInt(s1,s2,n,s3));
	};
};



/* === */ 

//--- END ----
#endif

