Package com.google.caja.parser.js

Examples of com.google.caja.parser.js.Expression


    // body.
    var:
    for (Var v : vars) {
      if ("arguments".equals(v.name)) { continue; // special in function body
      Symbol s = v.s.getSymbol(v.name);
      Expression value;
      int initPos;
      boolean isConst;
      AncestorChain<Identifier> write;

      switch (s.writes.size()) {
        case 1:
          write = s.writes.get(0);
          if (write.parent.node instanceof Declaration) {
            initPos = write.parent.node instanceof FunctionDeclaration
                ? -// hoisted
                : positions.get(write);
            AncestorChain<Declaration> d = write.parent.cast(Declaration.class);
            value = d.node.getInitializer();

            isConst = isConst(value);
            if (!isConst
                && (!isSinglyInlineable(value) || s.reads.size() > 1)) {
              continue var;
            }
          } else {
            continue var;
          }
          break;
        case 0:
          initPos = -1;
          value = null;
          write = null;
          isConst = true;
          break;
        default:
          continue var;
      }

      // If there is at most one assignment at the top level of the function
      // and all reads occur after that, and the value is constant, then
      // inline uses.

      // TODO: we can safely inline the reads that are okay.

      // TODO: check that reads are in the same function
      // or before the first call or member dereference op.

      int nInlined = 0;
      for (AncestorChain<Identifier> read : s.reads) {
        // If the read occur afterwards lexically, then, since we
        // know the declaration appears at the top of a run of
        // declarations in a function body, then it isn't being read by
        // any of the earlier declarations ; so the read must happen
        // after the var is initialized.
        if (positions.get(read) < initPos) { continue; }
        if (write != null && !inSameFn(write, read)) {
          // Can't reuse reference values across function boundaries.
          if (!isConst) { continue; }
          // If the use is across function boundaries, and there might have
          // been a non-local transfer of control, then we can't inline.
          if (initPos > v.s.earliestNonLocalXfer) { continue; }
        }

        AncestorChain<Reference> toReplace = read.parent.cast(Reference.class);
        Expression repl;
        if (value == null) {
          FilePosition fp = toReplace.node.getFilePosition();
          repl = Operation.create(fp, Operator.VOID, new IntegerLiteral(fp, 0));
        } else {
          repl = (Expression) value.clone();
View Full Code Here


      return;
    }
    ObjectConstructor envJson;
    try {
      Parser p = parser(cp, mq);
      Expression e = p.parseExpression(true); // TODO(mikesamuel): limit to JSON
      p.getTokenQueue().expectEmpty();
      if (!(e instanceof ObjectConstructor)) {
        mq.addMessage(
            MessageType.IO_ERROR,
            MessagePart.Factory.valueOf("Invalid JSON in " + f));
View Full Code Here

  private static boolean isCommaOperatorInForLoop(
      AncestorChain<ExpressionStmt> es) {
    if (es.parent == null || !(es.parent.node instanceof ForLoop)) {
      return false;
    }
    Expression e = es.node.getExpression();

    return isCommaOperationNotEvaluatedForValue(e);
  }
View Full Code Here

  private static boolean isCommaOperationNotEvaluatedForValue(Expression e) {
    if (!(e instanceof Operation)) { return false; }
    Operation op = (Operation) e;
    if (op.getOperator() != Operator.COMMA) { return false; }
    Expression left = op.children().get(0), right = op.children().get(1);
    return !shouldBeEvaluatedForValue(right)
        && (!shouldBeEvaluatedForValue(left)
            || isCommaOperationNotEvaluatedForValue(left));
  }
View Full Code Here

          ? new Block(n.getFilePosition(), newChildren) : n;
    } else if (n instanceof SwitchStmt) {
      return optimizeSwitch((SwitchStmt) n);
    } else if (n instanceof ReturnStmt) {
      ReturnStmt rs = (ReturnStmt) n;
      Expression returnValue = rs.getReturnValue();
      Expression optReturnValue = returnValue != null
          ? (Expression) optimize(returnValue, false)
          : null;
      if (optReturnValue != null && returnValue != null  // 2nd implied by 1st
          && "undefined".equals(returnValue.typeOf())
          && optReturnValue.simplifyForSideEffect() == null) {
        return new ReturnStmt(rs.getFilePosition(), null);
      } else if (optReturnValue != returnValue) {
        return new ReturnStmt(rs.getFilePosition(), optReturnValue);
      }
      return rs;
    } else {
      List<? extends ParseTreeNode> children = n.children();
      int nChildren = children.size();
      List<ParseTreeNode> newChildren = null;
      boolean childNeedsBlock = (
          n instanceof FunctionConstructor || n instanceof TryStmt
          || n instanceof CatchStmt || n instanceof FinallyStmt
          || n instanceof SwitchCase);
      for (int i = 0; i < nChildren; ++i) {
        ParseTreeNode child = children.get(i);
        ParseTreeNode newChild = optimize(child, childNeedsBlock);
        if (child != newChild) {
          if (newChildren == null) {
            newChildren = Lists.newArrayList(nChildren);
          }
          newChildren.addAll(children.subList(newChildren.size(), i));
          newChildren.add(newChild);
        }
      }
      if (newChildren != null) {
        newChildren.addAll(children.subList(newChildren.size(), nChildren));
      }
      List<? extends ParseTreeNode> outChildren = newChildren == null
          ? children : newChildren;
      if (n instanceof ExpressionStmt) {
        Expression e = (Expression) outChildren.get(0);
        Expression simple = e.simplifyForSideEffect();
        if (simple == null) { return new Noop(n.getFilePosition()); }
        if (simple != e) {
          newChildren = Collections.<ParseTreeNode>singletonList(simple);
        }
      } else if (n instanceof Conditional) {
View Full Code Here

            //   { foo(); return bar(); }  ->  { return foo(), bar(); }
            ++end;
          }
          if (end - start >= 2) {
            progress = true;
            Expression joined = null;
            for (Statement toJoin : stmts.subList(start, end)) {
              List<? extends ParseTreeNode> tjChildren = toJoin.children();
              // tjChildren can be empty for return statements that implicitly
              // return undefined.
              Expression e = tjChildren.isEmpty()
                  ? undef(FilePosition.endOf(toJoin.getFilePosition()))
                  : (Expression) tjChildren.get(0);
              joined = joined == null ? e : commaOp(joined, e);
            }
            Statement newChild;
View Full Code Here

    // In the first two cases we end up with nested hook expressions.
    // In the third, we need to special case the last condition.

    // So we start to build an expression from left to right.
    int pos = n;
    Expression e = expressionChildOf(condParts.get(--pos));
    if (!hasElse) {
      Expression lastCond = (Expression) condParts.get(--pos);
      if (Operation.is(lastCond, Operator.NOT)) {
        e = Operation.createInfix(
            Operator.LOGICAL_OR, (Expression) lastCond.children().get(0), e);
      } else {
        e = Operation.createInfix(Operator.LOGICAL_AND, lastCond, e);
      }
    }

    while (pos > 0) {
      Expression clause = expressionChildOf(condParts.get(--pos));
      Expression cond = (Expression) condParts.get(--pos);
      FilePosition fpos = FilePosition.span(
          cond.getFilePosition(), e.getFilePosition());
      if (clause instanceof BooleanLiteral && e instanceof BooleanLiteral) {
        BooleanLiteral a = (BooleanLiteral) clause,
            b = (BooleanLiteral) e;
        if (a.getValue() == b.getValue()) {
          e = commaOp(cond, a).fold(false);
        } else {
          // cond ? true : false -> !!cond
          int nNotsNeeded = a.getValue() ? 2 : 1;
          if (nNotsNeeded == 2 && "boolean".equals(cond.typeOf())) {
            nNotsNeeded = 0;
          }
          e = cond;
          while (--nNotsNeeded >= 0) {
            e = Operation.create(e.getFilePosition(), Operator.NOT, e)
                .fold(false);
          }
        }
      } else if (Operation.is(cond, Operator.NOT)) {
        Expression notCond = ((Operation) cond).children().get(0);
        e = Operation.create(fpos, Operator.TERNARY, notCond, e, clause);
      } else {
        e = Operation.create(fpos, Operator.TERNARY, cond, clause, e);
      }
      e = optimizeExpressionFlow(e);
View Full Code Here

    Operation op = (Operation) e;
    List<? extends Expression> operands = op.children();
    Expression[] newOperands = null;
    int n = operands.size();
    for (int i = 0; i < n; ++i) {
      Expression operand = operands.get(i);
      Expression newOperand = optimizeExpressionFlow(operand);
      if (operand != newOperand) {
        if (newOperands == null) {
          newOperands = operands.toArray(new Expression[n]);
        }
        newOperands[i] = newOperand;
      }
    }
    Operator oper = op.getOperator();
    FilePosition pos = e.getFilePosition();
    if (oper != Operator.TERNARY) {
      return newOperands == null ? e : Operation.create(pos, oper, newOperands);
    }
    // (c ? x,z : y,z) -> (c ? x:y),z
    Expression[] ternaryOperands = newOperands != null
        ? newOperands : operands.toArray(new Expression[3]);
    Expression c = ternaryOperands[0];
    Expression x = ternaryOperands[1];
    Expression y = ternaryOperands[2];
    while (Operation.is(c, Operator.NOT)) {
      c = ((Operation) c).children().get(0);
      Expression t = x;
      x = y;
      y = t;
    }
    if (ParseTreeNodes.deepEquals(x, y)) {
      if (c.simplifyForSideEffect() == null) { return x; }
      return commaOp(pos, c, x);
    }
    if (isSimple(c)) {
      // If a reference fails with an exception because it is undefined, then
      // control would never reach the second identical expression.
      if (ParseTreeNodes.deepEquals(c, x)) {
        // (c ? c : y) -> c || y     if c not side effecting
        return Operation.create(pos, Operator.LOGICAL_OR, c, y);
      } else if (ParseTreeNodes.deepEquals(c, y)) {
        // (c ? x : c) -> c && x     if c not side effecting
        return Operation.create(pos, Operator.LOGICAL_AND, c, x);
      }
    }
    // TODO(mikesamuel): if c is simple and not a global reference, optimize
    // out he common head as well.
    CommaCommonalities opt = commaCommonalities(x, y);
    if (opt != null) {
      // Both reduced sides can't be null since we checked above whether
      // x and y are structurally identical.
      if (opt.aReduced == null) {
        // (c ? z: y,z)  ->  (c || y),z
        return commaOp(
            pos,
            Operation.createInfix(Operator.LOGICAL_OR, c, opt.bReduced),
            opt.commonTail);
      } else if (opt.bReduced == null) {
        // (c ? x,z : z)  ->  (c && x),z
        return commaOp(
            pos,
            Operation.createInfix(Operator.LOGICAL_AND, c, opt.aReduced),
            opt.commonTail);
      } else {
        // (c ? x,z : y,z) -> (c ? x : y),z
        return commaOp(
            pos,
            optimizeExpressionFlow(
                Operation.createTernary(c, opt.aReduced, opt.bReduced)),
            opt.commonTail);
      }
    }
    ternaryOperands[0] = c;
    ternaryOperands[1] = x;
    ternaryOperands[2] = y;
    if (x instanceof Operation && y instanceof Operation) {
      Operation xop = (Operation) x;
      Operation yop = (Operation) y;
      Operator xoper = xop.getOperator();
      if (xoper == yop.getOperator()) {
        List<? extends Expression> xoperands = xop.children();
        List<? extends Expression> yoperands = yop.children();
        int nOperands = xoperands.size();
        if (nOperands == yoperands.size()) {
          Expression xoperand0 = xoperands.get(0);
          // We can often pull the rightmost operand out since it would be
          // evaluated last regardless.
          if (nOperands == 2
              && ParseTreeNodes.deepEquals(xoperands.get(1), yoperands.get(1))
              && xoper.getCategory() != OperatorCategory.ASSIGNMENT
View Full Code Here

    int aSize = aChain.size(), bSize = bChain.size();
    int minSize = Math.min(aSize, bSize);
    int nCommon = 0;
    for (int i = 0; i < minSize; ++i) {
      Expression ael = aChain.get(aSize - 1 - i);
      Expression bel = bChain.get(bSize - 1 - i);
      if (!ParseTreeNodes.deepEquals(ael, bel)) { break; }
      ++nCommon;
    }
    if (nCommon == 0) { return null; }
    CommaCommonalities c = new CommaCommonalities();
View Full Code Here

      e = operands.get(0);
      chain.add(operands.get(1));
    }
    chain.add(e);
    for (int i = 0, j = chain.size(); i < --j; ++i) {
      Expression t = chain.get(i);
      chain.set(i, chain.get(j));
      chain.set(j, t);
    }
    return chain;
  }
View Full Code Here

TOP

Related Classes of com.google.caja.parser.js.Expression

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.