#include <iostream>

//#include "funky.hpp"

using namespace std;

struct funkyInt
{
  virtual int operator() ()=0;
};

struct funkyStack
{
  virtual int operator () (int)=0;
};

struct fint:funkyInt
{
  int arg;
  fint(int _arg)
  {
    arg = _arg;
  }
  int operator () ()
  {
    return arg;
  }
};

struct fpush:funkyStack
{
  funkyInt * arg;
  funkyStack * next;
  fpush(funkyInt * _arg, funkyStack * _next=0)
  {
    arg = _arg;
    next = _next;
  }
  int operator() (int i)
  {
    if (i != 0 && next != 0)
      return (*next)(i-1);
    return (*arg)();
  }
};

struct fpop:funkyStack
{
  funkyStack * next;
  fpop(funkyStack * _next)
  {
    next = _next;
  }
  int operator () ()
  {
    return (*next)(0);
  }
  int operator () (int i)
  {
    return (*next)(i+1);
  }
};


struct functor
{
  int (*f) (int,int);
  funkyInt * arg1;
  funkyInt * arg2;
  functor(funkyInt*_arg1, funkyInt*_arg2,int (*_f)(int,int))
  {
    arg1 = _arg1;
    arg2 = _arg2;
    f = _f;
  }
  functor(funkyInt*_arg1, int (*_f)(int,int))
  {
    arg1 = _arg1;
    arg2 = 0;
    f = _f;
  }
  int operator () ()
  {
    if (arg2)
      return (*f)((*arg1)(),(*arg2)());
    return (*f)((*arg1)());
  }
};

int adde(int a, int b)
{
  return a+b;
}

int main()
{
  cout << "funky coding style\n";
  
  fint cinq(5);
  //finc six(&cinq);
//   cout << six() << "=inc(5)\n";
   fint quatre(4);
//   fadd add(&cinq,&quatre);
//   cout << add() << "=add(4,5)\n";
//   fadd add2(&add,&cinq);
//   cout << add2() << "=add(add(4,5),5)\n";
//   fsub sub(&add2,&quatre);
//   cout << sub() << "=sub(add(4,5),4)\n";
//   fmul mul(&sub,&add2);
//   cout << mul() << "=mul(sub(add(4,5),4),add(add(4,5),5))\n";
//   fpow pow(&cinq,&quatre);
//   cout << pow() << "=pow(5,4)\n";
  
  fpush stack(&cinq);
  fpush st2(&quatre,&stack);
  fpush st3(&quatre,&st2);
  fpop st4(&st3);
  fpop st5(&st4);
  fpop st6(&st5);
  cout << st6() << "\n";
  
  functor un(&cinq,&quatre,&adde);
  cout << un() << '\n';
  
  return 0;
}
