mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-02-03 18:47:53 +00:00
make query_prototype
take trait, rename hello_world to compiler
This commit is contained in:
parent
5472cfdbc8
commit
2ddc8032ee
11 changed files with 111 additions and 21 deletions
62
README.md
62
README.md
|
@ -13,6 +13,68 @@ This system is heavily inspired by adapton, glimmer, and rustc's query
|
|||
system. So credit goes to Eduard-Mihai Burtescu, Matthew Hammer,
|
||||
Yehuda Katz, and Michael Woerister.
|
||||
|
||||
## Key idea
|
||||
|
||||
The key idea of `salsa` is that you define two things:
|
||||
|
||||
- **Inputs**: the base inputs to your system. You can change these
|
||||
whenever you like.
|
||||
- **Queries**: values derived from those inputs. These are defined via
|
||||
"pure functions" (no side effects). The results of queries can be
|
||||
memoized to avoid recomputing them a lot. When you make changes to
|
||||
the inputs, we'll figure out (fairly intelligently) when we can
|
||||
re-use these memoized values and when we have to recompute them.
|
||||
|
||||
## How to use Salsa in three easy steps
|
||||
|
||||
Using salsa is as easy as 1, 2, 3...
|
||||
|
||||
1. Define one or more **query context traits** that contain the inputs
|
||||
and queries you will need. We'll start with one such trait, but
|
||||
later on you can use more than one to break up your system into
|
||||
components (or spread your code across crates).
|
||||
2. **Implement the queries** using the `query_definition!` macro.
|
||||
3. Create the **query context implementation**, which contains a full
|
||||
listing of all the inputs/queries you will be using. The query
|
||||
content implementation will contain the storage for all of the
|
||||
inputs/queries and may also contain anything else that your code
|
||||
needs (e.g., configuration data).
|
||||
|
||||
Let's walk through an example! This is [the `hello_world`
|
||||
example](examples/hello_world) from the repository.
|
||||
|
||||
### Step 1: Define a query context trait
|
||||
|
||||
The "query context" is the central struct that holds all the state for
|
||||
your application. It has the current values of all your inputs, the
|
||||
values of any memoized queries you have executed thus far, and
|
||||
dependency information between them.
|
||||
|
||||
```rust
|
||||
pub trait HelloWorldContext: salsa::QueryContext {
|
||||
salsa::query_prototype! {
|
||||
/// The fundamental **input** to the system: contains a
|
||||
/// complete list of files.
|
||||
fn all_files() for AllFiles;
|
||||
|
||||
/// A **derived value**: filtered list of paths representing
|
||||
/// jpegs.
|
||||
fn jpegs() for Jpegs;
|
||||
|
||||
/// A **derived value**: the size of the biggest image. To
|
||||
/// avoid doing actual image manipulating, we'll use the silly
|
||||
/// metric of the longest file name. =)
|
||||
fn largest() for Largest;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
###
|
||||
|
||||
Let's make a very simple, hello-world sort of example. We'll make two inputs,
|
||||
each of whihc is
|
||||
|
||||
|
||||
## Goals
|
||||
|
||||
It tries to hit a few goals:
|
||||
|
|
|
@ -2,8 +2,8 @@ use crate::compiler;
|
|||
use salsa::{query_definition, query_prototype};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait ClassTableQueryContext: compiler::CompilerQueryContext {
|
||||
query_prototype! {
|
||||
query_prototype! {
|
||||
pub trait ClassTableQueryContext: compiler::CompilerQueryContext {
|
||||
/// Get the fields.
|
||||
fn fields() for Fields;
|
||||
|
46
src/lib.rs
46
src/lib.rs
|
@ -232,16 +232,44 @@ impl DefaultKey for () {
|
|||
#[macro_export]
|
||||
macro_rules! query_prototype {
|
||||
(
|
||||
$(
|
||||
$(#[$attr:meta])*
|
||||
fn $method_name:ident() for $query_type:ty;
|
||||
)*
|
||||
$(#[$attr:meta])* $v:vis trait $name:ident $($t:tt)*
|
||||
) => {
|
||||
$(
|
||||
$(#[$attr])*
|
||||
fn $method_name(&self) -> $crate::QueryTable<'_, Self, $query_type>;
|
||||
)*
|
||||
}
|
||||
$crate::query_prototype! {
|
||||
attr[$(#[$attr])*];
|
||||
headers[$v, $name, ];
|
||||
tokens[$($t)*];
|
||||
}
|
||||
};
|
||||
|
||||
(
|
||||
attr[$($trait_attr:tt)*];
|
||||
headers[$v:vis, $name:ident, $($header:tt)*];
|
||||
tokens[{
|
||||
$(
|
||||
$(#[$method_attr:meta])*
|
||||
fn $method_name:ident() for $query_type:ty;
|
||||
)*
|
||||
}];
|
||||
) => {
|
||||
$($trait_attr)* $v trait $name $($header)* {
|
||||
$(
|
||||
$(#[$method_attr])*
|
||||
fn $method_name(&self) -> $crate::QueryTable<'_, Self, $query_type>;
|
||||
)*
|
||||
}
|
||||
};
|
||||
|
||||
(
|
||||
attr[$($attr:tt)*];
|
||||
headers[$($headers:tt)*];
|
||||
tokens[$token:tt $($tokens:tt)*];
|
||||
) => {
|
||||
$crate::query_prototype! {
|
||||
attr[$($attr)*];
|
||||
headers[$($headers)* $token];
|
||||
tokens[$($tokens)*];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Creates a **Query Definition** type. This defines the input (key)
|
||||
|
|
|
@ -22,8 +22,8 @@ salsa::query_context_storage! {
|
|||
}
|
||||
}
|
||||
|
||||
trait QueryContext: salsa::QueryContext {
|
||||
salsa::query_prototype! {
|
||||
salsa::query_prototype! {
|
||||
trait QueryContext: salsa::QueryContext {
|
||||
// `a` and `b` depend on each other and form a cycle
|
||||
fn memoized_a() for MemoizedA;
|
||||
fn memoized_b() for MemoizedB;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::implementation::{TestContext, TestContextImpl};
|
||||
|
||||
crate trait MemoizedDepInputsContext: TestContext {
|
||||
salsa::query_prototype! {
|
||||
salsa::query_prototype! {
|
||||
crate trait MemoizedDepInputsContext: TestContext {
|
||||
fn dep_memoized2() for Memoized2;
|
||||
fn dep_memoized1() for Memoized1;
|
||||
fn dep_derived1() for Derived1;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::implementation::{TestContext, TestContextImpl};
|
||||
|
||||
crate trait MemoizedInputsContext: TestContext {
|
||||
salsa::query_prototype! {
|
||||
salsa::query_prototype! {
|
||||
crate trait MemoizedInputsContext: TestContext {
|
||||
fn max() for Max;
|
||||
fn input1() for Input1;
|
||||
fn input2() for Input2;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::implementation::{TestContext, TestContextImpl};
|
||||
use salsa::QueryContext;
|
||||
|
||||
crate trait MemoizedVolatileContext: TestContext {
|
||||
salsa::query_prototype! {
|
||||
salsa::query_prototype! {
|
||||
crate trait MemoizedVolatileContext: TestContext {
|
||||
// Queries for testing a "volatile" value wrapped by
|
||||
// memoization.
|
||||
fn memoized2() for Memoized2;
|
||||
|
|
|
@ -2,8 +2,8 @@ crate trait CounterContext: salsa::QueryContext {
|
|||
fn increment(&self) -> usize;
|
||||
}
|
||||
|
||||
crate trait QueryContext: CounterContext {
|
||||
salsa::query_prototype! {
|
||||
salsa::query_prototype! {
|
||||
crate trait QueryContext: CounterContext {
|
||||
fn memoized() for Memoized;
|
||||
fn volatile() for Volatile;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue