1//! Provides a macro to simplify operator overloading.
2//!
3//! To use, include the following:
4//! ```
5//! extern crate overload;
6//! use overload::overload;
7//! use std::ops; // <- don't forget this or you'll get nasty errors
8//! ```
9//!
10//! # Introduction
11//!
12//! Suppose we have the following `struct` definition:
13//! ```
14//! #[derive(PartialEq, Debug)]
15//! struct Val {
16//! v: i32
17//! }
18//! ```
19//! We can overload the addition of `Val`s like so:
20//! ```
21//! # extern crate overload;
22//! # use overload::overload;
23//! # use std::ops;
24//! # #[derive(PartialEq, Debug)]
25//! # struct Val {
26//! # v: i32
27//! # }
28//! overload!((a: Val) + (b: Val) -> Val { Val { v: a.v + b.v } });
29//! ```
30//! The macro call above generates the following code:
31//! ```ignore
32//! impl ops::Add<Val> for Val {
33//! type Output = Val;
34//! fn add(self, b: Val) -> Self::Output {
35//! let a = self;
36//! Val { v: a.v + b.v }
37//! }
38//! }
39//! ```
40//! We are now able to add `Val`s:
41//! ```
42//! # extern crate overload;
43//! # use overload::overload;
44//! # use std::ops;
45//! # #[derive(PartialEq, Debug)]
46//! # struct Val {
47//! # v: i32
48//! # }
49//! # overload!((a: Val) + (b: Val) -> Val { Val { v: a.v + b.v } });
50//! assert_eq!(Val{v:3} + Val{v:5}, Val{v:8});
51//! ```
52//!
53//! # Owned and borrowed types
54//!
55//! If we also wanted to overload addition for the borrowed type `&Val` we could write:
56//! ```
57//! # extern crate overload;
58//! # use overload::overload;
59//! # use std::ops;
60//! # #[derive(PartialEq, Debug)]
61//! # struct Val {
62//! # v: i32
63//! # }
64//! overload!((a: &Val) + (b: &Val) -> Val { Val { v: a.v + b.v } });
65//! ```
66//! We might also want to overload addition between the owned and borrowed types:
67//! ```
68//! # extern crate overload;
69//! # use overload::overload;
70//! # use std::ops;
71//! # #[derive(PartialEq, Debug)]
72//! # struct Val {
73//! # v: i32
74//! # }
75//! overload!((a: Val) + (b: &Val) -> Val { Val { v: a.v + b.v } });
76//! overload!((a: &Val) + (b: Val) -> Val { Val { v: a.v + b.v } });
77//! ```
78//! Let's see how we can write these combinations more concisely.
79//!
80//! We can include a `?` in front of a type to indicate that it should stand in for both the owned and borrowed type.
81//!
82//! To overload addition for all four combinations between `Val` and `&Val` we can therefore simply include a `?` in front of both types:
83//! ```
84//! # extern crate overload;
85//! # use overload::overload;
86//! # use std::ops;
87//! # #[derive(PartialEq, Debug)]
88//! # struct Val {
89//! # v: i32
90//! # }
91//! overload!((a: ?Val) + (b: ?Val) -> Val { Val { v: a.v + b.v } });
92//! ```
93//! The macro call above generates the following code:
94//! ```ignore
95//! impl ops::Add<Val> for Val {
96//! type Output = Val;
97//! fn add(self, b: Val) -> Self::Output {
98//! let a = self;
99//! Val { v: a.v + b.v }
100//! }
101//! }
102//!
103//! impl ops::Add<&Val> for Val {
104//! type Output = Val;
105//! fn add(self, b: &Val) -> Self::Output {
106//! let a = self;
107//! Val { v: a.v + b.v }
108//! }
109//! }
110//!
111//! impl ops::Add<Val> for &Val {
112//! type Output = Val;
113//! fn add(self, b: Val) -> Self::Output {
114//! let a = self;
115//! Val { v: a.v + b.v }
116//! }
117//! }
118//!
119//! impl ops::Add<&Val> for &Val {
120//! type Output = Val;
121//! fn add(self, b: &Val) -> Self::Output {
122//! let a = self;
123//! Val { v: a.v + b.v }
124//! }
125//! }
126//! ```
127//! We are now able to add `Val`s and `&Val`s in any combination:
128//! ```
129//! # extern crate overload;
130//! # use overload::overload;
131//! # use std::ops;
132//! # #[derive(PartialEq, Debug)]
133//! # struct Val {
134//! # v: i32
135//! # }
136//! # overload!((a: ?Val) + (b: ?Val) -> Val { Val { v: a.v + b.v } });
137//! assert_eq!(Val{v:3} + Val{v:5}, Val{v:8});
138//! assert_eq!(Val{v:3} + &Val{v:5}, Val{v:8});
139//! assert_eq!(&Val{v:3} + Val{v:5}, Val{v:8});
140//! assert_eq!(&Val{v:3} + &Val{v:5}, Val{v:8});
141//! ```
142//!
143//! # Binary operators
144//!
145//! The general syntax to overload a binary operator between types `<a_type>` and `<b_type>` is:
146//! ```ignore
147//! overload!((<a_ident>: <a_type>) <op> (<b_ident>: <b_type>) -> <out_type> { /*body*/ });
148//! ```
149//! Inside the body you can use `<a_ident>` and `<b_ident>` freely to perform any computation.
150//!
151//! The last line of the body needs to be an expression (i.e. no `;` at the end of the line) of type `<out_type>`.
152//!
153//! | Operator | Example | Trait |
154//! |----------|-----------------------------------------------------------------|--------|
155//! | + | `overload!((a: A) + (b: B) -> C { /*...*/ );` | Add |
156//! | - | `overload!((a: A) - (b: B) -> C { /*...*/ );` | Sub |
157//! | * | `overload!((a: A) * (b: B) -> C { /*...*/ );` | Mul |
158//! | / | `overload!((a: A) / (b: B) -> C { /*...*/ );` | Div |
159//! | % | `overload!((a: A) % (b: B) -> C { /*...*/ );` | Rem |
160//! | & | `overload!((a: A) & (b: B) -> C { /*...*/ );` | BitAnd |
161//! | \| | <code>overload!((a: A) | (b: B) -> C { /\*...*\/ );</code> | BitOr |
162//! | ^ | `overload!((a: A) ^ (b: B) -> C { /*...*/ );` | BitXor |
163//! | << | `overload!((a: A) << (b: B) -> C { /*...*/ );` | Shl |
164//! | >> | `overload!((a: A) >> (b: B) -> C { /*...*/ );` | Shr |
165//!
166//! # Assignment operators
167//!
168//! The general syntax to overload an assignment operator between types `<a_type>` and `<b_type>` is:
169//! ```ignore
170//! overload!((<a_ident>: &mut <a_type>) <op> (<b_ident>: <b_type>) { /*body*/ });
171//! ```
172//! Inside the body you can use `<a_ident>` and `<b_ident>` freely to perform any computation and mutate `<a_ident>` as desired.
173//!
174//! | Operator | Example | Trait |
175//! |----------|------------------------------------------------------------------|--------------|
176//! | += | `overload!((a: &mut A) += (b: B) { /*...*/ );` | AddAssign |
177//! | -= | `overload!((a: &mut A) -= (b: B) { /*...*/ );` | SubAssign |
178//! | *= | `overload!((a: &mut A) *= (b: B) { /*...*/ );` | MulAssign |
179//! | /= | `overload!((a: &mut A) /= (b: B) { /*...*/ );` | DivAssign |
180//! | %= | `overload!((a: &mut A) %= (b: B) { /*...*/ );` | RemAssign |
181//! | &= | `overload!((a: &mut A) &= (b: B) { /*...*/ );` | BitAndAssign |
182//! | \|= | <code>overload!((a: &mut A) |= (b: B) { /\*...*\/ );</code> | BitOrAssign |
183//! | ^= | `overload!((a: &mut A) ^= (b: B) { /*...*/ );` | BitXorAssign |
184//! | <<= | `overload!((a: &mut A) <<= (b: B) { /*...*/ );` | ShlAssign |
185//! | >>= | `overload!((a: &mut A) >>= (b: B) { /*...*/ );` | ShrAssign |
186//!
187//! # Unary operators
188//!
189//! The general syntax to overload a unary operator for type `<a_type>` is:
190//! ```ignore
191//! overload!(<op> (<a_ident>: <a_type>) -> <out_type> { /*body*/ });
192//! ```
193//! Inside the body you can use `<a_ident>` freely to perform any computation.
194//!
195//! The last line of the body needs to be an expression (i.e. no `;` at the end of the line) of type `<out_type>`.
196//!
197//! | Operator | Example | Trait |
198//! |----------|---------------------------------------------------------|-------|
199//! | - | `overload!(- (a: A) -> B { /*...*/ );` | Neg |
200//! | ! | `overload!(! (a: A) -> B { /*...*/ );` | Not |
201//!
202//! # Notes
203//!
204//! Remember that you can only overload operators between one or more types if at least one of the types is defined in the current crate.
205
206#[macro_use]
207mod unary;
208
209#[macro_use]
210mod assignment;
211
212#[macro_use]
213mod binary;
214
215/// Overloads an operator. See the [module level documentation](index.html) for more information.
216#[macro_export(local_inner_macros)]
217macro_rules! overload {
218 // Unary (both owned and borrowed)
219 ($op:tt ($i:ident : ? $t:ty) -> $out:ty $body:block) => (
220 _overload_unary!($op, $i, $t, $out, $body);
221 _overload_unary!($op, $i, &$t, $out, $body);
222 );
223 // Unary (either owned or borrowed)
224 ($op:tt ($i:ident : $t:ty) -> $out:ty $body:block) => (
225 _overload_unary!($op, $i, $t, $out, $body);
226 );
227 // Assignment (both owned and borrowed)
228 (($li:ident : &mut $lt:ty) $op:tt ($ri:ident : ? $rt:ty) $body:block) => (
229 _overload_assignment!($op, $li, $lt, $ri, $rt, $body);
230 _overload_assignment!($op, $li, $lt, $ri, &$rt, $body);
231 );
232 // Assignment (either owned or borrowed)
233 (($li:ident : &mut $lt:ty) $op:tt ($ri:ident : $rt:ty) $body:block) => (
234 _overload_assignment!($op, $li, $lt, $ri, $rt, $body);
235 );
236 // Binary (both - both)
237 (($li:ident : ? $lt:ty) $op:tt ($ri:ident : ? $rt:ty) -> $out:ty $body:block) => (
238 _overload_binary!($op, $li, $lt, $ri, $rt, $out, $body);
239 _overload_binary!($op, $li, $lt, $ri, &$rt, $out, $body);
240 _overload_binary!($op, $li, &$lt, $ri, $rt, $out, $body);
241 _overload_binary!($op, $li, &$lt, $ri, &$rt, $out, $body);
242 );
243 // Binary (both - either)
244 (($li:ident : ? $lt:ty) $op:tt ($ri:ident : $rt:ty) -> $out:ty $body:block) => (
245 _overload_binary!($op, $li, $lt, $ri, $rt, $out, $body);
246 _overload_binary!($op, $li, &$lt, $ri, $rt, $out, $body);
247 );
248 // Binary (either - both)
249 (($li:ident : $lt:ty) $op:tt ($ri:ident : ? $rt:ty) -> $out:ty $body:block) => (
250 _overload_binary!($op, $li, $lt, $ri, $rt, $out, $body);
251 _overload_binary!($op, $li, $lt, $ri, &$rt, $out, $body);
252 );
253 // Binary (either - either)
254 (($li:ident : $lt:ty) $op:tt ($ri:ident : $rt:ty) -> $out:ty $body:block) => (
255 _overload_binary!($op, $li, $lt, $ri, $rt, $out, $body);
256 );
257}
258