
#include <iostream>

using namespace std;

class stack
{
	public:
	stack  * _back;
	int * _data;
	stack(int & data)
	{
		_data = & data;
		_back = 0;
	}
	stack(stack * back, int & data)
	{
		_data = & data;
		_back = back;
	}
	operator int *()
	{
		return _data;
	}
};

/*
 * 1
 * 2
 * 3
 * -3
 * -2
*/

//char * stack
/*
class fpush
{
    public:
    fpush * _back;
    const char * _data;
    fpush(fpush * back, const char * data)
    {
        _back = back;
        _data = data;
    }
    virtual const char * operator () (int index)
    {
        if (index > 0)
            return (*_back)(index-1);
        return _data;
    }
    virtual operator const char * ()
    {
        return _data;
    }
};

class fpop:public fpush
{
    public:
    fpop(fpush * back):fpush(back,0)
    {
        _back = back;
        _data = 0;
    }
    const char * operator () (int index)
    {
        _data = (*_back)(index+1);
        return _data;
    }
    operator const char * ()
    {
        if (!_data)
            operator()(0);
        return _data;
    }
};
*/
//string functor

class funcString
{
    public:
    virtual char operator () (int index) { return 0;}
};

class fstr:public funcString
{
    public:
    const char * _data;
    int _len;
    fstr(const char * data)
    {
        _data = data;
        _len = 0;
        do
        {
            _len++;
        }while (*(_data+_len));
    }
    virtual char operator () (int index)
    {
        if (index < _len)
            return *(_data + index);
        return 0;
    }
};

class fins:public fstr
{
    public:
    funcString * _back;
    int _start,
        _end;
    fins(funcString & back, const char * data, int start,  int end):fstr(data)
    {
        _back = & back;
        _start = start;
        _end = end;
    }
    char operator () (int index)
    {
        if (index < _start)
            return (*_back)(index);
        else if (index >= _start+_len)
            return (*_back)(index - _len + _end);
        return *(_data + index - _start);
    }
};

class fupper:public funcString
{
    public:
    funcString * _back;
    fupper(funcString & back)
    {
        _back = & back;
    }
    char operator() (int index)
    {
        if ((*_back)(index) >= 'a')
            return (*_back)(index) - 32;
        return (*_back)(index);
    }
};

class fsubstr:public funcString
{
    public:
    funcString * _back;
    int _start,
        _len;
    fsubstr(funcString & back,int start, int len):funcString()
    {
        _back = & back;
        _start = start;
        _len = len;
    }
    char operator () (int index)
    {
        if (index < _len)
            return (*_back)(_start+index);
        return 0;
    }
};

//fint

class funcInt
{
    public:
    virtual int operator () ()
    {
        return 0;
    }
};

class fint:public funcInt
{
    public:
    int _data;
    fint()
    {
        _data = 0;
    }
    fint(int data)
    {
        _data = data;
    }
    virtual int operator () ()
    {
        return _data;
    }
};

class fadd:public fint
{
    public:
    funcInt * _back;
    fadd(funcInt & back, int data):fint(data)
    {
        _back = &back;
    }
    int operator () ()
    {
        return (*_back)() + _data;
    }
};

int main()
{
    cout << "fucking functional stack" << endl;

    fstr a("hello world");
    fins b(a," god damn",5,0);
    fins c(b,"shitty ass",6,3);
    fupper d(c);
    fsubstr e(d,6,10);
    
    for (int i=0; i<40;i++)
        cout << e(i);
    cout << endl;
    
    fint aa(5);
    fadd bb(aa,6);
    
    cout << bb() << endl;
    
    int i = 12;
    stack ii(i);
    cout << (*ii)<< endl;
    
    
    return 0;
}
