Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ impl NetworkProtocol for GraphQLNetworkProtocol {
let mut graphql_root_types = None;

let (type_system_document, type_system_extension_documents) =
parse_graphql_schema(db).to_owned()?;
parse_graphql_schema(db).try_ok()?.split();

let (mut result, mut directives, mut refetch_fields) =
process_graphql_type_system_document(
Expand Down
10 changes: 5 additions & 5 deletions crates/graphql_network_protocol/src/read_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub fn parse_graphql_schema<TNetworkProtocol: NetworkProtocol + 'static>(
db: &IsographDatabase<TNetworkProtocol>,
) -> Result<
(
MemoRef<GraphQLTypeSystemDocument>,
GraphQLTypeSystemDocument,
BTreeMap<RelativePathToSourceFile, MemoRef<GraphQLTypeSystemExtensionDocument>>,
),
WithLocation<SchemaParseError>,
Expand All @@ -35,18 +35,18 @@ pub fn parse_graphql_schema<TNetworkProtocol: NetworkProtocol + 'static>(
.iter()
{
let extensions_document =
parse_schema_extensions_file(db, *schema_extension_source_id).to_owned()?;
parse_schema_extensions_file(db, *schema_extension_source_id).try_ok()?;
schema_extensions.insert(*relative_path, extensions_document);
}

Ok((db.intern(schema), schema_extensions))
Ok((schema, schema_extensions))
}

#[memo]
pub fn parse_schema_extensions_file<TNetworkProtocol: NetworkProtocol + 'static>(
db: &IsographDatabase<TNetworkProtocol>,
schema_extension_source_id: SourceId<SchemaSource>,
) -> Result<MemoRef<GraphQLTypeSystemExtensionDocument>, WithLocation<SchemaParseError>> {
) -> Result<GraphQLTypeSystemExtensionDocument, WithLocation<SchemaParseError>> {
let SchemaSource {
content,
text_source,
Expand All @@ -55,5 +55,5 @@ pub fn parse_schema_extensions_file<TNetworkProtocol: NetworkProtocol + 'static>
let schema_extensions = parse_schema_extensions(content, *text_source)
.map_err(|with_span| with_span.to_with_location(*text_source))?;

Ok(db.intern(schema_extensions))
Ok(schema_extensions)
}
20 changes: 10 additions & 10 deletions crates/pico/src/view.rs → crates/pico/src/field_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ pub trait Counter: Singleton + Default + Copy + Eq + 'static {
fn increment(self) -> Self;
}

pub type Projector<Db, T> = for<'a> fn(&'a Db) -> &'a T;
pub type FieldProjector<Db, T> = for<'a> fn(&'a Db) -> &'a T;

pub struct View<'a, Db: Database, T, C: Counter> {
pub struct FieldView<'a, Db: Database, T, C: Counter> {
db: &'a Db,
projector: Projector<Db, T>,
projector: FieldProjector<Db, T>,
phantom: PhantomData<C>,
}

