promql/ast.go
func Walk(v Visitor, node Node, path []Node) error {
	var err error
	if v, err = v.Visit(node, path); v == nil || err != nil {
		return err
	}
	path = append(path, node)

	switch n := node.(type) {
	case *EvalStmt:
		if err := Walk(v, n.Expr, path); err != nil {
			return err
		}

	case Expressions:
		for _, e := range n {
			if err := Walk(v, e, path); err != nil {
				return err
			}
		}
	case *AggregateExpr:
		if n.Param != nil {
			if err := Walk(v, n.Param, path); err != nil {
				return err
			}
		}
		if err := Walk(v, n.Expr, path); err != nil {
			return err
		}

	case *BinaryExpr:
		if err := Walk(v, n.LHS, path); err != nil {
			return err
		}
		if err := Walk(v, n.RHS, path); err != nil {
			return err
		}

	case *Call:
		if err := Walk(v, n.Args, path); err != nil {
			return err
		}

	case *SubqueryExpr:
		if err := Walk(v, n.Expr, path); err != nil {
			return err
		}

	case *ParenExpr:
		if err := Walk(v, n.Expr, path); err != nil {
			return err
		}

	case *UnaryExpr:
		if err := Walk(v, n.Expr, path); err != nil {
			return err
		}

	case *MatrixSelector, *NumberLiteral, *StringLiteral, *VectorSelector:
		// nothing to do

	default:
		panic(errors.Errorf("promql.Walk: unhandled node type %T", node))
	}

	_, err = v.Visit(nil, nil)
	return err
}
func Walk(v Visitor, node Node, path []Node) error {
	var err error
	if v, err = v.Visit(node, path); v == nil || err != nil {
		return err
	}
	path = append(path, node)

	switch n := node.(type) {
	case *EvalStmt:
		if err := Walk(v, n.Expr, path); err != nil {
			return err
		}

	case Expressions:
		for _, e := range n {
			if err := Walk(v, e, path); err != nil {
				return err
			}
		}
	case *AggregateExpr:
		if n.Param != nil {
			if err := Walk(v, n.Param, path); err != nil {
				return err
			}
		}
		if err := Walk(v, n.Expr, path); err != nil {
			return err
		}

	case *BinaryExpr:
		if err := Walk(v, n.LHS, path); err != nil {
			return err
		}
		if err := Walk(v, n.RHS, path); err != nil {
			return err
		}

	case *Call:
		if err := Walk(v, n.Args, path); err != nil {
			return err
		}

	case *SubqueryExpr:
		if err := Walk(v, n.Expr, path); err != nil {
			return err
		}

	case *ParenExpr:
		if err := Walk(v, n.Expr, path); err != nil {
			return err
		}

	case *UnaryExpr:
		if err := Walk(v, n.Expr, path); err != nil {
			return err
		}

	case *MatrixSelector, *NumberLiteral, *StringLiteral, *VectorSelector:
		// nothing to do

	default:
		panic(errors.Errorf("promql.Walk: unhandled node type %T", node))
	}

	_, err = v.Visit(nil, nil)
	return err
}
// Walk traverses an AST in depth-first order: It starts by calling
// v.Visit(node, path); node must not be nil. If the visitor w returned by
// v.Visit(node, path) is not nil and the visitor returns no error, Walk is
// invoked recursively with visitor w for each of the non-nil children of node,
// followed by a call of w.Visit(nil), returning an error
// As the tree is descended the path of previous nodes is provided.