Tries to rewrite steps to union expressions. @param cc compilation context @return original or new expression @throws QueryException query exception
(final CompileContext cc)
| 894 | * @throws QueryException query exception |
| 895 | */ |
| 896 | private Expr toUnion(final CompileContext cc) throws QueryException { |
| 897 | // function for rewriting a list to a union expression |
| 898 | final QueryBiFunction<Expr, Expr, Expr> rewrite = (step, next) -> { |
| 899 | // do not rewrite (a, b)/<c/> |
| 900 | if(step == null || next != null && next.has(Flag.CNS)) return step; |
| 901 | // (a, b)/c → (a | b)/a |
| 902 | if(step instanceof final List lst) return lst.toUnion(cc); |
| 903 | // a[b, c] → a[b | c] |
| 904 | if(step instanceof final Filter fltr && !fltr.mayBePositional() && |
| 905 | fltr.root instanceof final List lst) { |
| 906 | final Expr st = lst.toUnion(cc); |
| 907 | if(st != fltr.root) return Filter.get(cc, fltr.info(), st, fltr.exprs); |
| 908 | } |
| 909 | // replicate(a, 2)/b → a/b |
| 910 | if(step.seqType().type instanceof NodeType) { |
| 911 | if(REPLICATE.is(step) && ((FnReplicate) step).singleEval(false)) return step.arg(0); |
| 912 | if(step instanceof final SingletonSeq ss) return ss.itemAt(0); |
| 913 | } |
| 914 | return step; |
| 915 | }; |
| 916 | |
| 917 | // only rewrite root expression if subsequent step yields nodes |
| 918 | boolean changed = false; |
| 919 | if(steps[0].seqType().type instanceof NodeType) { |
| 920 | final Expr rt = rewrite.apply(root, steps[0]); |
| 921 | if(rt != root) { |
| 922 | root = rt; |
| 923 | changed = true; |
| 924 | } |
| 925 | } |
| 926 | |
| 927 | changed |= cc.ok(root, true, () -> { |
| 928 | boolean chngd = false; |
| 929 | final int sl = steps.length; |
| 930 | for(int s = 0; s < sl; s++) { |
| 931 | final Expr step = rewrite.apply(steps[s], s + 1 < sl ? steps[s + 1] : null); |
| 932 | if(step != steps[s]) { |
| 933 | steps[s] = step; |
| 934 | chngd = true; |
| 935 | } |
| 936 | cc.updateFocus(step, true); |
| 937 | } |
| 938 | return chngd; |
| 939 | }); |
| 940 | |
| 941 | return changed ? get(info, root, steps) : this; |
| 942 | } |
| 943 | |
| 944 | /** |
| 945 | * Merges adjacent steps. |