### Description

As we have more rules doing analysis across plans, a number of methods are useful to add to the `QueryPlan` class itself, mainly around expressions:

```
- expressions() - return the expressions declared by this plan
- references() - return the references from the expressions above
```
x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/plan/QueryPlan.java
public void forEachExpression(Consumer<? super Expression> rule) {
        forEachExpression(Expression.class, rule);
    }
    public <E extends Expression> void forEachExpression(Class<E> typeToken, Consumer<? super E> rule) {
        forEachPropertyOnly(Object.class, e -> doForEachExpression(e, exp -> exp.forEachDown(typeToken, rule)));
    }
    public void forEachExpressionDown(Consumer<? super Expression> rule) {
        forEachExpressionDown(Expression.class, rule);
    }
    public <E extends Expression> void forEachExpressionDown(Class<? extends E> typeToken, Consumer<? super E> rule) {
        forEachPropertyDown(Object.class, e -> doForEachExpression(e, exp -> exp.forEachDown(typeToken, rule)));
    }
    public void forEachExpressionUp(Consumer<? super Expression> rule) {
        forEachExpressionUp(Expression.class, rule);
    }
    public <E extends Expression> void forEachExpressionUp(Class<E> typeToken, Consumer<? super E> rule) {
        forEachPropertyUp(Object.class, e -> doForEachExpression(e, exp -> exp.forEachUp(typeToken, rule)));
    }
    @SuppressWarnings("unchecked")
    private void doForEachExpression(Object arg, Consumer<Expression> traversal) {
        if (arg instanceof Expression) {
            traversal.accept((Expression) arg);
        } else if (arg instanceof Collection<?> c) {
            for (Object o : c) {
                doForEachExpression(o, traversal);
            }
        }
    }
}