summaryrefslogtreecommitdiff
path: root/Lib/d/doperators.swg
blob: f651c392856c4fc3259b171c7b32dfec947e996d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* -----------------------------------------------------------------------------
 * doperators.swg
 *
 * Mapping of C++ operator overloading methods to D.
 * ----------------------------------------------------------------------------- */

%pragma(d) imdmodulecode=%{
mixin template SwigOperatorDefinitions() {
  public override bool opEquals(Object o) {
    if (auto rhs = cast(typeof(this))o) {
      if (swigCPtr == rhs.swigCPtr) return true;
      static if (is(typeof(swigOpEquals(rhs)))) {
        return swigOpEquals(rhs);
      } else {
        return false; 
      }
    }
    return super.opEquals(o);
  }
%}
// opEquals is emitted in pure C mode as well to define two proxy classes
// pointing to the same struct as equal.

#ifdef __cplusplus
%rename(swigOpPos) *::operator+();
%rename(swigOpPos) *::operator+() const;
%rename(swigOpNeg) *::operator-();
%rename(swigOpNeg) *::operator-() const;
%rename(swigOpCom) *::operator~();
%rename(swigOpCom) *::operator~() const;
%rename(swigOpInc) *::operator++();
%rename(swigOpDec) *::operator--();
%ignoreoperator(PLUSPLUS) *::operator++(int);
%ignoreoperator(MINUSMINUS) *::operator--(int);
// The postfix increment/decrement operators are ignored because they are
// rewritten to (auto t = e, ++e, t) in D2. The unary * operator (used for
// pointer dereferencing in C/C++) isn't mapped to opUnary("*") by default,
// despite this would be possible in D2 – the difference in member access
// semantics would only lead to confusion in most cases.

%rename(swigOpAdd) *::operator+;
%rename(swigOpSub) *::operator-;
%rename(swigOpMul) *::operator*;
%rename(swigOpDiv) *::operator/;
%rename(swigOpMod) *::operator%;
%rename(swigOpAnd) *::operator&;
%rename(swigOpOr) *::operator|;
%rename(swigOpXor) *::operator^;
%rename(swigOpShl) *::operator<<;
%rename(swigOpShr) *::operator>>;

%rename(swigOpAddAssign) *::operator+=;
%rename(swigOpSubAssign) *::operator-=;
%rename(swigOpMulAssign) *::operator*=;
%rename(swigOpDivAssign) *::operator/=;
%rename(swigOpModAssign) *::operator%=;
%rename(swigOpAndAssign) *::operator&=;
%rename(swigOpOrAssign) *::operator|=;
%rename(swigOpXorAssign) *::operator^=;
%rename(swigOpShlAssign) *::operator<<=;
%rename(swigOpShrAssign) *::operator>>=;

%rename(opIndex) *::operator[];
// opIndexAssign is not currently generated, it needs more extensive support
// mechanisms.

%rename(opCall) *::operator();

%rename(swigOpEquals) *::operator==;
%rename(swigOpLt) *::operator<;
%rename(swigOpLtEquals) *::operator<=;
%rename(swigOpGt) *::operator>;
%rename(swigOpGtEquals) *::operator>=;

// a != b is rewritten as !a.opEquals(b) in D.
%ignoreoperator(NOTEQUAL) operator!=;

// The logic operators are not overridable in D.
%ignoreoperator(LAND) operator&&;
%ignoreoperator(LOR) operator||;

// The C++ assignment operator does not translate well to D where the proxy
// classes have reference semantics.
%ignoreoperator(EQ) operator=;

%pragma(d) imdmodulecode=%{  
  public override int opCmp(Object o) {
    static if (__traits(compiles, swigOpLt(typeof(this).init) &&
        swigOpEquals(typeof(this).init))) {
      if (auto rhs = cast(typeof(this))o) {
        if (swigOpLt(rhs)) {
          return -1;
        } else if (swigOpEquals(rhs)) {
          return 0;
        } else {
          return 1;
        }
      }
    }
    return super.opCmp(o);
  }

  private template swigOpBinary(string operator, string name) {
    enum swigOpBinary = `public void opOpAssign(string op, T)(T rhs) if (op == "` ~ operator ~
      `" && __traits(compiles, swigOp` ~ name ~ `Assign(rhs))) { swigOp` ~ name ~ `Assign(rhs);}` ~
      `public auto opBinary(string op, T)(T rhs) if (op == "` ~ operator ~
      `" && __traits(compiles, swigOp` ~ name ~ `(rhs))) { return swigOp` ~ name ~ `(rhs);}`;
  }
  mixin(swigOpBinary!("+", "Add"));
  mixin(swigOpBinary!("-", "Sub"));
  mixin(swigOpBinary!("*", "Mul"));
  mixin(swigOpBinary!("/", "Div"));
  mixin(swigOpBinary!("%", "Mod"));
  mixin(swigOpBinary!("&", "And"));
  mixin(swigOpBinary!("|", "Or"));
  mixin(swigOpBinary!("^", "Xor"));
  mixin(swigOpBinary!("<<", "Shl"));
  mixin(swigOpBinary!(">>", "Shr"));
  
  private template swigOpUnary(string operator, string name) {
    enum swigOpUnary = `public auto opUnary(string op)() if (op == "` ~ operator ~
      `" && __traits(compiles, swigOp` ~ name ~ `())) { return swigOp` ~ name ~ `();}`;   
  }
  mixin(swigOpUnary!("+", "Pos"));
  mixin(swigOpUnary!("-", "Neg"));
  mixin(swigOpUnary!("~", "Com"));
  mixin(swigOpUnary!("++", "Inc"));
  mixin(swigOpUnary!("--", "Dec"));
%}
#endif

%pragma(d) imdmodulecode=%{
}
%}