//! This crate provides salsa's macros and attributes. #![recursion_limit = "256"] #[macro_use] extern crate quote; use proc_macro::TokenStream; mod database_storage; mod parenthesized; mod query_group; /// The decorator that defines a salsa "query group" trait. This is a /// trait that defines everything that a block of queries need to /// execute, as well as defining the queries themselves that are /// exported for others to use. /// /// This macro declares the "prototype" for a group of queries. It will /// expand into a trait and a set of structs, one per query. /// /// For each query, you give the name of the accessor method to invoke /// the query (e.g., `my_query`, below), as well as its parameter /// types and the output type. You also give the name for a query type /// (e.g., `MyQuery`, below) that represents the query, and optionally /// other details, such as its storage. /// /// # Examples /// /// The simplest example is something like this: /// /// ```ignore /// #[salsa::query_group] /// trait TypeckDatabase { /// #[salsa::input] // see below for other legal attributes /// fn my_query(&self, input: u32) -> u64; /// /// /// Queries can have any number of inputs (including zero); if there /// /// is not exactly one input, then the key type will be /// /// a tuple of the input types, so in this case `(u32, f32)`. /// fn other_query(&self, input1: u32, input2: f32) -> u64; /// } /// ``` /// /// Here is a list of legal `salsa::XXX` attributes: /// /// - Storage attributes: control how the query data is stored and set. These /// are described in detail in the section below. /// - `#[salsa::input]` /// - `#[salsa::memoized]` /// - `#[salsa::dependencies]` /// - Query execution: /// - `#[salsa::invoke(path::to::my_fn)]` -- for a non-input, this /// indicates the function to call when a query must be /// recomputed. The default is to call a function in the same /// module with the same name as the query. /// - `#[query_type(MyQueryTypeName)]` specifies the name of the /// dummy struct created for the query. Default is the name of the /// query, in camel case, plus the word "Query" (e.g., /// `MyQueryQuery` and `OtherQueryQuery` in the examples above). /// /// # Storage attributes /// /// Here are the possible storage values for each query. The default /// is `storage memoized`. /// /// ## Input queries /// /// Specifying `storage input` will give you an **input /// query**. Unlike derived queries, whose value is given by a /// function, input queries are explicitly set by doing /// `db.query(QueryType).set(key, value)` (where `QueryType` is the /// `type` specified for the query). Accessing a value that has not /// yet been set will panic. Each time you invoke `set`, we assume the /// value has changed, and so we will potentially re-execute derived /// queries that read (transitively) from this input. /// /// ## Derived queries /// /// Derived queries are specified by a function. /// /// - `#[salsa::memoized]` (the default) -- The result is memoized /// between calls. If the inputs have changed, we will recompute /// the value, but then compare against the old memoized value, /// which can significantly reduce the amount of recomputation /// required in new revisions. This does require that the value /// implements `Eq`. /// - `#[salsa::dependencies]` -- does not cache the value, so it will /// be recomputed every time it is needed. We do track the inputs, however, /// so if they have not changed, then things that rely on this query /// may be known not to have changed. /// /// ## Attribute combinations /// /// Some attributes are mutually exclusive. For example, it is an error to add /// multiple storage specifiers or to annotate a function to `invoke` on an /// `input` query. #[proc_macro_attribute] pub fn query_group(args: TokenStream, input: TokenStream) -> TokenStream { query_group::query_group(args, input) } /// This attribute is placed on your database struct. It takes a list of the /// query groups that your database supports. The format looks like so: /// /// ```rust,ignore /// #[salsa::database(MyQueryGroup1, MyQueryGroup2)] /// struct MyDatabase { /// runtime: salsa::Runtime, // <-- your database will need this field, too /// } /// ``` /// /// Here, the struct `MyDatabase` would support the two query groups /// `MyQueryGroup1` and `MyQueryGroup2`. In addition to the `database` /// attribute, the struct needs to have a `runtime` field (of type /// [`salsa::Runtime`]) and to implement the `salsa::Database` trait. /// /// See [the `hello_world` example][hw] for more details. /// /// [`salsa::Runtime`]: struct.Runtime.html /// [hw]: https://github.com/salsa-rs/salsa/tree/master/examples/hello_world #[proc_macro_attribute] pub fn database(args: TokenStream, input: TokenStream) -> TokenStream { database_storage::database(args, input) }