TypePtr ParameterExpression::getTypeSpec(AnalysisResultPtr ar,
                                         bool forInference) {
  const Type::TypePtrMap &types = Type::GetTypeHintTypes(m_hhType);
  Type::TypePtrMap::const_iterator iter;

  TypePtr ret;
  if (m_type.empty()) {
    ret = Type::Some;
  } else if ((iter = types.find(m_type)) != types.end()) {
    ret = iter->second;
  } else {
    ret = getTypeSpecForClass(ar, forInference);
  }

  ConstantExpressionPtr p;
  if (ret->isPrimitive() &&
      m_defaultValue &&
      (p = dynamic_pointer_cast<ConstantExpression>(m_defaultValue)) &&
      p->isNull()) {
    // if we have a primitive type on the LHS w/ a default
    // of null, then don't bother to infer it's type, since we will
    // not specialize for this case
    ret = Type::Some;
  }

  // we still want the above to run, so to record errors and infer defaults
  if (m_ref && forInference) {
    ret = Type::Variant;
  }

  return ret;
}
void AssignmentExpression::outputCPPImpl(CodeGenerator &cg,
                                         AnalysisResultPtr ar) {
  bool ref = (m_ref && m_value->isRefable());

  bool setNull = false;

  if (SpecialAssignment(cg, ar, m_variable, m_value, NULL, ref)) {
    return;
  }

  if (m_variable->is(Expression::KindOfSimpleVariable) &&
      m_value->is(Expression::KindOfConstantExpression)) {
    ConstantExpressionPtr exp =
      dynamic_pointer_cast<ConstantExpression>(m_value);
    if (exp->isNull()) setNull = true;
  }

  bool wrapped = true;
  if (setNull) {
    cg_printf("setNull(");
    m_variable->outputCPP(cg, ar);
  } else {
    if ((wrapped = !isUnused())) {
      cg_printf("(");
    }
    m_variable->outputCPP(cg, ar);
    cg_printf(" = ");

    wrapValue(cg, ar, m_value, ref, false);
  }
  if (wrapped) {
    cg_printf(")");
  }
}
void AssignmentExpression::onParseRecur(AnalysisResultConstPtr ar,
                                        ClassScopePtr scope) {
  // This is that much we can do during parse phase.
  TypePtr type;
  if (m_value->is(Expression::KindOfScalarExpression)) {
    type = static_pointer_cast<ScalarExpression>(m_value)->inferenceImpl(
      ar, Type::Some, false);
  } else if (m_value->is(Expression::KindOfUnaryOpExpression)) {
    UnaryOpExpressionPtr uexp =
      dynamic_pointer_cast<UnaryOpExpression>(m_value);
    if (uexp->getOp() == T_ARRAY) {
      type = Type::Array;
    }
  }
  if (!type) type = Type::Some;

  if (m_variable->is(Expression::KindOfConstantExpression)) {
    // ...as in ClassConstant statement
    // We are handling this one here, not in ClassConstant, purely because
    // we need "value" to store in constant table.
    ConstantExpressionPtr exp =
      dynamic_pointer_cast<ConstantExpression>(m_variable);
    scope->getConstants()->add(exp->getName(), type, m_value, ar, m_variable);
  } else if (m_variable->is(Expression::KindOfSimpleVariable)) {
    SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(m_variable);
    scope->getVariables()->add(var->getName(), type, true, ar,
                               shared_from_this(), scope->getModifiers());
    var->clearContext(Declaration); // to avoid wrong CodeError
  } else {
    ASSERT(false); // parse phase shouldn't handle anything else
  }
}
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;
}
Beispiel #5
0
void ClassConstant::onParseRecur(AnalysisResultConstPtr ar,
                                 ClassScopePtr scope) {
  ConstantTablePtr constants = scope->getConstants();

  if (scope->isTrait()) {
    parseTimeFatal(Compiler::InvalidTraitStatement,
                   "Traits cannot have constants");
  }

  if (isAbstract()) {
    for (int i = 0; i < m_exp->getCount(); i++) {
      ConstantExpressionPtr exp =
        dynamic_pointer_cast<ConstantExpression>((*m_exp)[i]);
      const std::string &name = exp->getName();
      if (constants->isPresent(name)) {
        exp->parseTimeFatal(Compiler::DeclaredConstantTwice,
                                   "Cannot redeclare %s::%s",
                                   scope->getOriginalName().c_str(),
                                   name.c_str());
      }

      // HACK: break attempts to write global constants here;
      // see ConstantExpression::preOptimize
      exp->setContext(Expression::LValue);

      // Unlike with assignment expression below, nothing needs to be added
      // to the scope's constant table
    }
  } else {
    for (int i = 0; i < m_exp->getCount(); i++) {
      AssignmentExpressionPtr assignment =
        dynamic_pointer_cast<AssignmentExpression>((*m_exp)[i]);

      ExpressionPtr var = assignment->getVariable();
      const std::string &name =
        dynamic_pointer_cast<ConstantExpression>(var)->getName();
      if (constants->isPresent(name)) {
        assignment->parseTimeFatal(Compiler::DeclaredConstantTwice,
                                   "Cannot redeclare %s::%s",
                                   scope->getOriginalName().c_str(),
                                   name.c_str());
      } else {
        if (isTypeconst()) {
          // We do not want type constants to be available at run time.
          // To ensure this we do not want them to be added to the constants
          // table. The constants table is used to inline values for expressions
          // See ClassConstantExpression::preOptimize.
          // AssignmentExpression::onParseRecur essentially adds constants to
          // the constant table so we skip it.
          continue;
        }
        assignment->onParseRecur(ar, scope);
      }
    }
  }
}
Beispiel #6
0
bool Option::Load(bool &option, ExpressionPtr value) {
  ConstantExpressionPtr v = dynamic_pointer_cast<ConstantExpression>(value);
  if (!v || !v->isBoolean()) {
    Logger::Error("Line %d: invalid boolean: %s", value->getLocation()->line1,
                  value->getText().c_str());
    return false;
  }
  option = v->getBooleanValue();
  return true;
}
Beispiel #7
0
ExpressionPtr Parser::getDynamicVariable(ExpressionPtr exp, bool encap) {
  NamePtr n;
  if (encap) {
    ConstantExpressionPtr var = exp->cast<ConstantExpression>();
    if (var) {
      n = Name::fromString(this, var->getName());
    }
  } else {
    n = Name::fromExp(this, exp);
  }
  return NEW_EXP(Variable, n);
}
Beispiel #8
0
ExpressionPtr Parser::getDynamicVariable(ExpressionPtr exp, bool encap) {
  if (encap) {
    ConstantExpressionPtr var = exp->unsafe_cast<ConstantExpression>();
    NamePtr n;
    if (var) {
      n = Name::fromString(this, var->getName());
    }
    return NEW_EXP(Variable, n);
  }

  return createDynamicVariable(exp);
}
void ParameterExpression::outputCPPImpl(CodeGenerator &cg,
                                        AnalysisResultPtr ar) {
  FunctionScopePtr func =
    dynamic_pointer_cast<FunctionScope>(ar->getScope());
  VariableTablePtr variables = func->getVariables();
  TypePtr paramType = func->getParamType(cg.getItemIndex());
  bool isCVarRef = false;
  if (cg.getContext() == CodeGenerator::CppStaticMethodWrapper ||
      (!variables->isLvalParam(m_name) &&
       !variables->getAttribute(VariableTable::ContainsDynamicVariable) &&
       !variables->getAttribute(VariableTable::ContainsExtract) &&
       !m_ref)) {
    if (paramType->is(Type::KindOfVariant) ||
        paramType->is(Type::KindOfSome)) {
      cg_printf("CVarRef");
      isCVarRef = true;
    }
    else if (paramType->is(Type::KindOfArray)) cg_printf("CArrRef");
    else if (paramType->is(Type::KindOfString)) cg_printf("CStrRef");
    else paramType->outputCPPDecl(cg, ar);
  } else {
    paramType->outputCPPDecl(cg, ar);
  }

  cg_printf(" %s%s", Option::VariablePrefix, m_name.c_str());
  if (m_defaultValue) {
    CodeGenerator::Context context = cg.getContext();
    bool comment =  context == CodeGenerator::CppImplementation ||
      (context == CodeGenerator::CppDeclaration && func->isInlined());
    if (comment) {
      cg_printf(" // ");
    }
    cg_printf(" = ");
    ConstantExpressionPtr con =
      dynamic_pointer_cast<ConstantExpression>(m_defaultValue);
    if (isCVarRef && con && con->isNull()) {
      cg_printf("null_variant");
    } else {
      if (comment) {
        cg.setContext(CodeGenerator::CppParameterDefaultValueImpl);
      } else {
        cg.setContext(CodeGenerator::CppParameterDefaultValueDecl);
      }
      m_defaultValue->outputCPP(cg, ar);
      cg.setContext(context);
    }
    if (comment) {
      cg_printf("\n");
    }
  }
}
Beispiel #10
0
ExpressionPtr Parser::getDynamicVariable(ExpressionPtr exp, bool encap) {
  if (encap) {
    ConstantExpressionPtr var = dynamic_pointer_cast<ConstantExpression>(exp);
    if (var) {
      return NEW_EXP(SimpleVariable, var->getName());
    }
  } else {
    ScalarExpressionPtr var = dynamic_pointer_cast<ScalarExpression>(exp);
    if (var) {
      return NEW_EXP(SimpleVariable, var->getString());
    }
  }
  return createDynamicVariable(exp);
}
Beispiel #11
0
StatementPtr IfStatement::postOptimize(AnalysisResultConstPtr ar) {
  // we cannot optimize away the code inside if statement, because
  // there may be a goto that goes into if statement.
  if (hasReachableLabel()) {
    return StatementPtr();
  }

  bool changed = false;
  for (int i = 0; i < m_stmts->getCount(); i++) {
    IfBranchStatementPtr branch =
      dynamic_pointer_cast<IfBranchStatement>((*m_stmts)[i]);
    ExpressionPtr condition = branch->getCondition();
    if (!branch->getStmt() || !branch->getStmt()->hasImpl()) {
      if (!condition ||
          (i == m_stmts->getCount() - 1 &&
           !condition->hasEffect())) {
        // remove else branch without C++ implementation.
        m_stmts->removeElement(i);
        changed = true;
      } else if (condition->is(Expression::KindOfConstantExpression)) {
        ConstantExpressionPtr exp =
          dynamic_pointer_cast<ConstantExpression>(condition);
        // Remove if (false) branch without C++ implementation.
        // if (true) branch without C++ implementation is kept unless
        // it is the last branch. In general we cannot let a if (true)
        // branch short-circuit the rest branches which if removed may
        // cause g++ to complain unreferenced variables.
        if (exp->isBoolean()) {
          if (!exp->getBooleanValue() ||
              (exp->getBooleanValue() && i == m_stmts->getCount() - 1)) {
            m_stmts->removeElement(i);
            changed = true;
            i--;
          }
        }
      }
    }
  }
  if (m_stmts->getCount() == 0) {
    return NULL_STATEMENT();
  } else {
    return changed ? static_pointer_cast<Statement>(shared_from_this())
                   : StatementPtr();
  }
}
void AssignmentExpression::analyzeProgram(AnalysisResultPtr ar) {
  m_variable->analyzeProgram(ar);
  m_value->analyzeProgram(ar);
  if (ar->getPhase() == AnalysisResult::AnalyzeAll) {
    if (m_ref && m_variable->is(Expression::KindOfSimpleVariable)) {
      SimpleVariablePtr var =
        dynamic_pointer_cast<SimpleVariable>(m_variable);
      const std::string &name = var->getName();
      VariableTablePtr variables = ar->getScope()->getVariables();
      variables->addUsed(name);
    }
    if (m_variable->is(Expression::KindOfConstantExpression)) {
      ConstantExpressionPtr exp =
        dynamic_pointer_cast<ConstantExpression>(m_variable);
      if (!m_value->isScalar()) {
        ar->getScope()->getConstants()->setDynamic(ar, exp->getName());
      }
    }
  }
}
ExpressionPtr ClassConstantExpression::preOptimize(AnalysisResultPtr ar) {
  if (ar->getPhase() < AnalysisResult::FirstPreOptimize) {
    return ExpressionPtr();
  }
  if (m_redeclared) return ExpressionPtr();
  ClassScopePtr cls = ar->resolveClass(m_className);
  if (!cls || cls->isRedeclaring()) return ExpressionPtr();
  ConstantTablePtr constants = cls->getConstants();
  if (constants->isExplicitlyDeclared(m_varName)) {
    ConstructPtr decl = constants->getValue(m_varName);
    if (decl) {
      ExpressionPtr value = dynamic_pointer_cast<Expression>(decl);
      if (!m_visited) {
        m_visited = true;
        ar->pushScope(cls);
        ExpressionPtr optExp = value->preOptimize(ar);
        ar->popScope();
        m_visited = false;
        if (optExp) value = optExp;
      }
      if (value->isScalar()) {
        // inline the value
        if (value->is(Expression::KindOfScalarExpression)) {
          ScalarExpressionPtr exp =
            dynamic_pointer_cast<ScalarExpression>(Clone(value));
          exp->setComment(getText());
          return exp;
        } else if (value->is(Expression::KindOfConstantExpression)) {
          // inline the value
          ConstantExpressionPtr exp =
            dynamic_pointer_cast<ConstantExpression>(Clone(value));
          exp->setComment(getText());
          return exp;
        }
      }
    }
  }
  return ExpressionPtr();
}
ExpressionPtr BinaryOpExpression::simplifyLogical(AnalysisResultPtr ar) {
  if (m_exp1->is(Expression::KindOfConstantExpression)) {
    ConstantExpressionPtr con =
      dynamic_pointer_cast<ConstantExpression>(m_exp1);
    if (con->isBoolean()) {
      if (con->getBooleanValue()) {
        if (ar->getPhase() >= AnalysisResult::PostOptimize) {
          // true && v (true AND v) => v
          ASSERT(m_exp2->getType()->is(Type::KindOfBoolean));
          if (m_op == T_BOOLEAN_AND || m_op == T_LOGICAL_AND) return m_exp2;
        }
        // true || v (true OR v) => true
        if (m_op == T_BOOLEAN_OR || m_op == T_LOGICAL_OR) {
          return CONSTANT("true");
        }
      } else {
        if (ar->getPhase() >= AnalysisResult::PostOptimize) {
          ASSERT(m_exp2->getType()->is(Type::KindOfBoolean));
          // false || v (false OR v) => v
          if (m_op == T_BOOLEAN_OR || m_op == T_LOGICAL_OR) return m_exp2;
        }
        // false && v (false AND v) => false
        if (m_op == T_BOOLEAN_AND || m_op == T_LOGICAL_AND) {
          return CONSTANT("false");
        }
      }
    }
  }
  if (m_exp2->is(Expression::KindOfConstantExpression)) {
    ConstantExpressionPtr con =
      dynamic_pointer_cast<ConstantExpression>(m_exp2);
    if (con->isBoolean()) {
      if (con->getBooleanValue()) {
        if (ar->getPhase() >= AnalysisResult::PostOptimize) {
          ASSERT(m_exp1->getType()->is(Type::KindOfBoolean));
          // v && true (v AND true) => v
          if (m_op == T_BOOLEAN_AND || m_op == T_LOGICAL_AND) return m_exp1;
        }
        // v || true (v OR true) => true when v does not have effect
        if (m_op == T_BOOLEAN_OR || m_op == T_LOGICAL_OR) {
          if (!m_exp1->hasEffect()) return CONSTANT("true");
        }
      } else {
        if (ar->getPhase() >= AnalysisResult::PostOptimize) {
          ASSERT(m_exp1->getType()->is(Type::KindOfBoolean));
          // v || false (v OR false) => v
          if (m_op == T_BOOLEAN_OR || m_op == T_LOGICAL_OR) return m_exp1;
        }
        // v && false (v AND false) => false when v does not have effect
        if (m_op == T_BOOLEAN_AND || m_op == T_LOGICAL_AND) {
          if (!m_exp1->hasEffect()) return CONSTANT("false");
        }
      }
    }
  }
  return ExpressionPtr();
}
void ParameterExpression::outputCPPImpl(CodeGenerator &cg,
                                        AnalysisResultPtr ar) {
  FunctionScopePtr func = getFunctionScope();
  VariableTablePtr variables = func->getVariables();
  Symbol *sym = variables->getSymbol(m_name);
  assert(sym && sym->isParameter());

  bool inHeader = cg.isFileOrClassHeader();
  cg.setFileOrClassHeader(true);
  CodeGenerator::Context context = cg.getContext();
  bool typedWrapper = (context == CodeGenerator::CppTypedParamsWrapperImpl ||
                       context == CodeGenerator::CppTypedParamsWrapperDecl);

  TypePtr paramType =
    typedWrapper && func->getParamTypeSpec(sym->getParameterIndex()) ?
    Type::Variant : func->getParamType(sym->getParameterIndex());
  bool wrapper = typedWrapper ||
    context == CodeGenerator::CppFunctionWrapperImpl ||
    context == CodeGenerator::CppFunctionWrapperDecl;

  bool isCVarRef = false;
  const char *prefix = "";
  if (m_ref) {
    cg_printf("VRefParam");
    if (!wrapper) {
      prefix = "r";
    }
  } else if (wrapper ||
      (!variables->isLvalParam(m_name) &&
       !variables->getAttribute(VariableTable::ContainsDynamicVariable) &&
       !variables->getAttribute(VariableTable::ContainsExtract))) {
    if (paramType->is(Type::KindOfVariant) ||
        paramType->is(Type::KindOfSome)) {
      cg_printf("CVarRef");
      isCVarRef = true;
    }
    else if (paramType->is(Type::KindOfArray))  cg_printf("CArrRef");
    else if (paramType->is(Type::KindOfString)) cg_printf("CStrRef");
    else paramType->outputCPPDecl(cg, ar, getScope());
  } else {
    paramType->outputCPPDecl(cg, ar, getScope());
  }

  cg_printf(" %s%s%s",
            prefix, Option::VariablePrefix,
            CodeGenerator::FormatLabel(m_name).c_str());
  if (m_defaultValue && sym->getParameterIndex() >= func->getMinParamCount()) {
    bool comment = context == CodeGenerator::CppTypedParamsWrapperImpl ||
      context == CodeGenerator::CppFunctionWrapperImpl ||
      context == CodeGenerator::CppImplementation ||
      (context == CodeGenerator::CppDeclaration && func->isInlined());
    if (comment) {
      cg_printf(" // ");
    }
    cg_printf(" = ");
    ConstantExpressionPtr con =
      dynamic_pointer_cast<ConstantExpression>(m_defaultValue);

    bool done = false;
    if (con && con->isNull()) {
      done = true;
      if (isCVarRef) {
        cg_printf("null_variant");
      } else if (paramType->is(Type::KindOfVariant) ||
                 paramType->is(Type::KindOfSome)) {
        cg_printf("null");
      } else if (paramType->is(Type::KindOfObject)) {
        cg_printf("Object()");
      } else if (paramType->is(Type::KindOfArray)) {
        cg_printf("Array()");
      } else if (paramType->is(Type::KindOfString)) {
        cg_printf("String()");
      } else {
        done = false;
      }
    }
    if (!done) {
      if (comment) {
        cg.setContext(CodeGenerator::CppParameterDefaultValueImpl);
      } else {
        cg.setContext(CodeGenerator::CppParameterDefaultValueDecl);
      }
      bool isScalar = m_defaultValue->isScalar();
      if (isCVarRef && isScalar) {
        ASSERT(!cg.hasScalarVariant());
        cg.setScalarVariant();
      }
      m_defaultValue->outputCPP(cg, ar);
      if (isCVarRef && isScalar) cg.clearScalarVariant();
      ASSERT(!cg.hasScalarVariant());
      cg.setContext(context);
    }
    if (comment) {
      cg_printf("\n");
    }
  }
  cg.setFileOrClassHeader(inHeader);
}
void AssignmentExpression::outputCPPImpl(CodeGenerator &cg,
                                         AnalysisResultPtr ar) {
  BlockScopePtr scope = ar->getScope();
  bool ref = (m_ref && m_value->isRefable());

  bool setNull = false;
  bool arrayLike = false;

  if (m_variable->is(Expression::KindOfArrayElementExpression)) {
    ArrayElementExpressionPtr exp =
      dynamic_pointer_cast<ArrayElementExpression>(m_variable);
    if (!exp->isSuperGlobal() && !exp->isDynamicGlobal()) {
      exp->getVariable()->outputCPP(cg, ar);
      if (exp->getOffset()) {
        cg_printf(".set(");
        exp->getOffset()->outputCPP(cg, ar);
        cg_printf(", (");
      } else {
        cg_printf(".append((");
      }
      wrapValue(cg, ar, m_value, ref, true);
      cg_printf(")");
      ExpressionPtr off = exp->getOffset();
      if (off) {
        ScalarExpressionPtr sc =
          dynamic_pointer_cast<ScalarExpression>(off);
        if (sc) {
          if (sc->isLiteralString()) {
            String s(sc->getLiteralString());
            int64 n;
            if (!s.get()->isStrictlyInteger(n)) {
              cg_printf(", true"); // skip toKey() at run time
            }
          }
        }
      }
      cg_printf(")");
      return;
    }
  } else if (m_variable->is(Expression::KindOfObjectPropertyExpression)) {
    ObjectPropertyExpressionPtr var(
      dynamic_pointer_cast<ObjectPropertyExpression>(m_variable));
    if (!var->isValid()) {
      var->outputCPPObject(cg, ar);
      cg_printf("o_set(");
      var->outputCPPProperty(cg, ar);
      cg_printf(", %s", ref ? "ref(" : "");
      m_value->outputCPP(cg, ar);
      cg_printf("%s, %s)",
                ref ? ")" : "",
                ar->getClassScope() ? "s_class_name" : "empty_string");
      return;
    }
  } else if (m_variable->is(Expression::KindOfSimpleVariable) &&
      m_value->is(Expression::KindOfConstantExpression)) {
    ConstantExpressionPtr exp =
      dynamic_pointer_cast<ConstantExpression>(m_value);
    if (exp->isNull()) setNull = true;
  }

  bool wrapped = true;
  if (setNull) {
    cg_printf("setNull(");
    m_variable->outputCPP(cg, ar);
  } else {
    if ((wrapped = !isUnused())) {
      cg_printf("(");
    }
    m_variable->outputCPP(cg, ar);
    cg_printf(" = ");

    wrapValue(cg, ar, m_value, ref, arrayLike);
  }
  if (wrapped) {
    cg_printf(")");
  }
}
void AssignmentExpression::outputCPPImpl(CodeGenerator &cg,
                                         AnalysisResultPtr ar) {
  BlockScopePtr scope = ar->getScope();
  bool ref = (m_ref && !m_value->is(Expression::KindOfNewObjectExpression));

  bool setElement = false; // turning $a['elem'] = $b into $a.set('elem', $b);
  bool type_cast = false;
  bool setNull = false;
  TypePtr m_actualType;

  if (m_variable->is(Expression::KindOfArrayElementExpression)) {
    ArrayElementExpressionPtr exp =
      dynamic_pointer_cast<ArrayElementExpression>(m_variable);
    m_actualType = m_variable->getActualType();
    if (m_actualType && m_actualType->getKindOf() == Type::KindOfVariant
        && !ref) {
      //type_cast = true;
    }
    if (!exp->isSuperGlobal() && !exp->isDynamicGlobal()) {
      exp->getVariable()->outputCPP(cg, ar);
      if (exp->getOffset()) {
        cg.printf(".set(");
        exp->getOffset()->outputCPP(cg, ar);
        cg.printf(", (");
      } else {
        cg.printf(".append((");
      }
      if (type_cast) {
        m_actualType->outputCPPCast(cg, ar);
        cg.printf("(");
      }
      if (ref && m_value->isRefable()) cg.printf("ref(");
      m_value->outputCPP(cg, ar);
      if (ref && m_value->isRefable()) cg.printf(")");
      if (type_cast) cg.printf(")");
      cg.printf(")");
      ExpressionPtr off = exp->getOffset();
      if (off) {
        ScalarExpressionPtr sc =
          dynamic_pointer_cast<ScalarExpression>(off);
        if (sc) {
          int64 hash = sc->getHash();
          if (hash >= 0) {
            cg.printf(", 0x%016llXLL", hash);
          } else {
            cg.printf(", -1");
          }
          if (sc->isLiteralString()) {
            String s(sc->getLiteralString());
            int64 n;
            if (!s.get()->isStrictlyInteger(n)) {
              cg.printf(", true"); // skip toKey() at run time
            }
          }
        }
      }
      cg.printf(")");
      setElement = true;
    }
  }
  if (m_variable->is(Expression::KindOfSimpleVariable) &&
      m_value->is(Expression::KindOfConstantExpression)) {
    ConstantExpressionPtr exp =
      dynamic_pointer_cast<ConstantExpression>(m_value);
    if (exp->isNull()) setNull = true;
  }

  if (!setElement) {
    if (setNull) {
      cg.printf("setNull(");
      m_variable->outputCPP(cg, ar);
    } else {
      cg.printf("(");
      m_variable->outputCPP(cg, ar);
      cg.printf(" = ");

      if (type_cast) {
        m_actualType->outputCPPCast(cg, ar);
        cg.printf("(");
      }
      if (ref && m_value->isRefable()) cg.printf("ref(");
      m_value->outputCPP(cg, ar);
      if (ref && m_value->isRefable()) cg.printf(")");
      if (type_cast) cg.printf(")");
    }
    cg.printf(")");
  }
}
StatementPtr IfStatement::preOptimize(AnalysisResultPtr ar) {
  if (ar->getPhase() < AnalysisResult::FirstPreOptimize) {
    return StatementPtr();
  }

  bool changed = false;
  int i;
  int j;
  for (i = 0; i < m_stmts->getCount(); i++) {
    IfBranchStatementPtr branch =
      dynamic_pointer_cast<IfBranchStatement>((*m_stmts)[i]);
    ExpressionPtr condition = branch->getCondition();
    if (!condition) {
      StatementPtr stmt = branch->getStmt();
      if (stmt && stmt->is(KindOfIfStatement)) {
        StatementListPtr sub_stmts =
          dynamic_pointer_cast<IfStatement>(stmt)->m_stmts;
        m_stmts->removeElement(i);
        changed = true;
        for (j = 0; j < sub_stmts->getCount(); j++) {
          m_stmts->insertElement((*sub_stmts)[j], i++);
        }
      }
      break;
    } else if (condition->is(Expression::KindOfConstantExpression)) {
      ConstantExpressionPtr exp =
        dynamic_pointer_cast<ConstantExpression>(condition);
      if (exp->isBoolean()) {
        if (exp->getBooleanValue()) {
          // if (true) branch
          for (j = i + 1; j < m_stmts->getCount(); j++) {
            if ((*m_stmts)[j]->hasDecl()) break;
          }
          // no declarations after if (true)
          if (j == m_stmts->getCount()) break;
        } else {
          // if (false) branch
          if (!branch->hasDecl()) {
            m_stmts->removeElement(i);
            changed = true;
            i--;
          }
        }
      }
    }
  }

  if (i == m_stmts->getCount()) return StatementPtr();

  // either else branch or if (true) branch without further declarations

  i++;
  while (i < m_stmts->getCount()) {
    m_stmts->removeElement(i);
    changed = true;
  }

  // if there is only one branch left, return stmt.
  if (m_stmts->getCount() == 1) {
    return dynamic_pointer_cast<IfBranchStatement>((*m_stmts)[0])->getStmt();
  } else if (m_stmts->getCount() == 0) {
    return NULL_STATEMENT();
  } else {
    return changed ? static_pointer_cast<Statement>(shared_from_this())
                   : StatementPtr();
  }
}
Beispiel #19
0
void ClassConstant::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  if (cg.getContext() != CodeGenerator::CppClassConstantsDecl &&
      cg.getContext() != CodeGenerator::CppClassConstantsImpl) {
    return;
  }

  ClassScopePtr scope = getClassScope();
  for (int i = 0; i < m_exp->getCount(); i++) {
    AssignmentExpressionPtr exp =
      dynamic_pointer_cast<AssignmentExpression>((*m_exp)[i]);
    ConstantExpressionPtr var =
      dynamic_pointer_cast<ConstantExpression>(exp->getVariable());
    TypePtr type = scope->getConstants()->getFinalType(var->getName());
    ExpressionPtr value = exp->getValue();
    if (scope->getConstants()->isDynamic(var->getName())) {
        continue;
    }
    switch (cg.getContext()) {
    case CodeGenerator::CppClassConstantsDecl:
      cg_printf("extern const ");
      if (type->is(Type::KindOfString)) {
        cg_printf("StaticString");
      } else {
        type->outputCPPDecl(cg, ar, getScope());
      }
      cg_printf(" %s%s%s%s;\n",
                Option::ClassConstantPrefix, scope->getId().c_str(),
                Option::IdPrefix.c_str(), var->getName().c_str());
      break;
    case CodeGenerator::CppClassConstantsImpl: {
      bool isString = type->is(Type::KindOfString);
      bool isVariant = Type::IsMappedToVariant(type);
      ScalarExpressionPtr scalarExp =
        dynamic_pointer_cast<ScalarExpression>(value);
      bool stringForVariant = false;
      if (isVariant && scalarExp &&
          scalarExp->getActualType() &&
          scalarExp->getActualType()->is(Type::KindOfString)) {
        cg_printf("static const StaticString %s%s%s%s%sv(LITSTR_INIT(%s));\n",
                  Option::ClassConstantPrefix, scope->getId().c_str(),
                  Option::IdPrefix.c_str(), var->getName().c_str(),
                  Option::IdPrefix.c_str(),
                  scalarExp->getCPPLiteralString().c_str());
        stringForVariant = true;
      }
      cg_printf("const ");
      if (isString) {
        cg_printf("StaticString");
      } else {
        type->outputCPPDecl(cg, ar, getScope());
      }
      value->outputCPPBegin(cg, ar);
      cg_printf(" %s%s%s%s",
                Option::ClassConstantPrefix, scope->getId().c_str(),
                Option::IdPrefix.c_str(), var->getName().c_str());
      cg_printf(isString ? "(" : " = ");
      if (stringForVariant) {
        cg_printf("%s%s%s%s%sv",
                  Option::ClassConstantPrefix, scope->getId().c_str(),
                  Option::IdPrefix.c_str(), var->getName().c_str(),
                  Option::IdPrefix.c_str());
      } else if (isString && scalarExp) {
        cg_printf("LITSTR_INIT(%s)",
                  scalarExp->getCPPLiteralString().c_str());
      } else {
        value->outputCPP(cg, ar);
      }
      cg_printf(isString ? ");\n" : ";\n");
      value->outputCPPEnd(cg, ar);
      break;
    }
    default:
      assert(false);
    }
  }
}
Beispiel #20
0
void ClassConstant::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  bool lazyInit = cg.getContext() == CodeGenerator::CppLazyStaticInitializer;
  if (cg.getContext() != CodeGenerator::CppClassConstantsDecl &&
      cg.getContext() != CodeGenerator::CppClassConstantsImpl &&
      !lazyInit) {
    return;
  }

  ClassScopePtr scope = getClassScope();
  for (int i = 0; i < m_exp->getCount(); i++) {
    AssignmentExpressionPtr exp =
      dynamic_pointer_cast<AssignmentExpression>((*m_exp)[i]);
    ConstantExpressionPtr var =
      dynamic_pointer_cast<ConstantExpression>(exp->getVariable());
    TypePtr type = scope->getConstants()->getFinalType(var->getName());
    ExpressionPtr value = exp->getValue();
    if (!scope->getConstants()->isDynamic(var->getName()) == lazyInit) {
        continue;
    }
    switch (cg.getContext()) {
    case CodeGenerator::CppClassConstantsDecl:
      cg_printf("extern const ");
      if (type->is(Type::KindOfString)) {
        cg_printf("StaticString");
      } else {
        type->outputCPPDecl(cg, ar, getScope());
      }
      cg_printf(" %s%s_%s;\n", Option::ClassConstantPrefix,
                scope->getId(cg).c_str(),
                var->getName().c_str());
      break;
    case CodeGenerator::CppClassConstantsImpl: {
      cg_printf("const ");
      bool isString = type->is(Type::KindOfString);
      if (isString) {
        cg_printf("StaticString");
      } else {
        type->outputCPPDecl(cg, ar, getScope());
      }
      value->outputCPPBegin(cg, ar);
      cg_printf(" %s%s_%s", Option::ClassConstantPrefix,
                scope->getId(cg).c_str(),
                var->getName().c_str());
      cg_printf(isString ? "(" : " = ");
      ScalarExpressionPtr scalarExp =
        dynamic_pointer_cast<ScalarExpression>(value);
      if (isString && scalarExp) {
        cg_printf("LITSTR_INIT(%s)",
                  scalarExp->getCPPLiteralString(cg).c_str());
      } else {
        value->outputCPP(cg, ar);
      }
      cg_printf(isString ? ");\n" : ";\n");
      value->outputCPPEnd(cg, ar);
      break;
    }
    case CodeGenerator::CppLazyStaticInitializer:
      value->outputCPPBegin(cg, ar);
      cg_printf("g->%s%s_%s = ", Option::ClassConstantPrefix,
                scope->getId(cg).c_str(),
                var->getName().c_str());
      value->outputCPP(cg, ar);
      cg_printf(";\n");
      value->outputCPPEnd(cg, ar);
      break;
    default:
      ASSERT(false);
    }
  }
}