Пример #1
0
  /**
   * Fills in all used scopes of the given one.
   *
   * @param curr current scope
   * @return IDs of all directly reachable scopes
   * @throws QueryException if a variable directly calls itself
   */
  private int[] neighbors(final Scope curr) throws QueryException {
    final IntList adj = new IntList(0);
    final boolean ok =
        curr.visit(
            new ASTVisitor() {
              @Override
              public boolean staticVar(final StaticVar var) {
                return var != curr && neighbor(var);
              }

              @Override
              public boolean staticFuncCall(final StaticFuncCall call) {
                return neighbor(call.func());
              }

              @Override
              public boolean inlineFunc(final Scope sub) {
                return sub.visit(this);
              }

              @Override
              public boolean funcItem(final FuncItem func) {
                return neighbor(func);
              }

              /**
               * Adds a neighbor of the currently inspected scope.
               *
               * @param scp the neighbor
               * @return {@code true} for convenience
               */
              private boolean neighbor(final Scope scp) {
                final int old = id(scp), id = old == -1 ? add(scp) : old;
                if (old == -1 || !adj.contains(id)) adj.add(id);
                return true;
              }
            });

    if (!ok) {
      final StaticVar var = (StaticVar) curr;
      throw CIRCREF_X.get(var.info, "$" + var.name);
    }
    return adj.finish();
  }
Пример #2
0
  @Override
  public Item item(final QueryContext qc, final InputInfo ii) throws QueryException {
    final Data data = checkData(qc);
    final String path = path(1, qc);
    final Item item = toItem(exprs[2], qc);
    final Options opts = toOptions(3, Q_OPTIONS, new Options(), qc);

    final Updates updates = qc.resources.updates();
    final IntList docs = data.resources.docs(path);
    int d = 0;

    // delete binary resources
    final IOFile bin = data.meta.binary(path);
    if (bin == null || bin.isDir()) throw BXDB_REPLACE_X.get(info, path);

    if (item instanceof Bin) {
      updates.add(new DBStore(data, path, item, info), qc);
    } else {
      if (bin.exists()) updates.add(new DBDelete(data, path, info), qc);
      final NewInput input = checkInput(item, token(path));
      if (docs.isEmpty() || docs.get(0) == 0) {
        // no replacement of first document (because of TableDiskAccess#insert, used > 0, pre = 0)
        updates.add(new DBAdd(data, input, opts, qc, info), qc);
      } else {
        updates.add(new ReplaceDoc(docs.get(0), data, input, opts, qc, info), qc);
        d = 1;
      }
    }

    // delete old documents
    final int ds = docs.size();
    for (; d < ds; d++) updates.add(new DeleteNode(docs.get(d), data, info), qc);
    return null;
  }
Пример #3
0
  /**
   * Algorithm of Tarjan for computing the strongly connected components of a graph.
   *
   * @param v current node
   * @throws QueryException if a variable directly calls itself
   */
  private void tarjan(final int v) throws QueryException {
    final int ixv = 2 * v, llv = ixv + 1, idx = next++;
    while (list.size() <= llv) list.add(-1);
    list.set(ixv, idx);
    list.set(llv, idx);

    stack.push(v);

    for (final int w : adjacentTo(v)) {
      final int ixw = 2 * w, llw = ixw + 1;
      if (list.size() <= ixw || list.get(ixw) < 0) {
        // Successor w has not yet been visited; recurse on it
        tarjan(w);
        list.set(llv, Math.min(list.get(llv), list.get(llw)));
      } else if (stack.contains(w)) {
        // Successor w is in stack S and hence in the current SCC
        list.set(llv, Math.min(list.get(llv), list.get(ixw)));
      }
    }

    // If v is a root node, pop the stack and generate an SCC
    if (list.get(llv) == list.get(ixv)) {
      int w;
      Scope[] out = null;
      do {
        w = stack.pop();
        final Scope scp = scopes.get(w);
        out = out == null ? new Scope[] {scp} : Array.add(out, scp);
      } while (w != v);
      result.add(out);
    }
  }
