@Override public boolean uses(final Use u) { for (final Expr p : pred) { if (u == Use.POS && p.type().mayBeNum() || p.uses(u)) return true; } return false; }
@Override public Expr compile(final QueryContext ctx) throws QueryException { for (int e = 0; e < expr.length; e++) expr[e] = expr[e].compile(ctx); // compute number of results size = 0; for (final Expr e : expr) { final long c = e.size(); if (c == -1) { size = c; break; } size += c; } // evaluate sequence type type = SeqType.EMP; Value[] val = new Value[expr.length]; for (int v = 0; v < expr.length; v++) { final Expr e = expr[v]; // check if all expressions are values if (val != null) { if (e.isValue()) val[v] = (Value) e; else val = null; } // skip expression that will not add any results if (e.isEmpty()) continue; // evaluate sequence type final SeqType et = e.type(); type = type == SeqType.EMP ? et : SeqType.get( et.type == type.type ? et.type : AtomType.ITEM, et.mayBeZero() && type.mayBeZero() ? Occ.ZERO_MORE : Occ.ONE_MORE); } // return cached integer sequence, cached values or self reference Expr e = this; final int s = (int) size; if (val != null && size <= Integer.MAX_VALUE) { if (type.type == AtomType.STR) e = StrSeq.get(val, s); else if (type.type == AtomType.BLN) e = BlnSeq.get(val, s); else if (type.type == AtomType.FLT) e = FltSeq.get(val, s); else if (type.type == AtomType.DBL) e = DblSeq.get(val, s); else if (type.type == AtomType.DEC) e = DecSeq.get(val, s); else if (type.type == AtomType.BYT) e = BytSeq.get(val, s); else if (type.type.instanceOf(AtomType.ITR)) e = IntSeq.get(val, s, type.type); else { final ValueBuilder vb = new ValueBuilder(s); for (final Value v : val) vb.add(v); e = vb.value(); } } return optPre(e, ctx); }
@Override public Expr optimize(final QueryContext ctx, final VarScope scp) throws QueryException { final int ar = expr.length - 1; final Expr f = expr[ar]; final Type t = f.type().type; if (t instanceof FuncType) { final FuncType ft = (FuncType) t; if (ft.args != null && ft.args.length != ar) throw INVARITY.get(info, f, ar); if (ft.ret != null) type = ft.ret; } if (f instanceof XQFunctionExpr) { // maps can only contain fully evaluated Values, so this is safe if (allAreValues() && f instanceof Map) return optPre(value(ctx), ctx); // try to inline the function if (!(f instanceof FuncItem && comesFrom((FuncItem) f)) && !updating) { final Expr[] args = Arrays.copyOf(expr, expr.length - 1); final Expr inl = ((XQFunctionExpr) f).inlineExpr(args, ctx, scp, info); if (inl != null) return inl; } } return this; }
/** * Returns a boolean equivalent for the specified expression. If the specified expression yields a * boolean value anyway, it will be returned as is. Otherwise, it will be wrapped into a boolean * function. * * @param e expression to be rewritten * @return expression */ protected final Expr compBln(final Expr e) { return e.type().eq(SeqType.BLN) ? e : Function.BOOLEAN.get(input, e); }