1use crate::stmt::{ExprExists, Input};
2
3use super::{
4 Entry, EntryMut, EntryPath, ExprAnd, ExprAny, ExprArg, ExprBinaryOp, ExprCast, ExprError,
5 ExprFunc, ExprInList, ExprInSubquery, ExprIsNull, ExprIsVariant, ExprLet, ExprList, ExprMap,
6 ExprMatch, ExprNot, ExprOr, ExprProject, ExprRecord, ExprStmt, Node, Projection, Substitute,
7 Value, Visit, VisitMut, expr_reference::ExprReference,
8};
9use std::fmt;
10
11#[derive(Clone, PartialEq)]
36pub enum Expr {
37 And(ExprAnd),
39
40 Any(ExprAny),
42
43 Arg(ExprArg),
45
46 BinaryOp(ExprBinaryOp),
48
49 Cast(ExprCast),
51
52 Default,
55
56 Error(ExprError),
58
59 Exists(ExprExists),
61
62 Func(ExprFunc),
64
65 InList(ExprInList),
67
68 InSubquery(ExprInSubquery),
70
71 IsNull(ExprIsNull),
74
75 IsVariant(ExprIsVariant),
77
78 Let(ExprLet),
81
82 Map(ExprMap),
84
85 Match(ExprMatch),
87
88 Not(ExprNot),
90
91 Or(ExprOr),
93
94 Project(ExprProject),
96
97 Record(ExprRecord),
99
100 Reference(ExprReference),
104
105 List(ExprList),
107
108 Stmt(ExprStmt),
110
111 Value(Value),
113}
114
115impl Expr {
116 pub const TRUE: Expr = Expr::Value(Value::Bool(true));
118
119 pub const FALSE: Expr = Expr::Value(Value::Bool(false));
121
122 pub const DEFAULT: Expr = Expr::Default;
124
125 pub fn null() -> Self {
127 Self::Value(Value::Null)
128 }
129
130 pub fn is_value_null(&self) -> bool {
132 matches!(self, Self::Value(Value::Null))
133 }
134
135 pub fn is_true(&self) -> bool {
137 matches!(self, Self::Value(Value::Bool(true)))
138 }
139
140 pub fn is_false(&self) -> bool {
142 matches!(self, Self::Value(Value::Bool(false)))
143 }
144
145 pub fn is_unsatisfiable(&self) -> bool {
150 self.is_false() || self.is_value_null()
151 }
152
153 pub fn is_default(&self) -> bool {
155 matches!(self, Self::Default)
156 }
157
158 pub fn is_value(&self) -> bool {
160 matches!(self, Self::Value(..))
161 }
162
163 pub fn is_stmt(&self) -> bool {
165 matches!(self, Self::Stmt(..))
166 }
167
168 pub fn is_binary_op(&self) -> bool {
170 matches!(self, Self::BinaryOp(..))
171 }
172
173 pub fn is_arg(&self) -> bool {
175 matches!(self, Self::Arg(_))
176 }
177
178 pub fn is_always_non_nullable(&self) -> bool {
183 match self {
184 Self::Value(value) => !value.is_null(),
186 Self::And(_) | Self::Or(_) | Self::Not(_) => true,
188 Self::Any(_) => true,
190 Self::BinaryOp(_) => true,
192 Self::IsNull(_) => true,
194 Self::IsVariant(_) => true,
196 Self::Exists(_) => true,
198 Self::InList(_) | Self::InSubquery(_) => true,
200 _ => false,
202 }
203 }
204
205 pub fn into_value(self) -> Value {
211 match self {
212 Self::Value(value) => value,
213 _ => todo!(),
214 }
215 }
216
217 pub fn into_stmt(self) -> ExprStmt {
223 match self {
224 Self::Stmt(stmt) => stmt,
225 _ => todo!(),
226 }
227 }
228
229 pub fn is_stable(&self) -> bool {
233 match self {
234 Self::Value(_) => true,
236
237 Self::Default => false,
239
240 Self::Error(_) => true,
242
243 Self::Record(expr_record) => expr_record.iter().all(|expr| expr.is_stable()),
245 Self::List(expr_list) => expr_list.items.iter().all(|expr| expr.is_stable()),
246 Self::Cast(expr_cast) => expr_cast.expr.is_stable(),
247 Self::BinaryOp(expr_binary) => {
248 expr_binary.lhs.is_stable() && expr_binary.rhs.is_stable()
249 }
250 Self::And(expr_and) => expr_and.iter().all(|expr| expr.is_stable()),
251 Self::Any(expr_any) => expr_any.expr.is_stable(),
252 Self::Or(expr_or) => expr_or.iter().all(|expr| expr.is_stable()),
253 Self::IsNull(expr_is_null) => expr_is_null.expr.is_stable(),
254 Self::IsVariant(expr_is_variant) => expr_is_variant.expr.is_stable(),
255 Self::Not(expr_not) => expr_not.expr.is_stable(),
256 Self::InList(expr_in_list) => {
257 expr_in_list.expr.is_stable() && expr_in_list.list.is_stable()
258 }
259 Self::Project(expr_project) => expr_project.base.is_stable(),
260 Self::Let(expr_let) => {
261 expr_let.bindings.iter().all(|b| b.is_stable()) && expr_let.body.is_stable()
262 }
263 Self::Map(expr_map) => expr_map.base.is_stable() && expr_map.map.is_stable(),
264 Self::Match(expr_match) => {
265 expr_match.subject.is_stable()
266 && expr_match.arms.iter().all(|arm| arm.expr.is_stable())
267 }
268
269 Self::Reference(_) | Self::Arg(_) => true,
271
272 Self::Stmt(_) | Self::Func(_) | Self::InSubquery(_) | Self::Exists(_) => false,
275 }
276 }
277
278 pub fn is_const(&self) -> bool {
288 self.is_const_at_depth(0)
289 }
290
291 fn is_const_at_depth(&self, map_depth: usize) -> bool {
295 match self {
296 Self::Value(_) => true,
298
299 Self::Arg(arg) => arg.nesting < map_depth,
301
302 Self::Error(_) => true,
304
305 Self::Reference(_)
307 | Self::Stmt(_)
308 | Self::InSubquery(_)
309 | Self::Exists(_)
310 | Self::Default
311 | Self::Func(_) => false,
312
313 Self::Record(expr_record) => expr_record
315 .iter()
316 .all(|expr| expr.is_const_at_depth(map_depth)),
317 Self::List(expr_list) => expr_list
318 .items
319 .iter()
320 .all(|expr| expr.is_const_at_depth(map_depth)),
321 Self::Cast(expr_cast) => expr_cast.expr.is_const_at_depth(map_depth),
322 Self::BinaryOp(expr_binary) => {
323 expr_binary.lhs.is_const_at_depth(map_depth)
324 && expr_binary.rhs.is_const_at_depth(map_depth)
325 }
326 Self::And(expr_and) => expr_and
327 .iter()
328 .all(|expr| expr.is_const_at_depth(map_depth)),
329 Self::Any(expr_any) => expr_any.expr.is_const_at_depth(map_depth),
330 Self::Not(expr_not) => expr_not.expr.is_const_at_depth(map_depth),
331 Self::Or(expr_or) => expr_or.iter().all(|expr| expr.is_const_at_depth(map_depth)),
332 Self::IsNull(expr_is_null) => expr_is_null.expr.is_const_at_depth(map_depth),
333 Self::IsVariant(expr_is_variant) => expr_is_variant.expr.is_const_at_depth(map_depth),
334 Self::InList(expr_in_list) => {
335 expr_in_list.expr.is_const_at_depth(map_depth)
336 && expr_in_list.list.is_const_at_depth(map_depth)
337 }
338 Self::Project(expr_project) => expr_project.base.is_const_at_depth(map_depth),
339
340 Self::Let(expr_let) => {
343 expr_let
344 .bindings
345 .iter()
346 .all(|b| b.is_const_at_depth(map_depth))
347 && expr_let.body.is_const_at_depth(map_depth + 1)
348 }
349 Self::Map(expr_map) => {
352 expr_map.base.is_const_at_depth(map_depth)
353 && expr_map.map.is_const_at_depth(map_depth + 1)
354 }
355 Self::Match(expr_match) => {
356 expr_match.subject.is_const_at_depth(map_depth)
357 && expr_match
358 .arms
359 .iter()
360 .all(|arm| arm.expr.is_const_at_depth(map_depth))
361 }
362 }
363 }
364
365 pub fn is_eval(&self) -> bool {
371 match self {
372 Self::Value(_) => true,
374
375 Self::Arg(_) => true,
377
378 Self::Error(_) => true,
380
381 Self::Default
383 | Self::Reference(_)
384 | Self::Stmt(_)
385 | Self::InSubquery(_)
386 | Self::Exists(_) => false,
387
388 Self::Record(expr_record) => expr_record.iter().all(|expr| expr.is_eval()),
390 Self::List(expr_list) => expr_list.items.iter().all(|expr| expr.is_eval()),
391 Self::Cast(expr_cast) => expr_cast.expr.is_eval(),
392 Self::BinaryOp(expr_binary) => expr_binary.lhs.is_eval() && expr_binary.rhs.is_eval(),
393 Self::And(expr_and) => expr_and.iter().all(|expr| expr.is_eval()),
394 Self::Any(expr_any) => expr_any.expr.is_eval(),
395 Self::Or(expr_or) => expr_or.iter().all(|expr| expr.is_eval()),
396 Self::Not(expr_not) => expr_not.expr.is_eval(),
397 Self::IsNull(expr_is_null) => expr_is_null.expr.is_eval(),
398 Self::IsVariant(expr_is_variant) => expr_is_variant.expr.is_eval(),
399 Self::InList(expr_in_list) => {
400 expr_in_list.expr.is_eval() && expr_in_list.list.is_eval()
401 }
402 Self::Project(expr_project) => expr_project.base.is_eval(),
403 Self::Let(expr_let) => {
404 expr_let.bindings.iter().all(|b| b.is_eval()) && expr_let.body.is_eval()
405 }
406 Self::Map(expr_map) => expr_map.base.is_eval() && expr_map.map.is_eval(),
407 Self::Match(expr_match) => {
408 expr_match.subject.is_eval() && expr_match.arms.iter().all(|arm| arm.expr.is_eval())
409 }
410 Self::Func(_) => false,
411 }
412 }
413
414 pub fn map_projections(&self, f: impl FnMut(&Projection) -> Projection) -> Self {
417 struct MapProjections<T>(T);
418
419 impl<T: FnMut(&Projection) -> Projection> VisitMut for MapProjections<T> {
420 fn visit_projection_mut(&mut self, i: &mut Projection) {
421 *i = self.0(i);
422 }
423 }
424
425 let mut mapped = self.clone();
426 MapProjections(f).visit_expr_mut(&mut mapped);
427 mapped
428 }
429
430 #[track_caller]
436 pub fn entry(&self, path: impl EntryPath) -> Option<Entry<'_>> {
437 let mut ret = Entry::Expr(self);
438
439 for step in path.step_iter() {
440 ret = match ret {
441 Entry::Expr(Self::Record(expr)) => Entry::Expr(&expr[step]),
442 Entry::Expr(Self::List(expr)) => Entry::Expr(&expr.items[step]),
443 Entry::Value(Value::Record(record))
444 | Entry::Expr(Self::Value(Value::Record(record))) => Entry::Value(&record[step]),
445 Entry::Value(Value::List(items)) | Entry::Expr(Self::Value(Value::List(items))) => {
446 Entry::Value(&items[step])
447 }
448 _ => return None,
449 }
450 }
451
452 Some(ret)
453 }
454
455 #[track_caller]
462 pub fn entry_mut(&mut self, path: impl EntryPath) -> EntryMut<'_> {
463 let mut ret = EntryMut::Expr(self);
464
465 for step in path.step_iter() {
466 ret = match ret {
467 EntryMut::Expr(Self::Record(expr)) => EntryMut::Expr(&mut expr[step]),
468 EntryMut::Value(Value::Record(record))
469 | EntryMut::Expr(Self::Value(Value::Record(record))) => {
470 EntryMut::Value(&mut record[step])
471 }
472 _ => todo!("ret={ret:#?}; step={step:#?}"),
473 }
474 }
475
476 ret
477 }
478
479 pub fn take(&mut self) -> Self {
482 std::mem::replace(self, Self::Value(Value::Null))
483 }
484
485 pub fn substitute(&mut self, input: impl Input) {
488 Substitute::new(input).visit_expr_mut(self);
489 }
490}
491
492impl Node for Expr {
493 fn visit<V: Visit>(&self, mut visit: V) {
494 visit.visit_expr(self);
495 }
496
497 fn visit_mut<V: VisitMut>(&mut self, mut visit: V) {
498 visit.visit_expr_mut(self);
499 }
500}
501
502impl From<bool> for Expr {
505 fn from(value: bool) -> Self {
506 Self::Value(Value::from(value))
507 }
508}
509
510impl From<i64> for Expr {
511 fn from(value: i64) -> Self {
512 Self::Value(value.into())
513 }
514}
515
516impl From<&i64> for Expr {
517 fn from(value: &i64) -> Self {
518 Self::Value(value.into())
519 }
520}
521
522impl From<String> for Expr {
523 fn from(value: String) -> Self {
524 Self::Value(value.into())
525 }
526}
527
528impl From<&String> for Expr {
529 fn from(value: &String) -> Self {
530 Self::Value(value.into())
531 }
532}
533
534impl From<&str> for Expr {
535 fn from(value: &str) -> Self {
536 Self::Value(value.into())
537 }
538}
539
540impl From<Value> for Expr {
541 fn from(value: Value) -> Self {
542 Self::Value(value)
543 }
544}
545
546impl<E1, E2> From<(E1, E2)> for Expr
547where
548 E1: Into<Self>,
549 E2: Into<Self>,
550{
551 fn from(value: (E1, E2)) -> Self {
552 Self::Record(value.into())
553 }
554}
555
556impl fmt::Debug for Expr {
557 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
558 match self {
559 Self::And(e) => e.fmt(f),
560 Self::Any(e) => e.fmt(f),
561 Self::Arg(e) => e.fmt(f),
562 Self::BinaryOp(e) => e.fmt(f),
563 Self::Cast(e) => e.fmt(f),
564 Self::Default => write!(f, "Default"),
565 Self::Error(e) => e.fmt(f),
566 Self::Exists(e) => e.fmt(f),
567 Self::Func(e) => e.fmt(f),
568 Self::InList(e) => e.fmt(f),
569 Self::InSubquery(e) => e.fmt(f),
570 Self::IsNull(e) => e.fmt(f),
571 Self::IsVariant(e) => e.fmt(f),
572 Self::Let(e) => e.fmt(f),
573 Self::Map(e) => e.fmt(f),
574 Self::Match(e) => e.fmt(f),
575 Self::Not(e) => e.fmt(f),
576 Self::Or(e) => e.fmt(f),
577 Self::Project(e) => e.fmt(f),
578 Self::Record(e) => e.fmt(f),
579 Self::Reference(e) => e.fmt(f),
580 Self::List(e) => e.fmt(f),
581 Self::Stmt(e) => e.fmt(f),
582 Self::Value(e) => e.fmt(f),
583 }
584 }
585}