salsa/examples/hello_world/implementation.rs

93 lines
2.7 KiB
Rust
Raw Normal View History

2018-09-28 15:40:20 +00:00
use crate::class_table::{self, ClassTableQueryContext};
use crate::compiler::{CompilerQueryContext, Interner};
use salsa::dyn_descriptor::DynDescriptor;
use salsa::BaseQueryContext;
use salsa::Query;
use salsa::QueryTable;
use std::cell::RefCell;
use std::fmt::Write;
#[derive(Default)]
pub struct QueryContextImpl {
storage: QueryContextImplStorage,
interner: Interner,
execution_stack: RefCell<Vec<DynDescriptor>>,
}
// The intention is that plus the impl of `ClassTableQueryContext`
// below will eventually be generated by a macro, so that you just
// have to name the queries.
#[allow(non_snake_case)]
#[derive(Default)]
struct QueryContextImplStorage {
AllClasses: <class_table::AllClasses as Query<QueryContextImpl>>::Storage,
AllFields: <class_table::AllFields as Query<QueryContextImpl>>::Storage,
Fields: <class_table::Fields as Query<QueryContextImpl>>::Storage,
}
impl ClassTableQueryContext for QueryContextImpl {
fn all_classes(&self) -> QueryTable<'_, Self, class_table::AllClasses> {
QueryTable::new(
self,
&self.storage.AllClasses,
DynDescriptor::from_key::<Self, class_table::AllClasses>,
)
}
fn all_fields(&self) -> QueryTable<'_, Self, class_table::AllFields> {
QueryTable::new(
self,
&self.storage.AllFields,
DynDescriptor::from_key::<Self, class_table::AllFields>,
)
}
fn fields(&self) -> QueryTable<'_, Self, class_table::Fields> {
QueryTable::new(
self,
&self.storage.Fields,
DynDescriptor::from_key::<Self, class_table::Fields>,
)
}
}
impl CompilerQueryContext for QueryContextImpl {
fn interner(&self) -> &Interner {
&self.interner
}
}
impl BaseQueryContext for QueryContextImpl {
type QueryDescriptor = DynDescriptor;
fn execute_query_implementation<Q>(
&self,
descriptor: Self::QueryDescriptor,
key: &Q::Key,
) -> Q::Value
where
Q: Query<Self>,
{
self.execution_stack.borrow_mut().push(descriptor);
let value = Q::execute(self, key.clone());
self.execution_stack.borrow_mut().pop();
value
}
fn report_unexpected_cycle(&self, descriptor: Self::QueryDescriptor) -> ! {
let execution_stack = self.execution_stack.borrow();
let start_index = (0..execution_stack.len())
.rev()
.filter(|&i| execution_stack[i] == descriptor)
.next()
.unwrap();
let mut message = format!("Internal error, cycle detected:\n");
for descriptor in &execution_stack[start_index..] {
writeln!(message, "- {:?}\n", descriptor).unwrap();
}
panic!(message)
}
}