Пример #4
0
  /**
   * Formats the specified number and returns a string representation.
   *
   * @param item item
   * @param pics pictures
   * @param ii input info
   * @return picture variables
   * @throws QueryException query exception
   */
  private byte[] format(final ANum item, final Picture[] pics, final InputInfo ii)
      throws QueryException {

    // Rule 1: return results for NaN
    final double d = item.dbl(ii);
    if (Double.isNaN(d)) return nan;

    // Rule 2: check if value if negative (smaller than zero or -0)
    final boolean neg = d < 0 || d == 0 && Double.doubleToLongBits(d) == Long.MIN_VALUE;
    final Picture pic = pics[neg && pics.length == 2 ? 1 : 0];
    final IntList res = new IntList(), intgr = new IntList(), fract = new IntList();
    int exp = 0;

    // Rule 3: percent/permille
    ANum num = item;
    if (pic.pc) num = (ANum) Calc.MULT.ev(num, Int.get(100), ii);
    if (pic.pm) num = (ANum) Calc.MULT.ev(num, Int.get(1000), ii);

    if (Double.isInfinite(num.dbl(ii))) {
      // Rule 4: infinity
      intgr.add(new TokenParser(inf).toArray());
    } else {
      // Rule 5: exponent
      if (pic.minExp != 0 && d != 0) {
        BigDecimal dec = num.dec(ii).abs().stripTrailingZeros();
        int scl = 0;
        if (dec.compareTo(BigDecimal.ONE) >= 0) {
          scl = dec.setScale(0, RoundingMode.HALF_DOWN).precision();
        } else {
          while (dec.compareTo(BigDecimal.ONE) < 0) {
            dec = dec.multiply(BigDecimal.TEN);
            scl--;
          }
          scl++;
        }
        exp = scl - pic.min[0];
        if (exp != 0) {
          final BigDecimal n = BigDecimal.TEN.pow(Math.abs(exp));
          num = (ANum) Calc.MULT.ev(num, Dec.get(exp > 0 ? BigDecimal.ONE.divide(n) : n), ii);
        }
      }
      num = num.round(pic.maxFrac, true).abs();

      // convert positive number to string
      final String s =
          (num instanceof Dbl || num instanceof Flt
                  ? Dec.get(BigDecimal.valueOf(num.dbl(ii)))
                  : num)
              .toString();

      // integer/fractional separator
      final int sep = s.indexOf('.');

      // create integer part
      final int sl = s.length();
      final int il = sep == -1 ? sl : sep;
      for (int i = il; i < pic.min[0]; ++i) intgr.add(zero);
      // fractional number: skip leading 0
      if (!s.startsWith("0.") || pic.min[0] > 0) {
        for (int i = 0; i < il; i++) intgr.add(zero + s.charAt(i) - '0');
      }

      // squeeze in grouping separators
      if (pic.group[0].length == 1 && pic.group[0][0] > 0) {
        // regular pattern with repeating separators
        for (int p = intgr.size() - (neg ? 2 : 1); p > 0; --p) {
          if (p % pic.group[0][0] == 0) intgr.insert(intgr.size() - p, grouping);
        }
      } else {
        // irregular pattern, or no separators at all
        final int gl = pic.group[0].length;
        for (int g = 0; g < gl; ++g) {
          final int pos = intgr.size() - pic.group[0][g];
          if (pos > 0) intgr.insert(pos, grouping);
        }
      }

      // create fractional part
      final int fl = sep == -1 ? 0 : sl - il - 1;
      if (fl != 0) for (int i = sep + 1; i < sl; i++) fract.add(zero + s.charAt(i) - '0');
      for (int i = fl; i < pic.min[1]; ++i) fract.add(zero);

      // squeeze in grouping separators in a reverse manner
      final int ul = fract.size();
      for (int p = pic.group[1].length - 1; p >= 0; p--) {
        final int pos = pic.group[1][p];
        if (pos < ul) fract.insert(pos, grouping);
      }
    }

    // add minus sign
    if (neg && pics.length != 2) res.add(minus);
    // add prefix and integer part
    res.add(pic.prefSuf[0].toArray()).add(intgr.finish());
    // add fractional part
    if (!fract.isEmpty()) res.add(decimal).add(fract.finish());
    // add exponent
    if (pic.minExp != 0) {
      res.add(exponent);
      if (exp < 0) res.add(minus);
      final String s = Integer.toString(Math.abs(exp));
      final int sl = s.length();
      for (int i = sl; i < pic.minExp; i++) res.add(zero);
      for (int i = 0; i < sl; i++) res.add(zero + s.charAt(i) - '0');
    }
    // add suffix
    res.add(pic.prefSuf[1].toArray());
    return new TokenBuilder(res.finish()).finish();
  }