void ConstantExpression::onParse(AnalysisResultConstPtr ar,
                                 FileScopePtr scope) {
  ar->parseOnDemandByConstant(m_name);
}
ExpressionPtr UnaryOpExpression::preOptimize(AnalysisResultConstPtr ar) {
  Variant value;
  Variant result;

  if (m_exp && ar->getPhase() >= AnalysisResult::FirstPreOptimize) {
    if (m_op == T_UNSET) {
      if (m_exp->isScalar() ||
          (m_exp->is(KindOfExpressionList) &&
           static_pointer_cast<ExpressionList>(m_exp)->getCount() == 0)) {
        recomputeEffects();
        return CONSTANT("null");
      }
      return ExpressionPtr();
    }
  }

  if (m_op == T_ISSET && m_exp->is(KindOfExpressionList) &&
      static_pointer_cast<ExpressionList>(m_exp)->getListKind() ==
      ExpressionList::ListKindParam) {
    ExpressionListPtr el(static_pointer_cast<ExpressionList>(m_exp));
    result = true;
    int i = 0, n = el->getCount();
    for (; i < n; i++) {
      ExpressionPtr e((*el)[i]);
      if (!e || !e->isScalar() || !e->getScalarValue(value)) break;
      if (!isset(value)) {
        result = false;
      }
    }
    if (i == n) {
      return replaceValue(makeScalarExpression(ar, result));
    }
  } else if (m_op != T_ARRAY &&
             m_exp &&
             m_exp->isScalar() &&
             m_exp->getScalarValue(value) &&
             preCompute(value, result)) {
    return replaceValue(makeScalarExpression(ar, result));
  } else if (m_op == T_BOOL_CAST) {
    switch (m_exp->getKindOf()) {
      default: break;
      case KindOfBinaryOpExpression: {
        int op = static_pointer_cast<BinaryOpExpression>(m_exp)->getOp();
        switch (op) {
          case T_LOGICAL_OR:
          case T_BOOLEAN_OR:
          case T_LOGICAL_AND:
          case T_BOOLEAN_AND:
          case T_LOGICAL_XOR:
          case T_INSTANCEOF:
          case '<':
          case T_IS_SMALLER_OR_EQUAL:
          case '>':
          case T_IS_GREATER_OR_EQUAL:
          case T_IS_IDENTICAL:
          case T_IS_NOT_IDENTICAL:
          case T_IS_EQUAL:
          case T_IS_NOT_EQUAL:
            return m_exp;
        }
        break;
      }
      case KindOfUnaryOpExpression: {
        int op = static_pointer_cast<UnaryOpExpression>(m_exp)->getOp();
        switch (op) {
          case T_BOOL_CAST:
          case '!':
          case T_ISSET:
          case T_EMPTY:
          case T_PRINT:
            return m_exp;
        }
        break;
      }
    }
  }
  return ExpressionPtr();
}