(final CompileContext cc)
| 34 | } |
| 35 | |
| 36 | @Override |
| 37 | Expr opt(final CompileContext cc) throws QueryException { |
| 38 | flatten(cc); |
| 39 | |
| 40 | // determine type |
| 41 | SeqType st = Types.GNODE_ZM; |
| 42 | for(final Expr expr : exprs) { |
| 43 | final SeqType st2 = expr.seqType(); |
| 44 | if(!st2.zero()) { |
| 45 | if(!(st2.type instanceof NodeType)) return null; |
| 46 | st = st.intersect(st2); |
| 47 | // check for incompatible node types |
| 48 | if(st == null) return Empty.VALUE; |
| 49 | } |
| 50 | } |
| 51 | exprType.assign(st.union(Occ.ZERO)).data(exprs); |
| 52 | |
| 53 | final ExprList list = new ExprList(exprs.length); |
| 54 | for(final Expr expr : exprs) { |
| 55 | if(expr == Empty.VALUE) { |
| 56 | // empty operand: * intersect () → () |
| 57 | return Empty.VALUE; |
| 58 | } else if(list.contains(expr) && !expr.has(Flag.CNS, Flag.NDT)) { |
| 59 | // remove duplicates: * intersect * → * |
| 60 | cc.info(OPTREMOVE_X_X, expr, (Supplier<?>) this::description); |
| 61 | } else { |
| 62 | list.add(expr); |
| 63 | } |
| 64 | } |
| 65 | exprs = list.finish(); |
| 66 | |
| 67 | final Expr ex = rewrite(Union.class, (invert, ops) -> |
| 68 | invert ? new Union(info, ops) : new Intersect(info, ops), cc); |
| 69 | if(ex != null) { |
| 70 | cc.info(OPTREWRITE_X_X, (Supplier<?>) this::description, ex); |
| 71 | return ex; |
| 72 | } |
| 73 | return null; |
| 74 | } |
| 75 | |
| 76 | @Override |
| 77 | And mergePredicates(final Expr[] preds, final CompileContext cc) { |
nothing calls this directly
no test coverage detected