mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-23 05:07:27 +00:00
wip
This commit is contained in:
parent
4e295f2257
commit
daba89c278
7 changed files with 150 additions and 450 deletions
|
@ -21,8 +21,3 @@ mod setup_input_struct;
|
||||||
mod setup_interned_struct;
|
mod setup_interned_struct;
|
||||||
mod setup_tracked_struct;
|
mod setup_tracked_struct;
|
||||||
mod unexpected_cycle_recovery;
|
mod unexpected_cycle_recovery;
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! setup_fn {
|
|
||||||
() => {};
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,4 +6,12 @@ macro_rules! macro_if {
|
||||||
|
|
||||||
(false => $($t:tt)*) => {
|
(false => $($t:tt)*) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
(if true { $($t:tt)* } else { $($f:tt)*}) => {
|
||||||
|
$($t)*
|
||||||
|
};
|
||||||
|
|
||||||
|
(if false { $($t:tt)* } else { $($f:tt)*}) => {
|
||||||
|
$($f)*
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,315 +1,6 @@
|
||||||
/// Macro for setting up a function with no arguments (but the database).
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! setup_constant_fn {
|
|
||||||
(
|
|
||||||
// Attributes on the function
|
|
||||||
attrs: [$(#[$attr:meta]),*],
|
|
||||||
|
|
||||||
// Visibility of the function
|
|
||||||
vis: $vis:vis,
|
|
||||||
|
|
||||||
// Name of the function
|
|
||||||
fn_name: $fn_name:ident,
|
|
||||||
|
|
||||||
// Name of the `'db` lifetime that the user gave; if they didn't, then defaults to `'db`
|
|
||||||
db_lt: $db_lt:lifetime,
|
|
||||||
|
|
||||||
// Path to the database trait that the user's database parameter used
|
|
||||||
Db: $Db:path,
|
|
||||||
|
|
||||||
// Name of the database parameter given by the user.
|
|
||||||
db: $db:ident,
|
|
||||||
|
|
||||||
// Return type of the function (may reference `$generics`).
|
|
||||||
output_ty: $output_ty:ty,
|
|
||||||
|
|
||||||
// Function body, may reference identifiers defined in `$input_pats` and the generics from `$generics`
|
|
||||||
inner_fn: $inner_fn:item,
|
|
||||||
|
|
||||||
// Path to the cycle recovery function to use.
|
|
||||||
cycle_recovery_fn: ($($cycle_recovery_fn:tt)*),
|
|
||||||
|
|
||||||
// Name of cycle recovery strategy variant to use.
|
|
||||||
cycle_recovery_strategy: $cycle_recovery_strategy:ident,
|
|
||||||
|
|
||||||
// Annoyingly macro-rules hygiene does not extend to items defined in the macro.
|
|
||||||
// We have the procedural macro generate names for those items that are
|
|
||||||
// not used elsewhere in the user's code.
|
|
||||||
unused_names: [
|
|
||||||
$zalsa:ident,
|
|
||||||
$Configuration:ident,
|
|
||||||
$FN_CACHE:ident,
|
|
||||||
$inner:ident,
|
|
||||||
]
|
|
||||||
) => {
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
$vis struct $fn_name {
|
|
||||||
_priv: std::convert::Infallible,
|
|
||||||
}
|
|
||||||
|
|
||||||
$(#[$attr])*
|
|
||||||
$vis fn $fn_name<$db_lt>(
|
|
||||||
$db: &$db_lt dyn $Db,
|
|
||||||
) -> $output_ty {
|
|
||||||
use salsa::plumbing as $zalsa;
|
|
||||||
|
|
||||||
struct $Configuration;
|
|
||||||
|
|
||||||
static $FN_CACHE: $zalsa::IngredientCache<$zalsa::function::IngredientImpl<$Configuration>> =
|
|
||||||
$zalsa::IngredientCache::new();
|
|
||||||
|
|
||||||
impl $Configuration {
|
|
||||||
fn fn_ingredient(db: &dyn $Db) -> &$zalsa::function::IngredientImpl<$Configuration> {
|
|
||||||
$FN_CACHE.get_or_create(db.as_salsa_database(), || {
|
|
||||||
<dyn $Db as $Db>::zalsa_db(db);
|
|
||||||
db.add_or_lookup_jar_by_type(&$Configuration)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $zalsa::function::Configuration for $Configuration {
|
|
||||||
const DEBUG_NAME: &'static str = stringify!($fn_name);
|
|
||||||
|
|
||||||
type DbView = dyn $Db;
|
|
||||||
|
|
||||||
type SalsaStruct<$db_lt> = $zalsa::Singleton;
|
|
||||||
|
|
||||||
type Input<$db_lt> = ();
|
|
||||||
|
|
||||||
type Output<$db_lt> = $output_ty;
|
|
||||||
|
|
||||||
const CYCLE_STRATEGY: $zalsa::CycleRecoveryStrategy = $zalsa::CycleRecoveryStrategy::$cycle_recovery_strategy;
|
|
||||||
|
|
||||||
fn should_backdate_value(
|
|
||||||
old_value: &Self::Output<'_>,
|
|
||||||
new_value: &Self::Output<'_>,
|
|
||||||
) -> bool {
|
|
||||||
$zalsa::should_backdate_value(old_value, new_value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn execute<'db>($db: &'db Self::DbView, (): ()) -> Self::Output<'db> {
|
|
||||||
$inner_fn
|
|
||||||
|
|
||||||
$inner($db)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recover_from_cycle<'db>(
|
|
||||||
db: &$db_lt dyn $Db,
|
|
||||||
cycle: &$zalsa::Cycle,
|
|
||||||
(): (),
|
|
||||||
) -> Self::Output<'db> {
|
|
||||||
$($cycle_recovery_fn)*(
|
|
||||||
db,
|
|
||||||
cycle,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn id_to_input<'db>(db: &'db Self::DbView, key: salsa::Id) -> Self::Input<'db> {
|
|
||||||
()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $zalsa::Jar for $Configuration {
|
|
||||||
fn create_ingredients(
|
|
||||||
&self,
|
|
||||||
first_index: $zalsa::IngredientIndex,
|
|
||||||
) -> Vec<Box<dyn $zalsa::Ingredient>> {
|
|
||||||
vec![
|
|
||||||
Box::new(<$zalsa::function::IngredientImpl<$Configuration>>::new(
|
|
||||||
first_index,
|
|
||||||
)),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $fn_name {
|
|
||||||
pub fn accumulated<$db_lt, A: salsa::Accumulator>(
|
|
||||||
$db: &$db_lt dyn $Db,
|
|
||||||
) -> Vec<A> {
|
|
||||||
use salsa::plumbing as $zalsa;
|
|
||||||
let key = $zalsa::AsId::as_id(&$zalsa::Singleton);
|
|
||||||
let database_key_index = $Configuration::fn_ingredient($db).database_key_index(key);
|
|
||||||
$zalsa::accumulated_by($db.as_salsa_database(), database_key_index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$zalsa::attach_database($db, || {
|
|
||||||
$Configuration::fn_ingredient($db).fetch($db, $zalsa::AsId::as_id(&$zalsa::Singleton)).clone()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Macro for setting up a function that must intern its arguments.
|
/// Macro for setting up a function that must intern its arguments.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! setup_struct_fn {
|
macro_rules! setup_fn {
|
||||||
(
|
|
||||||
// Attributes on the function
|
|
||||||
attrs: [$(#[$attr:meta]),*],
|
|
||||||
|
|
||||||
// Visibility of the function
|
|
||||||
vis: $vis:vis,
|
|
||||||
|
|
||||||
// Name of the function
|
|
||||||
fn_name: $fn_name:ident,
|
|
||||||
|
|
||||||
// Name of the `'db` lifetime that the user gave; if they didn't, then defaults to `'db`
|
|
||||||
db_lt: $db_lt:lifetime,
|
|
||||||
|
|
||||||
// Path to the database trait that the user's database parameter used
|
|
||||||
Db: $Db:path,
|
|
||||||
|
|
||||||
// Name of the database parameter given by the user.
|
|
||||||
db: $db:ident,
|
|
||||||
|
|
||||||
// An identifier for each function argument EXCEPT the database.
|
|
||||||
// We prefer to use the identifier the user gave, but if the user gave a pattern
|
|
||||||
// (e.g., `(a, b): (u32, u32)`) we will synthesize an identifier.
|
|
||||||
input_id: $input_id:ident,
|
|
||||||
|
|
||||||
// Types of the function arguments (may reference `$generics`).
|
|
||||||
input_ty: $input_ty:ty,
|
|
||||||
|
|
||||||
// Return type of the function (may reference `$generics`).
|
|
||||||
output_ty: $output_ty:ty,
|
|
||||||
|
|
||||||
// Function body, may reference identifiers defined in `$input_pats` and the generics from `$generics`
|
|
||||||
inner_fn: $inner_fn:item,
|
|
||||||
|
|
||||||
// Path to the cycle recovery function to use.
|
|
||||||
cycle_recovery_fn: ($($cycle_recovery_fn:tt)*),
|
|
||||||
|
|
||||||
// Name of cycle recovery strategy variant to use.
|
|
||||||
cycle_recovery_strategy: $cycle_recovery_strategy:ident,
|
|
||||||
|
|
||||||
// If true, this is specifiable.
|
|
||||||
is_specifiable: $is_specifiable:tt,
|
|
||||||
|
|
||||||
// Annoyingly macro-rules hygiene does not extend to items defined in the macro.
|
|
||||||
// We have the procedural macro generate names for those items that are
|
|
||||||
// not used elsewhere in the user's code.
|
|
||||||
unused_names: [
|
|
||||||
$zalsa:ident,
|
|
||||||
$Configuration:ident,
|
|
||||||
$FN_CACHE:ident,
|
|
||||||
$inner:ident,
|
|
||||||
]
|
|
||||||
) => {
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
$vis struct $fn_name {
|
|
||||||
_priv: std::convert::Infallible,
|
|
||||||
}
|
|
||||||
|
|
||||||
$(#[$attr])*
|
|
||||||
$vis fn $fn_name<$db_lt>(
|
|
||||||
$db: &$db_lt dyn $Db,
|
|
||||||
$input_id: $input_ty,
|
|
||||||
) -> $output_ty {
|
|
||||||
use salsa::plumbing as $zalsa;
|
|
||||||
|
|
||||||
struct $Configuration;
|
|
||||||
|
|
||||||
static $FN_CACHE: $zalsa::IngredientCache<$zalsa::function::IngredientImpl<$Configuration>> =
|
|
||||||
$zalsa::IngredientCache::new();
|
|
||||||
|
|
||||||
impl $Configuration {
|
|
||||||
fn fn_ingredient(db: &dyn $Db) -> &$zalsa::function::IngredientImpl<$Configuration> {
|
|
||||||
$FN_CACHE.get_or_create(db.as_salsa_database(), || {
|
|
||||||
<dyn $Db as $Db>::zalsa_db(db);
|
|
||||||
db.add_or_lookup_jar_by_type(&$Configuration)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $zalsa::function::Configuration for $Configuration {
|
|
||||||
const DEBUG_NAME: &'static str = stringify!($fn_name);
|
|
||||||
|
|
||||||
type DbView = dyn $Db;
|
|
||||||
|
|
||||||
type SalsaStruct<$db_lt> = $input_ty;
|
|
||||||
|
|
||||||
type Input<$db_lt> = $input_ty;
|
|
||||||
|
|
||||||
type Output<$db_lt> = $output_ty;
|
|
||||||
|
|
||||||
const CYCLE_STRATEGY: $zalsa::CycleRecoveryStrategy = $zalsa::CycleRecoveryStrategy::$cycle_recovery_strategy;
|
|
||||||
|
|
||||||
fn should_backdate_value(
|
|
||||||
old_value: &Self::Output<'_>,
|
|
||||||
new_value: &Self::Output<'_>,
|
|
||||||
) -> bool {
|
|
||||||
$zalsa::should_backdate_value(old_value, new_value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn execute<'db>($db: &'db Self::DbView, $input_id: $input_ty) -> Self::Output<'db> {
|
|
||||||
$inner_fn
|
|
||||||
|
|
||||||
$inner($db, $input_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recover_from_cycle<'db>(
|
|
||||||
db: &$db_lt dyn $Db,
|
|
||||||
cycle: &$zalsa::Cycle,
|
|
||||||
$input_id: $input_ty,
|
|
||||||
) -> Self::Output<'db> {
|
|
||||||
$($cycle_recovery_fn)*(db, cycle, $input_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn id_to_input<'db>(db: &'db Self::DbView, key: salsa::Id) -> Self::Input<'db> {
|
|
||||||
$zalsa::LookupId::lookup_id(key, db.as_salsa_database())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $zalsa::Jar for $Configuration {
|
|
||||||
fn create_ingredients(
|
|
||||||
&self,
|
|
||||||
first_index: $zalsa::IngredientIndex,
|
|
||||||
) -> Vec<Box<dyn $zalsa::Ingredient>> {
|
|
||||||
vec![
|
|
||||||
Box::new(<$zalsa::function::IngredientImpl<$Configuration>>::new(
|
|
||||||
first_index,
|
|
||||||
)),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $fn_name {
|
|
||||||
pub fn accumulated<$db_lt, A: salsa::Accumulator>(
|
|
||||||
$db: &$db_lt dyn $Db,
|
|
||||||
$input_id: $input_ty,
|
|
||||||
) -> Vec<A> {
|
|
||||||
use salsa::plumbing as $zalsa;
|
|
||||||
let key = $zalsa::AsId::as_id(&$input_id);
|
|
||||||
let database_key_index = $Configuration::fn_ingredient($db).database_key_index(key);
|
|
||||||
$zalsa::accumulated_by($db.as_salsa_database(), database_key_index)
|
|
||||||
}
|
|
||||||
|
|
||||||
$zalsa::macro_if! { $is_specifiable =>
|
|
||||||
pub fn specify<$db_lt>(
|
|
||||||
$db: &$db_lt dyn $Db,
|
|
||||||
$input_id: $input_ty,
|
|
||||||
value: $output_ty,
|
|
||||||
) {
|
|
||||||
let key = $zalsa::AsId::as_id(&$input_id);
|
|
||||||
$Configuration::fn_ingredient($db).specify_and_record(
|
|
||||||
$db,
|
|
||||||
key,
|
|
||||||
value,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$zalsa::attach_database($db, || {
|
|
||||||
$Configuration::fn_ingredient($db).fetch($db, $zalsa::AsId::as_id(&$input_id)).clone()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Macro for setting up a function that must intern its arguments.
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! setup_interned_fn {
|
|
||||||
(
|
(
|
||||||
// Attributes on the function
|
// Attributes on the function
|
||||||
attrs: [$(#[$attr:meta]),*],
|
attrs: [$(#[$attr:meta]),*],
|
||||||
|
@ -349,6 +40,12 @@ macro_rules! setup_interned_fn {
|
||||||
// Name of cycle recovery strategy variant to use.
|
// Name of cycle recovery strategy variant to use.
|
||||||
cycle_recovery_strategy: $cycle_recovery_strategy:ident,
|
cycle_recovery_strategy: $cycle_recovery_strategy:ident,
|
||||||
|
|
||||||
|
// If true, this is specifiable.
|
||||||
|
is_specifiable: $is_specifiable:tt,
|
||||||
|
|
||||||
|
// If true, the input needs an interner (because it has >1 argument).
|
||||||
|
needs_interner: $needs_interner:tt,
|
||||||
|
|
||||||
// Annoyingly macro-rules hygiene does not extend to items defined in the macro.
|
// Annoyingly macro-rules hygiene does not extend to items defined in the macro.
|
||||||
// We have the procedural macro generate names for those items that are
|
// We have the procedural macro generate names for those items that are
|
||||||
// not used elsewhere in the user's code.
|
// not used elsewhere in the user's code.
|
||||||
|
@ -375,17 +72,45 @@ macro_rules! setup_interned_fn {
|
||||||
|
|
||||||
struct $Configuration;
|
struct $Configuration;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
struct $InternedData<$db_lt>(
|
|
||||||
std::ptr::NonNull<$zalsa::interned::Value<$Configuration>>,
|
|
||||||
std::marker::PhantomData<&'db $zalsa::interned::Value<$Configuration>>,
|
|
||||||
);
|
|
||||||
|
|
||||||
static $FN_CACHE: $zalsa::IngredientCache<$zalsa::function::IngredientImpl<$Configuration>> =
|
static $FN_CACHE: $zalsa::IngredientCache<$zalsa::function::IngredientImpl<$Configuration>> =
|
||||||
$zalsa::IngredientCache::new();
|
$zalsa::IngredientCache::new();
|
||||||
|
|
||||||
static $INTERN_CACHE: $zalsa::IngredientCache<$zalsa::interned::IngredientImpl<$Configuration>> =
|
$zalsa::macro_if! {
|
||||||
$zalsa::IngredientCache::new();
|
if $needs_interner {
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
struct $InternedData<$db_lt>(
|
||||||
|
std::ptr::NonNull<$zalsa::interned::Value<$Configuration>>,
|
||||||
|
std::marker::PhantomData<&'db $zalsa::interned::Value<$Configuration>>,
|
||||||
|
);
|
||||||
|
|
||||||
|
static $INTERN_CACHE: $zalsa::IngredientCache<$zalsa::interned::IngredientImpl<$Configuration>> =
|
||||||
|
$zalsa::IngredientCache::new();
|
||||||
|
|
||||||
|
impl $zalsa::SalsaStructInDb for $InternedData<'_> {
|
||||||
|
fn register_dependent_fn(_db: &dyn $zalsa::Database, _index: $zalsa::IngredientIndex) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $zalsa::interned::Configuration for $Configuration {
|
||||||
|
const DEBUG_NAME: &'static str = "Configuration";
|
||||||
|
|
||||||
|
type Data<$db_lt> = ($($input_ty),*);
|
||||||
|
|
||||||
|
type Struct<$db_lt> = $InternedData<$db_lt>;
|
||||||
|
|
||||||
|
unsafe fn struct_from_raw<'db>(
|
||||||
|
ptr: std::ptr::NonNull<$zalsa::interned::Value<Self>>,
|
||||||
|
) -> Self::Struct<'db> {
|
||||||
|
$InternedData(ptr, std::marker::PhantomData)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deref_struct(s: Self::Struct<'_>) -> &$zalsa::interned::Value<Self> {
|
||||||
|
unsafe { s.0.as_ref() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
type $InternedData<$db_lt> = ($($input_ty),*);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl $Configuration {
|
impl $Configuration {
|
||||||
fn fn_ingredient(db: &dyn $Db) -> &$zalsa::function::IngredientImpl<$Configuration> {
|
fn fn_ingredient(db: &dyn $Db) -> &$zalsa::function::IngredientImpl<$Configuration> {
|
||||||
|
@ -395,19 +120,17 @@ macro_rules! setup_interned_fn {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn intern_ingredient(
|
$zalsa::macro_if! { $needs_interner =>
|
||||||
db: &dyn $Db,
|
fn intern_ingredient(
|
||||||
) -> &$zalsa::interned::IngredientImpl<$Configuration> {
|
db: &dyn $Db,
|
||||||
$INTERN_CACHE.get_or_create(db.as_salsa_database(), || {
|
) -> &$zalsa::interned::IngredientImpl<$Configuration> {
|
||||||
db.add_or_lookup_jar_by_type(&$Configuration).successor(0)
|
$INTERN_CACHE.get_or_create(db.as_salsa_database(), || {
|
||||||
})
|
db.add_or_lookup_jar_by_type(&$Configuration).successor(0)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $zalsa::SalsaStructInDb for $InternedData<'_> {
|
|
||||||
fn register_dependent_fn(_db: &dyn $zalsa::Database, _index: $zalsa::IngredientIndex) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $zalsa::function::Configuration for $Configuration {
|
impl $zalsa::function::Configuration for $Configuration {
|
||||||
const DEBUG_NAME: &'static str = stringify!($fn_name);
|
const DEBUG_NAME: &'static str = stringify!($fn_name);
|
||||||
|
|
||||||
|
@ -443,25 +166,13 @@ macro_rules! setup_interned_fn {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn id_to_input<'db>(db: &'db Self::DbView, key: salsa::Id) -> Self::Input<'db> {
|
fn id_to_input<'db>(db: &'db Self::DbView, key: salsa::Id) -> Self::Input<'db> {
|
||||||
$Configuration::intern_ingredient(db).data(key).clone()
|
$zalsa::macro_if! {
|
||||||
}
|
if $needs_interner {
|
||||||
}
|
$Configuration::intern_ingredient(db).data(key).clone()
|
||||||
|
} else {
|
||||||
impl $zalsa::interned::Configuration for $Configuration {
|
$zalsa::LookupId::lookup_id(key, db.as_salsa_database())
|
||||||
const DEBUG_NAME: &'static str = "Configuration";
|
}
|
||||||
|
}
|
||||||
type Data<$db_lt> = ($($input_ty),*);
|
|
||||||
|
|
||||||
type Struct<$db_lt> = $InternedData<$db_lt>;
|
|
||||||
|
|
||||||
unsafe fn struct_from_raw<'db>(
|
|
||||||
ptr: std::ptr::NonNull<$zalsa::interned::Value<Self>>,
|
|
||||||
) -> Self::Struct<'db> {
|
|
||||||
$InternedData(ptr, std::marker::PhantomData)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deref_struct(s: Self::Struct<'_>) -> &$zalsa::interned::Value<Self> {
|
|
||||||
unsafe { s.0.as_ref() }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,14 +181,24 @@ macro_rules! setup_interned_fn {
|
||||||
&self,
|
&self,
|
||||||
first_index: $zalsa::IngredientIndex,
|
first_index: $zalsa::IngredientIndex,
|
||||||
) -> Vec<Box<dyn $zalsa::Ingredient>> {
|
) -> Vec<Box<dyn $zalsa::Ingredient>> {
|
||||||
vec![
|
$zalsa::macro_if! {
|
||||||
Box::new(<$zalsa::function::IngredientImpl<$Configuration>>::new(
|
if $needs_interner {
|
||||||
first_index,
|
vec![
|
||||||
)),
|
Box::new(<$zalsa::function::IngredientImpl<$Configuration>>::new(
|
||||||
Box::new(<$zalsa::interned::IngredientImpl<$Configuration>>::new(
|
first_index,
|
||||||
first_index.successor(0)
|
)),
|
||||||
)),
|
Box::new(<$zalsa::interned::IngredientImpl<$Configuration>>::new(
|
||||||
]
|
first_index.successor(0)
|
||||||
|
)),
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
vec![
|
||||||
|
Box::new(<$zalsa::function::IngredientImpl<$Configuration>>::new(
|
||||||
|
first_index,
|
||||||
|
)),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,15 +208,42 @@ macro_rules! setup_interned_fn {
|
||||||
$($input_id: $input_ty,)*
|
$($input_id: $input_ty,)*
|
||||||
) -> Vec<A> {
|
) -> Vec<A> {
|
||||||
use salsa::plumbing as $zalsa;
|
use salsa::plumbing as $zalsa;
|
||||||
let key = $Configuration::intern_ingredient($db).intern_id($db.runtime(), ($($input_id),*));
|
let key = $zalsa::macro_if! {
|
||||||
|
if $needs_interner {
|
||||||
|
$Configuration::intern_ingredient($db).intern_id($db.runtime(), ($($input_id),*))
|
||||||
|
} else {
|
||||||
|
$zalsa::AsId::as_id(&($($input_id),*))
|
||||||
|
}
|
||||||
|
};
|
||||||
let database_key_index = $Configuration::fn_ingredient($db).database_key_index(key);
|
let database_key_index = $Configuration::fn_ingredient($db).database_key_index(key);
|
||||||
$zalsa::accumulated_by($db.as_salsa_database(), database_key_index)
|
$zalsa::accumulated_by($db.as_salsa_database(), database_key_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$zalsa::macro_if! { $is_specifiable =>
|
||||||
|
pub fn specify<$db_lt>(
|
||||||
|
$db: &$db_lt dyn $Db,
|
||||||
|
$($input_id: $input_ty,)*
|
||||||
|
value: $output_ty,
|
||||||
|
) {
|
||||||
|
let key = $zalsa::AsId::as_id(&($($input_id),*));
|
||||||
|
$Configuration::fn_ingredient($db).specify_and_record(
|
||||||
|
$db,
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$zalsa::attach_database($db, || {
|
$zalsa::attach_database($db, || {
|
||||||
let key = $Configuration::intern_ingredient($db).intern_id($db.runtime(), ($($input_id),*));
|
$zalsa::macro_if! {
|
||||||
$Configuration::fn_ingredient($db).fetch($db, key).clone()
|
if $needs_interner {
|
||||||
|
let key = $Configuration::intern_ingredient($db).intern_id($db.runtime(), ($($input_id),*));
|
||||||
|
$Configuration::fn_ingredient($db).fetch($db, key).clone()
|
||||||
|
} else {
|
||||||
|
$Configuration::fn_ingredient($db).fetch($db, $zalsa::AsId::as_id(&($($input_id),*))).clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -93,78 +93,38 @@ impl Macro {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match function_type {
|
let needs_interner = match function_type {
|
||||||
FunctionType::Constant => Ok(crate::debug::dump_tokens(
|
FunctionType::RequiresInterning => true,
|
||||||
fn_name,
|
FunctionType::Constant | FunctionType::SalsaStruct => false,
|
||||||
quote![salsa::plumbing::setup_constant_fn! {
|
};
|
||||||
attrs: [#(#attrs),*],
|
|
||||||
vis: #vis,
|
Ok(crate::debug::dump_tokens(
|
||||||
fn_name: #fn_name,
|
fn_name,
|
||||||
db_lt: #db_lt,
|
quote![salsa::plumbing::setup_fn! {
|
||||||
Db: #db_path,
|
attrs: [#(#attrs),*],
|
||||||
db: #db_ident,
|
vis: #vis,
|
||||||
output_ty: #output_ty,
|
fn_name: #fn_name,
|
||||||
inner_fn: #inner_fn,
|
db_lt: #db_lt,
|
||||||
cycle_recovery_fn: #cycle_recovery_fn,
|
Db: #db_path,
|
||||||
cycle_recovery_strategy: #cycle_recovery_strategy,
|
db: #db_ident,
|
||||||
unused_names: [
|
input_ids: [#(#input_ids),*],
|
||||||
#zalsa,
|
input_tys: [#(#input_tys),*],
|
||||||
#Configuration,
|
output_ty: #output_ty,
|
||||||
#FN_CACHE,
|
inner_fn: #inner_fn,
|
||||||
#inner,
|
cycle_recovery_fn: #cycle_recovery_fn,
|
||||||
]
|
cycle_recovery_strategy: #cycle_recovery_strategy,
|
||||||
}],
|
is_specifiable: #is_specifiable,
|
||||||
)),
|
needs_interner: #needs_interner,
|
||||||
FunctionType::RequiresInterning => Ok(crate::debug::dump_tokens(
|
unused_names: [
|
||||||
fn_name,
|
#zalsa,
|
||||||
quote![salsa::plumbing::setup_interned_fn! {
|
#Configuration,
|
||||||
attrs: [#(#attrs),*],
|
#InternedData,
|
||||||
vis: #vis,
|
#FN_CACHE,
|
||||||
fn_name: #fn_name,
|
#INTERN_CACHE,
|
||||||
db_lt: #db_lt,
|
#inner,
|
||||||
Db: #db_path,
|
]
|
||||||
db: #db_ident,
|
}],
|
||||||
input_ids: [#(#input_ids),*],
|
))
|
||||||
input_tys: [#(#input_tys),*],
|
|
||||||
output_ty: #output_ty,
|
|
||||||
inner_fn: #inner_fn,
|
|
||||||
cycle_recovery_fn: #cycle_recovery_fn,
|
|
||||||
cycle_recovery_strategy: #cycle_recovery_strategy,
|
|
||||||
unused_names: [
|
|
||||||
#zalsa,
|
|
||||||
#Configuration,
|
|
||||||
#InternedData,
|
|
||||||
#FN_CACHE,
|
|
||||||
#INTERN_CACHE,
|
|
||||||
#inner,
|
|
||||||
]
|
|
||||||
}],
|
|
||||||
)),
|
|
||||||
FunctionType::SalsaStruct => Ok(crate::debug::dump_tokens(
|
|
||||||
fn_name,
|
|
||||||
quote![salsa::plumbing::setup_struct_fn! {
|
|
||||||
attrs: [#(#attrs),*],
|
|
||||||
vis: #vis,
|
|
||||||
fn_name: #fn_name,
|
|
||||||
db_lt: #db_lt,
|
|
||||||
Db: #db_path,
|
|
||||||
db: #db_ident,
|
|
||||||
input_id: #(#input_ids,)*
|
|
||||||
input_ty: #(#input_tys,)*
|
|
||||||
output_ty: #output_ty,
|
|
||||||
inner_fn: #inner_fn,
|
|
||||||
cycle_recovery_fn: #cycle_recovery_fn,
|
|
||||||
cycle_recovery_strategy: #cycle_recovery_strategy,
|
|
||||||
is_specifiable: #is_specifiable,
|
|
||||||
unused_names: [
|
|
||||||
#zalsa,
|
|
||||||
#Configuration,
|
|
||||||
#FN_CACHE,
|
|
||||||
#inner,
|
|
||||||
]
|
|
||||||
}],
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validity_check<'item>(&self, item: &'item syn::ItemFn) -> syn::Result<ValidFn<'item>> {
|
fn validity_check<'item>(&self, item: &'item syn::ItemFn) -> syn::Result<ValidFn<'item>> {
|
||||||
|
|
|
@ -114,16 +114,15 @@ impl FromId for Id {
|
||||||
|
|
||||||
/// As a special case, we permit `Singleton` to be converted to an `Id`.
|
/// As a special case, we permit `Singleton` to be converted to an `Id`.
|
||||||
/// This is useful for declaring functions with no arguments.
|
/// This is useful for declaring functions with no arguments.
|
||||||
impl AsId for salsa_struct::Singleton {
|
impl AsId for () {
|
||||||
fn as_id(&self) -> Id {
|
fn as_id(&self) -> Id {
|
||||||
Id::from_u32(0)
|
Id::from_u32(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromId for salsa_struct::Singleton {
|
impl FromId for () {
|
||||||
fn from_id(id: Id) -> Self {
|
fn from_id(id: Id) -> Self {
|
||||||
assert_eq!(0, id.as_u32());
|
assert_eq!(0, id.as_u32());
|
||||||
salsa_struct::Singleton
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,6 @@ pub mod plumbing {
|
||||||
pub use crate::runtime::Stamp;
|
pub use crate::runtime::Stamp;
|
||||||
pub use crate::runtime::StampedValue;
|
pub use crate::runtime::StampedValue;
|
||||||
pub use crate::salsa_struct::SalsaStructInDb;
|
pub use crate::salsa_struct::SalsaStructInDb;
|
||||||
pub use crate::salsa_struct::Singleton;
|
|
||||||
pub use crate::storage::views;
|
pub use crate::storage::views;
|
||||||
pub use crate::storage::HasStorage;
|
pub use crate::storage::HasStorage;
|
||||||
pub use crate::storage::IngredientCache;
|
pub use crate::storage::IngredientCache;
|
||||||
|
@ -95,11 +94,9 @@ pub mod plumbing {
|
||||||
pub use salsa_macro_rules::maybe_clone;
|
pub use salsa_macro_rules::maybe_clone;
|
||||||
pub use salsa_macro_rules::maybe_cloned_ty;
|
pub use salsa_macro_rules::maybe_cloned_ty;
|
||||||
pub use salsa_macro_rules::setup_accumulator_impl;
|
pub use salsa_macro_rules::setup_accumulator_impl;
|
||||||
pub use salsa_macro_rules::setup_constant_fn;
|
pub use salsa_macro_rules::setup_fn;
|
||||||
pub use salsa_macro_rules::setup_input_struct;
|
pub use salsa_macro_rules::setup_input_struct;
|
||||||
pub use salsa_macro_rules::setup_interned_fn;
|
|
||||||
pub use salsa_macro_rules::setup_interned_struct;
|
pub use salsa_macro_rules::setup_interned_struct;
|
||||||
pub use salsa_macro_rules::setup_struct_fn;
|
|
||||||
pub use salsa_macro_rules::setup_tracked_struct;
|
pub use salsa_macro_rules::setup_tracked_struct;
|
||||||
pub use salsa_macro_rules::unexpected_cycle_recovery;
|
pub use salsa_macro_rules::unexpected_cycle_recovery;
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,6 @@ pub trait SalsaStructInDb {
|
||||||
fn register_dependent_fn(db: &dyn Database, index: IngredientIndex);
|
fn register_dependent_fn(db: &dyn Database, index: IngredientIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A ZST that implements [`SalsaStructInDb`]
|
impl SalsaStructInDb for () {
|
||||||
///
|
|
||||||
/// It is used for implementing "constant" tracked function
|
|
||||||
/// (ones that only take a database as an argument).
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
|
||||||
pub struct Singleton;
|
|
||||||
|
|
||||||
impl SalsaStructInDb for Singleton {
|
|
||||||
fn register_dependent_fn(_db: &dyn Database, _index: IngredientIndex) {}
|
fn register_dependent_fn(_db: &dyn Database, _index: IngredientIndex) {}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue