Skip to main content

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