Skip to content

Commit

Permalink
Allow query outputs to refer to a FieldRef. (#615)
Browse files Browse the repository at this point in the history
  • Loading branch information
obi1kenobi committed Jun 13, 2024
1 parent ead46c5 commit 8a2e8d0
Show file tree
Hide file tree
Showing 262 changed files with 952 additions and 931 deletions.
5 changes: 1 addition & 4 deletions trustfall_core/src/frontend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,10 +599,7 @@ where
// TODO: fixme, temporary hack to avoid changing the IRQueryComponent struct
let hacked_outputs = component_outputs
.into_iter()
.filter_map(|(k, v)| match v {
FieldRef::ContextField(c) => Some((k, c)),
FieldRef::FoldSpecificField(_) => None,
})
.filter(|(k, v)| !matches!(&v, FieldRef::FoldSpecificField(..)))
.collect();

Ok(IRQueryComponent {
Expand Down
97 changes: 57 additions & 40 deletions trustfall_core/src/interpreter/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,29 +193,37 @@ fn construct_outputs<'query, AdapterT: Adapter<'query>>(
let mut output_iterator = iterator;

for output_name in output_names.iter() {
let context_field = &root_component.outputs[output_name];
let vertex_id = context_field.vertex_id;
let field_ref = &root_component.outputs[output_name];

let moved_iterator = Box::new(output_iterator.map(move |context| {
let new_vertex = context.vertices[&vertex_id].clone();
context.move_to_vertex(new_vertex)
}));
match field_ref {
FieldRef::ContextField(context_field) => {
let vertex_id = context_field.vertex_id;

let resolve_info = ResolveInfo::new(query, vertex_id, true);
let moved_iterator = Box::new(output_iterator.map(move |context| {
let new_vertex = context.vertices[&vertex_id].clone();
context.move_to_vertex(new_vertex)
}));

let type_name = &root_component.vertices[&vertex_id].type_name;
let field_data_iterator = adapter.resolve_property(
moved_iterator,
type_name,
&context_field.field_name,
&resolve_info,
);
query = resolve_info.into_inner();
let resolve_info = ResolveInfo::new(query, vertex_id, true);

output_iterator = Box::new(field_data_iterator.map(|(mut context, value)| {
context.values.push(value);
context
}));
let type_name = &root_component.vertices[&vertex_id].type_name;
let field_data_iterator = adapter.resolve_property(
moved_iterator,
type_name,
&context_field.field_name,
&resolve_info,
);
query = resolve_info.into_inner();

output_iterator = Box::new(field_data_iterator.map(|(mut context, value)| {
context.values.push(value);
context
}));
}
FieldRef::FoldSpecificField(_) => {
unreachable!("found fold-specific field in component outputs: {root_component:#?}")
}
}
}
let expected_output_names: BTreeSet<_> = query.indexed_query.outputs.keys().cloned().collect();
carrier.query = Some(query);
Expand Down Expand Up @@ -648,27 +656,36 @@ mismatch on whether the fold below {expanding_from_vid:?} was inside an `@option
// This is a slimmed-down version of computing a context field:
// - it does not restore the prior active vertex after getting each value
// - it already knows that the context field is guaranteed to exist
let context_field = &fold.component.outputs[output_name.as_ref()];
let vertex_id = context_field.vertex_id;
let moved_iterator = Box::new(output_iterator.map(move |context| {
let new_vertex = context.vertices[&vertex_id].clone();
context.move_to_vertex(new_vertex)
}));

let query = cloned_carrier.query.take().expect("query was not returned");
let resolve_info = ResolveInfo::new(query, vertex_id, true);
let field_data_iterator = cloned_adapter.resolve_property(
moved_iterator,
&fold.component.vertices[&vertex_id].type_name,
&context_field.field_name,
&resolve_info,
);
cloned_carrier.query = Some(resolve_info.into_inner());

output_iterator = Box::new(field_data_iterator.map(|(mut context, value)| {
context.values.push(value);
context
}));
let field_ref = &fold.component.outputs[output_name.as_ref()];

match field_ref {
FieldRef::ContextField(context_field) => {
let vertex_id = context_field.vertex_id;
let moved_iterator = Box::new(output_iterator.map(move |context| {
let new_vertex = context.vertices[&vertex_id].clone();
context.move_to_vertex(new_vertex)
}));

let query = cloned_carrier.query.take().expect("query was not returned");
let resolve_info = ResolveInfo::new(query, vertex_id, true);
let field_data_iterator = cloned_adapter.resolve_property(
moved_iterator,
&fold.component.vertices[&vertex_id].type_name,
&context_field.field_name,
&resolve_info,
);
cloned_carrier.query = Some(resolve_info.into_inner());

output_iterator =
Box::new(field_data_iterator.map(|(mut context, value)| {
context.values.push(value);
context
}));
}
FieldRef::FoldSpecificField(_) => {
unreachable!("found fold-specific field in component outputs: {fold:#?}")
}
}
}

for mut folded_context in output_iterator {
Expand Down
16 changes: 8 additions & 8 deletions trustfall_core/src/interpreter/helpers/correctness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use std::{collections::BTreeMap, fmt::Debug, num::NonZeroUsize, sync::Arc};
use crate::{
interpreter::{Adapter, DataContext, InterpretedQuery, ResolveEdgeInfo, ResolveInfo},
ir::{
ContextField, EdgeParameters, Eid, FieldValue, IREdge, IRQuery, IRQueryComponent, IRVertex,
TransparentValue, Type, Vid,
ContextField, EdgeParameters, Eid, FieldRef, FieldValue, IREdge, IRQuery, IRQueryComponent,
IRVertex, TransparentValue, Type, Vid,
},
schema::{Schema, SchemaAdapter},
TryIntoStruct,
Expand Down Expand Up @@ -166,11 +166,11 @@ fn make_resolve_info_for_property_check(
edges: Default::default(),
folds: Default::default(),
outputs: btreemap! {
property_name.clone() => ContextField {
property_name.clone() => FieldRef::ContextField(ContextField {
vertex_id: vid,
field_name: property_name.clone(),
field_type: Type::parse(property_type).expect("not a valid type"),
}
})
},
}),
variables: Default::default(),
Expand Down Expand Up @@ -324,11 +324,11 @@ fn make_resolve_edge_info_for_edge_check(
},
folds: Default::default(),
outputs: btreemap! {
property_name.clone() => ContextField {
property_name.clone() => FieldRef::ContextField(ContextField {
vertex_id: vid,
field_name: property_name,
field_type: Type::parse("String!").expect("not a valid type"),
}
})
},
}),
variables: Default::default(),
Expand Down Expand Up @@ -493,11 +493,11 @@ fn make_resolve_info_for_type_coercion(
edges: Default::default(),
folds: Default::default(),
outputs: btreemap! {
typename_property.clone() => ContextField {
typename_property.clone() => FieldRef::ContextField(ContextField {
vertex_id: vid,
field_name: typename_property.clone(),
field_type: Type::parse("String!").expect("not a valid type"),
}
})
},
}),
variables: Default::default(),
Expand Down
4 changes: 2 additions & 2 deletions trustfall_core/src/interpreter/hints/vertex_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ impl<T: InternalVertexInfo + super::sealed::__Sealed> VertexInfo for T {
let properties = current_component
.outputs
.values()
.filter(|c| c.vertex_id == current_vertex.vid)
.map(|c| RequiredProperty::new(c.field_name.clone()));
.filter(|c| c.defined_at() == current_vertex.vid)
.map(|c| RequiredProperty::new(c.field_name_arc()));

let properties = properties.chain(
current_vertex
Expand Down
4 changes: 2 additions & 2 deletions trustfall_core/src/ir/indexed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ fn add_data_from_component(
}

for (output_name, field) in component.outputs.iter() {
let output_vid = field.vertex_id;
let output_vid = field.defined_at();

// the output must be from a vertex in this component
let output_component =
Expand All @@ -166,7 +166,7 @@ fn add_data_from_component(
let output_name = output_name.clone();
let output_type = get_output_type(
output_vid,
&field.field_type,
field.field_type(),
&component_optional_vertices,
are_folds_optional,
);
Expand Down
9 changes: 8 additions & 1 deletion trustfall_core/src/ir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ pub struct IRQueryComponent {
pub folds: BTreeMap<Eid, Arc<IRFold>>,

#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub outputs: BTreeMap<Arc<str>, ContextField>,
pub outputs: BTreeMap<Arc<str>, FieldRef>,
}

/// Intermediate representation of a query
Expand Down Expand Up @@ -318,6 +318,13 @@ impl FieldRef {
}
}

pub fn field_name_arc(&self) -> Arc<str> {
match self {
FieldRef::ContextField(c) => c.field_name.clone(),
FieldRef::FoldSpecificField(f) => f.kind.field_name().into(),
}
}

/// The vertex ID at which this reference is considered defined.
pub fn defined_at(&self) -> Vid {
match self {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ Ok(TestIRQuery(
),
},
outputs: {
"value": ContextField(
"value": ContextField(ContextField(
vertex_id: Vid(1),
field_name: "value",
field_type: "Int",
),
)),
},
),
variables: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ Ok(TestIRQuery(
),
},
outputs: {
"value": ContextField(
"value": ContextField(ContextField(
vertex_id: Vid(1),
field_name: "value",
field_type: "Int",
),
)),
},
),
variables: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ Ok(TestIRQuery(
),
},
outputs: {
"value": ContextField(
"value": ContextField(ContextField(
vertex_id: Vid(1),
field_name: "value",
field_type: "Int",
),
)),
},
),
variables: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ Ok(TestIRQuery(
),
},
outputs: {
"value": ContextField(
"value": ContextField(ContextField(
vertex_id: Vid(1),
field_name: "value",
field_type: "Int",
),
)),
},
),
variables: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ Ok(TestIRQuery(
),
},
outputs: {
"value": ContextField(
"value": ContextField(ContextField(
vertex_id: Vid(1),
field_name: "value",
field_type: "Int",
),
)),
},
),
variables: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ Ok(TestIRQuery(
),
},
outputs: {
"intNonNullList": ContextField(
"intNonNullList": ContextField(ContextField(
vertex_id: Vid(1),
field_name: "intNonNullList",
field_type: "[Int]!",
),
"nonNullIntList": ContextField(
)),
"nonNullIntList": ContextField(ContextField(
vertex_id: Vid(1),
field_name: "nonNullIntList",
field_type: "[Int!]",
),
)),
},
),
variables: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ Ok(TestIRQuery(
),
},
outputs: {
"intNonNullList": ContextField(
"intNonNullList": ContextField(ContextField(
vertex_id: Vid(1),
field_name: "intNonNullList",
field_type: "[Int]!",
),
"nonNullIntList": ContextField(
)),
"nonNullIntList": ContextField(ContextField(
vertex_id: Vid(1),
field_name: "nonNullIntList",
field_type: "[Int!]",
),
)),
},
),
variables: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ Ok(TestIRQuery(
),
},
outputs: {
"name": ContextField(
"name": ContextField(ContextField(
vertex_id: Vid(1),
field_name: "name",
field_type: "String",
),
"value": ContextField(
)),
"value": ContextField(ContextField(
vertex_id: Vid(1),
field_name: "value",
field_type: "Int",
),
)),
},
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ Ok(TestIRQuery(
),
},
outputs: {
"succ_is_named": ContextField(
"succ_is_named": ContextField(ContextField(
vertex_id: Vid(2),
field_name: "name",
field_type: "String",
),
"zero": ContextField(
)),
"zero": ContextField(ContextField(
vertex_id: Vid(1),
field_name: "value",
field_type: "Int",
),
)),
},
),
),
Expand Down
Loading

0 comments on commit 8a2e8d0

Please sign in to comment.