1use std::collections::BTreeSet;
2
3use crate::{analyzer::FunctionId, symbols::*};
4use lora_ast::{
5 BinaryOp, Direction, ListPredicateKind, RangeLiteral, SortDirection, Span, UnaryOp,
6};
7
8#[derive(Debug, Clone)]
9pub struct ResolvedQuery {
10 pub clauses: Vec<ResolvedClause>,
11 pub unions: Vec<ResolvedUnionPart>,
14}
15
16#[derive(Debug, Clone)]
17pub struct ResolvedUnionPart {
18 pub all: bool,
20 pub clauses: Vec<ResolvedClause>,
22}
23
24#[derive(Debug, Clone)]
25pub enum ResolvedClause {
26 Match(ResolvedMatch),
27 Unwind(ResolvedUnwind),
28 Create(ResolvedCreate),
29 Merge(ResolvedMerge),
30 Delete(ResolvedDelete),
31 Set(ResolvedSet),
32 Remove(ResolvedRemove),
33 Foreach(ResolvedForeach),
34 Return(ResolvedReturn),
35 With(ResolvedWith),
36 CallSubquery(ResolvedCallSubquery),
37}
38
39#[derive(Debug, Clone)]
45pub struct ResolvedCallSubquery {
46 pub clauses: Vec<ResolvedClause>,
47 pub return_vars: Vec<VarId>,
50}
51
52#[derive(Debug, Clone)]
53pub struct ResolvedMatch {
54 pub optional: bool,
55 pub pattern: ResolvedPattern,
56 pub where_: Option<ResolvedExpr>,
57}
58
59#[derive(Debug, Clone)]
60pub struct ResolvedUnwind {
61 pub expr: ResolvedExpr,
62 pub alias: VarId,
63}
64
65#[derive(Debug, Clone)]
66pub struct ResolvedCreate {
67 pub pattern: ResolvedPattern,
68}
69
70#[derive(Debug, Clone)]
71pub struct ResolvedMerge {
72 pub pattern_part: ResolvedPatternPart,
73 pub actions: Vec<ResolvedMergeAction>,
74}
75
76#[derive(Debug, Clone)]
77pub struct ResolvedMergeAction {
78 pub on_match: bool,
79 pub set: ResolvedSet,
80}
81
82#[derive(Debug, Clone)]
83pub struct ResolvedDelete {
84 pub detach: bool,
85 pub expressions: Vec<ResolvedExpr>,
86}
87
88#[derive(Debug, Clone)]
89pub struct ResolvedSet {
90 pub items: Vec<ResolvedSetItem>,
91}
92
93#[derive(Debug, Clone)]
94pub enum ResolvedSetItem {
95 SetProperty {
96 target: ResolvedExpr,
97 value: ResolvedExpr,
98 },
99 SetVariable {
100 variable: VarId,
101 value: ResolvedExpr,
102 },
103 MutateVariable {
104 variable: VarId,
105 value: ResolvedExpr,
106 },
107 SetLabels {
108 variable: VarId,
109 labels: Vec<String>,
110 },
111}
112
113#[derive(Debug, Clone)]
114pub struct ResolvedRemove {
115 pub items: Vec<ResolvedRemoveItem>,
116}
117
118#[derive(Debug, Clone)]
124pub struct ResolvedForeach {
125 pub variable: VarId,
126 pub list: ResolvedExpr,
127 pub body: Vec<ResolvedClause>,
128}
129
130#[derive(Debug, Clone)]
131pub enum ResolvedRemoveItem {
132 Labels {
133 variable: VarId,
134 labels: Vec<String>,
135 },
136 Property {
137 expr: ResolvedExpr,
138 },
139}
140
141#[derive(Debug, Clone)]
142pub struct ResolvedReturn {
143 pub distinct: bool,
144 pub items: Vec<ResolvedProjection>,
145 pub include_existing: bool,
146 pub order: Vec<ResolvedSortItem>,
147 pub skip: Option<ResolvedExpr>,
148 pub limit: Option<ResolvedExpr>,
149}
150
151#[derive(Debug, Clone)]
152pub struct ResolvedWith {
153 pub distinct: bool,
154 pub items: Vec<ResolvedProjection>,
155 pub include_existing: bool,
156 pub order: Vec<ResolvedSortItem>,
157 pub skip: Option<ResolvedExpr>,
158 pub limit: Option<ResolvedExpr>,
159 pub where_: Option<ResolvedExpr>,
160}
161
162#[derive(Debug, Clone)]
163pub struct ResolvedProjection {
164 pub expr: ResolvedExpr,
165 pub output: VarId,
166 pub name: std::sync::Arc<str>,
170 pub explicit_alias: bool,
172 pub span: Span,
173}
174
175#[derive(Debug, Clone)]
176pub struct ResolvedSortItem {
177 pub expr: ResolvedExpr,
178 pub direction: SortDirection,
179}
180
181#[derive(Debug, Clone)]
182pub struct ResolvedPattern {
183 pub parts: Vec<ResolvedPatternPart>,
184}
185
186#[derive(Debug, Clone)]
187pub struct ResolvedPatternPart {
188 pub binding: Option<VarId>,
189 pub element: ResolvedPatternElement,
190}
191
192#[derive(Debug, Clone)]
193pub enum ResolvedPatternElement {
194 Node {
195 var: Option<VarId>,
196 labels: Vec<Vec<String>>,
198 properties: Option<ResolvedExpr>,
199 },
200 NodeChain {
201 head: ResolvedNode,
202 chain: Vec<ResolvedChain>,
203 },
204 ShortestPath {
205 all: bool,
206 head: ResolvedNode,
207 chain: Vec<ResolvedChain>,
208 },
209}
210
211#[derive(Debug, Clone)]
212pub struct ResolvedNode {
213 pub var: Option<VarId>,
214 pub labels: Vec<Vec<String>>,
216 pub properties: Option<ResolvedExpr>,
217}
218
219#[derive(Debug, Clone)]
220pub struct ResolvedChain {
221 pub rel: ResolvedRel,
222 pub node: ResolvedNode,
223}
224
225#[derive(Debug, Clone)]
226pub struct ResolvedRel {
227 pub var: Option<VarId>,
228 pub types: Vec<String>,
229 pub direction: Direction,
230 pub range: Option<RangeLiteral>,
231 pub properties: Option<ResolvedExpr>,
232}
233
234#[derive(Debug, Clone)]
235pub enum ResolvedExpr {
236 Variable(VarId),
237 Literal(LiteralValue),
238 Property {
239 expr: Box<ResolvedExpr>,
240 property: String,
241 },
242 Binary {
243 lhs: Box<ResolvedExpr>,
244 op: BinaryOp,
245 rhs: Box<ResolvedExpr>,
246 },
247 Unary {
248 op: UnaryOp,
249 expr: Box<ResolvedExpr>,
250 },
251 Function {
252 function: FunctionId,
253 distinct: bool,
254 args: Vec<ResolvedExpr>,
255 },
256 List(Vec<ResolvedExpr>),
257 Map(Vec<(String, ResolvedExpr)>),
258 Case {
259 input: Option<Box<ResolvedExpr>>,
260 alternatives: Vec<(ResolvedExpr, ResolvedExpr)>,
261 else_expr: Option<Box<ResolvedExpr>>,
262 },
263 Parameter(String),
264 ListPredicate {
265 kind: ListPredicateKind,
266 variable: VarId,
267 list: Box<ResolvedExpr>,
268 predicate: Box<ResolvedExpr>,
269 },
270 ListComprehension {
271 variable: VarId,
272 list: Box<ResolvedExpr>,
273 filter: Option<Box<ResolvedExpr>>,
274 map_expr: Option<Box<ResolvedExpr>>,
275 },
276 Reduce {
277 accumulator: VarId,
278 init: Box<ResolvedExpr>,
279 variable: VarId,
280 list: Box<ResolvedExpr>,
281 expr: Box<ResolvedExpr>,
282 },
283 MapProjection {
284 base: Box<ResolvedExpr>,
285 selectors: Vec<ResolvedMapSelector>,
286 },
287 Index {
288 expr: Box<ResolvedExpr>,
289 index: Box<ResolvedExpr>,
290 },
291 Slice {
292 expr: Box<ResolvedExpr>,
293 from: Option<Box<ResolvedExpr>>,
294 to: Option<Box<ResolvedExpr>>,
295 },
296 ExistsSubquery {
297 pattern: ResolvedPattern,
298 where_: Option<Box<ResolvedExpr>>,
299 reads: Vec<VarId>,
303 },
304 PatternComprehension {
305 pattern: ResolvedPattern,
306 where_: Option<Box<ResolvedExpr>>,
307 map_expr: Box<ResolvedExpr>,
308 reads: Vec<VarId>,
311 },
312}
313
314#[derive(Debug, Clone)]
315pub enum ResolvedMapSelector {
316 Property(String),
317 AllProperties,
318 Literal(String, ResolvedExpr),
319}
320
321#[derive(Debug, Clone, PartialEq)]
322pub enum LiteralValue {
323 Integer(i64),
324 Float(f64),
325 String(String),
326 TypeName(String),
327 Bool(bool),
328 Null,
329}
330
331impl ResolvedExpr {
332 pub fn collect_vars(&self, out: &mut BTreeSet<VarId>) {
338 let expr = self;
339 match expr {
340 ResolvedExpr::Variable(v) => {
341 out.insert(*v);
342 }
343 ResolvedExpr::Property { expr, .. } => ResolvedExpr::collect_vars(expr, out),
344 ResolvedExpr::Binary { lhs, rhs, .. } => {
345 ResolvedExpr::collect_vars(lhs, out);
346 ResolvedExpr::collect_vars(rhs, out);
347 }
348 ResolvedExpr::Unary { expr, .. } => ResolvedExpr::collect_vars(expr, out),
349 ResolvedExpr::Function { args, .. } => {
350 for arg in args {
351 ResolvedExpr::collect_vars(arg, out);
352 }
353 }
354 ResolvedExpr::List(items) => {
355 for item in items {
356 ResolvedExpr::collect_vars(item, out);
357 }
358 }
359 ResolvedExpr::Map(items) => {
360 for (_, v) in items {
361 ResolvedExpr::collect_vars(v, out);
362 }
363 }
364 ResolvedExpr::Case {
365 input,
366 alternatives,
367 else_expr,
368 } => {
369 if let Some(e) = input {
370 ResolvedExpr::collect_vars(e, out);
371 }
372 for (w, t) in alternatives {
373 ResolvedExpr::collect_vars(w, out);
374 ResolvedExpr::collect_vars(t, out);
375 }
376 if let Some(e) = else_expr {
377 ResolvedExpr::collect_vars(e, out);
378 }
379 }
380 ResolvedExpr::ListPredicate {
381 variable,
382 list,
383 predicate,
384 ..
385 } => {
386 out.insert(*variable);
387 ResolvedExpr::collect_vars(list, out);
388 ResolvedExpr::collect_vars(predicate, out);
389 }
390 ResolvedExpr::ListComprehension {
391 variable,
392 list,
393 filter,
394 map_expr,
395 ..
396 } => {
397 out.insert(*variable);
398 ResolvedExpr::collect_vars(list, out);
399 if let Some(f) = filter {
400 ResolvedExpr::collect_vars(f, out);
401 }
402 if let Some(m) = map_expr {
403 ResolvedExpr::collect_vars(m, out);
404 }
405 }
406 ResolvedExpr::Reduce {
407 accumulator,
408 init,
409 variable,
410 list,
411 expr,
412 ..
413 } => {
414 out.insert(*accumulator);
415 out.insert(*variable);
416 ResolvedExpr::collect_vars(init, out);
417 ResolvedExpr::collect_vars(list, out);
418 ResolvedExpr::collect_vars(expr, out);
419 }
420 ResolvedExpr::Index { expr, index } => {
421 ResolvedExpr::collect_vars(expr, out);
422 ResolvedExpr::collect_vars(index, out);
423 }
424 ResolvedExpr::Slice { expr, from, to } => {
425 ResolvedExpr::collect_vars(expr, out);
426 if let Some(f) = from {
427 ResolvedExpr::collect_vars(f, out);
428 }
429 if let Some(t) = to {
430 ResolvedExpr::collect_vars(t, out);
431 }
432 }
433 ResolvedExpr::MapProjection { base, selectors } => {
434 ResolvedExpr::collect_vars(base, out);
435 for sel in selectors {
436 if let ResolvedMapSelector::Literal(_, e) = sel {
437 ResolvedExpr::collect_vars(e, out);
438 }
439 }
440 }
441 ResolvedExpr::ExistsSubquery {
445 pattern, where_, ..
446 } => {
447 pattern.collect_vars(out);
448 if let Some(w) = where_ {
449 ResolvedExpr::collect_vars(w, out);
450 }
451 }
452 ResolvedExpr::PatternComprehension {
453 pattern,
454 where_,
455 map_expr,
456 ..
457 } => {
458 pattern.collect_vars(out);
459 if let Some(w) = where_ {
460 ResolvedExpr::collect_vars(w, out);
461 }
462 ResolvedExpr::collect_vars(map_expr, out);
463 }
464 ResolvedExpr::Literal(_) | ResolvedExpr::Parameter(_) => {}
465 }
466 }
467}
468
469impl ResolvedPattern {
470 pub fn collect_vars(&self, out: &mut BTreeSet<VarId>) {
473 let pattern = self;
474 let node = |n: &ResolvedNode, out: &mut BTreeSet<VarId>| {
475 out.extend(n.var);
476 if let Some(p) = &n.properties {
477 ResolvedExpr::collect_vars(p, out);
478 }
479 };
480 for part in &pattern.parts {
481 out.extend(part.binding);
482 match &part.element {
483 ResolvedPatternElement::Node {
484 var, properties, ..
485 } => {
486 out.extend(*var);
487 if let Some(p) = properties {
488 ResolvedExpr::collect_vars(p, out);
489 }
490 }
491 ResolvedPatternElement::NodeChain { head, chain }
492 | ResolvedPatternElement::ShortestPath { head, chain, .. } => {
493 node(head, out);
494 for link in chain {
495 out.extend(link.rel.var);
496 if let Some(p) = &link.rel.properties {
497 ResolvedExpr::collect_vars(p, out);
498 }
499 node(&link.node, out);
500 }
501 }
502 }
503 }
504 }
505}