vortex_array/optimizer/
rules.rs1use std::any::type_name;
5use std::fmt::Debug;
6use std::marker::PhantomData;
7
8use vortex_error::VortexResult;
9
10use crate::array::ArrayRef;
11use crate::vtable::ArrayId;
12use crate::vtable::VTable;
13
14pub trait Matcher: Send + Sync + 'static {
16 type View<'a>;
17
18 fn key(&self) -> MatchKey;
20
21 fn try_match<'a>(&self, array: &'a ArrayRef) -> Option<Self::View<'a>>;
23}
24
25#[derive(Clone, Debug, PartialEq, Eq, Hash)]
26pub enum MatchKey {
27 Any,
28 Array(ArrayId),
29}
30
31#[derive(Debug)]
33pub struct AnyArray;
34impl Matcher for AnyArray {
35 type View<'a> = &'a ArrayRef;
36
37 fn key(&self) -> MatchKey {
38 MatchKey::Any
39 }
40
41 fn try_match<'a>(&self, array: &'a ArrayRef) -> Option<Self::View<'a>> {
42 Some(array)
43 }
44}
45
46#[derive(Debug)]
48pub struct Exact<V: VTable> {
49 id: ArrayId,
50 _phantom: PhantomData<V>,
51}
52impl<V: VTable> Matcher for Exact<V> {
53 type View<'a> = &'a V::Array;
54
55 fn key(&self) -> MatchKey {
56 MatchKey::Array(self.id.clone())
57 }
58
59 fn try_match<'a>(&self, parent: &'a ArrayRef) -> Option<Self::View<'a>> {
60 parent.as_opt::<V>()
61 }
62}
63impl<V: VTable> Exact<V> {
64 pub unsafe fn new_unchecked(id: ArrayId) -> Self {
71 Self {
72 id,
73 _phantom: PhantomData,
74 }
75 }
76}
77impl<V: VTable> From<&'static V> for Exact<V> {
78 fn from(vtable: &'static V) -> Self {
79 Self {
80 id: vtable.id(),
81 _phantom: PhantomData,
82 }
83 }
84}
85
86pub trait ArrayReduceRule<M: Matcher>: Debug + Send + Sync + 'static {
88 fn matcher(&self) -> M;
90
91 fn reduce(&self, array: M::View<'_>) -> VortexResult<Option<ArrayRef>>;
98}
99
100pub trait ArrayParentReduceRule<Child: Matcher, Parent: Matcher>:
102 Debug + Send + Sync + 'static
103{
104 fn child(&self) -> Child;
106
107 fn parent(&self) -> Parent;
109
110 fn reduce_parent(
117 &self,
118 child: Child::View<'_>,
119 parent: Parent::View<'_>,
120 child_idx: usize,
121 ) -> VortexResult<Option<ArrayRef>>;
122}
123
124pub trait DynArrayReduceRule: Debug + Send + Sync {
126 fn key(&self) -> MatchKey;
127
128 fn reduce(&self, array: &ArrayRef) -> VortexResult<Option<ArrayRef>>;
129}
130
131pub trait DynArrayParentReduceRule: Debug + Send + Sync {
133 fn child_key(&self) -> MatchKey;
134
135 fn parent_key(&self) -> MatchKey;
136
137 fn reduce_parent(
138 &self,
139 array: &ArrayRef,
140 parent: &ArrayRef,
141 child_idx: usize,
142 ) -> VortexResult<Option<ArrayRef>>;
143}
144
145pub(crate) struct ReduceRuleAdapter<M, R> {
147 rule: R,
148 _phantom: PhantomData<M>,
149}
150
151impl<M, R> ReduceRuleAdapter<M, R> {
152 pub(crate) fn new(rule: R) -> Self {
153 Self {
154 rule,
155 _phantom: PhantomData,
156 }
157 }
158}
159
160impl<M: Matcher, R: ArrayReduceRule<M>> Debug for ReduceRuleAdapter<M, R> {
161 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162 f.debug_struct("ArrayReduceRuleAdapter")
163 .field("matcher", &type_name::<M>())
164 .field("rule", &self.rule)
165 .finish()
166 }
167}
168
169pub(crate) struct ParentReduceRuleAdapter<Child: Matcher, Parent: Matcher, R> {
171 rule: R,
172 _phantom: PhantomData<(Child, Parent)>,
173}
174
175impl<Child: Matcher, Parent: Matcher, R> ParentReduceRuleAdapter<Child, Parent, R> {
176 pub(crate) fn new(rule: R) -> Self {
177 Self {
178 rule,
179 _phantom: PhantomData,
180 }
181 }
182}
183
184impl<Child: Matcher, Parent: Matcher, R: Debug> Debug
185 for ParentReduceRuleAdapter<Child, Parent, R>
186{
187 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
188 f.debug_struct("ArrayParentReduceRuleAdapter")
189 .field("child", &type_name::<Child>())
190 .field("parent", &type_name::<Parent>())
191 .field("rule", &self.rule)
192 .finish()
193 }
194}
195
196impl<M: Matcher, R: ArrayReduceRule<M>> DynArrayReduceRule for ReduceRuleAdapter<M, R> {
197 fn key(&self) -> MatchKey {
198 self.rule.matcher().key()
199 }
200
201 fn reduce(&self, array: &ArrayRef) -> VortexResult<Option<ArrayRef>> {
202 let Some(view) = self.rule.matcher().try_match(array) else {
203 return Ok(None);
204 };
205 self.rule.reduce(view)
206 }
207}
208
209impl<Child, Parent, R> DynArrayParentReduceRule for ParentReduceRuleAdapter<Child, Parent, R>
210where
211 Child: Matcher,
212 Parent: Matcher,
213 R: ArrayParentReduceRule<Child, Parent>,
214{
215 fn child_key(&self) -> MatchKey {
216 self.rule.child().key()
217 }
218
219 fn parent_key(&self) -> MatchKey {
220 self.rule.parent().key()
221 }
222
223 fn reduce_parent(
224 &self,
225 child: &ArrayRef,
226 parent: &ArrayRef,
227 child_idx: usize,
228 ) -> VortexResult<Option<ArrayRef>> {
229 let Some(child_view) = self.rule.child().try_match(child) else {
230 return Ok(None);
231 };
232 let Some(parent_view) = self.rule.parent().try_match(parent) else {
233 return Ok(None);
234 };
235 self.rule.reduce_parent(child_view, parent_view, child_idx)
236 }
237}