#ifndef __FUNCTION_AMV
	#define __FUNCTION_AMV

#include <ostream>
#include "stringAMV.h"
#include "amvdefs.h"

namespace amv	{

template <class type>
class function	{
	public:
		enum function_type	{ UNARY,BINARY	};
	private:
		string name;
		union	{
			type (*pFunc)(const type &);
			type (*pFuncb)(const type &,const type &);
		};
		function_type ft;
	public:
		typedef type (*pFunction)(const type &);
		typedef type (*pFunctionb)(const type &, const type &);
		function(const string &nameFunction,/*pFunction*/void * pf, function_type newft=UNARY):
		name(nameFunction),pFunc((pFunction)pf), ft(newft)
			{
			}
/*		function(const string &nameFunction,pFunctionb pf):
		name(nameFunction),pFuncb(pf), ft(BINARY)
			{
			}*/
		function(): name(), pFunc(0), ft(UNARY)
			{
			}
		function(const function &f):
		name(f.name), pFunc(f.pFunc), ft(f.ft)
			{
			}
/*		void initialize(const string &nameFunction, pFunction pf)
			{
			name=nameFunction;
			pFunc=pf;
			}*/
		string getName() const
			{
			return name;
			}
		pFunction getFunction() const
			{
			return pFunc;
			}
		pFunctionb getFunctionb() const
			{
			return pFuncb;
			}
		bool isUnary() const
			{
			return ft==UNARY;
			}
		bool isBinary() const
			{
			return ft==BINARY;
			}

/*		type operator()(const type &t) const
			{
			return (*pFunc)(t);
			}
		type operator()(const type &t1, const type &t2) const
			{
			return (*pFuncb)(t1,t2);
			}
*/
	operator<(const function &op2)
		{
		return (name<op2.name);
		}
	operator==(const function &op2)
		{
		return (name==op2.name);
		}
	friend ostream &operator<<(ostream &os,const function &f)
		{
		os<<'{'<<f.name<<','<<f.pFunc<<'}';
		return os;
		}

};
/*
void *pf=(void *)f;
_asm
	{
	mov         eax,dword ptr [ebp-0Ch]
	push        eax
	mov         ecx,[ebp-8]
	push        ecx
	mov         edx,[ebp-4]
	push        edx
	call        pf
	add         esp,0Ch
	}
*/
/*
template <class type>//por ahora es template
class function	{
	string name;
	void *pFunction;
	int nArguments;

	public:
		function(const string &nameFunction,void *pf, int na=1):
		name(nameFunction),pFunction(pf), nArguments(na)
			{
			}
		function(): name(), pFunction(0), nArguments(0)
			{
			}
		function(const function &f):
		name(f.name), pFunction(f.pFunction), nArguments(f.nArguments)
			{
			}
		void initialize(const string &nameFunction, void *pf, int na=1)
			{
			name=nameFunction;
			pFunction=pf;
			nArguments=na;
			}
		string getName() const
			{
			return name;
			}
		void *getFunction() const
			{
			return pFunction;
			}

		type operator()(const type &t) const
			{
			return (*pFunc)(t);
			}

	operator<(const function &op2)
		{
		return (name<op2.name);
		}
	operator==(const function &op2)
		{
		return (name==op2.name);
		}
	friend ostream &operator<<(ostream &os,const function &f)
		{
		os<<'{'<<f.name<<','<<f.pFunction<<'}';
		return os;
		}

};
*/
}

#endif