salsa/examples/compiler/compiler.rs
Niko Matsakis fad97eeb6a remove the DB parameter
This had two unexpected consequences, one unfortunate, one "medium":

* All `salsa::Database` must be `'static`. This falls out from
`Q::DynDb` not having access to any lifetimes, but also the defaulting
rules for `dyn QueryGroup` that make it `dyn QueryGroup + 'static`. We
don't really support generic databases anyway yet so this isn't a big
deal, and we can add workarounds later (ideally via GATs).

* It is now statically impossible to invoke `snapshot` from a query,
and so we don't need to test that it panics. This is because the
signature of `snapshot` returns a `Snapshot<Self>` and that is not
accessible to a `dyn QueryGroup` type. Similarly, invoking
`Runtime::snapshot` directly is not possible becaues it is
crate-private. So I removed the test. This seems ok, but eventually I
would like to expose ways for queries to do parallel
execution (matklad and I had talked about a "speculation" primitive
for enabling that).

* This commit is 99% boilerplate I did with search-and-replace. I also
rolled in a few other changes I might have preferred to factor out,
most notably removing the `GetQueryTable` plumbing trait in favor of
free-methods, but it was awkward to factor them out and get all the
generics right (so much simpler in this version).
2020-07-04 14:17:11 +00:00

73 lines
1.9 KiB
Rust

use std::sync::Arc;
use crate::{interner::Interner, values::*};
#[salsa::query_group(CompilerDatabase)]
pub trait Compiler: Interner {
#[salsa::input]
fn input_string(&self) -> Arc<String>;
/// Get the fields.
fn fields(&self, class: Class) -> Arc<Vec<Field>>;
/// Get the list of all classes
fn all_classes(&self) -> Arc<Vec<Class>>;
/// Get the list of all fields
fn all_fields(&self) -> Arc<Vec<Field>>;
}
/// This function parses a dummy language with the following structure:
///
/// Classes are defined one per line, consisting of a comma-separated list of fields.
///
/// Example:
///
/// ```
/// lorem,ipsum
/// dolor,sit,amet,
/// consectetur,adipiscing,elit
/// ```
fn all_classes(db: &dyn Compiler) -> Arc<Vec<Class>> {
let string = db.input_string();
let rows = string.split('\n');
let classes: Vec<_> = rows
.filter(|string| !string.is_empty())
.map(|string| {
let fields = string
.trim()
.split(',')
.filter(|string| !string.is_empty())
.map(|name_str| {
let name = name_str.to_owned();
let field_data = FieldData { name };
db.intern_field(field_data)
})
.collect();
let class_data = ClassData { fields };
db.intern_class(class_data)
})
.collect();
Arc::new(classes)
}
fn fields(db: &dyn Compiler, class: Class) -> Arc<Vec<Field>> {
let class = db.lookup_intern_class(class);
let fields = class.fields.clone();
Arc::new(fields)
}
fn all_fields(db: &dyn Compiler) -> Arc<Vec<Field>> {
Arc::new(
db.all_classes()
.iter()
.cloned()
.flat_map(|class| {
let fields = db.fields(class);
(0..fields.len()).map(move |i| fields[i])
})
.collect(),
)
}