#ifndef ___VAR_BINOP_H
#define ___VAR_BINOP_H
#define ___BIN_OP_IF0(type_a,type_b,type_A,type_B,a,b,op)\
if(a.data->type == type_a && b.data->type == type_b) {\
   ret = a.type_A op b.type_B;\
}
#define ___BIN_OP_IF(a,b,op)\
if(a.is_ref()&&b.is_ref()) ret = a.get_value() op b.get_value();\
else if(a.is_ref()&&!b.is_ref()) ret = a.get_value() op b;\
else if(!a.is_ref()&&b.is_ref()) ret = a op b.get_value();\
else ___BIN_OP_IF0(VAR_DATA::LONG_TYPE,VAR_DATA::LONG_TYPE,data->value.lvalue,data->value.lvalue,a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::LONG_TYPE,VAR_DATA::DOUBLE_TYPE,data->value.lvalue,data->value.dvalue->real(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::LONG_TYPE,VAR_DATA::STRING_TYPE,to_string(),data->get_svalue(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::DOUBLE_TYPE,VAR_DATA::LONG_TYPE,data->value.dvalue->real(),data->value.lvalue,a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::DOUBLE_TYPE,VAR_DATA::DOUBLE_TYPE,data->value.dvalue->real(),data->value.dvalue->real(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::DOUBLE_TYPE,VAR_DATA::STRING_TYPE,to_string(),data->get_svalue(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::STRING_TYPE,VAR_DATA::LONG_TYPE,data->get_svalue(),to_string(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::STRING_TYPE,VAR_DATA::DOUBLE_TYPE,data->get_svalue(),to_string(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::STRING_TYPE,VAR_DATA::STRING_TYPE,data->get_svalue(),data->get_svalue(),a,b,op)
#define ___ABIN_OP_IF(a,b,op)\
if(a.is_ref()&&b.is_ref()) ret = a.get_value() op b.get_value();\
else if(a.is_ref()&&!b.is_ref()) ret = a.get_value() op b;\
else if(!a.is_ref()&&b.is_ref()) ret = a op b.get_value();\
else ___BIN_OP_IF0(VAR_DATA::LONG_TYPE,VAR_DATA::LONG_TYPE,data->value.lvalue,data->value.lvalue,a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::LONG_TYPE,VAR_DATA::DOUBLE_TYPE,to_double(),to_double(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::LONG_TYPE,VAR_DATA::STRING_TYPE,to_double(),to_double(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::DOUBLE_TYPE,VAR_DATA::LONG_TYPE,to_double(),to_double(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::DOUBLE_TYPE,VAR_DATA::DOUBLE_TYPE,data->get_dvalue(),data->get_dvalue(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::DOUBLE_TYPE,VAR_DATA::STRING_TYPE,to_double(),to_double(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::STRING_TYPE,VAR_DATA::LONG_TYPE,to_double(),to_double(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::STRING_TYPE,VAR_DATA::DOUBLE_TYPE,to_double(),to_double(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::STRING_TYPE,VAR_DATA::STRING_TYPE,to_double(),to_double(),a,b,op)
#define ___INT_ABIN_OP_IF(a,b,op)\
if(a.is_ref()&&b.is_ref()) ret = a.get_value() op b.get_value();\
else if(a.is_ref()&&!b.is_ref()) ret = a.get_value() op b;\
else if(!a.is_ref()&&b.is_ref()) ret = a op b.get_value();\
else ___BIN_OP_IF0(VAR_DATA::LONG_TYPE,VAR_DATA::LONG_TYPE,data->value.lvalue,data->value.lvalue,a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::LONG_TYPE,VAR_DATA::DOUBLE_TYPE,data->value.lvalue,to_long(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::LONG_TYPE,VAR_DATA::STRING_TYPE,data->value.lvalue,to_long(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::DOUBLE_TYPE,VAR_DATA::LONG_TYPE,to_long(),data->value.lvalue,a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::DOUBLE_TYPE,VAR_DATA::DOUBLE_TYPE,to_long(),to_long(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::DOUBLE_TYPE,VAR_DATA::STRING_TYPE,to_long(),to_long(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::STRING_TYPE,VAR_DATA::LONG_TYPE,to_long(),data->value.lvalue,a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::STRING_TYPE,VAR_DATA::DOUBLE_TYPE,to_long(),to_long(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::STRING_TYPE,VAR_DATA::STRING_TYPE,to_long(),to_long(),a,b,op)
#define ___INT_BIN_OP_IF(a,b,op)\
if(a.is_ref()&&b.is_ref()) ret = a.get_value() op b.get_value();\
else if(a.is_ref()&&!b.is_ref()) ret = a.get_value() op b;\
else if(!a.is_ref()&&b.is_ref()) ret = a op b.get_value();\
else ___BIN_OP_IF0(VAR_DATA::LONG_TYPE,VAR_DATA::LONG_TYPE,data->value.lvalue,data->value.lvalue,a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::LONG_TYPE,VAR_DATA::DOUBLE_TYPE,data->value.lvalue.real(),data->value.dvalue->real().real(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::LONG_TYPE,VAR_DATA::STRING_TYPE,data->value.lvalue.real(),data->get_svalue().real(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::DOUBLE_TYPE,VAR_DATA::LONG_TYPE,data->value.dvalue->real().real(),data->value.lvalue.real(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::DOUBLE_TYPE,VAR_DATA::DOUBLE_TYPE,data->value.dvalue->real(),data->value.dvalue->real(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::DOUBLE_TYPE,VAR_DATA::STRING_TYPE,data->value.dvalue->real().real(),data->get_svalue().real(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::STRING_TYPE,VAR_DATA::LONG_TYPE,data->get_svalue().real(),data->value.lvalue.real(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::STRING_TYPE,VAR_DATA::DOUBLE_TYPE,data->get_svalue().real(),data->value.dvalue->real().real(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::STRING_TYPE,VAR_DATA::STRING_TYPE,data->get_svalue(),data->get_svalue(),a,b,op)
#define ___BBIN_OP_IF(a,b,op)\
if(a.is_ref()&&b.is_ref()) ret = a.get_value() op b.get_value();\
else if(a.is_ref()&&!b.is_ref()) ret = a.get_value() op b;\
else if(!a.is_ref()&&b.is_ref()) ret = a op b.get_value();\
else ___BIN_OP_IF0(VAR_DATA::LONG_TYPE,VAR_DATA::LONG_TYPE,to_bool(),to_bool(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::LONG_TYPE,VAR_DATA::DOUBLE_TYPE,to_bool(),to_bool(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::LONG_TYPE,VAR_DATA::STRING_TYPE,to_bool(),to_bool(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::DOUBLE_TYPE,VAR_DATA::LONG_TYPE,to_bool(),to_bool(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::DOUBLE_TYPE,VAR_DATA::DOUBLE_TYPE,to_bool(),to_bool(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::DOUBLE_TYPE,VAR_DATA::STRING_TYPE,to_bool(),to_bool(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::STRING_TYPE,VAR_DATA::LONG_TYPE,to_bool(),to_bool(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::STRING_TYPE,VAR_DATA::DOUBLE_TYPE,to_bool(),to_bool(),a,b,op)\
else ___BIN_OP_IF0(VAR_DATA::STRING_TYPE,VAR_DATA::STRING_TYPE,to_bool(),to_bool(),a,b,op)
#endif /*___VAR_BINOP_H*/
