liter_derive/
lib.rs

1mod database;
2mod sql;
3mod table;
4mod tuple;
5mod value;
6
7use proc_macro::TokenStream;
8
9#[proc_macro_attribute]
10pub fn database(attr: TokenStream, item: TokenStream) -> TokenStream {
11	database::run(attr, item)
12}
13
14#[proc_macro_derive(Table, attributes(key, check, unique))]
15pub fn derive_table(annotated_item: TokenStream) -> TokenStream {
16	table::derive(annotated_item)
17}
18
19#[proc_macro_derive(Value)]
20pub fn derive_value(annotated_item: TokenStream) -> TokenStream {
21	value::derive(annotated_item)
22}
23
24/// Generate trait implementations for heterogeneous tuples
25///
26/// # Syntax
27///
28/// The attribute expects a range literal as an argument, and it can only be applied to a trait `impl` block.
29/// The "range literal" must include start and end bounds, and they have to be integer literals.
30/// Both `..` and `..=` forms are supported.
31///
32/// The trait `impl` block is a regular `impl` block that will be copied for each generated tuple implementation, with two important changes.
33/// Firstly, the required generic type parameters will be declared for each generated `impl` block (starting from `A`, `B`, `C`, then onto `Aa`, `Ab`, `Ac` and so on).
34/// Secondly, each `impl` block has access to the (pseudo-)macros `each!`, `Each!` and `Every!`.
35///
36/// For instance:
37/// ```
38/// use liter_derive::impl_tuple;
39///
40/// trait Thing {}
41/// trait TupleOfThings {}
42///
43/// #[impl_tuple(2..=4)]
44/// impl TupleOfThings for Each!(T) where Every!(T => T: Thing): '_ {}
45/// ```
46///
47///
48/// Generates:
49/// ```
50/// # trait Thing {}
51/// # trait TupleOfThings {}
52/// impl<A, B> TupleOfThings for (A, B)
53/// where
54///     A: Thing,
55///     B: Thing,
56/// {}
57/// impl<A, B, C> TupleOfThings for (A, B, C)
58/// where
59///     A: Thing,
60///     B: Thing,
61///     C: Thing,
62/// {}
63/// impl<A, B, C, D> TupleOfThings for (A, B, C, D)
64/// where
65///     A: Thing,
66///     B: Thing,
67///     C: Thing,
68///     D: Thing,
69/// {}
70/// ```
71///
72///
73/// Inside the `impl` block, any provided item will be copied into the generated blocks, and special accommodation (in the form of macros) is made for `fn`, `const`, and `type` items.
74/// Note that this excludes macro invocations in item position, which are copied over unchanged.
75///
76/// # Macros
77///
78/// The following example implements a trait to turn a reference to a tuple into a tuple of references, i.e. from `&(A, B, C)` to `(&A, &B, &C)`.
79/// Though rather abstract, this can be useful for traits.
80/// In any case, the example shows all three available (pseudo-)macros.
81///
82/// ```
83/// use liter_derive::impl_tuple;
84///
85/// pub trait Tuple<'l> {
86///     type Ref: 'l;
87///     type Mut: 'l;
88///     fn take_ref(&'l self) -> Self::Ref;
89/// }
90///
91/// #[impl_tuple(2..=16)]
92/// impl<'l> Tuple<'l> for Each!(T) where Every!(T => T: 'l): '_ {
93///     type Ref = Each!(T => &'l T);
94///     type Mut = Each!(T => &'l mut T);
95///
96///     /// `&(A, B, C)` → `(&A, &B, &C)`
97///     fn take_ref(&'l self) -> Self::Ref {
98///         each!{ref field => field}
99///     }
100/// }
101/// ```
102///
103/// Only `each!` (lower-case) is a genuine "macro-by-example" macro as evaluated by the compiler proper.
104/// The other two, which I term "pseudo-macros", count as macros syntactically, and they are used like macros, but they are "expanded" by `#[impl_tuple]` rather than the regular macro process.
105/// As a consequence (among other things), they will not be suggested or understood by IDEs.
106/// It's also not possible to nest them, or use them in the arguments to any other macro invocation.
107///
108/// ## `Each!` in Types & Expressions
109///
110/// `Each!` (a pseudo-macro) is made available in two distinct places: primarily, in "type positions", where it "expands" to a tuple type, and secondarily in expressions, where it allows accessing trait constants, for instance.
111///
112/// The simplest form is seen in the "self type" in the example: `impl<'l> Tuple<'l> for Each!(T)`.
113/// `Each!(T)` is a shorthand for `Each!(T => T)`, which is the form used in the `type` item as `type Ref = Each!(T => &'l T);`.
114/// That invocation, inside the `impl` block for the tuple `(A, B)`, would expand to `(&'l A, &'l B)`.
115/// A tuple where, for each of the tuple's types, it replaces every `T` (or whatever identifier comes before the `=>`) with the corresponding type parameter.
116/// Naturally, `Each!(T)` expands to just `(A, B)`.
117///
118/// `Each!` is also available in expressions (i.e. the "actual code" in `fn` item bodies, but also the expressions that define a `const` item).
119/// There, it works almost exactly the same as in type positions (the shorthand without `=>` isn't available), at least textually.
120/// The `T` (or whatever) is replaced in a [`syn::Expr`] instead of a type, yielding a tuple expression, instead of a tuple type.
121/// This allows accessing items (e.g. `const`s) associated with the types.
122///
123/// ## `Every!` in Type Bounds
124///
125/// The pseudo-macro `Every!`, "expands" into a set of type bounds.
126/// Unfortunately, even though this "expands" to both sides of the `:` in the [`syn::PredicateType`], syntactically it only "counts" as the left side.
127/// Because of this, the invocation needs to be be followed by `: '_` (or something similar), like so: `Every!(T => T: Clone): '_`.
128/// The `'_` or whatever else you choose to put there is discarded by the macro, so it only needs to be valid syntactically.
129///
130/// ## `each!` in `fn` Items
131///
132/// Inside `fn` items, the macro `each!` is made available.
133/// It allows operating on *each* of the tuples fields individually, returning the results as a tuple.
134/// ```
135/// macro_rules! each {
136///     ($b:expr) => { ... };
137///     ($i:pat => $b:expr) => { ... };
138///     (@$slf:expr, $i:pat => $b:expr) => { ... }
139/// }
140/// ```
141///
142/// This macro may take 3 forms.  
143/// In the first form, `$b` is simply repeated as many times as the tuple has fields, such that it results in a tuple of the same length (i.e `($b, $b, $b, …, $b)`).  
144/// The second form does this too, but gives `$b` access to a different field of the tuple each time (in order, obviously).
145/// The field can be accessed under the identifier given to `$i`.
146/// It expands to `({let $i = self.0; $b}, {let $i = self.1; $b}, …)`.
147/// Note that `$i` is a pattern `pat` and not just an identifier `ident`, which allows not only destructuring assignments (convenient but could be done in the block `$b` too), but also because it may be necessary to specify the identifier you want to use as `ref thing` when you want to work on the tuple fields by reference.  
148/// The third and final form is exactly like the second, except that it can give access to the fields of a tuple that isn't necessarily `self`, as long as it has the same number of fields (or more, theoretically).
149/// It expands to `({let $i = $slf.0; $b}, {let $i = $slf.1; $b}, …)`.
150///
151/// The `macro_rules!` definition for `each!`, which is different for every generated `impl` block, is injected as the first statement into the body of every `fn` item and also every `const` item that's defined by a block expression (`{…; …; …}`).
152#[proc_macro_attribute]
153pub fn impl_tuple(attr: TokenStream, item: TokenStream) -> TokenStream {
154	tuple::run(attr, item)
155}