moore_derive/
lib.rs

1// Copyright (c) 2016-2021 Fabian Schuiki
2
3//! Procedural macros for the moore compiler.
4
5extern crate proc_macro;
6use proc_macro::TokenStream;
7use quote::quote;
8
9mod accept_visitor;
10mod all_node;
11mod arena;
12mod node;
13mod node_data;
14mod query;
15mod visitor;
16mod walk_visitor;
17
18/// Pick the first lifetime from a `syn::Generics`, or create one.
19///
20/// This either returns the first lifetime in the generics, or adds a new
21/// lifetime.
22fn first_lifetime(gen: &mut syn::Generics) -> syn::Lifetime {
23    // Check if there already is a lifetime that we can use.
24    if let Some(ltdef) = gen.lifetimes().next() {
25        return ltdef.lifetime.clone();
26    }
27
28    // Otherwise generate one.
29    let ltdef: syn::LifetimeDef = syn::parse_str("'a").unwrap();
30    let lt = ltdef.lifetime.clone();
31    gen.params.insert(0, syn::GenericParam::Lifetime(ltdef));
32    lt
33}
34
35/// Generate an `AcceptVisitor` implementation.
36#[proc_macro_derive(AcceptVisitor, attributes(dont_visit))]
37pub fn accept_visitor(input: TokenStream) -> TokenStream {
38    accept_visitor::accept_visitor(input, false)
39}
40
41/// Generate an `AcceptVisitor`, `ForEachNode`, and `ForEachChild` implementation.
42#[proc_macro_derive(AcceptVisitorAndForeach, attributes(dont_visit))]
43pub fn accept_visitor_and_foreach(input: TokenStream) -> TokenStream {
44    accept_visitor::accept_visitor(input, true)
45}
46
47/// Wrap a struct or enum in a `Node`.
48#[proc_macro_attribute]
49pub fn node(args: TokenStream, input: TokenStream) -> TokenStream {
50    node::node(args, input)
51}
52
53/// Generate an `AnyNodeData` implementation.
54#[proc_macro_derive(AnyNodeData, attributes(name, forward, indefinite, definite))]
55pub fn node_data(input: TokenStream) -> TokenStream {
56    node_data::node_data(input)
57}
58
59/// Generate corresponding `*_visit_*` functions in a visitor.
60#[proc_macro_attribute]
61pub fn walk_visitor(args: TokenStream, input: TokenStream) -> TokenStream {
62    walk_visitor::walk_visitor(args, input)
63}
64
65/// Convenience macro to derive `AcceptVisitorAndForeach` and `walk_visitor`.
66#[proc_macro_attribute]
67pub fn visit(_args: TokenStream, input: TokenStream) -> TokenStream {
68    let input = proc_macro2::TokenStream::from(input);
69    TokenStream::from(quote! {
70        #[moore_derive::walk_visitor]
71        #[derive(moore_derive::AcceptVisitorAndForeach)]
72        #input
73    })
74}
75
76/// Convenience macro to derive `AcceptVisitor` and `walk_visitor`.
77#[proc_macro_attribute]
78pub fn visit_without_foreach(_args: TokenStream, input: TokenStream) -> TokenStream {
79    let input = proc_macro2::TokenStream::from(input);
80    TokenStream::from(quote! {
81        #[moore_derive::walk_visitor]
82        #[derive(moore_derive::AcceptVisitor)]
83        #input
84    })
85}
86
87/// Generate a `AllNode` enum.
88#[proc_macro]
89pub fn derive_all_node(input: TokenStream) -> TokenStream {
90    all_node::all_node(input)
91}
92
93/// Mark a node to be included in the `AllNode` enum.
94#[proc_macro_attribute]
95pub fn all_node(args: TokenStream, input: TokenStream) -> TokenStream {
96    all_node::mark_all_node(args, input)
97}
98
99/// Generate a `Visitor` trait.
100#[proc_macro]
101pub fn derive_visitor(input: TokenStream) -> TokenStream {
102    visitor::visitor(input)
103}
104
105/// Mark a function as a compiler query.
106#[proc_macro_attribute]
107pub fn query(args: TokenStream, input: TokenStream) -> TokenStream {
108    query::mark_query(args, input)
109}
110
111/// Generate a compiler query database.
112#[proc_macro]
113pub fn derive_query_db(input: TokenStream) -> TokenStream {
114    query::derive_query_db(input)
115}
116
117/// Generate an arena struct.
118#[proc_macro]
119pub fn derive_arena(input: TokenStream) -> TokenStream {
120    arena::derive_arena(input)
121}
122
123/// Mark an item to be allocatable in an arena.
124#[proc_macro_attribute]
125pub fn arena(args: TokenStream, input: TokenStream) -> TokenStream {
126    arena::mark_arena(args, input)
127}