graphrecords_query/registry/
template.rs1use 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}