Home | History | Annotate | Download | only in d
      1 /* -----------------------------------------------------------------------------
      2  * doperators.swg
      3  *
      4  * Mapping of C++ operator overloading methods to D.
      5  * ----------------------------------------------------------------------------- */
      6 
      7 #if (SWIG_D_VERSION == 1)
      8 
      9 %pragma(d) imdmodulecode=%{
     10 template SwigOperatorDefinitions() {
     11   public override int opEquals(Object o) {
     12     if (auto rhs = cast(typeof(this))o) {
     13       if (swigCPtr == rhs.swigCPtr) return 1;
     14       static if (is(typeof(swigOpEquals(rhs)))) {
     15         return swigOpEquals(rhs) ? 1 : 0;
     16       } else {
     17         return 0;
     18       }
     19     }
     20     return super.opEquals(o);
     21   }
     22 %}
     23 // opEquals is emitted in pure C mode as well to define two proxy classes
     24 // pointing to the same struct as equal.
     25 
     26 #ifdef __cplusplus
     27 %rename(opPos) *::operator+();
     28 %rename(opPos) *::operator+() const;
     29 %rename(opNeg) *::operator-();
     30 %rename(opNeg) *::operator-() const;
     31 %rename(opCom) *::operator~();
     32 %rename(opCom) *::operator~() const;
     33 
     34 %rename(opAdd) *::operator+;
     35 %rename(opAddAssign) *::operator+=;
     36 %rename(opSub) *::operator-;
     37 %rename(opSubAssign) *::operator-=;
     38 %rename(opMul) *::operator*;
     39 %rename(opMulAssign) *::operator*=;
     40 %rename(opDiv) *::operator/;
     41 %rename(opDivAssign) *::operator/=;
     42 %rename(opMod) *::operator%;
     43 %rename(opModAssign) *::operator%=;
     44 %rename(opAnd) *::operator&;
     45 %rename(opAndAssign) *::operator&=;
     46 %rename(opOr) *::operator|;
     47 %rename(opOrAssign) *::operator|=;
     48 %rename(opXor) *::operator^;
     49 %rename(opXorAssign) *::operator^=;
     50 %rename(opShl) *::operator<<;
     51 %rename(opShlAssign) *::operator<<=;
     52 %rename(opShr) *::operator>>;
     53 %rename(opShrAssign) *::operator>>=;
     54 
     55 %rename(opIndex) *::operator[](unsigned) const;
     56 // opIndexAssign is not currently generated, it needs more extensive support
     57 // mechanisms.
     58 
     59 %rename(opCall) *::operator();
     60 
     61 // !a is not overrideable in D1.
     62 %ignoreoperator(LNOT) operator!;
     63 
     64 // opCmp is used in D.
     65 %rename(swigOpEquals) *::operator==;
     66 %rename(swigOpLt) *::operator<;
     67 %rename(swigOpLtEquals) *::operator<=;
     68 %rename(swigOpGt) *::operator>;
     69 %rename(swigOpGtEquals) *::operator>=;
     70 
     71 // a != b is rewritten as !a.opEquals(b) in D.
     72 %ignoreoperator(NOTEQUAL) operator!=;
     73 
     74 // The logic operators are not overrideable in D.
     75 %ignoreoperator(LAND) operator&&;
     76 %ignoreoperator(LOR) operator||;
     77 
     78 // ++/--a is rewritten as a +/-= 1 in D1,so ignore the prefix operators.
     79 %ignoreoperator(PLUSPLUS) *::operator++();
     80 %ignoreoperator(MINUSMINUS) *::operator--();
     81 %rename(swigOpInc) *::operator++(int);
     82 %rename(swigOpDec) *::operator--(int);
     83 
     84 // The C++ assignment operator does not translate well to D where the proxy
     85 // classes have reference semantics.
     86 %ignoreoperator(EQ) operator=;
     87 
     88 %pragma(d) imdmodulecode=%{
     89   public override int opCmp(Object o) {
     90     static if (is(typeof(swigOpLt(typeof(this).init) &&
     91         swigOpEquals(typeof(this).init)))) {
     92       if (auto rhs = cast(typeof(this))o) {
     93         if (swigOpLt(rhs)) {
     94           return -1;
     95         } else if (swigOpEquals(rhs)) {
     96           return 0;
     97         } else {
     98           return 1;
     99         }
    100       }
    101     }
    102     return super.opCmp(o);
    103   }
    104 
    105   public typeof(this) opPostInc(T = int)(T unused = 0) {
    106     static assert(
    107       is(typeof(swigOpInc(int.init))),
    108       "opPostInc called on " ~ typeof(this).stringof ~ ", but no postfix " ~
    109         "increment operator exists in the corresponding C++ class."
    110     );
    111     return swigOpInc(int.init);
    112   }
    113 
    114   public typeof(this) opPostDec(T = int)(T unused = 0) {
    115     static assert(
    116       is(typeof(swigOpDec(int.init))),
    117       "opPostInc called on " ~ typeof(this).stringof ~ ", but no postfix " ~
    118         "decrement operator exists in the corresponding C++ class."
    119     );
    120     return swigOpDec(int.init);
    121   }
    122 %}
    123 #endif
    124 
    125 %pragma(d) imdmodulecode=%{
    126 }
    127 %}
    128 
    129 #else
    130 %pragma(d) imdmodulecode=%{
    131 mixin template SwigOperatorDefinitions() {
    132   public override bool opEquals(Object o) {
    133     if (auto rhs = cast(typeof(this))o) {
    134       if (swigCPtr == rhs.swigCPtr) return true;
    135       static if (is(typeof(swigOpEquals(rhs)))) {
    136         return swigOpEquals(rhs);
    137       } else {
    138         return false;
    139       }
    140     }
    141     return super.opEquals(o);
    142   }
    143 %}
    144 // opEquals is emitted in pure C mode as well to define two proxy classes
    145 // pointing to the same struct as equal.
    146 
    147 #ifdef __cplusplus
    148 %rename(swigOpPos) *::operator+();
    149 %rename(swigOpPos) *::operator+() const;
    150 %rename(swigOpNeg) *::operator-();
    151 %rename(swigOpNeg) *::operator-() const;
    152 %rename(swigOpCom) *::operator~();
    153 %rename(swigOpCom) *::operator~() const;
    154 %rename(swigOpInc) *::operator++();
    155 %rename(swigOpDec) *::operator--();
    156 %ignoreoperator(PLUSPLUS) *::operator++(int);
    157 %ignoreoperator(MINUSMINUS) *::operator--(int);
    158 // The postfix increment/decrement operators are ignored because they are
    159 // rewritten to (auto t = e, ++e, t) in D2. The unary * operator (used for
    160 // pointer dereferencing in C/C++) isn't mapped to opUnary("*") by default,
    161 // despite this would be possible in D2  the difference in member access
    162 // semantics would only lead to confusion in most cases.
    163 
    164 %rename(swigOpAdd) *::operator+;
    165 %rename(swigOpSub) *::operator-;
    166 %rename(swigOpMul) *::operator*;
    167 %rename(swigOpDiv) *::operator/;
    168 %rename(swigOpMod) *::operator%;
    169 %rename(swigOpAnd) *::operator&;
    170 %rename(swigOpOr) *::operator|;
    171 %rename(swigOpXor) *::operator^;
    172 %rename(swigOpShl) *::operator<<;
    173 %rename(swigOpShr) *::operator>>;
    174 
    175 %rename(swigOpAddAssign) *::operator+=;
    176 %rename(swigOpSubAssign) *::operator-=;
    177 %rename(swigOpMulAssign) *::operator*=;
    178 %rename(swigOpDivAssign) *::operator/=;
    179 %rename(swigOpModAssign) *::operator%=;
    180 %rename(swigOpAndAssign) *::operator&=;
    181 %rename(swigOpOrAssign) *::operator|=;
    182 %rename(swigOpXorAssign) *::operator^=;
    183 %rename(swigOpShlAssign) *::operator<<=;
    184 %rename(swigOpShrAssign) *::operator>>=;
    185 
    186 %rename(opIndex) *::operator[];
    187 // opIndexAssign is not currently generated, it needs more extensive support
    188 // mechanisms.
    189 
    190 %rename(opCall) *::operator();
    191 
    192 %rename(swigOpEquals) *::operator==;
    193 %rename(swigOpLt) *::operator<;
    194 %rename(swigOpLtEquals) *::operator<=;
    195 %rename(swigOpGt) *::operator>;
    196 %rename(swigOpGtEquals) *::operator>=;
    197 
    198 // a != b is rewritten as !a.opEquals(b) in D.
    199 %ignoreoperator(NOTEQUAL) operator!=;
    200 
    201 // The logic operators are not overrideable in D.
    202 %ignoreoperator(LAND) operator&&;
    203 %ignoreoperator(LOR) operator||;
    204 
    205 // The C++ assignment operator does not translate well to D where the proxy
    206 // classes have reference semantics.
    207 %ignoreoperator(EQ) operator=;
    208 
    209 %pragma(d) imdmodulecode=%{
    210   public override int opCmp(Object o) {
    211     static if (__traits(compiles, swigOpLt(typeof(this).init) &&
    212         swigOpEquals(typeof(this).init))) {
    213       if (auto rhs = cast(typeof(this))o) {
    214         if (swigOpLt(rhs)) {
    215           return -1;
    216         } else if (swigOpEquals(rhs)) {
    217           return 0;
    218         } else {
    219           return 1;
    220         }
    221       }
    222     }
    223     return super.opCmp(o);
    224   }
    225 
    226   private template swigOpBinary(string operator, string name) {
    227     enum swigOpBinary = `public void opOpAssign(string op, T)(T rhs) if (op == "` ~ operator ~
    228       `" && __traits(compiles, swigOp` ~ name ~ `Assign(rhs))) { swigOp` ~ name ~ `Assign(rhs);}` ~
    229       `public auto opBinary(string op, T)(T rhs) if (op == "` ~ operator ~
    230       `" && __traits(compiles, swigOp` ~ name ~ `(rhs))) { return swigOp` ~ name ~ `(rhs);}`;
    231   }
    232   mixin(swigOpBinary!("+", "Add"));
    233   mixin(swigOpBinary!("-", "Sub"));
    234   mixin(swigOpBinary!("*", "Mul"));
    235   mixin(swigOpBinary!("/", "Div"));
    236   mixin(swigOpBinary!("%", "Mod"));
    237   mixin(swigOpBinary!("&", "And"));
    238   mixin(swigOpBinary!("|", "Or"));
    239   mixin(swigOpBinary!("^", "Xor"));
    240   mixin(swigOpBinary!("<<", "Shl"));
    241   mixin(swigOpBinary!(">>", "Shr"));
    242 
    243   private template swigOpUnary(string operator, string name) {
    244     enum swigOpUnary = `public auto opUnary(string op)() if (op == "` ~ operator ~
    245       `" && __traits(compiles, swigOp` ~ name ~ `())) { return swigOp` ~ name ~ `();}`;
    246   }
    247   mixin(swigOpUnary!("+", "Pos"));
    248   mixin(swigOpUnary!("-", "Neg"));
    249   mixin(swigOpUnary!("~", "Com"));
    250   mixin(swigOpUnary!("++", "Inc"));
    251   mixin(swigOpUnary!("--", "Dec"));
    252 %}
    253 #endif
    254 
    255 %pragma(d) imdmodulecode=%{
    256 }
    257 %}
    258 
    259 #endif
    260