doperators.swg 7.9 KB

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