#include <iostream>

using namespace std;

int
main()
{
      cout << "#ifndef ___VAR_BINOP_H" << endl;
      cout << "#define ___VAR_BINOP_H" << endl;
      cout << "#define ___BIN_OP_IF0(type_a,type_b,type_A,type_B,a,b,op)\\" << endl;
      cout << "if(a.data.type == type_a && b.data.type == type_b) {\\" << endl;
      cout << "   ret = a.type_A op b.type_B;\\" << endl;
      cout << "}" << endl;
{
      const char * type_a[] = {
         //"VAR_DATA::CHAR_TYPE",
         //"VAR_DATA::SHORT_TYPE",
         //"VAR_DATA::INT_TYPE",
         ///"VAR_DATA::FLOAT_TYPE",
         "VAR_DATA::LONG_TYPE",
         "VAR_DATA::DOUBLE_TYPE",
         "VAR_DATA::STRING_TYPE",
         //"VAR_DATA::BOOL_TYPE",
          0,
      };
      const char * type_b[] = {
         //"data.value.cvalue",
         //"data.value.svalue",
         //"data.value.ivalue",
         //"data.value.gvalue",
         "data.value.lvalue",
         "data.value.dvalue",
         "to_string()",
         //"data.value.bvalue",
         0,
      };
      cout << "#define ___BIN_OP_IF(a,b,op)\\" << endl;
      for(size_t i = 0; type_a[i] != 0; i++) {
         for(size_t j = 0; type_a[j] != 0; j++) {
            if(i != 0 || j != 0) {
               cout << "else ";
            }
            if(type_b[i] == string("to_string()") && type_b[j] == string("to_string()")) {
               cout << "___BIN_OP_IF0(" << type_a[i] << "," << type_a[j]
                    << "," << "data.svalue" << "," << "data.svalue" << ",a,b,op)";
            }
            else if(type_b[i] != string("to_string()") && type_b[j] == string("to_string()")) {
               cout << "___BIN_OP_IF0(" << type_a[i] << "," << type_a[j]
                    << "," << "to_string()" << "," << "data.svalue" << ",a,b,op)";
            }
            else if(type_b[i] == string("to_string()") && type_b[j] != string("to_string()")) {
               cout << "___BIN_OP_IF0(" << type_a[i] << "," << type_a[j]
                    << "," << "data.svalue" << "," << "to_string()" << ",a,b,op)";
            }
            else {
               cout << "___BIN_OP_IF0(" << type_a[i] << "," << type_a[j]  
                    << "," << type_b[i] << "," << type_b[j] << ",a,b,op)";
            }
            if(type_a[i+1] != 0 || type_a[j+1] != 0) {
               cout << "\\" << endl;
            }
            else {
               cout << endl;
            }
         }
      }
}
{
      const char * type_a[] = {
         //"VAR_DATA::CHAR_TYPE",
         //"VAR_DATA::SHORT_TYPE",
         //"VAR_DATA::BOOL_TYPE",
         //"VAR_DATA::INT_TYPE",
         //"VAR_DATA::FLOAT_TYPE",
         "VAR_DATA::LONG_TYPE",
         "VAR_DATA::DOUBLE_TYPE",
         "VAR_DATA::STRING_TYPE",
          0,
      };
      const char * type_b[] = {
         //"data.value.cvalue",
         //"data.value.svalue",
         //"data.value.bvalue",
         //"data.value.ivalue",
         //"data.value.gvalue",
         "data.value.lvalue",
         "data.value.dvalue",
         "to_double()",
         0,
      };
      cout << "#define ___ABIN_OP_IF(a,b,op)\\" << endl;
      for(size_t i = 0; type_a[i] != 0; i++) {
         for(size_t j = 0; type_a[j] != 0; j++) {
            if(i != 0 || j != 0) {
               cout << "else ";
            }
            cout << "___BIN_OP_IF0(" << type_a[i] << "," << type_a[j]
                 << "," << type_b[i] << "," << type_b[j] << ",a,b,op)";
            if(type_a[i+1] != 0 || type_a[j+1] != 0) {
               cout << "\\" << endl;
            }
            else {
               cout << endl;
            }
         }
      }
}
{
      const char * type_a[] = {
         //"VAR_DATA::CHAR_TYPE",
         //"VAR_DATA::SHORT_TYPE",
         //"VAR_DATA::BOOL_TYPE",
         //"VAR_DATA::INT_TYPE",
         //"VAR_DATA::FLOAT_TYPE",
         "VAR_DATA::LONG_TYPE",
         "VAR_DATA::DOUBLE_TYPE",
         "VAR_DATA::STRING_TYPE",
          0,
      };
      const char * type_b[] = {
         //"data.value.cvalue",
         //"data.value.svalue",
         //"data.value.bvalue",
         //"data.value.ivalue",
         //"to_long()",
         "data.value.lvalue",
         "to_long()",
         "to_long()",
         0,
      };
      cout << "#define ___INT_ABIN_OP_IF(a,b,op)\\" << endl;
      for(size_t i = 0; type_a[i] != 0; i++) {
         for(size_t j = 0; type_a[j] != 0; j++) {
            if(i != 0 || j != 0) {
               cout << "else ";
            }
            cout << "___BIN_OP_IF0(" << type_a[i] << "," << type_a[j]
                 << "," << type_b[i] << "," << type_b[j] << ",a,b,op)";
            if(type_a[i+1] != 0 || type_a[j+1] != 0) {
               cout << "\\" << endl;
            }
            else {
               cout << endl;
            }
         }
      }
}

{
      const char * type_a[] = {
         ///"VAR_DATA::CHAR_TYPE",
         //"VAR_DATA::SHORT_TYPE",
         //"VAR_DATA::BOOL_TYPE",
         //"VAR_DATA::INT_TYPE",
         //"VAR_DATA::FLOAT_TYPE",
         "VAR_DATA::LONG_TYPE",
         "VAR_DATA::DOUBLE_TYPE",
         "VAR_DATA::STRING_TYPE",
          0,
      };
      const char * type_b[] = {
         //"data.value.cvalue",
         //"data.value.svalue",
         //"data.value.bvalue",
         //"data.value.ivalue",
         //"data.value.gvalue",
         "data.value.lvalue",
         "data.value.dvalue",
         "data.svalue",
         0,
      };
      cout << "#define ___INT_BIN_OP_IF(a,b,op)\\" << endl;
      for(size_t i = 0; type_a[i] != 0; i++) {
         for(size_t j = 0; type_a[j] != 0; j++) {
            if(i != 0 || j != 0) {
               cout << "else ";
            }
            cout << "___BIN_OP_IF0(" << type_a[i] << "," << type_a[j]
                 << "," << type_b[i] << "," << type_b[j] << ",a,b,op)";
            if(type_a[i+1] != 0 || type_a[j+1] != 0) {
               cout << "\\" << endl;
            }
            else {
               cout << endl;
            }
         }
      }
}

      cout << "#endif /*___VAR_BINOP_H*/" << endl;
   return 0;
}