impl<'a, Db: Database, T, C: Counter> View<'a, Db, T, C> {
pub fn new(db: &'a Db, projector: Projector<Db, T>) -> Self {
impl<'a, Db: Database, T, C: Counter> FieldView<'a, Db, T, C> {
pub fn new(db: &'a Db, projector: FieldProjector<Db, T>) -> Self {
Self {
db,
projector,
Expand Down Expand Up @@ -44,16 +44,16 @@ impl<'a, Db: Database, T, C: Counter> View<'a, Db, T, C> {
}
}

pub type ProjectorMut<Db, T> = for<'a> fn(&'a mut Db) -> &'a mut T;
pub type FieldProjectorMut<Db, T> = for<'a> fn(&'a mut Db) -> &'a mut T;

pub struct MutView<'a, Db: Database, T, C: Counter> {
pub struct FieldViewMut<'a, Db: Database, T, C: Counter> {
db: &'a mut Db,
projector: ProjectorMut<Db, T>,
projector: FieldProjectorMut<Db, T>,
phantom: PhantomData<C>,
}

impl<'a, Db: Database, T, C: Counter> MutView<'a, Db, T, C> {
pub fn new(db: &'a mut Db, projector: ProjectorMut<Db, T>) -> Self {
impl<'a, Db: Database, T, C: Counter> FieldViewMut<'a, Db, T, C> {
pub fn new(db: &'a mut Db, projector: FieldProjectorMut<Db, T>) -> Self {
Self {
db,
projector,
Expand Down
4 changes: 2 additions & 2 deletions crates/pico/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ mod derived_node;
mod dyn_eq;
mod epoch;
mod execute_memoized_function;
mod field_view;
mod garbage_collection;
mod index;
mod intern;
pub mod macro_fns;
mod memo_ref;
mod retained_query;
mod source;
mod view;
mod with_serialize;

pub use database::*;
pub use derived_node::*;
pub use dyn_eq::*;
pub use execute_memoized_function::*;
pub use field_view::*;
pub use intern::*;
pub use memo_ref::*;
pub use retained_query::*;
pub use source::*;
pub use view::*;
pub use with_serialize::*;
148 changes: 145 additions & 3 deletions crates/pico/src/memo_ref.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,66 @@
use std::{marker::PhantomData, ops::Deref};
use std::{
any::Any,
hash::{Hash, Hasher},
marker::PhantomData,
ops::Deref,
};

use crate::{DatabaseDyn, DerivedNodeId, ParamId, dependency::NodeKind};
use intern::InternId;

use crate::{DatabaseDyn, DerivedNodeId, ParamId, dependency::NodeKind};
type MemoRefProjectorStep = for<'a> fn(&'a dyn Any) -> &'a dyn Any;

const MAX_PROJECTOR_STEPS: usize = 4;

#[inline(always)]
fn step_identity(value: &dyn Any) -> &dyn Any {
value
}

#[inline(always)]
fn step_result_ok<T: 'static, E: 'static>(value: &dyn Any) -> &dyn Any {
match value
.downcast_ref::<Result<T, E>>()
.expect("MemoRef<Result<..>>: underlying value has unexpected type")
{
Ok(t) => t as &dyn Any,
Err(_) => unreachable!("Ok projection used only after Ok check"),
}
}

#[inline(always)]
fn step_option_some<T: 'static>(value: &dyn Any) -> &dyn Any {
match value
.downcast_ref::<Option<T>>()
.expect("MemoRef<Option<..>>: underlying value has unexpected type")
{
Some(t) => t as &dyn Any,
None => unreachable!("Some projection used only after Some check"),
}
}

#[inline(always)]
fn step_tuple_0<T0: 'static, T1: 'static>(value: &dyn Any) -> &dyn Any {
let (t0, _) = value
.downcast_ref::<(T0, T1)>()
.expect("MemoRef<(..)>: underlying value has unexpected type");
t0 as &dyn Any
}

#[inline(always)]
fn step_tuple_1<T0: 'static, T1: 'static>(value: &dyn Any) -> &dyn Any {
let (_, t1) = value
.downcast_ref::<(T0, T1)>()
.expect("MemoRef<(..)>: underlying value has unexpected type");
t1 as &dyn Any
}

#[derive(Debug)]
pub struct MemoRef<T> {
pub(crate) db: *const dyn DatabaseDyn,
pub(crate) derived_node_id: DerivedNodeId,
projectors: [MemoRefProjectorStep; MAX_PROJECTOR_STEPS],
projectors_len: u8,
phantom: PhantomData<T>,
}

Expand All @@ -27,12 +80,23 @@ impl<T> PartialEq for MemoRef<T> {

impl<T> Eq for MemoRef<T> {}

#[allow(clippy::unnecessary_cast)]
impl<T> Hash for MemoRef<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
let data_ptr = self.db as *const dyn DatabaseDyn as *const ();
data_ptr.hash(state);
self.derived_node_id.hash(state);
}
}

#[allow(clippy::unnecessary_cast)]
impl<T: 'static + Clone> MemoRef<T> {
pub fn new(db: &dyn DatabaseDyn, derived_node_id: DerivedNodeId) -> Self {
Self {
db: db as *const _ as *const dyn DatabaseDyn,
derived_node_id,
projectors: [step_identity; MAX_PROJECTOR_STEPS],
projectors_len: 0,
phantom: PhantomData,
}
}
Expand Down Expand Up @@ -63,6 +127,84 @@ impl<T: 'static> Deref for MemoRef<T> {
NodeKind::Derived(self.derived_node_id),
revision.time_updated,
);
value.downcast_ref::<T>().unwrap()
if self.projectors_len == 0 {
return value
.downcast_ref::<T>()
.expect("MemoRef: projector chain produced unexpected type");
}
let mut any_ref = value;
let len = self.projectors_len as usize;
for step in &self.projectors[..len] {
any_ref = (step)(any_ref);
}
any_ref
.downcast_ref::<T>()
.expect("MemoRef: projector chain produced unexpected type")
}
}

