moore-derive 0.13.2

Procedural macros for the moore compiler framework.
Documentation
// Copyright (c) 2016-2021 Fabian Schuiki

//! Procedural macros for the moore compiler.

extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;

mod accept_visitor;
mod all_node;
mod arena;
mod node;
mod node_data;
mod query;
mod visitor;
mod walk_visitor;

/// Pick the first lifetime from a `syn::Generics`, or create one.
///
/// This either returns the first lifetime in the generics, or adds a new
/// lifetime.
fn first_lifetime(gen: &mut syn::Generics) -> syn::Lifetime {
    // Check if there already is a lifetime that we can use.
    if let Some(ltdef) = gen.lifetimes().next() {
        return ltdef.lifetime.clone();
    }

    // Otherwise generate one.
    let ltdef: syn::LifetimeDef = syn::parse_str("'a").unwrap();
    let lt = ltdef.lifetime.clone();
    gen.params.insert(0, syn::GenericParam::Lifetime(ltdef));
    lt
}

/// Generate an `AcceptVisitor` implementation.
#[proc_macro_derive(AcceptVisitor, attributes(dont_visit))]
pub fn accept_visitor(input: TokenStream) -> TokenStream {
    accept_visitor::accept_visitor(input, false)
}

/// Generate an `AcceptVisitor`, `ForEachNode`, and `ForEachChild` implementation.
#[proc_macro_derive(AcceptVisitorAndForeach, attributes(dont_visit))]
pub fn accept_visitor_and_foreach(input: TokenStream) -> TokenStream {
    accept_visitor::accept_visitor(input, true)
}

/// Wrap a struct or enum in a `Node`.
#[proc_macro_attribute]
pub fn node(args: TokenStream, input: TokenStream) -> TokenStream {
    node::node(args, input)
}

/// Generate an `AnyNodeData` implementation.
#[proc_macro_derive(AnyNodeData, attributes(name, forward, indefinite, definite))]
pub fn node_data(input: TokenStream) -> TokenStream {
    node_data::node_data(input)
}

/// Generate corresponding `*_visit_*` functions in a visitor.
#[proc_macro_attribute]
pub fn walk_visitor(args: TokenStream, input: TokenStream) -> TokenStream {
    walk_visitor::walk_visitor(args, input)
}

/// Convenience macro to derive `AcceptVisitorAndForeach` and `walk_visitor`.
#[proc_macro_attribute]
pub fn visit(_args: TokenStream, input: TokenStream) -> TokenStream {
    let input = proc_macro2::TokenStream::from(input);
    TokenStream::from(quote! {
        #[moore_derive::walk_visitor]
        #[derive(moore_derive::AcceptVisitorAndForeach)]
        #input
    })
}

/// Convenience macro to derive `AcceptVisitor` and `walk_visitor`.
#[proc_macro_attribute]
pub fn visit_without_foreach(_args: TokenStream, input: TokenStream) -> TokenStream {
    let input = proc_macro2::TokenStream::from(input);
    TokenStream::from(quote! {
        #[moore_derive::walk_visitor]
        #[derive(moore_derive::AcceptVisitor)]
        #input
    })
}

/// Generate a `AllNode` enum.
#[proc_macro]
pub fn derive_all_node(input: TokenStream) -> TokenStream {
    all_node::all_node(input)
}

/// Mark a node to be included in the `AllNode` enum.
#[proc_macro_attribute]
pub fn all_node(args: TokenStream, input: TokenStream) -> TokenStream {
    all_node::mark_all_node(args, input)
}

/// Generate a `Visitor` trait.
#[proc_macro]
pub fn derive_visitor(input: TokenStream) -> TokenStream {
    visitor::visitor(input)
}

/// Mark a function as a compiler query.
#[proc_macro_attribute]
pub fn query(args: TokenStream, input: TokenStream) -> TokenStream {
    query::mark_query(args, input)
}

/// Generate a compiler query database.
#[proc_macro]
pub fn derive_query_db(input: TokenStream) -> TokenStream {
    query::derive_query_db(input)
}

/// Generate an arena struct.
#[proc_macro]
pub fn derive_arena(input: TokenStream) -> TokenStream {
    arena::derive_arena(input)
}

/// Mark an item to be allocatable in an arena.
#[proc_macro_attribute]
pub fn arena(args: TokenStream, input: TokenStream) -> TokenStream {
    arena::mark_arena(args, input)
}