Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-plan/src/plans/aexpr/traverse.rs
6940 views
1
use super::*;
2
3
impl AExpr {
4
/// Push the inputs of this node to the given container, in reverse order.
5
/// This ensures the primary node responsible for the name is pushed last.
6
///
7
/// This is subtlely different from `children_rev` as this only includes the input expressions,
8
/// not expressions used during evaluation.
9
pub fn inputs_rev<E>(&self, container: &mut E)
10
where
11
E: Extend<Node>,
12
{
13
use AExpr::*;
14
15
match self {
16
Column(_) | Literal(_) | Len => {},
17
BinaryExpr { left, op: _, right } => {
18
container.extend([*right, *left]);
19
},
20
Cast { expr, .. } => container.extend([*expr]),
21
Sort { expr, .. } => container.extend([*expr]),
22
Gather { expr, idx, .. } => {
23
container.extend([*idx, *expr]);
24
},
25
SortBy { expr, by, .. } => {
26
container.extend(by.iter().cloned().rev());
27
container.extend([*expr]);
28
},
29
Filter { input, by } => {
30
container.extend([*by, *input]);
31
},
32
Agg(agg_e) => match agg_e.get_input() {
33
NodeInputs::Single(node) => container.extend([node]),
34
NodeInputs::Many(nodes) => container.extend(nodes.into_iter().rev()),
35
NodeInputs::Leaf => {},
36
},
37
Ternary {
38
truthy,
39
falsy,
40
predicate,
41
} => {
42
container.extend([*predicate, *falsy, *truthy]);
43
},
44
AnonymousFunction { input, .. } | Function { input, .. } => {
45
container.extend(input.iter().rev().map(|e| e.node()))
46
},
47
Explode { expr: e, .. } => container.extend([*e]),
48
Window {
49
function,
50
partition_by,
51
order_by,
52
options: _,
53
} => {
54
if let Some((n, _)) = order_by {
55
container.extend([*n]);
56
}
57
container.extend(partition_by.iter().rev().cloned());
58
container.extend([*function]);
59
},
60
Eval {
61
expr,
62
evaluation,
63
variant: _,
64
} => {
65
// We don't use the evaluation here because it does not contain inputs.
66
_ = evaluation;
67
container.extend([*expr]);
68
},
69
Slice {
70
input,
71
offset,
72
length,
73
} => {
74
container.extend([*length, *offset, *input]);
75
},
76
}
77
}
78
79
/// Push the children of this node to the given container, in reverse order.
80
/// This ensures the primary node responsible for the name is pushed last.
81
///
82
/// This is subtlely different from `input_rev` as this only all expressions included in the
83
/// expression not only the input expressions,
84
pub fn children_rev<E: Extend<Node>>(&self, container: &mut E) {
85
use AExpr::*;
86
87
match self {
88
Column(_) | Literal(_) | Len => {},
89
BinaryExpr { left, op: _, right } => {
90
container.extend([*right, *left]);
91
},
92
Cast { expr, .. } => container.extend([*expr]),
93
Sort { expr, .. } => container.extend([*expr]),
94
Gather { expr, idx, .. } => {
95
container.extend([*idx, *expr]);
96
},
97
SortBy { expr, by, .. } => {
98
container.extend(by.iter().cloned().rev());
99
container.extend([*expr]);
100
},
101
Filter { input, by } => {
102
container.extend([*by, *input]);
103
},
104
Agg(agg_e) => match agg_e.get_input() {
105
NodeInputs::Single(node) => container.extend([node]),
106
NodeInputs::Many(nodes) => container.extend(nodes.into_iter().rev()),
107
NodeInputs::Leaf => {},
108
},
109
Ternary {
110
truthy,
111
falsy,
112
predicate,
113
} => {
114
container.extend([*predicate, *falsy, *truthy]);
115
},
116
AnonymousFunction { input, .. } | Function { input, .. } => {
117
container.extend(input.iter().rev().map(|e| e.node()))
118
},
119
Explode { expr: e, .. } => container.extend([*e]),
120
Window {
121
function,
122
partition_by,
123
order_by,
124
options: _,
125
} => {
126
if let Some((n, _)) = order_by {
127
container.extend([*n]);
128
}
129
container.extend(partition_by.iter().rev().cloned());
130
container.extend([*function]);
131
},
132
Eval {
133
expr,
134
evaluation,
135
variant: _,
136
} => container.extend([*evaluation, *expr]),
137
Slice {
138
input,
139
offset,
140
length,
141
} => {
142
container.extend([*length, *offset, *input]);
143
},
144
}
145
}
146
147
pub fn replace_inputs(mut self, inputs: &[Node]) -> Self {
148
use AExpr::*;
149
let input = match &mut self {
150
Column(_) | Literal(_) | Len => return self,
151
Cast { expr, .. } => expr,
152
Explode { expr, .. } => expr,
153
BinaryExpr { left, right, .. } => {
154
*left = inputs[0];
155
*right = inputs[1];
156
return self;
157
},
158
Gather { expr, idx, .. } => {
159
*expr = inputs[0];
160
*idx = inputs[1];
161
return self;
162
},
163
Sort { expr, .. } => expr,
164
SortBy { expr, by, .. } => {
165
*expr = inputs[0];
166
by.clear();
167
by.extend_from_slice(&inputs[1..]);
168
return self;
169
},
170
Filter { input, by, .. } => {
171
*input = inputs[0];
172
*by = inputs[1];
173
return self;
174
},
175
Agg(a) => {
176
match a {
177
IRAggExpr::Quantile { expr, quantile, .. } => {
178
*expr = inputs[0];
179
*quantile = inputs[1];
180
},
181
_ => {
182
a.set_input(inputs[0]);
183
},
184
}
185
return self;
186
},
187
Ternary {
188
truthy,
189
falsy,
190
predicate,
191
} => {
192
*truthy = inputs[0];
193
*falsy = inputs[1];
194
*predicate = inputs[2];
195
return self;
196
},
197
AnonymousFunction { input, .. } | Function { input, .. } => {
198
assert_eq!(input.len(), inputs.len());
199
for (e, node) in input.iter_mut().zip(inputs.iter()) {
200
e.set_node(*node);
201
}
202
return self;
203
},
204
Eval {
205
expr,
206
evaluation,
207
variant: _,
208
} => {
209
*expr = inputs[0];
210
_ = evaluation; // Intentional.
211
return self;
212
},
213
Slice {
214
input,
215
offset,
216
length,
217
} => {
218
*input = inputs[0];
219
*offset = inputs[1];
220
*length = inputs[2];
221
return self;
222
},
223
Window {
224
function,
225
partition_by,
226
order_by,
227
..
228
} => {
229
let offset = order_by.is_some() as usize;
230
*function = inputs[0];
231
partition_by.clear();
232
partition_by.extend_from_slice(&inputs[1..inputs.len() - offset]);
233
if let Some((_, options)) = order_by {
234
*order_by = Some((*inputs.last().unwrap(), *options));
235
}
236
return self;
237
},
238
};
239
*input = inputs[0];
240
self
241
}
242
}
243
244
impl IRAggExpr {
245
pub fn get_input(&self) -> NodeInputs {
246
use IRAggExpr::*;
247
use NodeInputs::*;
248
match self {
249
Min { input, .. } => Single(*input),
250
Max { input, .. } => Single(*input),
251
Median(input) => Single(*input),
252
NUnique(input) => Single(*input),
253
First(input) => Single(*input),
254
Last(input) => Single(*input),
255
Mean(input) => Single(*input),
256
Implode(input) => Single(*input),
257
Quantile { expr, quantile, .. } => Many(vec![*expr, *quantile]),
258
Sum(input) => Single(*input),
259
Count { input, .. } => Single(*input),
260
Std(input, _) => Single(*input),
261
Var(input, _) => Single(*input),
262
AggGroups(input) => Single(*input),
263
}
264
}
265
pub fn set_input(&mut self, input: Node) {
266
use IRAggExpr::*;
267
let node = match self {
268
Min { input, .. } => input,
269
Max { input, .. } => input,
270
Median(input) => input,
271
NUnique(input) => input,
272
First(input) => input,
273
Last(input) => input,
274
Mean(input) => input,
275
Implode(input) => input,
276
Quantile { expr, .. } => expr,
277
Sum(input) => input,
278
Count { input, .. } => input,
279
Std(input, _) => input,
280
Var(input, _) => input,
281
AggGroups(input) => input,
282
};
283
*node = input;
284
}
285
}
286
287
pub enum NodeInputs {
288
Leaf,
289
Single(Node),
290
Many(Vec<Node>),
291
}
292
293
impl NodeInputs {
294
pub fn first(&self) -> Node {
295
match self {
296
NodeInputs::Single(node) => *node,
297
NodeInputs::Many(nodes) => nodes[0],
298
NodeInputs::Leaf => panic!(),
299
}
300
}
301
}
302
303