// The shared expression walker: desugar, the binder, and autoparam all // traverse expressions with it (including the pattern-carrying subquery // nodes' inner WHERE/projection expressions).
package ast // Walk visits e and every sub-expression in pre-order. Returning false // from f skips the node's children (the node itself was already visited). // Pattern-carrying nodes (Exists/CountSub/PatternComp) descend into their // inner WHERE / projection expressions and the patterns' inline property // expressions, so a pass that rewrites literals or checks references sees // every expression a query evaluates. func ( Expr, func(Expr) bool) { if == nil || !() { return } switch n := .(type) { case *Unary: (.Expr, ) case *Binary: (.LHS, ) (.RHS, ) case *Func: for , := range .Args { (, ) } case *ListExpr: for , := range .Elems { (, ) } case *In: (.Expr, ) (.List, ) case *IsNull: (.Expr, ) case *Case: (.Operand, ) for , := range .Whens { (.Cond, ) (.Result, ) } (.Else, ) case *Cost: if .Weight.Kind == CostExpr { (.Weight.Expr, ) } case *Exists: walkPattern(.Pattern, ) (.Where, ) case *CountSub: walkPattern(.Pattern, ) (.Where, ) case *ListPred: (.List, ) (.Pred, ) case *Reduce: (.Init, ) (.List, ) (.Body, ) case *ListComp: (.List, ) (.Filter, ) (.Map, ) case *PatternComp: walkPattern(.Pattern, ) (.Where, ) (.Proj, ) case *Index: (.Base, ) (.Idx, ) case *Slice: (.Base, ) (.From, ) (.To, ) case *PropOf: (.Base, ) case *MapProj: for , := range .Entries { if .Kind == MapProjField { (.Expr, ) } } case *MapLit: for , := range .Fields { (.Val, ) } } } // walkPattern visits the inline property expressions of a pattern's nodes // and rels. func walkPattern( *Pattern, func(Expr) bool) { if == nil { return } for , := range .Start.PropExprs { Walk(.Val, ) } for := range .Hops { for , := range .Hops[].Rel.PropExprs { Walk(.Val, ) } for , := range .Hops[].Node.PropExprs { Walk(.Val, ) } } }