コード例 #1
0
bool AssignmentExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
                                        int state) {
  if (m_variable->is(Expression::KindOfArrayElementExpression)) {
    ExpressionPtr exp = m_value;
    ExpressionPtr vv(
      static_pointer_cast<ArrayElementExpression>(m_variable)->getVariable());
    if ((vv->is(KindOfArrayElementExpression) ||
         vv->is(KindOfObjectPropertyExpression)) &&
        (vv->getContainedEffects() && (CreateEffect|AccessorEffect))) {
      /*
        We are in a case such as
          $a->b['c'] = ...;
          $a['b']['c'] = ...;
        Where evaluating m_variable may modify $a. Unless we can prove that
        the rhs is not referring to the same thing as $a, we must generate
        a temporary for it (note that we could do better with the following
        checks).
      */
      if (!(m_ref && exp->isRefable()) &&
          !exp->isTemporary() && !exp->isScalar() &&
          exp->getActualType() && !exp->getActualType()->isPrimitive() &&
          exp->getActualType()->getKindOf() != Type::KindOfString) {
        state |= Expression::StashAll;
      }
    }
  }

  return Expression::preOutputCPP(cg, ar, state);
}
コード例 #2
0
static void wrapValue(CodeGenerator &cg, AnalysisResultPtr ar,
                      ExpressionPtr exp, bool ref, bool array, bool varnr) {
  bool close = false;
  if (ref) {
    cg_printf("ref(");
    close = true;
  } else if (array && !exp->hasCPPTemp() &&
             !exp->isTemporary() && !exp->isScalar() &&
             exp->getActualType() && !exp->getActualType()->isPrimitive() &&
             exp->getActualType()->getKindOf() != Type::KindOfString) {
    cg_printf("wrap_variant(");
    close = true;
  } else if (varnr && exp->getCPPType()->isExactType()) {
    bool isScalar = exp->isScalar();
    if (!isScalar || !Option::UseScalarVariant) {
      cg_printf("VarNR(");
      close = true;
    } else if (isScalar) {
      ASSERT(!cg.hasScalarVariant());
      cg.setScalarVariant();
    }
  }
  exp->outputCPP(cg, ar);
  cg.clearScalarVariant();
  if (close) cg_printf(")");
}
コード例 #3
0
bool AssignmentExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
                                        int state) {
  if (m_variable->is(Expression::KindOfArrayElementExpression)) {
    ExpressionPtr exp = m_value;
    if (!(m_ref && exp->isRefable()) &&
        !exp->isTemporary() && !exp->isScalar() &&
        exp->getActualType() && !exp->getActualType()->isPrimitive() &&
        exp->getActualType()->getKindOf() != Type::KindOfString) {
      state |= Expression::StashAll;
    }
  }
  return Expression::preOutputCPP(cg, ar, state);
}
コード例 #4
0
int BinaryOpExpression::getConcatList(ExpressionPtrVec &ev, ExpressionPtr exp,
                                      bool &hasVoid) {
  if (!exp->hasCPPTemp()) {
    if (exp->is(Expression::KindOfUnaryOpExpression)) {
      UnaryOpExpressionPtr u = static_pointer_cast<UnaryOpExpression>(exp);
      if (u->getOp() == '(') {
        return getConcatList(ev, u->getExpression(), hasVoid);
      }
    } else if (exp->is(Expression::KindOfBinaryOpExpression)) {
      BinaryOpExpressionPtr b = static_pointer_cast<BinaryOpExpression>(exp);
      if (b->getOp() == '.') {
        if (b->getExp1()->is(Expression::KindOfSimpleVariable) &&
            b->getExp1()->isLocalExprAltered() &&
            !b->getExp1()->hasCPPTemp() &&
            b->getExp2()->hasEffect() &&
            !b->getExp2()->hasCPPTemp()) {
          /*
            In this case, the simple variable must be evaluated
            after b->getExp2(). But when we output a concat list we
            explicitly order the expressions from left to right.
          */
        } else {
          return getConcatList(ev, b->getExp1(), hasVoid) +
            getConcatList(ev, b->getExp2(), hasVoid);
        }
      }
    } else if (exp->is(Expression::KindOfEncapsListExpression)) {
      EncapsListExpressionPtr e =
        static_pointer_cast<EncapsListExpression>(exp);
      if (e->getType() != '`') {
        ExpressionListPtr el = e->getExpressions();
        int num = 0;
        for (int i = 0, s = el->getCount(); i < s; i++) {
          ExpressionPtr exp = (*el)[i];
          num += getConcatList(ev, exp, hasVoid);
        }
        return num;
      }
    }
  } else if (!exp->getActualType()) {
    return 0;
  }

  ev.push_back(exp);
  bool isVoid = !exp->getActualType();
  hasVoid |= isVoid;
  return isVoid ? 0 : 1;
}
コード例 #5
0
int BinaryOpExpression::getConcatList(ExpressionPtrVec &ev, ExpressionPtr exp,
                                      bool &hasVoid) {
  if (!exp->hasCPPTemp()) {
    if (exp->is(Expression::KindOfUnaryOpExpression)) {
      UnaryOpExpressionPtr u = static_pointer_cast<UnaryOpExpression>(exp);
      if (u->getOp() == '(') {
        return getConcatList(ev, u->getExpression(), hasVoid);
      }
    } else if (exp->is(Expression::KindOfBinaryOpExpression)) {
      BinaryOpExpressionPtr b = static_pointer_cast<BinaryOpExpression>(exp);
      if (b->getOp() == '.') {
        return getConcatList(ev, b->getExp1(), hasVoid) +
          getConcatList(ev, b->getExp2(), hasVoid);
      }
    } else if (exp->is(Expression::KindOfEncapsListExpression)) {
      EncapsListExpressionPtr e =
        static_pointer_cast<EncapsListExpression>(exp);
      if (e->getType() != '`') {
        ExpressionListPtr el = e->getExpressions();
        int num = 0;
        for (int i = 0, s = el->getCount(); i < s; i++) {
          ExpressionPtr exp = (*el)[i];
          num += getConcatList(ev, exp, hasVoid);
        }
        return num;
      }
    }
  }

  ev.push_back(exp);
  bool isVoid = !exp->getActualType();
  hasVoid |= isVoid;
  return isVoid ? 0 : 1;
}
コード例 #6
0
static void wrapValue(CodeGenerator &cg, AnalysisResultPtr ar,
                      ExpressionPtr exp, bool ref, bool array) {
  bool close = false;
  if (ref) {
    cg_printf("ref(");
    close = true;
  } else if (array && !exp->hasCPPTemp() &&
             !exp->isTemporary() && !exp->isScalar() &&
             exp->getActualType() && !exp->getActualType()->isPrimitive() &&
             exp->getActualType()->getKindOf() != Type::KindOfString) {
    cg_printf("wrap_variant(");
    close = true;
  }
  exp->outputCPP(cg, ar);
  if (close) cg_printf(")");
}
コード例 #7
0
ファイル: qop_expression.cpp プロジェクト: AviMoto/hiphop-php
void QOpExpression::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  if (!m_cppValue.empty()) {
    cg_printf("%s", m_cppValue.c_str());
  } else {
    ExpressionPtr expYes = m_expYes ? m_expYes : m_condition;
    bool wrapped = !isUnused();
    if (wrapped) {
      cg_printf("(");
    }
    wrapBoolean(cg, ar, m_condition);
    if (isUnused()) {
      cg_printf(" ? ");
      outputUnneededExpr(cg, ar, expYes);
      cg_printf(" : ");
      outputUnneededExpr(cg, ar, m_expNo);
    } else {
      TypePtr typeYes = expYes->getActualType();
      TypePtr typeNo = m_expNo->getActualType();
      const char *castType =
        typeYes && typeNo && Type::SameType(typeYes, typeNo) &&
        !typeYes->is(Type::KindOfVariant) &&
        expYes->isLiteralString() == m_expNo->isLiteralString()
        ? "" : "(Variant)";

      cg_printf(" ? (%s(", castType);
      expYes->outputCPP(cg, ar);
      cg_printf(")) : (%s(", castType);
      m_expNo->outputCPP(cg, ar);
      cg_printf("))");
    }
    if (wrapped) {
      cg_printf(")");
    }
  }
}
コード例 #8
0
TypePtr AssignmentExpression::
inferTypesImpl(AnalysisResultPtr ar, TypePtr type, bool coerce,
               ExpressionPtr variable,
               ExpressionPtr value /* = ExpressionPtr() */) {
  TypePtr ret = type;
  if (value) {
    if (coerce) {
      ret = value->inferAndCheck(ar, type, coerce);
    } else {
      ret = value->inferAndCheck(ar, NEW_TYPE(Some), coerce);
    }
  }

  BlockScopePtr scope = ar->getScope();
  if (variable->is(Expression::KindOfConstantExpression)) {
    // ...as in ClassConstant statement
    ConstantExpressionPtr exp =
      dynamic_pointer_cast<ConstantExpression>(variable);
    bool p;
    scope->getConstants()->check(exp->getName(), ret, true, ar, variable, p);
  } else if (variable->is(Expression::KindOfDynamicVariable)) {
    // simptodo: not too sure about this
    ar->getFileScope()->setAttribute(FileScope::ContainsLDynamicVariable);
  } else if (variable->is(Expression::KindOfSimpleVariable)) {
    SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable);
    if (var->getName() == "this" && ar->getClassScope()) {
      if (ar->isFirstPass()) {
        ar->getCodeError()->record(variable, CodeError::ReassignThis,
                                   variable);
      }
    }
    if (ar->getPhase() == AnalysisResult::LastInference && value) {
      if (!value->getExpectedType()) {
        value->setExpectedType(variable->getActualType());
      }
    }
  }
  // if the value may involve object, consider the variable as "referenced"
  // so that objects are not destructed prematurely.
  bool referenced = true;
  if (value && value->isScalar()) referenced = false;
  if (ret && ret->isNoObjectInvolved()) referenced = false;
  if (referenced && variable->is(Expression::KindOfSimpleVariable)) {
    SimpleVariablePtr var =
      dynamic_pointer_cast<SimpleVariable>(variable);
    const std::string &name = var->getName();
    VariableTablePtr variables = ar->getScope()->getVariables();
    variables->addReferenced(name);
  }

  TypePtr vt = variable->inferAndCheck(ar, ret, true);
  if (!coerce && type->is(Type::KindOfAny)) {
    ret = vt;
  }

  return ret;
}
コード例 #9
0
ファイル: expression.cpp プロジェクト: andyanx/hhvm
bool Expression::CheckNeededRHS(ExpressionPtr value) {
  bool needed = true;
  always_assert(value);
  while (value->is(KindOfAssignmentExpression)) {
    value = dynamic_pointer_cast<AssignmentExpression>(value)->getValue();
  }
  if (value->isScalar()) {
    needed = false;
  } else {
    TypePtr type = value->getType();
    if (type && (type->is(Type::KindOfSome) || type->is(Type::KindOfAny))) {
      type = value->getActualType();
    }
    if (type && type->isNoObjectInvolved()) needed = false;
  }
  return needed;
}
コード例 #10
0
void UnaryOpExpression::SetExpTypeForExistsContext(AnalysisResultPtr ar,
                                                   ExpressionPtr e,
                                                   bool allowPrimitives) {
  if (!e) return;
  TypePtr at(e->getActualType());
  if (!allowPrimitives && at &&
      at->isExactType() && at->isPrimitive()) {
    at = e->inferAndCheck(ar, Type::Variant, true);
  }
  TypePtr it(e->getImplementedType());
  TypePtr et(e->getExpectedType());
  if (et && et->is(Type::KindOfVoid)) e->setExpectedType(TypePtr());
  if (at && (!it || Type::IsMappedToVariant(it)) &&
      ((allowPrimitives && Type::HasFastCastMethod(at)) ||
       (!allowPrimitives &&
        (at->is(Type::KindOfObject) ||
         at->is(Type::KindOfArray) ||
         at->is(Type::KindOfString))))) {
    e->setExpectedType(it ? at : TypePtr());
  }
}
コード例 #11
0
static bool checkCopyElision(FunctionScopePtr func, ExpressionPtr exp) {
  if (!exp->getType()->is(Type::KindOfVariant) || func->isRefReturn()) {
    return false;
  }

  TypePtr imp = exp->getImplementedType();
  if (!imp) imp = exp->getActualType();
  if (!imp || !imp->is(Type::KindOfVariant)) return false;

  if (func->getNRVOFix() && exp->is(Expression::KindOfSimpleVariable)) {
    return true;
  }

  if (FunctionCallPtr fc = dynamic_pointer_cast<FunctionCall>(exp)) {
    FunctionScopePtr fs = fc->getFuncScope();
    if (!fs || fs->isRefReturn()) {
      return true;
    }
  }

  return false;
}
コード例 #12
0
static void outputStringExpr(CodeGenerator &cg, AnalysisResultPtr ar,
                             ExpressionPtr exp, bool asLitStr) {
  if (asLitStr && exp->isLiteralString()) {
    const std::string &s = exp->getLiteralString();
    char *enc = string_cplus_escape(s.c_str(), s.size());
    cg_printf("\"%s\", %d", enc, s.size());
    free(enc);
    return;
  }

  bool close = false;
  if ((exp->hasContext(Expression::LValue) &&
       (!exp->getActualType()->is(Type::KindOfString) ||
        (exp->getImplementedType() &&
         !exp->getImplementedType()->is(Type::KindOfString))))
      ||
      !exp->getType()->is(Type::KindOfString)) {
    cg_printf("toString(");
    close = true;
  }
  exp->outputCPP(cg, ar);
  if (close) cg_printf(")");
}
コード例 #13
0
void BinaryOpExpression::outputCPPImpl(CodeGenerator &cg,
                                       AnalysisResultPtr ar) {

    if (isOpEqual() && outputCPPImplOpEqual(cg, ar)) return;

    bool wrapped = true;
    switch (m_op) {
    case T_CONCAT_EQUAL:
        if (const char *prefix = stringBufferPrefix(cg, ar, m_exp1)) {
            SimpleVariablePtr sv = static_pointer_cast<SimpleVariable>(m_exp1);
            ExpressionPtrVec ev;
            bool hasVoid = false;
            getConcatList(ev, m_exp2, hasVoid);
            cg_printf("%s", stringBufferName(Option::TempPrefix, prefix,
                                             sv->getName().c_str()).c_str());
            outputStringBufExprs(ev, cg, ar);
            return;
        }
        cg_printf("concat_assign");
        break;
    case '.':
    {
        ExpressionPtr self = static_pointer_cast<Expression>(shared_from_this());
        ExpressionPtrVec ev;
        bool hasVoid = false;
        int num = getConcatList(ev, self, hasVoid);
        assert(!hasVoid);
        if (num <= MAX_CONCAT_ARGS) {
            assert(num >= 2);
            if (num == 2) {
                cg_printf("concat(");
            } else {
                if (num > MAX_CONCAT_ARGS) ar->m_concatLengths.insert(num);
                cg_printf("concat%d(", num);
            }
            for (size_t i = 0; i < ev.size(); i++) {
                ExpressionPtr exp = ev[i];
                if (i) cg_printf(", ");
                outputStringExpr(cg, ar, exp, false);
            }
            cg_printf(")");
        } else {
            cg_printf("StringBuffer()");
            outputStringBufExprs(ev, cg, ar);
            cg_printf(".detach()");
        }
    }
    return;
    case T_LOGICAL_XOR:
        cg_printf("logical_xor");
        break;
    case '|':
        cg_printf("bitwise_or");
        break;
    case '&':
        cg_printf("bitwise_and");
        break;
    case '^':
        cg_printf("bitwise_xor");
        break;
    case T_IS_IDENTICAL:
        cg_printf("same");
        break;
    case T_IS_NOT_IDENTICAL:
        cg_printf("!same");
        break;
    case T_IS_EQUAL:
        cg_printf("equal");
        break;
    case T_IS_NOT_EQUAL:
        cg_printf("!equal");
        break;
    case '<':
        cg_printf("less");
        break;
    case T_IS_SMALLER_OR_EQUAL:
        cg_printf("not_more");
        break;
    case '>':
        cg_printf("more");
        break;
    case T_IS_GREATER_OR_EQUAL:
        cg_printf("not_less");
        break;
    case '/':
        cg_printf("divide");
        break;
    case '%':
        cg_printf("modulo");
        break;
    case T_INSTANCEOF:
        cg_printf("instanceOf");
        break;
    default:
        wrapped = !isUnused();
        break;
    }

    if (wrapped) cg_printf("(");

    ExpressionPtr first = m_exp1;
    ExpressionPtr second = m_exp2;

    // we could implement these functions natively on String and Array classes
    switch (m_op) {
    case '+':
    case '-':
    case '*':
    case '/':
        if (!first->outputCPPArithArg(cg, ar, m_op == '+')) {
            TypePtr argType = first->hasCPPTemp() ?
                              first->getType() : first->getActualType();
            bool flag = castIfNeeded(getActualType(), argType, cg, ar, getScope());
            first->outputCPP(cg, ar);
            if (flag) {
                cg_printf(")");
            }
        }
        break;
    case T_SL:
    case T_SR:
        ASSERT(first->getType()->is(Type::KindOfInt64));
        first->outputCPP(cg, ar);
        break;
    default:
        first->outputCPP(cg, ar);
        break;
    }

    switch (m_op) {
    case T_PLUS_EQUAL:
        cg_printf(" += ");
        break;
    case T_MINUS_EQUAL:
        cg_printf(" -= ");
        break;
    case T_MUL_EQUAL:
        cg_printf(" *= ");
        break;
    case T_DIV_EQUAL:
        cg_printf(" /= ");
        break;
    case T_MOD_EQUAL:
        cg_printf(" %%= ");
        break;
    case T_AND_EQUAL:
        cg_printf(" &= ");
        break;
    case T_OR_EQUAL:
        cg_printf(" |= ");
        break;
    case T_XOR_EQUAL:
        cg_printf(" ^= ");
        break;
    case T_SL_EQUAL:
        cg_printf(" <<= ");
        break;
    case T_SR_EQUAL:
        cg_printf(" >>= ");
        break;
    case T_BOOLEAN_OR:
        cg_printf(" || ");
        break;
    case T_BOOLEAN_AND:
        cg_printf(" && ");
        break;
    case T_LOGICAL_OR:
        cg_printf(" || ");
        break;
    case T_LOGICAL_AND:
        cg_printf(" && ");
        break;
    default:
        switch (m_op) {
        case '+':
            cg_printf(" + ");
            break;
        case '-':
            cg_printf(" - ");
            break;
        case '*':
            cg_printf(" * ");
            break;
        case T_SL:
            cg_printf(" << ");
            break;
        case T_SR:
            cg_printf(" >> ");
            break;
        default:
            cg_printf(", ");
            break;
        }
        break;
    }

    switch (m_op) {
    case '+':
    case '-':
    case '*':
    case '/':
        if (!second->outputCPPArithArg(cg, ar, m_op == '+')) {
            TypePtr argType = second->hasCPPTemp() ?
                              second->getType() : second->getActualType();
            bool flag = castIfNeeded(getActualType(), argType, cg, ar, getScope());
            second->outputCPP(cg, ar);
            if (flag) {
                cg_printf(")");
            }
        }
        break;
    case T_INSTANCEOF:
    {
        if (second->isScalar()) {
            ScalarExpressionPtr scalar =
                dynamic_pointer_cast<ScalarExpression>(second);
            bool notQuoted = scalar && !scalar->isQuoted();
            std::string s = second->getLiteralString();
            if (s == "static" && notQuoted) {
                cg_printf("FrameInjection::GetStaticClassName(fi.getThreadInfo())");
            } else if (s != "") {
                if (s == "self" && notQuoted) {
                    ClassScopeRawPtr cls = getOriginalClass();
                    if (cls) {
                        s = cls->getOriginalName();
                    }
                } else if (s == "parent" && notQuoted) {
                    ClassScopeRawPtr cls = getOriginalClass();
                    if (cls && !cls->getParent().empty()) {
                        s = cls->getParent();
                    }
                }
                cg_printString(s, ar, shared_from_this());
            } else {
                second->outputCPP(cg, ar);
            }
        } else {
            second->outputCPP(cg, ar);
        }
        break;
    }
    case T_PLUS_EQUAL:
    case T_MINUS_EQUAL:
    case T_MUL_EQUAL:
    {
        TypePtr t1 = first->getCPPType();
        TypePtr t2 = second->getType();
        if (t1 && !t1->is(Type::KindOfArray) &&
                t2 && Type::IsCastNeeded(ar, t2, t1)) {
            t1->outputCPPCast(cg, ar, getScope());
            cg_printf("(");
            second->outputCPP(cg, ar);
            cg_printf(")");
        } else {
            second->outputCPP(cg, ar);
        }
        break;
    }
    case T_BOOLEAN_OR:
    case T_BOOLEAN_AND:
    case T_LOGICAL_AND:
    case T_LOGICAL_OR:
        if (isUnused()) {
            cg_printf("(");
            if (second->outputCPPUnneeded(cg, ar)) {
                cg_printf(",");
            }
            cg_printf("false)");
        } else {
            second->outputCPP(cg, ar);
        }
        break;
    default:
        second->outputCPP(cg, ar);
    }

    if (wrapped) cg_printf(")");
}
コード例 #14
0
void BinaryOpExpression::outputCPPImpl(CodeGenerator &cg,
                                       AnalysisResultPtr ar) {

  if (isOpEqual() && outputCPPImplOpEqual(cg, ar)) return;

  bool wrapped = true;
  switch (m_op) {
  case T_CONCAT_EQUAL:
    if (const char *prefix = stringBufferPrefix(cg, ar, m_exp1)) {
      SimpleVariablePtr sv = static_pointer_cast<SimpleVariable>(m_exp1);
      ExpressionPtrVec ev;
      bool hasVoid = false;
      getConcatList(ev, m_exp2, hasVoid);
      cg_printf("%s", stringBufferName(Option::TempPrefix, prefix,
                                       sv->getName().c_str()).c_str());
      outputStringBufExprs(ev, cg, ar);
      return;
    }
    cg_printf("concat_assign");
    break;
  case '.':
    {
      ExpressionPtr self = static_pointer_cast<Expression>(shared_from_this());
      ExpressionPtrVec ev;
      bool hasVoid = false;
      int num = getConcatList(ev, self, hasVoid);
      assert(!hasVoid);
      if ((num <= MAX_CONCAT_ARGS ||
           (Option::GenConcat &&
            cg.getOutput() != CodeGenerator::SystemCPP))) {
        assert(num >= 2);
        if (num == 2) {
          cg_printf("concat(");
        } else {
          if (num > MAX_CONCAT_ARGS) ar->m_concatLengths.insert(num);
          cg_printf("concat%d(", num);
        }
        for (size_t i = 0; i < ev.size(); i++) {
          ExpressionPtr exp = ev[i];
          if (i) cg_printf(", ");
          outputStringExpr(cg, ar, exp, false);
        }
        cg_printf(")");
      } else {
        cg_printf("StringBuffer()");
        outputStringBufExprs(ev, cg, ar);
        cg_printf(".detach()");
      }
    }
    return;
  case T_LOGICAL_XOR:         cg_printf("logical_xor");   break;
  case '|':                   cg_printf("bitwise_or");    break;
  case '&':                   cg_printf("bitwise_and");   break;
  case '^':                   cg_printf("bitwise_xor");   break;
  case T_IS_IDENTICAL:        cg_printf("same");          break;
  case T_IS_NOT_IDENTICAL:    cg_printf("!same");         break;
  case T_IS_EQUAL:            cg_printf("equal");         break;
  case T_IS_NOT_EQUAL:        cg_printf("!equal");        break;
  case '<':                   cg_printf("less");          break;
  case T_IS_SMALLER_OR_EQUAL: cg_printf("not_more");      break;
  case '>':                   cg_printf("more");          break;
  case T_IS_GREATER_OR_EQUAL: cg_printf("not_less");      break;
  case '/':                   cg_printf("divide");        break;
  case '%':                   cg_printf("modulo");        break;
  case T_INSTANCEOF:          cg_printf("instanceOf");    break;
  default:
    wrapped = !isUnused();
    break;
  }

  if (wrapped) cg_printf("(");

  ExpressionPtr first = m_exp1;
  ExpressionPtr second = m_exp2;

  // we could implement these functions natively on String and Array classes
  switch (m_op) {
  case '+':
  case '-':
  case '*':
  case '/': {
    TypePtr actualType = first->getActualType();

    if (actualType &&
        (actualType->is(Type::KindOfString) ||
         (m_op != '+' && actualType->is(Type::KindOfArray)))) {
      cg_printf("(Variant)(");
      first->outputCPP(cg, ar);
      cg_printf(")");
    } else {
      bool flag = castIfNeeded(getActualType(), actualType, cg, ar, getScope());
      first->outputCPP(cg, ar);
      if (flag) {
        cg_printf(")");
      }
    }
    break;
  }
  case T_SL:
  case T_SR:
    cg_printf("toInt64(");
    first->outputCPP(cg, ar);
    cg_printf(")");
    break;
  default:
    first->outputCPP(cg, ar);
    break;
  }

  switch (m_op) {
  case T_PLUS_EQUAL:          cg_printf(" += ");   break;
  case T_MINUS_EQUAL:         cg_printf(" -= ");   break;
  case T_MUL_EQUAL:           cg_printf(" *= ");   break;
  case T_DIV_EQUAL:           cg_printf(" /= ");   break;
  case T_MOD_EQUAL:           cg_printf(" %%= ");  break;
  case T_AND_EQUAL:           cg_printf(" &= ");   break;
  case T_OR_EQUAL:            cg_printf(" |= ");   break;
  case T_XOR_EQUAL:           cg_printf(" ^= ");   break;
  case T_SL_EQUAL:            cg_printf(" <<= ");  break;
  case T_SR_EQUAL:            cg_printf(" >>= ");  break;
  case T_BOOLEAN_OR:          cg_printf(" || ");   break;
  case T_BOOLEAN_AND:         cg_printf(" && ");   break;
  case T_LOGICAL_OR:          cg_printf(" || ");   break;
  case T_LOGICAL_AND:         cg_printf(" && ");   break;
  default:
    switch (m_op) {
    case '+':                   cg_printf(" + ");    break;
    case '-':                   cg_printf(" - ");    break;
    case '*':                   cg_printf(" * ");    break;
    case T_SL:                  cg_printf(" << ");   break;
    case T_SR:                  cg_printf(" >> ");   break;
    default:
      cg_printf(", ");
      break;
    }
    break;
  }

  switch (m_op) {
  case '+':
  case '-':
  case '*':
  case '/': {
    TypePtr actualType = second->getActualType();

    if (actualType &&
        (actualType->is(Type::KindOfString) ||
         (m_op != '+' && actualType->is(Type::KindOfArray)))) {
      cg_printf("(Variant)(");
      second->outputCPP(cg, ar);
      cg_printf(")");
    } else {
      bool flag = castIfNeeded(getActualType(), actualType, cg, ar, getScope());
      second->outputCPP(cg, ar);
      if (flag) {
        cg_printf(")");
      }
    }
    break;
  }
  case T_INSTANCEOF:
    {
      if (second->isScalar()) {
        std::string s = second->getLiteralString();
        std::string sLower = Util::toLower(s);
        if (sLower != "") {
          cg_printString(sLower, ar, shared_from_this());
        } else {
          second->outputCPP(cg, ar);
        }
      } else {
        second->outputCPP(cg, ar);
      }
      break;
    }
  case T_PLUS_EQUAL:
  case T_MINUS_EQUAL:
  case T_MUL_EQUAL:
    {
      TypePtr t1 = first->getCPPType();
      TypePtr t2 = second->getType();
      if (t1 && !t1->is(Type::KindOfArray) &&
          t2 && Type::IsCastNeeded(ar, t2, t1)) {
        t1->outputCPPCast(cg, ar, getScope());
        cg_printf("(");
        second->outputCPP(cg, ar);
        cg_printf(")");
      } else {
        second->outputCPP(cg, ar);
      }
      break;
    }
  case T_BOOLEAN_OR:
  case T_BOOLEAN_AND:
  case T_LOGICAL_AND:
  case T_LOGICAL_OR:
    if (isUnused()) {
      cg_printf("(");
      if (second->outputCPPUnneeded(cg, ar)) {
        cg_printf(",");
      }
      cg_printf("false)");
    } else {
      second->outputCPP(cg, ar);
    }
    break;
  default:
    second->outputCPP(cg, ar);
  }

  if (wrapped) cg_printf(")");
}
コード例 #15
0
ファイル: type.cpp プロジェクト: activeingredient/hiphop-php
void Type::Dump(ExpressionPtr exp) {
  Dump(exp->getExpectedType(), "Expected: %s\t");
  Dump(exp->getActualType(), "Actual: %s\n");
}
コード例 #16
0
bool ExpressionList::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
                                  int state) {
  if (m_kind == ListKindParam && !m_arrayElements) {
    return Expression::preOutputCPP(cg, ar, state|StashKidVars);
  }

  unsigned n = m_exps.size();
  bool inExpression = cg.inExpression();
  if (!inExpression && (state & FixOrder)) {
    return true;
  }

  cg.setInExpression(false);
  bool ret = false;
  if (m_arrayElements) {
    /*
     * would like to do:
     *  ret = Expression::preOutputCPP(cg, ar, state);
     * but icc has problems with the generated code.
     */
    ret = hasEffect();
  } else if (n > 1 && m_kind == ListKindLeft) {
    ret = true;
  } else {
    for (unsigned int i = 0; i < n; i++) {
      if (m_exps[i]->preOutputCPP(cg, ar, 0)) {
        ret = true;
        break;
      }
    }
    if (!ret) {
      ExpressionPtr e = m_exps[n - 1];
      if (hasContext(LValue) && !hasAnyContext(RefValue|InvokeArgument) &&
          !(e->hasContext(LValue) &&
            !e->hasAnyContext(RefValue|InvokeArgument))) {
        ret = true;
      } else if (hasContext(RefValue) &&
                 !e->hasAllContext(LValue|ReturnContext) &&
                 !e->hasContext(RefValue)) {
        ret = true;
      }
    }
  }

  if (!inExpression) return ret;

  cg.setInExpression(true);
  if (!ret) {
    if (state & FixOrder) {
      preOutputStash(cg, ar, state);
      return true;
    }
    return false;
  }

  cg.wrapExpressionBegin();
  if (m_arrayElements) {
    setCPPTemp(genCPPTemp(cg, ar));
    outputCPPInternal(cg, ar, true, true);
  } else {
    unsigned ix = isUnused() ? (unsigned)-1 :
      m_kind == ListKindLeft ? 0 : n - 1;
    for (unsigned int i = 0; i < n; i++) {
      ExpressionPtr e = m_exps[i];
      e->preOutputCPP(cg, ar, i == ix ? state : 0);
      if (i != ix) {
        if (e->outputCPPUnneeded(cg, ar)) {
          cg_printf(";\n");
        }
        e->setCPPTemp("/**/");
        continue;
      }
      /*
        We inlined a by-value function into the rhs of a by-ref assignment.
      */
      bool noRef = hasContext(RefValue) &&
        !e->hasAllContext(LValue|ReturnContext) &&
        !e->hasContext(RefValue) &&
        !e->isTemporary() &&
        Type::IsMappedToVariant(e->getActualType());
      /*
        If we need a non-const reference, but the expression is
        going to generate a const reference, fix it
      */
      bool lvSwitch =
        hasContext(LValue) && !hasAnyContext(RefValue|InvokeArgument) &&
        !(e->hasContext(LValue) &&
          !e->hasAnyContext(RefValue|InvokeArgument));

      if (e->hasAllContext(LValue|ReturnContext) && i + 1 == n) {
        e->clearContext(ReturnContext);
      }

      if (noRef || lvSwitch || (!i && n > 1)) {
        e->Expression::preOutputStash(cg, ar, state | FixOrder | StashAll);
        if (!(state & FixOrder)) {
          cg_printf("id(%s);\n", e->cppTemp().c_str());
        }
      }
      if (e->hasCPPTemp() &&
          Type::SameType(e->getGenType(), getGenType())) {
        string t = e->cppTemp();
        if (noRef) {
          cg_printf("CVarRef %s_nr = wrap_variant(%s);\n",
                    t.c_str(), t.c_str());
          t += "_nr";
        }

        if (lvSwitch) {
          cg_printf("Variant &%s_lv = const_cast<Variant&>(%s);\n",
                    t.c_str(), t.c_str());
          t += "_lv";
        }
        setCPPTemp(t);
      }
    }
  }
  return true;
}
コード例 #17
0
bool BinaryOpExpression::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
                                      int state) {
  if (isOpEqual()) return Expression::preOutputCPP(cg, ar, state);
  bool effect2 = m_exp2->hasEffect();
  const char *prefix = 0;
  if (effect2 || m_exp1->hasEffect()) {
    ExpressionPtr self = static_pointer_cast<Expression>(shared_from_this());
    ExpressionPtrVec ev;
    bool hasVoid = false;
    int numConcat = 0;
    bool ok = false;
    if (m_op == '.') {
      numConcat = getConcatList(ev, self, hasVoid);
      ok = hasVoid ||
           (numConcat > MAX_CONCAT_ARGS &&
            (!Option::GenConcat ||
             cg.getOutput() == CodeGenerator::SystemCPP));
    } else if (effect2 && m_op == T_CONCAT_EQUAL) {
      prefix = stringBufferPrefix(cg, ar, m_exp1);
      ok = prefix;
      if (!ok) {
        if (m_exp1->is(KindOfSimpleVariable)) {
          ok = true;
          ev.push_back(m_exp1);
          numConcat++;
        }
      }
      numConcat += getConcatList(ev, m_exp2, hasVoid);
    }
    if (ok) {
      if (!cg.inExpression()) return true;

      cg.wrapExpressionBegin();
      std::string buf;
      if (prefix) {
        SimpleVariablePtr sv(static_pointer_cast<SimpleVariable>(m_exp1));
        buf = stringBufferName(Option::TempPrefix, prefix,
                               sv->getName().c_str());
        m_cppTemp = "/**/";
      } else if (numConcat) {
        buf = m_cppTemp = genCPPTemp(cg, ar);
        buf += "_buf";
        cg_printf("StringBuffer %s;\n", buf.c_str());
      } else {
        m_cppTemp = "\"\"";
      }

      for (size_t i = 0; i < ev.size(); i++) {
        ExpressionPtr exp = ev[i];
        bool is_void = !exp->getActualType();
        exp->preOutputCPP(cg, ar, 0);
        if (!is_void) {
          cg_printf("%s.append(", buf.c_str());
          outputStringExpr(cg, ar, exp, true);
          cg_printf(")");
        } else {
          exp->outputCPPUnneeded(cg, ar);
        }
        cg_printf(";\n");
      }

      if (numConcat && !prefix) {
        cg_printf("CStrRef %s(%s.detach());\n",
                  m_cppTemp.c_str(), buf.c_str());
        if (m_op == T_CONCAT_EQUAL) {
          m_exp1->outputCPP(cg, ar);
          cg_printf(" = %s;\n", m_cppTemp.c_str());
        }
      }
      return true;
    }
  }

  if (!isShortCircuitOperator()) {
    return Expression::preOutputCPP(cg, ar, state);
  }

  if (!effect2) {
    return m_exp1->preOutputCPP(cg, ar, state);
  }

  bool fix_e1 = m_exp1->preOutputCPP(cg, ar, 0);
  if (!cg.inExpression()) {
    return fix_e1 || m_exp2->preOutputCPP(cg, ar, 0);
  }

  cg.setInExpression(false);
  bool fix_e2 = m_exp2->preOutputCPP(cg, ar, 0);
  cg.setInExpression(true);

  if (fix_e2) {
    cg.wrapExpressionBegin();
    std::string tmp = genCPPTemp(cg, ar);
    cg_printf("bool %s = (", tmp.c_str());
    m_exp1->outputCPP(cg, ar);
    cg_printf(");\n");
    cg_indentBegin("if (%s%s) {\n",
                   m_op == T_LOGICAL_OR || m_op == T_BOOLEAN_OR ? "!" : "",
                   tmp.c_str());
    m_exp2->preOutputCPP(cg, ar, 0);
    cg_printf("%s = (", tmp.c_str());
    m_exp2->outputCPP(cg, ar);
    cg_printf(");\n");
    cg_indentEnd("}\n");
    m_cppTemp = tmp;
  } else if (state & FixOrder) {
    preOutputStash(cg, ar, state);
    fix_e1 = true;
  }
  return fix_e1 || fix_e2;
}