(final Expr expr, final Expr next, final CompileContext cc)
| 115 | } |
| 116 | |
| 117 | @Override |
| 118 | Expr merge(final Expr expr, final Expr next, final CompileContext cc) throws QueryException { |
| 119 | final long size = expr.size(); |
| 120 | if(!expr.has(Flag.NDT) && !next.has(Flag.POS)) { |
| 121 | // merge expressions if next expression does not rely on the context |
| 122 | if(!next.has(Flag.CTX)) { |
| 123 | Expr count = null; |
| 124 | if(size != -1) { |
| 125 | count = Itr.get(size); |
| 126 | } else if(expr instanceof Range && expr.arg(0) == Itr.ONE && |
| 127 | expr.arg(1).seqType().instanceOf(Types.INTEGER_O)) { |
| 128 | count = expr.arg(1); |
| 129 | } |
| 130 | // (1 to 2) ! <x/> → replicate(<x/>, 2, true()) |
| 131 | // (1 to $c) ! 'A' → replicate('A', $c, false()) |
| 132 | if(count != null) return cc.replicate(next, count, info); |
| 133 | } |
| 134 | |
| 135 | if(next instanceof StandardFunc && !next.has(Flag.NDT)) { |
| 136 | // next operand relies on context and is a deterministic function call |
| 137 | final Expr[] args = next.args(); |
| 138 | if(REPLICATE.is(next) && ((FnReplicate) next).singleEval(true) && |
| 139 | args[0] instanceof ContextValue && !args[1].has(Flag.CTX)) { |
| 140 | if(REPLICATE.is(expr) && ((FnReplicate) expr).singleEval(true)) { |
| 141 | // replicate(E, C) ! replicate(., D) → replicate(E, C * D) |
| 142 | final Expr cnt = new Arith(info, expr.arg(1), args[1], Calc.MULTIPLY).optimize(cc); |
| 143 | return cc.function(REPLICATE, info, expr.arg(0), cnt); |
| 144 | } |
| 145 | if(expr instanceof final SingletonSeq ss && ss.singleItem()) { |
| 146 | // SINGLETONSEQ ! replicate(., C) → replicate(SINGLETONSEQ, C) |
| 147 | return cc.function(REPLICATE, info, expr, args[1]); |
| 148 | } |
| 149 | } else if(ITEMS_AT.is(next) && !args[0].has(Flag.CTX) && args[1] instanceof ContextValue) { |
| 150 | if(expr instanceof final RangeSeq rs) { |
| 151 | // (A to B) ! items-at(E, .) → util:range(E, A, B) |
| 152 | // reverse(A to B) ! items-at(E, .) → reverse(util:range(E, A, B)) |
| 153 | final Expr func = cc.function(_UTIL_RANGE, info, args[0], |
| 154 | Itr.get(rs.min()), Itr.get(rs.max())); |
| 155 | return rs.ascending() ? func : cc.function(REVERSE, info, func); |
| 156 | } |
| 157 | if(expr instanceof Range) { |
| 158 | // (START to END) ! items-at(X, .) → util:range(X, START, END) |
| 159 | return cc.function(_UTIL_RANGE, info, args[0], expr.arg(0), expr.arg(1)); |
| 160 | } |
| 161 | if(expr.seqType().instanceOf(Types.INTEGER_ZM)) { |
| 162 | // INTEGERS ! items-at(X, .) → items-at(X, INTEGERS) |
| 163 | return cc.function(ITEMS_AT, info, args[0], expr); |
| 164 | } |
| 165 | } else if(DATA.is(next) && (((FnData) next).contextAccess() || |
| 166 | args[0] instanceof ContextValue)) { |
| 167 | // E ! data(.) → data(E) |
| 168 | return cc.function(DATA, info, expr); |
| 169 | } else if(STRING_TO_CODEPOINTS.is(expr) && CODEPOINTS_TO_STRING.is(next) && |
| 170 | args[0] instanceof ContextValue) { |
| 171 | // string-to-codepoints(E) ! codepoints-to-string(.) → characters(E) |
| 172 | return cc.function(CHARACTERS, info, expr.args()); |
| 173 | } |
| 174 | } |
no test coverage detected