Skip to main content

graphrecords_query/registry/
template.rs

1use super::{
2    ArityDescriptor, Bindings, CapabilityRegistry, EmissionSpec, IndexDescriptor,
3    LaneShapeDescriptor, OperandDescriptor, OrderDescriptor, OutArityTable, ValueDescriptor,
4    VariableIdentifier,
5};
6
7#[derive(Clone, Debug)]
8pub enum IndexDescriptorTemplate {
9    Concrete(IndexDescriptor),
10    Variable(VariableIdentifier),
11    Expanded { parent: Box<Self>, child: Box<Self> },
12    GroupKeyOf(VariableIdentifier),
13}
14
15impl IndexDescriptorTemplate {
16    pub(super) fn fill(
17        &self,
18        bindings: &Bindings,
19        capabilities: &CapabilityRegistry,
20    ) -> IndexDescriptor {
21        match self {
22            Self::Concrete(index) => index.clone(),
23            Self::Variable(variable) => bindings
24                .index(*variable)
25                .unwrap_or_else(|| {
26                    panic!("registry output has no binding for index variable {variable}")
27                })
28                .clone(),
29            Self::Expanded { parent, child } => IndexDescriptor::expanded(
30                parent.fill(bindings, capabilities),
31                child.fill(bindings, capabilities),
32            ),
33            Self::GroupKeyOf(variable) => {
34                let value = bindings.value(*variable).unwrap_or_else(|| {
35                    panic!("registry output has no binding for value variable {variable}")
36                });
37
38                capabilities.group_key(value).unwrap_or_else(|| {
39                    panic!("registry admitted a grouping value without a group key domain")
40                })
41            }
42        }
43    }
44}
45
46#[derive(Clone, Debug)]
47pub enum ValueDescriptorTemplate {
48    Concrete(ValueDescriptor),
49    Variable(VariableIdentifier),
50    Index(IndexDescriptorTemplate),
51    EntityReference(IndexDescriptorTemplate),
52}
53
54impl ValueDescriptorTemplate {
55    pub(super) fn fill(
56        &self,
57        bindings: &Bindings,
58        capabilities: &CapabilityRegistry,
59    ) -> ValueDescriptor {
60        match self {
61            Self::Concrete(value) => value.clone(),
62            Self::Variable(variable) => bindings
63                .value(*variable)
64                .unwrap_or_else(|| {
65                    panic!("registry output has no binding for value variable {variable}")
66                })
67                .clone(),
68            Self::Index(index) => ValueDescriptor::index(index.fill(bindings, capabilities)),
69            Self::EntityReference(index) => {
70                ValueDescriptor::entity_reference_index(index.fill(bindings, capabilities))
71            }
72        }
73    }
74}
75
76#[derive(Clone, Debug)]
77pub enum LaneShapeDescriptorTemplate {
78    Indexed {
79        index: IndexDescriptorTemplate,
80        value: ValueDescriptorTemplate,
81    },
82    Bare {
83        value: ValueDescriptorTemplate,
84    },
85    Variable(VariableIdentifier),
86}
87
88impl LaneShapeDescriptorTemplate {
89    pub(super) fn fill(
90        &self,
91        bindings: &Bindings,
92        capabilities: &CapabilityRegistry,
93    ) -> LaneShapeDescriptor {
94        match self {
95            Self::Indexed { index, value } => LaneShapeDescriptor::Indexed {
96                index: index.fill(bindings, capabilities),
97                value: value.fill(bindings, capabilities),
98            },
99            Self::Bare { value } => LaneShapeDescriptor::Bare {
100                value: value.fill(bindings, capabilities),
101            },
102            Self::Variable(variable) => bindings
103                .shape(*variable)
104                .unwrap_or_else(|| {
105                    panic!("registry output has no binding for shape variable {variable}")
106                })
107                .clone(),
108        }
109    }
110}
111
112#[derive(Clone, Debug)]
113pub enum OrderDescriptorTemplate {
114    Concrete(OrderDescriptor),
115    Variable(VariableIdentifier),
116}
117
118impl OrderDescriptorTemplate {
119    pub(super) fn fill(&self, bindings: &Bindings) -> OrderDescriptor {
120        match self {
121            Self::Concrete(order) => *order,
122            Self::Variable(variable) => bindings.order(*variable).unwrap_or_else(|| {
123                panic!("registry output has no binding for order variable {variable}")
124            }),
125        }
126    }
127}
128
129#[derive(Clone, Debug)]
130pub enum ArityDescriptorTemplate {
131    Multiple(OrderDescriptorTemplate),
132    Single,
133    Definite,
134    Variable(VariableIdentifier),
135    EmissionOf {
136        input: VariableIdentifier,
137        emission: EmissionSpec,
138    },
139}
140
141impl ArityDescriptorTemplate {
142    pub(super) fn fill(&self, bindings: &Bindings, arities: &OutArityTable) -> ArityDescriptor {
143        match self {
144            Self::Multiple(order) => ArityDescriptor::Multiple {
145                order: order.fill(bindings),
146            },
147            Self::Single => ArityDescriptor::Single,
148            Self::Definite => ArityDescriptor::Definite,
149            Self::Variable(variable) => Self::bound_arity(bindings, *variable),
150            Self::EmissionOf { input, emission } => arities.resolve(
151                *emission,
152                Self::bound_arity(bindings, *input),
153                bindings.argument_retention(),
154            ),
155        }
156    }
157
158    fn bound_arity(bindings: &Bindings, variable: VariableIdentifier) -> ArityDescriptor {
159        bindings.arity(variable).unwrap_or_else(|| {
160            panic!("registry output has no binding for arity variable {variable}")
161        })
162    }
163}
164
165#[derive(Clone, Debug)]
166pub enum OperandDescriptorTemplate {
167    Lane {
168        shape: LaneShapeDescriptorTemplate,
169        arity: ArityDescriptorTemplate,
170    },
171    Group {
172        member: IndexDescriptorTemplate,
173        key: IndexDescriptorTemplate,
174        payload: Box<Self>,
175    },
176    Variable(VariableIdentifier),
177}
178
179impl OperandDescriptorTemplate {
180    pub(super) fn fill(
181        &self,
182        bindings: &Bindings,
183        capabilities: &CapabilityRegistry,
184        arities: &OutArityTable,
185    ) -> OperandDescriptor {
186        match self {
187            Self::Lane { shape, arity } => OperandDescriptor::Lane {
188                shape: shape.fill(bindings, capabilities),
189                arity: arity.fill(bindings, arities),
190            },
191            Self::Group {
192                member,
193                key,
194                payload,
195            } => OperandDescriptor::Group {
196                member: member.fill(bindings, capabilities),
197                key: key.fill(bindings, capabilities),
198                payload: Box::new(payload.fill(bindings, capabilities, arities)),
199            },
200            Self::Variable(variable) => bindings
201                .operand(*variable)
202                .unwrap_or_else(|| {
203                    panic!("registry output has no binding for operand variable {variable}")
204                })
205                .clone(),
206        }
207    }
208}