macros/lib.rs
1//! This module contains some macros for Charon. Due to technical reasons, Rust
2//! forces users to define such macros in a separate, dedicated library. Note
3//! that this doesn't apply to `macro_rules`.
4#![feature(non_exhaustive_omitted_patterns_lint)]
5
6extern crate proc_macro;
7
8use proc_macro::TokenStream;
9use quote::quote;
10
11mod enum_helpers;
12
13use enum_helpers::EnumMethodKind;
14
15#[proc_macro_derive(VariantName)]
16pub fn derive_variant_name(item: TokenStream) -> TokenStream {
17 enum_helpers::derive_variant_name(item.into()).into()
18}
19
20/// Macro to derive a function `fn variant_index_arity(&self) -> (u32, usize)`
21/// the pair (variant index, variant arity).
22/// Only works on enumerations, of course.
23#[proc_macro_derive(VariantIndexArity)]
24pub fn derive_variant_index_arity(item: TokenStream) -> TokenStream {
25 enum_helpers::derive_variant_index_arity(item.into()).into()
26}
27
28/// Macro `EnumIsA`
29///
30/// Derives functions of the form `fn is_{variant_name}(&self) -> bool` returning true
31/// if an enumeration instance is of some variant. For lists, it would generate
32/// `is_cons` and `is_nil`.
33/// Note that there already exists a crate implementing such macros,
34/// [`enum_methods`](https://docs.rs/enum-methods/0.0.8/enum_methods/), but
35/// it doesn't work when the enumeration has generic parameters and it seems
36/// dead (a PR from 2019 has never been merged), so it seems better to maintain
37/// our own code here (which is small) rather than doing PRs for this crate.
38#[proc_macro_derive(EnumIsA)]
39pub fn derive_enum_is_a(item: TokenStream) -> TokenStream {
40 enum_helpers::derive_enum_variant_method(item.into(), EnumMethodKind::EnumIsA).into()
41}
42
43/// Macro `EnumAsGetters`
44///
45/// Derives functions of the form `fn as_{variant_name}(&self) -> ...` checking
46/// that an enumeration instance is of the proper variant and returning shared
47/// borrows to its fields.
48/// Also see the comments for [crate::derive_enum_is_a]
49#[proc_macro_derive(EnumAsGetters)]
50pub fn derive_enum_as_getters(item: TokenStream) -> TokenStream {
51 let by_ref = enum_helpers::derive_enum_variant_method(
52 item.clone().into(),
53 EnumMethodKind::EnumAsGetters,
54 );
55 let by_ref_mut =
56 enum_helpers::derive_enum_variant_method(item.into(), EnumMethodKind::EnumAsMutGetters);
57 quote! {
58 #by_ref #by_ref_mut
59 }
60 .into()
61}
62
63/// Macro `EnumToGetters`
64///
65/// Derives functions of the form `fn to_{variant_name}(self) -> ...` checking
66/// that an enumeration instance is of the proper variant and returning its
67/// fields (while consuming the instance).
68/// Also see the comments for [crate::derive_enum_is_a]
69#[proc_macro_derive(EnumToGetters)]
70pub fn derive_enum_to_getters(item: TokenStream) -> TokenStream {
71 enum_helpers::derive_enum_variant_method(item.into(), EnumMethodKind::EnumToGetters).into()
72}