impl<T: 'static, E: 'static + Clone> MemoRef<Result<T, E>> {
pub fn try_ok(self) -> Result<MemoRef<T>, E> {
match self.deref() {
Ok(_) => {
let mut next = MemoRef::<T> {
db: self.db,
derived_node_id: self.derived_node_id,
projectors: self.projectors,
projectors_len: self.projectors_len + 1,
phantom: PhantomData,
};
let idx = self.projectors_len as usize;
next.projectors[idx] = step_result_ok::<T, E>;
Ok(next)
}
Err(err) => Err(err.clone()),
}
}
}

impl<T: 'static> MemoRef<Option<T>> {
pub fn try_some(self) -> Option<MemoRef<T>> {
match self.deref() {
Some(_) => {
let mut next = MemoRef::<T> {
db: self.db,
derived_node_id: self.derived_node_id,
projectors: self.projectors,
projectors_len: self.projectors_len + 1,
phantom: PhantomData,
};
let idx = self.projectors_len as usize;
next.projectors[idx] = step_option_some::<T>;
Some(next)
}
None => None,
}
}
}

impl<T0: 'static, T1: 'static> MemoRef<(T0, T1)> {
pub fn split(self) -> (MemoRef<T0>, MemoRef<T1>) {
let mut left = MemoRef::<T0> {
db: self.db,
derived_node_id: self.derived_node_id,
projectors: self.projectors,
projectors_len: self.projectors_len + 1,
phantom: PhantomData,
};
let idx = self.projectors_len as usize;
left.projectors[idx] = step_tuple_0::<T0, T1>;

let mut right = MemoRef::<T1> {
db: self.db,
derived_node_id: self.derived_node_id,
projectors: self.projectors,
projectors_len: self.projectors_len + 1,
phantom: PhantomData,
};
let idx = self.projectors_len as usize;
right.projectors[idx] = step_tuple_1::<T0, T1>;

(left, right)
}
}
8 changes: 2 additions & 6 deletions crates/pico/tests/intern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,19 @@ enum ProcessInputError {
}

#[memo]
fn first_letter(
db: &TestDatabase,
input_id: SourceId<Input>,
) -> Result<MemoRef<char>, FirstLetterError> {
fn first_letter(db: &TestDatabase, input_id: SourceId<Input>) -> Result<char, FirstLetterError> {
db.get(input_id)
.value
.chars()
.next()
.ok_or(FirstLetterError::EmptyString)
.map(|v| db.intern(v))
}

#[memo]
fn process_input(
db: &TestDatabase,
input_id: SourceId<Input>,
) -> Result<MemoRef<char>, ProcessInputError> {
let result = first_letter(db, input_id).to_owned()?;
let result = first_letter(db, input_id).try_ok()?;
Ok(result)
}
Loading
Loading