Skip to main content

reifydb_rql/expression/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4pub mod fragment;
5pub mod join;
6pub mod json;
7pub mod name;
8
9use crate::{
10	ast,
11	ast::{
12		ast::{Ast, AstInfix, AstLiteral, InfixOperator},
13		parse_str,
14	},
15	bump::{Bump, BumpBox},
16	convert_data_type,
17};
18
19pub fn parse_expression(rql: &str) -> Result<Vec<Expression>> {
20	let bump = Bump::new();
21	let statements = parse_str(&bump, rql)?;
22	if statements.is_empty() {
23		return Ok(vec![]);
24	}
25
26	let mut result = Vec::new();
27	for statement in statements {
28		for ast in statement.nodes {
29			result.push(ExpressionCompiler::compile(ast)?);
30		}
31	}
32
33	Ok(result)
34}
35
36use std::{
37	fmt,
38	fmt::{Display, Formatter},
39	str::FromStr,
40	sync::Arc,
41};
42
43use ast::ast::AstMatchArm;
44use reifydb_core::interface::identifier::{ColumnIdentifier, ColumnPrimitive};
45use reifydb_type::{
46	err,
47	error::Diagnostic,
48	fragment::Fragment,
49	value::{row_number::ROW_NUMBER_COLUMN_NAME, r#type::Type},
50};
51use serde::{Deserialize, Serialize};
52
53use crate::{Result, ast::ast::AstBlock, diagnostic::AstError};
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct AliasExpression {
57	pub alias: IdentExpression,
58	pub expression: Box<Expression>,
59	pub fragment: Fragment,
60}
61
62impl Display for AliasExpression {
63	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
64		Display::fmt(&self.alias, f)
65	}
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub enum Expression {
70	AccessSource(AccessPrimitiveExpression),
71
72	Alias(AliasExpression),
73
74	Cast(CastExpression),
75
76	Constant(ConstantExpression),
77
78	Column(ColumnExpression),
79
80	Add(AddExpression),
81
82	Div(DivExpression),
83
84	Call(CallExpression),
85
86	Rem(RemExpression),
87
88	Mul(MulExpression),
89
90	Sub(SubExpression),
91
92	Tuple(TupleExpression),
93
94	List(ListExpression),
95
96	Prefix(PrefixExpression),
97
98	GreaterThan(GreaterThanExpression),
99
100	GreaterThanEqual(GreaterThanEqExpression),
101
102	LessThan(LessThanExpression),
103
104	LessThanEqual(LessThanEqExpression),
105
106	Equal(EqExpression),
107
108	NotEqual(NotEqExpression),
109
110	Between(BetweenExpression),
111
112	And(AndExpression),
113
114	Or(OrExpression),
115
116	Xor(XorExpression),
117
118	In(InExpression),
119
120	Contains(ContainsExpression),
121
122	Type(TypeExpression),
123
124	Parameter(ParameterExpression),
125	Variable(VariableExpression),
126
127	If(IfExpression),
128	Map(MapExpression),
129	Extend(ExtendExpression),
130	SumTypeConstructor(SumTypeConstructorExpression),
131	IsVariant(IsVariantExpression),
132	FieldAccess(FieldAccessExpression),
133}
134
135#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
136pub struct AccessPrimitiveExpression {
137	pub column: ColumnIdentifier,
138}
139
140impl AccessPrimitiveExpression {
141	pub fn full_fragment_owned(&self) -> Fragment {
142		// For backward compatibility, merge primitive and column fragments
143		match &self.column.primitive {
144			ColumnPrimitive::Primitive {
145				primitive,
146				..
147			} => Fragment::merge_all([primitive.clone(), self.column.name.clone()]),
148			ColumnPrimitive::Alias(alias) => Fragment::merge_all([alias.clone(), self.column.name.clone()]),
149		}
150	}
151}
152
153#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
154pub enum ConstantExpression {
155	None {
156		fragment: Fragment,
157	},
158	Bool {
159		fragment: Fragment,
160	},
161	// any number
162	Number {
163		fragment: Fragment,
164	},
165	// any textual representation can be String, Text, ...
166	Text {
167		fragment: Fragment,
168	},
169	// any temporal representation can be Date, Time, DateTime, ...
170	Temporal {
171		fragment: Fragment,
172	},
173}
174
175impl Display for ConstantExpression {
176	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
177		match self {
178			ConstantExpression::None {
179				..
180			} => write!(f, "none"),
181			ConstantExpression::Bool {
182				fragment,
183			} => write!(f, "{}", fragment.text()),
184			ConstantExpression::Number {
185				fragment,
186			} => write!(f, "{}", fragment.text()),
187			ConstantExpression::Text {
188				fragment,
189			} => write!(f, "\"{}\"", fragment.text()),
190			ConstantExpression::Temporal {
191				fragment,
192			} => write!(f, "{}", fragment.text()),
193		}
194	}
195}
196
197#[derive(Debug, Clone, Serialize, Deserialize)]
198pub struct CastExpression {
199	pub fragment: Fragment,
200	pub expression: Box<Expression>,
201	pub to: TypeExpression,
202}
203
204impl CastExpression {
205	pub fn full_fragment_owned(&self) -> Fragment {
206		Fragment::merge_all([
207			self.fragment.clone(),
208			self.expression.full_fragment_owned(),
209			self.to.full_fragment_owned(),
210		])
211	}
212
213	pub fn lazy_fragment(&self) -> impl Fn() -> Fragment {
214		move || self.full_fragment_owned()
215	}
216}
217
218#[derive(Debug, Clone, Serialize, Deserialize)]
219pub struct TypeExpression {
220	pub fragment: Fragment,
221	pub ty: Type,
222}
223
224impl TypeExpression {
225	pub fn full_fragment_owned(&self) -> Fragment {
226		self.fragment.clone()
227	}
228
229	pub fn lazy_fragment(&self) -> impl Fn() -> Fragment {
230		move || self.full_fragment_owned()
231	}
232}
233
234#[derive(Debug, Clone, Serialize, Deserialize)]
235pub struct AddExpression {
236	pub left: Box<Expression>,
237	pub right: Box<Expression>,
238	pub fragment: Fragment,
239}
240
241#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct DivExpression {
243	pub left: Box<Expression>,
244	pub right: Box<Expression>,
245	pub fragment: Fragment,
246}
247
248#[derive(Debug, Clone, Serialize, Deserialize)]
249pub struct SubExpression {
250	pub left: Box<Expression>,
251	pub right: Box<Expression>,
252	pub fragment: Fragment,
253}
254
255#[derive(Debug, Clone, Serialize, Deserialize)]
256pub struct RemExpression {
257	pub left: Box<Expression>,
258	pub right: Box<Expression>,
259	pub fragment: Fragment,
260}
261
262#[derive(Debug, Clone, Serialize, Deserialize)]
263pub struct MulExpression {
264	pub left: Box<Expression>,
265	pub right: Box<Expression>,
266	pub fragment: Fragment,
267}
268
269#[derive(Debug, Clone, Serialize, Deserialize)]
270pub struct GreaterThanExpression {
271	pub left: Box<Expression>,
272	pub right: Box<Expression>,
273	pub fragment: Fragment,
274}
275
276impl GreaterThanExpression {
277	pub fn full_fragment_owned(&self) -> Fragment {
278		Fragment::merge_all([
279			self.left.full_fragment_owned(),
280			self.fragment.clone(),
281			self.right.full_fragment_owned(),
282		])
283	}
284}
285
286#[derive(Debug, Clone, Serialize, Deserialize)]
287pub struct GreaterThanEqExpression {
288	pub left: Box<Expression>,
289	pub right: Box<Expression>,
290	pub fragment: Fragment,
291}
292
293impl GreaterThanEqExpression {
294	pub fn full_fragment_owned(&self) -> Fragment {
295		Fragment::merge_all([
296			self.left.full_fragment_owned(),
297			self.fragment.clone(),
298			self.right.full_fragment_owned(),
299		])
300	}
301}
302
303#[derive(Debug, Clone, Serialize, Deserialize)]
304pub struct LessThanExpression {
305	pub left: Box<Expression>,
306	pub right: Box<Expression>,
307	pub fragment: Fragment,
308}
309
310impl LessThanExpression {
311	pub fn full_fragment_owned(&self) -> Fragment {
312		Fragment::merge_all([
313			self.left.full_fragment_owned(),
314			self.fragment.clone(),
315			self.right.full_fragment_owned(),
316		])
317	}
318}
319
320#[derive(Debug, Clone, Serialize, Deserialize)]
321pub struct LessThanEqExpression {
322	pub left: Box<Expression>,
323	pub right: Box<Expression>,
324	pub fragment: Fragment,
325}
326
327impl LessThanEqExpression {
328	pub fn full_fragment_owned(&self) -> Fragment {
329		Fragment::merge_all([
330			self.left.full_fragment_owned(),
331			self.fragment.clone(),
332			self.right.full_fragment_owned(),
333		])
334	}
335}
336
337#[derive(Debug, Clone, Serialize, Deserialize)]
338pub struct EqExpression {
339	pub left: Box<Expression>,
340	pub right: Box<Expression>,
341	pub fragment: Fragment,
342}
343
344impl EqExpression {
345	pub fn full_fragment_owned(&self) -> Fragment {
346		Fragment::merge_all([
347			self.left.full_fragment_owned(),
348			self.fragment.clone(),
349			self.right.full_fragment_owned(),
350		])
351	}
352}
353
354#[derive(Debug, Clone, Serialize, Deserialize)]
355pub struct NotEqExpression {
356	pub left: Box<Expression>,
357	pub right: Box<Expression>,
358	pub fragment: Fragment,
359}
360
361impl NotEqExpression {
362	pub fn full_fragment_owned(&self) -> Fragment {
363		Fragment::merge_all([
364			self.left.full_fragment_owned(),
365			self.fragment.clone(),
366			self.right.full_fragment_owned(),
367		])
368	}
369}
370
371#[derive(Debug, Clone, Serialize, Deserialize)]
372pub struct BetweenExpression {
373	pub value: Box<Expression>,
374	pub lower: Box<Expression>,
375	pub upper: Box<Expression>,
376	pub fragment: Fragment,
377}
378
379impl BetweenExpression {
380	pub fn full_fragment_owned(&self) -> Fragment {
381		Fragment::merge_all([
382			self.value.full_fragment_owned(),
383			self.fragment.clone(),
384			self.lower.full_fragment_owned(),
385			self.upper.full_fragment_owned(),
386		])
387	}
388}
389
390#[derive(Debug, Clone, Serialize, Deserialize)]
391pub struct AndExpression {
392	pub left: Box<Expression>,
393	pub right: Box<Expression>,
394	pub fragment: Fragment,
395}
396
397impl AndExpression {
398	pub fn full_fragment_owned(&self) -> Fragment {
399		Fragment::merge_all([
400			self.left.full_fragment_owned(),
401			self.fragment.clone(),
402			self.right.full_fragment_owned(),
403		])
404	}
405}
406
407#[derive(Debug, Clone, Serialize, Deserialize)]
408pub struct OrExpression {
409	pub left: Box<Expression>,
410	pub right: Box<Expression>,
411	pub fragment: Fragment,
412}
413
414impl OrExpression {
415	pub fn full_fragment_owned(&self) -> Fragment {
416		Fragment::merge_all([
417			self.left.full_fragment_owned(),
418			self.fragment.clone(),
419			self.right.full_fragment_owned(),
420		])
421	}
422}
423
424#[derive(Debug, Clone, Serialize, Deserialize)]
425pub struct XorExpression {
426	pub left: Box<Expression>,
427	pub right: Box<Expression>,
428	pub fragment: Fragment,
429}
430
431impl XorExpression {
432	pub fn full_fragment_owned(&self) -> Fragment {
433		Fragment::merge_all([
434			self.left.full_fragment_owned(),
435			self.fragment.clone(),
436			self.right.full_fragment_owned(),
437		])
438	}
439}
440
441#[derive(Debug, Clone, Serialize, Deserialize)]
442pub struct InExpression {
443	pub value: Box<Expression>,
444	pub list: Box<Expression>,
445	pub negated: bool,
446	pub fragment: Fragment,
447}
448
449impl InExpression {
450	pub fn full_fragment_owned(&self) -> Fragment {
451		Fragment::merge_all([
452			self.value.full_fragment_owned(),
453			self.fragment.clone(),
454			self.list.full_fragment_owned(),
455		])
456	}
457}
458
459#[derive(Debug, Clone, Serialize, Deserialize)]
460pub struct ContainsExpression {
461	pub value: Box<Expression>,
462	pub list: Box<Expression>,
463	pub fragment: Fragment,
464}
465
466impl ContainsExpression {
467	pub fn full_fragment_owned(&self) -> Fragment {
468		Fragment::merge_all([
469			self.value.full_fragment_owned(),
470			self.fragment.clone(),
471			self.list.full_fragment_owned(),
472		])
473	}
474}
475
476#[derive(Debug, Clone, Serialize, Deserialize)]
477pub struct ColumnExpression(pub ColumnIdentifier);
478
479impl ColumnExpression {
480	pub fn full_fragment_owned(&self) -> Fragment {
481		// Return just the column name for unqualified column references
482		self.0.name.clone()
483	}
484
485	pub fn column(&self) -> &ColumnIdentifier {
486		&self.0
487	}
488}
489
490impl Display for Expression {
491	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
492		match self {
493			Expression::AccessSource(AccessPrimitiveExpression {
494				column,
495			}) => match &column.primitive {
496				ColumnPrimitive::Primitive {
497					primitive,
498					..
499				} => {
500					write!(f, "{}.{}", primitive.text(), column.name.text())
501				}
502				ColumnPrimitive::Alias(alias) => {
503					write!(f, "{}.{}", alias.text(), column.name.text())
504				}
505			},
506			Expression::Alias(AliasExpression {
507				alias,
508				expression,
509				..
510			}) => {
511				write!(f, "{} as {}", expression, alias)
512			}
513			Expression::Cast(CastExpression {
514				expression: expr,
515				..
516			}) => write!(f, "{}", expr),
517			Expression::Constant(fragment) => {
518				write!(f, "Constant({})", fragment)
519			}
520			Expression::Column(ColumnExpression(column)) => {
521				write!(f, "{}", column.name.text())
522			}
523			Expression::Add(AddExpression {
524				left,
525				right,
526				..
527			}) => {
528				write!(f, "({} + {})", left, right)
529			}
530			Expression::Div(DivExpression {
531				left,
532				right,
533				..
534			}) => {
535				write!(f, "({} / {})", left, right)
536			}
537			Expression::Call(call) => write!(f, "{}", call),
538			Expression::Rem(RemExpression {
539				left,
540				right,
541				..
542			}) => {
543				write!(f, "({} % {})", left, right)
544			}
545			Expression::Mul(MulExpression {
546				left,
547				right,
548				..
549			}) => {
550				write!(f, "({} * {})", left, right)
551			}
552			Expression::Sub(SubExpression {
553				left,
554				right,
555				..
556			}) => {
557				write!(f, "({} - {})", left, right)
558			}
559			Expression::Tuple(tuple) => write!(f, "({})", tuple),
560			Expression::List(list) => write!(f, "{}", list),
561			Expression::Prefix(prefix) => write!(f, "{}", prefix),
562			Expression::GreaterThan(GreaterThanExpression {
563				left,
564				right,
565				..
566			}) => {
567				write!(f, "({} > {})", left, right)
568			}
569			Expression::GreaterThanEqual(GreaterThanEqExpression {
570				left,
571				right,
572				..
573			}) => {
574				write!(f, "({} >= {})", left, right)
575			}
576			Expression::LessThan(LessThanExpression {
577				left,
578				right,
579				..
580			}) => {
581				write!(f, "({} < {})", left, right)
582			}
583			Expression::LessThanEqual(LessThanEqExpression {
584				left,
585				right,
586				..
587			}) => {
588				write!(f, "({} <= {})", left, right)
589			}
590			Expression::Equal(EqExpression {
591				left,
592				right,
593				..
594			}) => {
595				write!(f, "({} == {})", left, right)
596			}
597			Expression::NotEqual(NotEqExpression {
598				left,
599				right,
600				..
601			}) => {
602				write!(f, "({} != {})", left, right)
603			}
604			Expression::Between(BetweenExpression {
605				value,
606				lower,
607				upper,
608				..
609			}) => {
610				write!(f, "({} BETWEEN {} AND {})", value, lower, upper)
611			}
612			Expression::And(AndExpression {
613				left,
614				right,
615				..
616			}) => {
617				write!(f, "({} and {})", left, right)
618			}
619			Expression::Or(OrExpression {
620				left,
621				right,
622				..
623			}) => {
624				write!(f, "({} or {})", left, right)
625			}
626			Expression::Xor(XorExpression {
627				left,
628				right,
629				..
630			}) => {
631				write!(f, "({} xor {})", left, right)
632			}
633			Expression::In(InExpression {
634				value,
635				list,
636				negated,
637				..
638			}) => {
639				if *negated {
640					write!(f, "({} NOT IN {})", value, list)
641				} else {
642					write!(f, "({} IN {})", value, list)
643				}
644			}
645			Expression::Contains(ContainsExpression {
646				value,
647				list,
648				..
649			}) => {
650				write!(f, "({} CONTAINS {})", value, list)
651			}
652			Expression::Type(TypeExpression {
653				fragment,
654				..
655			}) => write!(f, "{}", fragment.text()),
656			Expression::Parameter(param) => match param {
657				ParameterExpression::Positional {
658					fragment,
659					..
660				} => write!(f, "{}", fragment.text()),
661				ParameterExpression::Named {
662					fragment,
663				} => write!(f, "{}", fragment.text()),
664			},
665			Expression::Variable(var) => write!(f, "{}", var.fragment.text()),
666			Expression::If(if_expr) => write!(f, "{}", if_expr),
667			Expression::Map(map_expr) => write!(
668				f,
669				"MAP{{ {} }}",
670				map_expr.expressions
671					.iter()
672					.map(|expr| format!("{}", expr))
673					.collect::<Vec<_>>()
674					.join(", ")
675			),
676			Expression::Extend(extend_expr) => write!(
677				f,
678				"EXTEND{{ {} }}",
679				extend_expr
680					.expressions
681					.iter()
682					.map(|expr| format!("{}", expr))
683					.collect::<Vec<_>>()
684					.join(", ")
685			),
686			Expression::SumTypeConstructor(ctor) => write!(
687				f,
688				"{}::{}{{ {} }}",
689				ctor.sumtype_name.text(),
690				ctor.variant_name.text(),
691				ctor.columns
692					.iter()
693					.map(|(name, expr)| format!("{}: {}", name.text(), expr))
694					.collect::<Vec<_>>()
695					.join(", ")
696			),
697			Expression::IsVariant(e) => write!(f, "({} IS {})", e.expression, e.variant_name.text()),
698			Expression::FieldAccess(field_access) => write!(f, "{}", field_access),
699		}
700	}
701}
702
703#[derive(Debug, Clone, Serialize, Deserialize)]
704pub struct CallExpression {
705	pub func: IdentExpression,
706	pub args: Vec<Expression>,
707	pub fragment: Fragment,
708}
709
710impl CallExpression {
711	pub fn full_fragment_owned(&self) -> Fragment {
712		Fragment::Statement {
713			column: self.func.0.column(),
714			line: self.func.0.line(),
715			text: Arc::from(format!(
716				"{}({})",
717				self.func.0.text(),
718				self.args
719					.iter()
720					.map(|arg| arg.full_fragment_owned().text().to_string())
721					.collect::<Vec<_>>()
722					.join(",")
723			)),
724		}
725	}
726}
727
728impl Display for CallExpression {
729	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
730		let args = self.args.iter().map(|arg| format!("{}", arg)).collect::<Vec<_>>().join(", ");
731		write!(f, "{}({})", self.func, args)
732	}
733}
734
735#[derive(Debug, Clone, Serialize, Deserialize)]
736pub struct IdentExpression(pub Fragment);
737
738#[derive(Debug, Clone, Serialize, Deserialize)]
739pub enum ParameterExpression {
740	Positional {
741		fragment: Fragment,
742	},
743	Named {
744		fragment: Fragment,
745	},
746}
747
748impl ParameterExpression {
749	pub fn position(&self) -> Option<u32> {
750		match self {
751			ParameterExpression::Positional {
752				fragment,
753			} => fragment.text()[1..].parse().ok(),
754			ParameterExpression::Named {
755				..
756			} => None,
757		}
758	}
759
760	pub fn name(&self) -> Option<&str> {
761		match self {
762			ParameterExpression::Named {
763				fragment,
764			} => Some(&fragment.text()[1..]),
765			ParameterExpression::Positional {
766				..
767			} => None,
768		}
769	}
770}
771
772#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
773pub struct VariableExpression {
774	pub fragment: Fragment,
775}
776
777impl VariableExpression {
778	pub fn name(&self) -> &str {
779		// Extract variable name from token value (skip the '$')
780		let text = self.fragment.text();
781		if text.starts_with('$') {
782			&text[1..]
783		} else {
784			text
785		}
786	}
787}
788
789#[derive(Debug, Clone, Serialize, Deserialize)]
790pub struct IfExpression {
791	pub condition: Box<Expression>,
792	pub then_expr: Box<Expression>,
793	pub else_ifs: Vec<ElseIfExpression>,
794	pub else_expr: Option<Box<Expression>>,
795	pub fragment: Fragment,
796}
797
798#[derive(Debug, Clone, Serialize, Deserialize)]
799pub struct ElseIfExpression {
800	pub condition: Box<Expression>,
801	pub then_expr: Box<Expression>,
802	pub fragment: Fragment,
803}
804
805impl IfExpression {
806	pub fn full_fragment_owned(&self) -> Fragment {
807		self.fragment.clone()
808	}
809
810	pub fn lazy_fragment(&self) -> impl Fn() -> Fragment {
811		move || self.full_fragment_owned()
812	}
813}
814
815impl Display for IfExpression {
816	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
817		write!(f, "if {} {{ {} }}", self.condition, self.then_expr)?;
818
819		for else_if in &self.else_ifs {
820			write!(f, " else if {} {{ {} }}", else_if.condition, else_if.then_expr)?;
821		}
822
823		if let Some(else_expr) = &self.else_expr {
824			write!(f, " else {{ {} }}", else_expr)?;
825		}
826
827		Ok(())
828	}
829}
830
831impl IdentExpression {
832	pub fn name(&self) -> &str {
833		self.0.text()
834	}
835}
836
837impl Display for IdentExpression {
838	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
839		write!(f, "{}", self.0.text())
840	}
841}
842
843#[derive(Debug, Clone, Serialize, Deserialize)]
844pub enum PrefixOperator {
845	Minus(Fragment),
846	Plus(Fragment),
847	Not(Fragment),
848}
849
850impl PrefixOperator {
851	pub fn full_fragment_owned(&self) -> Fragment {
852		match self {
853			PrefixOperator::Minus(fragment) => fragment.clone(),
854			PrefixOperator::Plus(fragment) => fragment.clone(),
855			PrefixOperator::Not(fragment) => fragment.clone(),
856		}
857	}
858}
859
860impl Display for PrefixOperator {
861	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
862		match self {
863			PrefixOperator::Minus(_) => write!(f, "-"),
864			PrefixOperator::Plus(_) => write!(f, "+"),
865			PrefixOperator::Not(_) => write!(f, "not"),
866		}
867	}
868}
869
870#[derive(Debug, Clone, Serialize, Deserialize)]
871pub struct PrefixExpression {
872	pub operator: PrefixOperator,
873	pub expression: Box<Expression>,
874	pub fragment: Fragment,
875}
876
877impl PrefixExpression {
878	pub fn full_fragment_owned(&self) -> Fragment {
879		Fragment::merge_all([self.operator.full_fragment_owned(), self.expression.full_fragment_owned()])
880	}
881}
882
883impl Display for PrefixExpression {
884	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
885		write!(f, "({}{})", self.operator, self.expression)
886	}
887}
888
889#[derive(Debug, Clone, Serialize, Deserialize)]
890pub struct TupleExpression {
891	pub expressions: Vec<Expression>,
892	pub fragment: Fragment,
893}
894
895impl Display for TupleExpression {
896	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
897		let items = self.expressions.iter().map(|e| format!("{}", e)).collect::<Vec<_>>().join(", ");
898		write!(f, "({})", items)
899	}
900}
901
902#[derive(Debug, Clone, Serialize, Deserialize)]
903pub struct ListExpression {
904	pub expressions: Vec<Expression>,
905	pub fragment: Fragment,
906}
907
908impl Display for ListExpression {
909	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
910		let items = self.expressions.iter().map(|e| format!("{}", e)).collect::<Vec<_>>().join(", ");
911		write!(f, "[{}]", items)
912	}
913}
914
915pub struct ExpressionCompiler {}
916
917impl ExpressionCompiler {
918	pub fn compile(ast: Ast<'_>) -> Result<Expression> {
919		match ast {
920			Ast::Literal(literal) => match literal {
921				AstLiteral::Boolean(_) => Ok(Expression::Constant(ConstantExpression::Bool {
922					fragment: literal.fragment().to_owned(),
923				})),
924				AstLiteral::Number(_) => Ok(Expression::Constant(ConstantExpression::Number {
925					fragment: literal.fragment().to_owned(),
926				})),
927				AstLiteral::Temporal(_) => Ok(Expression::Constant(ConstantExpression::Temporal {
928					fragment: literal.fragment().to_owned(),
929				})),
930				AstLiteral::Text(_) => Ok(Expression::Constant(ConstantExpression::Text {
931					fragment: literal.fragment().to_owned(),
932				})),
933				AstLiteral::None(_) => Ok(Expression::Constant(ConstantExpression::None {
934					fragment: literal.fragment().to_owned(),
935				})),
936			},
937			Ast::Identifier(identifier) => {
938				// Create an unqualified column identifier
939
940				let column = ColumnIdentifier {
941					primitive: ColumnPrimitive::Primitive {
942						namespace: Fragment::Internal {
943							text: Arc::from("_context"),
944						},
945						primitive: Fragment::Internal {
946							text: Arc::from("_context"),
947						},
948					},
949					name: identifier.token.fragment.to_owned(),
950				};
951				Ok(Expression::Column(ColumnExpression(column)))
952			}
953			Ast::CallFunction(call) => {
954				// Build the full function name from namespace + function
955				let full_name = if call.function.namespaces.is_empty() {
956					call.function.name.text().to_string()
957				} else {
958					let namespace_path = call
959						.function
960						.namespaces
961						.iter()
962						.map(|ns| ns.text())
963						.collect::<Vec<_>>()
964						.join("::");
965					format!("{}::{}", namespace_path, call.function.name.text())
966				};
967
968				// Compile arguments
969				let mut arg_expressions = Vec::new();
970				for arg_ast in call.arguments.nodes {
971					let compiled = Self::compile(arg_ast)?;
972					let compiled = match &compiled {
973						Expression::Column(col_expr) => {
974							if let Ok(ty) = Type::from_str(col_expr.0.name.text()) {
975								Expression::Type(TypeExpression {
976									fragment: col_expr.0.name.clone(),
977									ty,
978								})
979							} else {
980								compiled
981							}
982						}
983						_ => compiled,
984					};
985					arg_expressions.push(compiled);
986				}
987
988				Ok(Expression::Call(CallExpression {
989					func: IdentExpression(Fragment::testing(&full_name)),
990					args: arg_expressions,
991					fragment: call.token.fragment.to_owned(),
992				}))
993			}
994			Ast::Infix(ast) => Self::infix(ast),
995			Ast::Between(between) => {
996				let value = Self::compile(BumpBox::into_inner(between.value))?;
997				let lower = Self::compile(BumpBox::into_inner(between.lower))?;
998				let upper = Self::compile(BumpBox::into_inner(between.upper))?;
999
1000				Ok(Expression::Between(BetweenExpression {
1001					value: Box::new(value),
1002					lower: Box::new(lower),
1003					upper: Box::new(upper),
1004					fragment: between.token.fragment.to_owned(),
1005				}))
1006			}
1007			Ast::Tuple(tuple) => {
1008				let mut expressions = Vec::with_capacity(tuple.len());
1009
1010				for ast in tuple.nodes {
1011					expressions.push(Self::compile(ast)?);
1012				}
1013
1014				Ok(Expression::Tuple(TupleExpression {
1015					expressions,
1016					fragment: tuple.token.fragment.to_owned(),
1017				}))
1018			}
1019			Ast::Prefix(prefix) => {
1020				let (fragment, operator) = match prefix.operator {
1021					ast::ast::AstPrefixOperator::Plus(token) => (
1022						token.fragment.to_owned(),
1023						PrefixOperator::Plus(token.fragment.to_owned()),
1024					),
1025					ast::ast::AstPrefixOperator::Negate(token) => (
1026						token.fragment.to_owned(),
1027						PrefixOperator::Minus(token.fragment.to_owned()),
1028					),
1029					ast::ast::AstPrefixOperator::Not(token) => (
1030						token.fragment.to_owned(),
1031						PrefixOperator::Not(token.fragment.to_owned()),
1032					),
1033				};
1034
1035				Ok(Expression::Prefix(PrefixExpression {
1036					operator,
1037					expression: Box::new(Self::compile(BumpBox::into_inner(prefix.node))?),
1038					fragment,
1039				}))
1040			}
1041			Ast::Cast(node) => {
1042				let mut tuple = node.tuple;
1043				let node = tuple.nodes.pop().unwrap();
1044				let bump_fragment = node.as_identifier().token.fragment;
1045				let ty = convert_data_type(&bump_fragment)?;
1046				let fragment = bump_fragment.to_owned();
1047
1048				let expr = tuple.nodes.pop().unwrap();
1049
1050				Ok(Expression::Cast(CastExpression {
1051					fragment: tuple.token.fragment.to_owned(),
1052					expression: Box::new(Self::compile(expr)?),
1053					to: TypeExpression {
1054						fragment,
1055						ty,
1056					},
1057				}))
1058			}
1059			Ast::Variable(var) => Ok(Expression::Variable(VariableExpression {
1060				fragment: var.token.fragment.to_owned(),
1061			})),
1062			Ast::Rownum(_rownum) => {
1063				// Compile rownum to a column reference for rownum
1064
1065				let column = ColumnIdentifier {
1066					primitive: ColumnPrimitive::Primitive {
1067						namespace: Fragment::Internal {
1068							text: Arc::from("_context"),
1069						},
1070						primitive: Fragment::Internal {
1071							text: Arc::from("_context"),
1072						},
1073					},
1074					name: Fragment::Internal {
1075						text: Arc::from(ROW_NUMBER_COLUMN_NAME),
1076					},
1077				};
1078				Ok(Expression::Column(ColumnExpression(column)))
1079			}
1080			Ast::If(if_ast) => {
1081				// Compile condition
1082				let condition = Box::new(Self::compile(BumpBox::into_inner(if_ast.condition))?);
1083
1084				// Compile then expression (take first expression from first statement in block)
1085				let then_expr = Box::new(Self::compile_block_as_expr(if_ast.then_block)?);
1086
1087				// Compile else_if chains
1088				let mut else_ifs = Vec::new();
1089				for else_if in if_ast.else_ifs {
1090					let else_if_condition =
1091						Box::new(Self::compile(BumpBox::into_inner(else_if.condition))?);
1092					let else_if_then = Box::new(Self::compile_block_as_expr(else_if.then_block)?);
1093					else_ifs.push(ElseIfExpression {
1094						condition: else_if_condition,
1095						then_expr: else_if_then,
1096						fragment: else_if.token.fragment.to_owned(),
1097					});
1098				}
1099
1100				// Compile optional else expression
1101				let else_expr = if let Some(else_block) = if_ast.else_block {
1102					Some(Box::new(Self::compile_block_as_expr(else_block)?))
1103				} else {
1104					None
1105				};
1106
1107				Ok(Expression::If(IfExpression {
1108					condition,
1109					then_expr,
1110					else_ifs,
1111					else_expr,
1112					fragment: if_ast.token.fragment.to_owned(),
1113				}))
1114			}
1115			Ast::Map(map) => {
1116				// Compile expressions in the map
1117				let mut expressions = Vec::with_capacity(map.nodes.len());
1118				for node in map.nodes {
1119					expressions.push(Self::compile(node)?);
1120				}
1121
1122				Ok(Expression::Map(MapExpression {
1123					expressions,
1124					fragment: map.token.fragment.to_owned(),
1125				}))
1126			}
1127			Ast::Extend(extend) => {
1128				// Compile expressions in the extend
1129				let mut expressions = Vec::with_capacity(extend.nodes.len());
1130				for node in extend.nodes {
1131					expressions.push(Self::compile(node)?);
1132				}
1133
1134				Ok(Expression::Extend(ExtendExpression {
1135					expressions,
1136					fragment: extend.token.fragment.to_owned(),
1137				}))
1138			}
1139			Ast::List(list) => {
1140				// Compile list expressions (used for IN [...] syntax)
1141				let mut expressions = Vec::with_capacity(list.nodes.len());
1142				for ast in list.nodes {
1143					expressions.push(Self::compile(ast)?);
1144				}
1145				Ok(Expression::List(ListExpression {
1146					expressions,
1147					fragment: list.token.fragment.to_owned(),
1148				}))
1149			}
1150			Ast::SumTypeConstructor(ctor) => {
1151				let mut columns = Vec::with_capacity(ctor.columns.keyed_values.len());
1152				for kv in ctor.columns.keyed_values {
1153					let name = kv.key.token.fragment.to_owned();
1154					let expr = Self::compile(BumpBox::into_inner(kv.value))?;
1155					columns.push((name, expr));
1156				}
1157				Ok(Expression::SumTypeConstructor(SumTypeConstructorExpression {
1158					namespace: ctor.namespace.to_owned(),
1159					sumtype_name: ctor.sumtype_name.to_owned(),
1160					variant_name: ctor.variant_name.to_owned(),
1161					columns,
1162					fragment: ctor.token.fragment.to_owned(),
1163				}))
1164			}
1165			Ast::IsVariant(is) => {
1166				let expression = Self::compile(BumpBox::into_inner(is.expression))?;
1167				Ok(Expression::IsVariant(IsVariantExpression {
1168					expression: Box::new(expression),
1169					namespace: is.namespace.map(|n| n.to_owned()),
1170					sumtype_name: is.sumtype_name.to_owned(),
1171					variant_name: is.variant_name.to_owned(),
1172					tag: None,
1173					fragment: is.token.fragment.to_owned(),
1174				}))
1175			}
1176			Ast::Match(match_ast) => Self::compile_match(match_ast),
1177			Ast::Identity(ident) => Ok(Expression::Variable(VariableExpression {
1178				fragment: ident.token.fragment.to_owned(),
1179			})),
1180			ast => unimplemented!("{:?}", ast),
1181		}
1182	}
1183
1184	/// Compile an AstBlock as a single expression.
1185	/// Takes the first expression from the first statement in the block.
1186	/// Used for IF/ELSE blocks in expression context.
1187	fn compile_block_as_expr(block: AstBlock<'_>) -> Result<Expression> {
1188		let fragment = block.token.fragment.to_owned();
1189		if let Some(first_stmt) = block.statements.into_iter().next() {
1190			if let Some(first_node) = first_stmt.nodes.into_iter().next() {
1191				return Self::compile(first_node);
1192			}
1193		}
1194		// Empty block → none
1195		Ok(Expression::Constant(ConstantExpression::None {
1196			fragment,
1197		}))
1198	}
1199
1200	/// Compile a MATCH expression by lowering it to an IfExpression.
1201	fn compile_match(match_ast: ast::ast::AstMatch<'_>) -> Result<Expression> {
1202		let fragment = match_ast.token.fragment.to_owned();
1203
1204		// Compile subject expression (if present)
1205		let subject = match match_ast.subject {
1206			Some(s) => Some(Self::compile(BumpBox::into_inner(s))?),
1207			None => None,
1208		};
1209
1210		// Extract the subject column name for field rewriting (if subject is a simple column)
1211		let subject_col_name = subject.as_ref().and_then(|s| match s {
1212			Expression::Column(ColumnExpression(col)) => Some(col.name.text().to_string()),
1213			_ => None,
1214		});
1215
1216		// Build list of (condition, result) pairs + optional else
1217		let mut branches: Vec<(Expression, Expression)> = Vec::new();
1218		let mut else_result: Option<Expression> = None;
1219
1220		for arm in match_ast.arms {
1221			match arm {
1222				AstMatchArm::Else {
1223					result,
1224				} => {
1225					else_result = Some(Self::compile(BumpBox::into_inner(result))?);
1226				}
1227				AstMatchArm::Value {
1228					pattern,
1229					guard,
1230					result,
1231				} => {
1232					let subject_expr = subject.clone().expect("Value arm requires a MATCH subject");
1233					let pattern_expr = Self::compile(BumpBox::into_inner(pattern))?;
1234
1235					// condition = subject == pattern
1236					let mut condition = Expression::Equal(EqExpression {
1237						left: Box::new(subject_expr),
1238						right: Box::new(pattern_expr),
1239						fragment: fragment.clone(),
1240					});
1241
1242					// If guard, condition = condition AND guard
1243					if let Some(guard) = guard {
1244						let guard_expr = Self::compile(BumpBox::into_inner(guard))?;
1245						condition = Expression::And(AndExpression {
1246							left: Box::new(condition),
1247							right: Box::new(guard_expr),
1248							fragment: fragment.clone(),
1249						});
1250					}
1251
1252					let result_expr = Self::compile(BumpBox::into_inner(result))?;
1253					branches.push((condition, result_expr));
1254				}
1255				AstMatchArm::IsVariant {
1256					namespace,
1257					sumtype_name,
1258					variant_name,
1259					destructure,
1260					guard,
1261					result,
1262				} => {
1263					let subject_expr = subject.clone().expect("IS arm requires a MATCH subject");
1264
1265					// Build field bindings for rewriting
1266					let bindings: Vec<(String, String)> = match (&destructure, &subject_col_name) {
1267						(Some(destr), Some(col_name)) => {
1268							let variant_lower = variant_name.text().to_lowercase();
1269							destr.fields
1270								.iter()
1271								.map(|f| {
1272									let field_name = f.text().to_string();
1273									let physical = format!(
1274										"{}_{}_{}",
1275										col_name,
1276										variant_lower,
1277										field_name.to_lowercase()
1278									);
1279									(field_name, physical)
1280								})
1281								.collect()
1282						}
1283						_ => vec![],
1284					};
1285
1286					// condition = subject IS [ns.]Type::Variant
1287					let mut condition = Expression::IsVariant(IsVariantExpression {
1288						expression: Box::new(subject_expr),
1289						namespace: namespace.map(|n| n.to_owned()),
1290						sumtype_name: sumtype_name.to_owned(),
1291						variant_name: variant_name.to_owned(),
1292						tag: None,
1293						fragment: fragment.clone(),
1294					});
1295
1296					// If guard, rewrite field refs in guard, then AND
1297					if let Some(guard) = guard {
1298						let mut guard_expr = Self::compile(BumpBox::into_inner(guard))?;
1299						Self::rewrite_field_refs(&mut guard_expr, &bindings);
1300						condition = Expression::And(AndExpression {
1301							left: Box::new(condition),
1302							right: Box::new(guard_expr),
1303							fragment: fragment.clone(),
1304						});
1305					}
1306
1307					let mut result_expr = Self::compile(BumpBox::into_inner(result))?;
1308					Self::rewrite_field_refs(&mut result_expr, &bindings);
1309					branches.push((condition, result_expr));
1310				}
1311				AstMatchArm::Variant {
1312					variant_name,
1313					destructure,
1314					guard,
1315					result,
1316				} => {
1317					let subject_expr =
1318						subject.clone().expect("Variant arm requires a MATCH subject");
1319
1320					// Build field bindings for rewriting
1321					let bindings: Vec<(String, String)> = match (&destructure, &subject_col_name) {
1322						(Some(destr), Some(col_name)) => {
1323							let variant_lower = variant_name.text().to_lowercase();
1324							destr.fields
1325								.iter()
1326								.map(|f| {
1327									let field_name = f.text().to_string();
1328									let physical = format!(
1329										"{}_{}_{}",
1330										col_name,
1331										variant_lower,
1332										field_name.to_lowercase()
1333									);
1334									(field_name, physical)
1335								})
1336								.collect()
1337						}
1338						_ => vec![],
1339					};
1340
1341					// condition = subject IS Variant (placeholder sumtype_name = variant_name)
1342					let mut condition = Expression::IsVariant(IsVariantExpression {
1343						expression: Box::new(subject_expr),
1344						namespace: None,
1345						sumtype_name: variant_name.to_owned(),
1346						variant_name: variant_name.to_owned(),
1347						tag: None,
1348						fragment: fragment.clone(),
1349					});
1350
1351					// If guard, rewrite field refs in guard, then AND
1352					if let Some(guard) = guard {
1353						let mut guard_expr = Self::compile(BumpBox::into_inner(guard))?;
1354						Self::rewrite_field_refs(&mut guard_expr, &bindings);
1355						condition = Expression::And(AndExpression {
1356							left: Box::new(condition),
1357							right: Box::new(guard_expr),
1358							fragment: fragment.clone(),
1359						});
1360					}
1361
1362					let mut result_expr = Self::compile(BumpBox::into_inner(result))?;
1363					Self::rewrite_field_refs(&mut result_expr, &bindings);
1364					branches.push((condition, result_expr));
1365				}
1366				AstMatchArm::Condition {
1367					condition,
1368					guard,
1369					result,
1370				} => {
1371					let mut cond = Self::compile(BumpBox::into_inner(condition))?;
1372
1373					if let Some(guard) = guard {
1374						let guard_expr = Self::compile(BumpBox::into_inner(guard))?;
1375						cond = Expression::And(AndExpression {
1376							left: Box::new(cond),
1377							right: Box::new(guard_expr),
1378							fragment: fragment.clone(),
1379						});
1380					}
1381
1382					let result_expr = Self::compile(BumpBox::into_inner(result))?;
1383					branches.push((cond, result_expr));
1384				}
1385			}
1386		}
1387
1388		// Assemble into IfExpression
1389		if branches.is_empty() {
1390			// Degenerate: only ELSE or empty match
1391			return Ok(else_result.unwrap_or(Expression::Constant(ConstantExpression::None {
1392				fragment,
1393			})));
1394		}
1395
1396		let (first_cond, first_then) = branches.remove(0);
1397
1398		let else_ifs: Vec<ElseIfExpression> = branches
1399			.into_iter()
1400			.map(|(cond, then_expr)| ElseIfExpression {
1401				condition: Box::new(cond),
1402				then_expr: Box::new(then_expr),
1403				fragment: fragment.clone(),
1404			})
1405			.collect();
1406
1407		Ok(Expression::If(IfExpression {
1408			condition: Box::new(first_cond),
1409			then_expr: Box::new(first_then),
1410			else_ifs,
1411			else_expr: else_result.map(Box::new),
1412			fragment,
1413		}))
1414	}
1415
1416	/// Rewrite field references in a compiled expression tree.
1417	/// Replaces Column expressions whose name matches a bound field name
1418	/// with the corresponding physical column name.
1419	pub(crate) fn rewrite_field_refs(expr: &mut Expression, bindings: &[(String, String)]) {
1420		if bindings.is_empty() {
1421			return;
1422		}
1423		match expr {
1424			Expression::Column(ColumnExpression(col)) => {
1425				let name = col.name.text().to_string();
1426				for (field_name, physical_name) in bindings {
1427					if name == *field_name {
1428						col.name = Fragment::internal(physical_name);
1429						break;
1430					}
1431				}
1432			}
1433			Expression::Add(e) => {
1434				Self::rewrite_field_refs(&mut e.left, bindings);
1435				Self::rewrite_field_refs(&mut e.right, bindings);
1436			}
1437			Expression::Sub(e) => {
1438				Self::rewrite_field_refs(&mut e.left, bindings);
1439				Self::rewrite_field_refs(&mut e.right, bindings);
1440			}
1441			Expression::Mul(e) => {
1442				Self::rewrite_field_refs(&mut e.left, bindings);
1443				Self::rewrite_field_refs(&mut e.right, bindings);
1444			}
1445			Expression::Div(e) => {
1446				Self::rewrite_field_refs(&mut e.left, bindings);
1447				Self::rewrite_field_refs(&mut e.right, bindings);
1448			}
1449			Expression::Rem(e) => {
1450				Self::rewrite_field_refs(&mut e.left, bindings);
1451				Self::rewrite_field_refs(&mut e.right, bindings);
1452			}
1453			Expression::Equal(e) => {
1454				Self::rewrite_field_refs(&mut e.left, bindings);
1455				Self::rewrite_field_refs(&mut e.right, bindings);
1456			}
1457			Expression::NotEqual(e) => {
1458				Self::rewrite_field_refs(&mut e.left, bindings);
1459				Self::rewrite_field_refs(&mut e.right, bindings);
1460			}
1461			Expression::GreaterThan(e) => {
1462				Self::rewrite_field_refs(&mut e.left, bindings);
1463				Self::rewrite_field_refs(&mut e.right, bindings);
1464			}
1465			Expression::GreaterThanEqual(e) => {
1466				Self::rewrite_field_refs(&mut e.left, bindings);
1467				Self::rewrite_field_refs(&mut e.right, bindings);
1468			}
1469			Expression::LessThan(e) => {
1470				Self::rewrite_field_refs(&mut e.left, bindings);
1471				Self::rewrite_field_refs(&mut e.right, bindings);
1472			}
1473			Expression::LessThanEqual(e) => {
1474				Self::rewrite_field_refs(&mut e.left, bindings);
1475				Self::rewrite_field_refs(&mut e.right, bindings);
1476			}
1477			Expression::And(e) => {
1478				Self::rewrite_field_refs(&mut e.left, bindings);
1479				Self::rewrite_field_refs(&mut e.right, bindings);
1480			}
1481			Expression::Or(e) => {
1482				Self::rewrite_field_refs(&mut e.left, bindings);
1483				Self::rewrite_field_refs(&mut e.right, bindings);
1484			}
1485			Expression::Xor(e) => {
1486				Self::rewrite_field_refs(&mut e.left, bindings);
1487				Self::rewrite_field_refs(&mut e.right, bindings);
1488			}
1489			Expression::Prefix(e) => {
1490				Self::rewrite_field_refs(&mut e.expression, bindings);
1491			}
1492			Expression::Cast(e) => {
1493				Self::rewrite_field_refs(&mut e.expression, bindings);
1494			}
1495			Expression::Call(e) => {
1496				for arg in &mut e.args {
1497					Self::rewrite_field_refs(arg, bindings);
1498				}
1499			}
1500			Expression::If(e) => {
1501				Self::rewrite_field_refs(&mut e.condition, bindings);
1502				Self::rewrite_field_refs(&mut e.then_expr, bindings);
1503				for else_if in &mut e.else_ifs {
1504					Self::rewrite_field_refs(&mut else_if.condition, bindings);
1505					Self::rewrite_field_refs(&mut else_if.then_expr, bindings);
1506				}
1507				if let Some(else_expr) = &mut e.else_expr {
1508					Self::rewrite_field_refs(else_expr, bindings);
1509				}
1510			}
1511			Expression::Alias(e) => {
1512				Self::rewrite_field_refs(&mut e.expression, bindings);
1513			}
1514			Expression::Tuple(e) => {
1515				for expr in &mut e.expressions {
1516					Self::rewrite_field_refs(expr, bindings);
1517				}
1518			}
1519			Expression::List(e) => {
1520				for expr in &mut e.expressions {
1521					Self::rewrite_field_refs(expr, bindings);
1522				}
1523			}
1524			Expression::Between(e) => {
1525				Self::rewrite_field_refs(&mut e.value, bindings);
1526				Self::rewrite_field_refs(&mut e.lower, bindings);
1527				Self::rewrite_field_refs(&mut e.upper, bindings);
1528			}
1529			Expression::In(e) => {
1530				Self::rewrite_field_refs(&mut e.value, bindings);
1531				Self::rewrite_field_refs(&mut e.list, bindings);
1532			}
1533			Expression::Contains(e) => {
1534				Self::rewrite_field_refs(&mut e.value, bindings);
1535				Self::rewrite_field_refs(&mut e.list, bindings);
1536			}
1537			// Leaf nodes that don't contain column references
1538			Expression::Constant(_)
1539			| Expression::AccessSource(_)
1540			| Expression::Type(_)
1541			| Expression::Parameter(_)
1542			| Expression::Variable(_)
1543			| Expression::Map(_)
1544			| Expression::Extend(_)
1545			| Expression::SumTypeConstructor(_)
1546			| Expression::IsVariant(_)
1547			| Expression::FieldAccess(_) => {}
1548		}
1549	}
1550
1551	fn infix(ast: AstInfix<'_>) -> Result<Expression> {
1552		match ast.operator {
1553			InfixOperator::Add(token) => {
1554				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1555				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1556				Ok(Expression::Add(AddExpression {
1557					left: Box::new(left),
1558					right: Box::new(right),
1559					fragment: token.fragment.to_owned(),
1560				}))
1561			}
1562			InfixOperator::Divide(token) => {
1563				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1564				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1565				Ok(Expression::Div(DivExpression {
1566					left: Box::new(left),
1567					right: Box::new(right),
1568					fragment: token.fragment.to_owned(),
1569				}))
1570			}
1571			InfixOperator::Subtract(token) => {
1572				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1573				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1574				Ok(Expression::Sub(SubExpression {
1575					left: Box::new(left),
1576					right: Box::new(right),
1577					fragment: token.fragment.to_owned(),
1578				}))
1579			}
1580			InfixOperator::Rem(token) => {
1581				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1582				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1583				Ok(Expression::Rem(RemExpression {
1584					left: Box::new(left),
1585					right: Box::new(right),
1586					fragment: token.fragment.to_owned(),
1587				}))
1588			}
1589			InfixOperator::Multiply(token) => {
1590				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1591				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1592				Ok(Expression::Mul(MulExpression {
1593					left: Box::new(left),
1594					right: Box::new(right),
1595					fragment: token.fragment.to_owned(),
1596				}))
1597			}
1598			InfixOperator::Call(token) => {
1599				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1600				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1601
1602				let func_name = match left {
1603					Expression::Column(ColumnExpression(column)) => column.name,
1604					Expression::Variable(var) => var.fragment,
1605					_ => panic!("unexpected left-hand side in call expression"),
1606				};
1607				let Expression::Tuple(tuple) = right else {
1608					panic!()
1609				};
1610
1611				Ok(Expression::Call(CallExpression {
1612					func: IdentExpression(func_name),
1613					args: tuple.expressions,
1614					fragment: token.fragment.to_owned(),
1615				}))
1616			}
1617			InfixOperator::GreaterThan(token) => {
1618				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1619				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1620
1621				Ok(Expression::GreaterThan(GreaterThanExpression {
1622					left: Box::new(left),
1623					right: Box::new(right),
1624					fragment: token.fragment.to_owned(),
1625				}))
1626			}
1627			InfixOperator::GreaterThanEqual(token) => {
1628				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1629				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1630
1631				Ok(Expression::GreaterThanEqual(GreaterThanEqExpression {
1632					left: Box::new(left),
1633					right: Box::new(right),
1634					fragment: token.fragment.to_owned(),
1635				}))
1636			}
1637			InfixOperator::LessThan(token) => {
1638				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1639				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1640
1641				Ok(Expression::LessThan(LessThanExpression {
1642					left: Box::new(left),
1643					right: Box::new(right),
1644					fragment: token.fragment.to_owned(),
1645				}))
1646			}
1647			InfixOperator::LessThanEqual(token) => {
1648				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1649				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1650
1651				Ok(Expression::LessThanEqual(LessThanEqExpression {
1652					left: Box::new(left),
1653					right: Box::new(right),
1654					fragment: token.fragment.to_owned(),
1655				}))
1656			}
1657			InfixOperator::Equal(token) => {
1658				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1659				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1660
1661				Ok(Expression::Equal(EqExpression {
1662					left: Box::new(left),
1663					right: Box::new(right),
1664					fragment: token.fragment.to_owned(),
1665				}))
1666			}
1667			InfixOperator::NotEqual(token) => {
1668				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1669				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1670
1671				Ok(Expression::NotEqual(NotEqExpression {
1672					left: Box::new(left),
1673					right: Box::new(right),
1674					fragment: token.fragment.to_owned(),
1675				}))
1676			}
1677			InfixOperator::As(token) => {
1678				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1679				let alias_fragment = match BumpBox::into_inner(ast.right) {
1680					Ast::Identifier(ident) => ident.token.fragment.to_owned(),
1681					Ast::Literal(AstLiteral::Text(text)) => {
1682						let raw = text.0.fragment.text();
1683						let unquoted = raw.trim_matches('"');
1684						Fragment::internal(unquoted)
1685					}
1686					_ => unimplemented!(),
1687				};
1688
1689				Ok(Expression::Alias(AliasExpression {
1690					alias: IdentExpression(alias_fragment),
1691					expression: Box::new(left),
1692					fragment: token.fragment.to_owned(),
1693				}))
1694			}
1695
1696			InfixOperator::And(token) => {
1697				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1698				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1699
1700				Ok(Expression::And(AndExpression {
1701					left: Box::new(left),
1702					right: Box::new(right),
1703					fragment: token.fragment.to_owned(),
1704				}))
1705			}
1706
1707			InfixOperator::Or(token) => {
1708				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1709				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1710
1711				Ok(Expression::Or(OrExpression {
1712					left: Box::new(left),
1713					right: Box::new(right),
1714					fragment: token.fragment.to_owned(),
1715				}))
1716			}
1717
1718			InfixOperator::Xor(token) => {
1719				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1720				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1721
1722				Ok(Expression::Xor(XorExpression {
1723					left: Box::new(left),
1724					right: Box::new(right),
1725					fragment: token.fragment.to_owned(),
1726				}))
1727			}
1728
1729			InfixOperator::In(token) => {
1730				let value = Self::compile(BumpBox::into_inner(ast.left))?;
1731				let list = Self::compile(BumpBox::into_inner(ast.right))?;
1732
1733				Ok(Expression::In(InExpression {
1734					value: Box::new(value),
1735					list: Box::new(list),
1736					negated: false,
1737					fragment: token.fragment.to_owned(),
1738				}))
1739			}
1740
1741			InfixOperator::NotIn(token) => {
1742				let value = Self::compile(BumpBox::into_inner(ast.left))?;
1743				let list = Self::compile(BumpBox::into_inner(ast.right))?;
1744
1745				Ok(Expression::In(InExpression {
1746					value: Box::new(value),
1747					list: Box::new(list),
1748					negated: true,
1749					fragment: token.fragment.to_owned(),
1750				}))
1751			}
1752
1753			InfixOperator::Contains(token) => {
1754				let value = Self::compile(BumpBox::into_inner(ast.left))?;
1755				let list = Self::compile(BumpBox::into_inner(ast.right))?;
1756
1757				Ok(Expression::Contains(ContainsExpression {
1758					value: Box::new(value),
1759					list: Box::new(list),
1760					fragment: token.fragment.to_owned(),
1761				}))
1762			}
1763
1764			InfixOperator::Assign(token) => {
1765				// Assignment operator (=) is not valid in expression context
1766				// Use == for equality comparison
1767				return Err(AstError::UnsupportedToken {
1768					fragment: token.fragment.to_owned(),
1769				}
1770				.into());
1771			}
1772
1773			InfixOperator::TypeAscription(token) => {
1774				match BumpBox::into_inner(ast.left) {
1775					Ast::Identifier(alias) => {
1776						let right = Self::compile(BumpBox::into_inner(ast.right))?;
1777
1778						Ok(Expression::Alias(AliasExpression {
1779							alias: IdentExpression(alias.token.fragment.to_owned()),
1780							expression: Box::new(right),
1781							fragment: token.fragment.to_owned(),
1782						}))
1783					}
1784					Ast::Literal(AstLiteral::Text(text)) => {
1785						// Handle string literals as alias names (common in MAP syntax)
1786						let right = Self::compile(BumpBox::into_inner(ast.right))?;
1787
1788						Ok(Expression::Alias(AliasExpression {
1789							alias: IdentExpression(text.0.fragment.to_owned()),
1790							expression: Box::new(right),
1791							fragment: token.fragment.to_owned(),
1792						}))
1793					}
1794					_ => {
1795						return err!(Diagnostic {
1796							code: "EXPR_001".to_string(),
1797							statement: None,
1798							message: "Invalid alias expression".to_string(),
1799							column: None,
1800							fragment: Fragment::None,
1801							label: Some("Only identifiers and string literals can be used as alias names".to_string()),
1802							help: Some("Use an identifier or string literal for the alias name".to_string()),
1803							notes: vec![],
1804							cause: None,
1805							operator_chain: None,
1806						});
1807					}
1808				}
1809			}
1810			InfixOperator::AccessNamespace(_token) => {
1811				// Handle namespace access: `ns::func(args)` → CallExpression with namespaced name
1812				// Extract namespace name from left side (always an identifier)
1813				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1814				let namespace = match &left {
1815					Expression::Column(ColumnExpression(col)) => col.name.text().to_string(),
1816					other => unimplemented!("unsupported namespace expression: {other:?}"),
1817				};
1818
1819				// The right side may contain keywords (e.g. `undefined`) that should be
1820				// treated as identifiers in a namespace context. Extract the name from the
1821				// raw AST token before compiling, so keywords are treated as identifier_or_keyword.
1822				let right_ast = BumpBox::into_inner(ast.right);
1823				Self::compile_namespace_right(&namespace, right_ast)
1824			}
1825
1826			InfixOperator::AccessTable(token) => {
1827				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1828				let right_ast = BumpBox::into_inner(ast.right);
1829				let field_name = right_ast.token().fragment.to_owned();
1830				let fragment = token.fragment.to_owned();
1831				Ok(Expression::FieldAccess(FieldAccessExpression {
1832					object: Box::new(left),
1833					field: field_name,
1834					fragment,
1835				}))
1836			}
1837		}
1838	}
1839
1840	/// Compile the right-hand side of a namespace access (`ns::...`).
1841	///
1842	/// Keywords like `undefined` or `true` are treated as identifiers in this
1843	/// context so that `is::none(x)` resolves to a function call rather
1844	/// than parsing `undefined` as the literal keyword.
1845	fn compile_namespace_right(namespace: &str, right_ast: Ast<'_>) -> Result<Expression> {
1846		// Helper: extract a token's text from any AST node that should be treated
1847		// as an identifier_or_keyword in namespace position.
1848		fn identifier_or_keyword_name(ast: &Ast<'_>) -> Option<String> {
1849			Some(ast.token().fragment.text().to_string())
1850		}
1851
1852		match right_ast {
1853			// ns::func(args)  where func is parsed as Infix(left, Call, right)
1854			Ast::Infix(infix) if matches!(infix.operator, InfixOperator::Call(_)) => {
1855				let func_name = identifier_or_keyword_name(&infix.left)
1856					.expect("namespace function name must be extractable");
1857				let full_name = format!("{}::{}", namespace, func_name);
1858
1859				let right = Self::compile(BumpBox::into_inner(infix.right))?;
1860				let Expression::Tuple(tuple) = right else {
1861					panic!("expected tuple arguments for namespaced call");
1862				};
1863
1864				Ok(Expression::Call(CallExpression {
1865					func: IdentExpression(Fragment::testing(&full_name)),
1866					args: tuple.expressions,
1867					fragment: infix.token.fragment.to_owned(),
1868				}))
1869			}
1870			// ns::func(args) where func is parsed as CallFunction
1871			// (happens when the namespace token is a keyword like `is`,
1872			// so the parser treats the right side as a standalone call)
1873			Ast::CallFunction(call) => {
1874				let func_name = call.function.name.text().to_string();
1875				let full_name = if call.function.namespaces.is_empty() {
1876					format!("{}::{}", namespace, func_name)
1877				} else {
1878					let sub_ns = call
1879						.function
1880						.namespaces
1881						.iter()
1882						.map(|ns| ns.text())
1883						.collect::<Vec<_>>()
1884						.join("::");
1885					format!("{}::{}::{}", namespace, sub_ns, func_name)
1886				};
1887
1888				let mut arg_expressions = Vec::new();
1889				for arg_ast in call.arguments.nodes {
1890					let compiled = Self::compile(arg_ast)?;
1891					let compiled = match &compiled {
1892						Expression::Column(col_expr) => {
1893							if let Ok(ty) = Type::from_str(col_expr.0.name.text()) {
1894								Expression::Type(TypeExpression {
1895									fragment: col_expr.0.name.clone(),
1896									ty,
1897								})
1898							} else {
1899								compiled
1900							}
1901						}
1902						_ => compiled,
1903					};
1904					arg_expressions.push(compiled);
1905				}
1906
1907				Ok(Expression::Call(CallExpression {
1908					func: IdentExpression(Fragment::testing(&full_name)),
1909					args: arg_expressions,
1910					fragment: call.token.fragment.to_owned(),
1911				}))
1912			}
1913			// ns::name  (bare namespaced reference, no call)
1914			other => {
1915				if let Some(name) = identifier_or_keyword_name(&other) {
1916					let full_name = format!("{}::{}", namespace, name);
1917					Ok(Expression::Column(ColumnExpression(ColumnIdentifier {
1918						primitive: ColumnPrimitive::Primitive {
1919							namespace: Fragment::Internal {
1920								text: Arc::from("_context"),
1921							},
1922							primitive: Fragment::Internal {
1923								text: Arc::from("_context"),
1924							},
1925						},
1926						name: Fragment::testing(&full_name),
1927					})))
1928				} else {
1929					let compiled = Self::compile(other)?;
1930					match compiled {
1931						Expression::Column(ColumnExpression(col)) => {
1932							let full_name = format!("{}::{}", namespace, col.name.text());
1933							Ok(Expression::Column(ColumnExpression(ColumnIdentifier {
1934								primitive: col.primitive,
1935								name: Fragment::testing(&full_name),
1936							})))
1937						}
1938						other => unimplemented!(
1939							"unsupported namespace right-hand side: {other:?}"
1940						),
1941					}
1942				}
1943			}
1944		}
1945	}
1946}
1947
1948#[derive(Debug, Clone, Serialize, Deserialize)]
1949pub struct MapExpression {
1950	pub expressions: Vec<Expression>,
1951	pub fragment: Fragment,
1952}
1953
1954#[derive(Debug, Clone, Serialize, Deserialize)]
1955pub struct ExtendExpression {
1956	pub expressions: Vec<Expression>,
1957	pub fragment: Fragment,
1958}
1959
1960#[derive(Debug, Clone, Serialize, Deserialize)]
1961pub struct SumTypeConstructorExpression {
1962	pub namespace: Fragment,
1963	pub sumtype_name: Fragment,
1964	pub variant_name: Fragment,
1965	pub columns: Vec<(Fragment, Expression)>,
1966	pub fragment: Fragment,
1967}
1968
1969#[derive(Debug, Clone, Serialize, Deserialize)]
1970pub struct IsVariantExpression {
1971	pub expression: Box<Expression>,
1972	pub namespace: Option<Fragment>,
1973	pub sumtype_name: Fragment,
1974	pub variant_name: Fragment,
1975	pub tag: Option<u8>,
1976	pub fragment: Fragment,
1977}
1978
1979#[derive(Debug, Clone, Serialize, Deserialize)]
1980pub struct FieldAccessExpression {
1981	pub object: Box<Expression>,
1982	pub field: Fragment,
1983	pub fragment: Fragment,
1984}
1985
1986impl FieldAccessExpression {
1987	pub fn full_fragment_owned(&self) -> Fragment {
1988		Fragment::merge_all([self.object.full_fragment_owned(), self.fragment.clone(), self.field.clone()])
1989	}
1990}
1991
1992impl Display for FieldAccessExpression {
1993	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1994		write!(f, "{}.{}", self.object, self.field.text())
1995	}
1996}
1997
1998/// Recursively extract all variable names referenced in an expression tree.
1999pub fn extract_variable_names(expr: &Expression) -> Vec<String> {
2000	let mut names = Vec::new();
2001	collect_variable_names(expr, &mut names);
2002	names
2003}
2004
2005fn collect_variable_names(expr: &Expression, names: &mut Vec<String>) {
2006	match expr {
2007		Expression::Variable(v) => {
2008			let name = v.name().to_string();
2009			if !names.contains(&name) {
2010				names.push(name);
2011			}
2012		}
2013		Expression::Add(e) => {
2014			collect_variable_names(&e.left, names);
2015			collect_variable_names(&e.right, names);
2016		}
2017		Expression::Sub(e) => {
2018			collect_variable_names(&e.left, names);
2019			collect_variable_names(&e.right, names);
2020		}
2021		Expression::Mul(e) => {
2022			collect_variable_names(&e.left, names);
2023			collect_variable_names(&e.right, names);
2024		}
2025		Expression::Div(e) => {
2026			collect_variable_names(&e.left, names);
2027			collect_variable_names(&e.right, names);
2028		}
2029		Expression::Rem(e) => {
2030			collect_variable_names(&e.left, names);
2031			collect_variable_names(&e.right, names);
2032		}
2033		Expression::GreaterThan(e) => {
2034			collect_variable_names(&e.left, names);
2035			collect_variable_names(&e.right, names);
2036		}
2037		Expression::GreaterThanEqual(e) => {
2038			collect_variable_names(&e.left, names);
2039			collect_variable_names(&e.right, names);
2040		}
2041		Expression::LessThan(e) => {
2042			collect_variable_names(&e.left, names);
2043			collect_variable_names(&e.right, names);
2044		}
2045		Expression::LessThanEqual(e) => {
2046			collect_variable_names(&e.left, names);
2047			collect_variable_names(&e.right, names);
2048		}
2049		Expression::Equal(e) => {
2050			collect_variable_names(&e.left, names);
2051			collect_variable_names(&e.right, names);
2052		}
2053		Expression::NotEqual(e) => {
2054			collect_variable_names(&e.left, names);
2055			collect_variable_names(&e.right, names);
2056		}
2057		Expression::And(e) => {
2058			collect_variable_names(&e.left, names);
2059			collect_variable_names(&e.right, names);
2060		}
2061		Expression::Or(e) => {
2062			collect_variable_names(&e.left, names);
2063			collect_variable_names(&e.right, names);
2064		}
2065		Expression::Xor(e) => {
2066			collect_variable_names(&e.left, names);
2067			collect_variable_names(&e.right, names);
2068		}
2069		Expression::Between(e) => {
2070			collect_variable_names(&e.value, names);
2071			collect_variable_names(&e.lower, names);
2072			collect_variable_names(&e.upper, names);
2073		}
2074		Expression::In(e) => {
2075			collect_variable_names(&e.value, names);
2076			collect_variable_names(&e.list, names);
2077		}
2078		Expression::Contains(e) => {
2079			collect_variable_names(&e.value, names);
2080			collect_variable_names(&e.list, names);
2081		}
2082		Expression::Prefix(e) => collect_variable_names(&e.expression, names),
2083		Expression::Cast(e) => collect_variable_names(&e.expression, names),
2084		Expression::Alias(e) => collect_variable_names(&e.expression, names),
2085		Expression::Call(e) => {
2086			for arg in &e.args {
2087				collect_variable_names(arg, names);
2088			}
2089		}
2090		Expression::Tuple(e) => {
2091			for expr in &e.expressions {
2092				collect_variable_names(expr, names);
2093			}
2094		}
2095		Expression::List(e) => {
2096			for expr in &e.expressions {
2097				collect_variable_names(expr, names);
2098			}
2099		}
2100		Expression::If(e) => {
2101			collect_variable_names(&e.condition, names);
2102			collect_variable_names(&e.then_expr, names);
2103			for else_if in &e.else_ifs {
2104				collect_variable_names(&else_if.condition, names);
2105				collect_variable_names(&else_if.then_expr, names);
2106			}
2107			if let Some(else_expr) = &e.else_expr {
2108				collect_variable_names(else_expr, names);
2109			}
2110		}
2111		Expression::Map(e) => {
2112			for expr in &e.expressions {
2113				collect_variable_names(expr, names);
2114			}
2115		}
2116		Expression::Extend(e) => {
2117			for expr in &e.expressions {
2118				collect_variable_names(expr, names);
2119			}
2120		}
2121		Expression::SumTypeConstructor(e) => {
2122			for (_, expr) in &e.columns {
2123				collect_variable_names(expr, names);
2124			}
2125		}
2126		Expression::IsVariant(e) => collect_variable_names(&e.expression, names),
2127		Expression::FieldAccess(e) => collect_variable_names(&e.object, names),
2128		// Leaf nodes with no sub-expressions
2129		Expression::Constant(_)
2130		| Expression::Column(_)
2131		| Expression::AccessSource(_)
2132		| Expression::Parameter(_)
2133		| Expression::Type(_) => {}
2134	}
2135}