overload/
lib.rs

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) &vert; (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) &vert;= (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}