예제 #1
0
bool ExpressionList::getScalarValue(Variant &value) {
  if (m_arrayElements) {
    if (isScalarArrayPairs()) {
      ArrayInit init(m_exps.size());
      for (unsigned int i = 0; i < m_exps.size(); i++) {
        ArrayPairExpressionPtr exp =
          dynamic_pointer_cast<ArrayPairExpression>(m_exps[i]);
        ExpressionPtr name = exp->getName();
        ExpressionPtr val = exp->getValue();
        if (!name) {
          Variant v;
          bool ret = val->getScalarValue(v);
          if (!ret) ASSERT(false);
          init.set(v);
        } else {
          Variant n;
          Variant v;
          bool ret1 = name->getScalarValue(n);
          bool ret2 = val->getScalarValue(v);
          if (!(ret1 && ret2)) return ExpressionPtr();
          init.set(n, v);
        }
      }
      value = Array(init.create());
      return true;
    }
    return false;
  }
  if (m_kind != ListKindParam && !hasEffect()) {
    ExpressionPtr v(listValue());
    return v ? v->getScalarValue(value) : false;
  }
  return false;
}
예제 #2
0
bool ExpressionList::getScalarValue(Variant &value) {
  if (m_elems_kind != ElemsKind::None) {
    if (isScalarArrayPairs()) {
      ArrayInit init(m_exps.size(), ArrayInit::Mixed{});
      for (unsigned int i = 0; i < m_exps.size(); i++) {
        ArrayPairExpressionPtr exp =
          dynamic_pointer_cast<ArrayPairExpression>(m_exps[i]);
        ExpressionPtr name = exp->getName();
        ExpressionPtr val = exp->getValue();
        if (!name) {
          Variant v;
          bool ret = val->getScalarValue(v);
          if (!ret) assert(false);
          init.append(v);
        } else {
          Variant n;
          Variant v;
          bool ret1 = name->getScalarValue(n);
          bool ret2 = val->getScalarValue(v);
          if (!(ret1 && ret2)) return false;
          init.setKeyUnconverted(n, v);
        }
      }
      value = Array(init.create());
      return true;
    }
    return false;
  }
  if (m_kind != ListKindParam && !hasEffect()) {
    ExpressionPtr v(listValue());
    return v ? v->getScalarValue(value) : false;
  }
  return false;
}
예제 #3
0
bool ExpressionList::getScalarValue(Variant &value) {
  if (!isScalarArrayPairs()) return false;
  ArrayInit init(m_exps.size());
  for (unsigned int i = 0; i < m_exps.size(); i++) {
    ArrayPairExpressionPtr exp =
      dynamic_pointer_cast<ArrayPairExpression>(m_exps[i]);
    ExpressionPtr name = exp->getName();
    ExpressionPtr val = exp->getValue();
    if (!name) {
      Variant v;
      bool ret = val->getScalarValue(v);
      if (!ret) ASSERT(false);
      init.set(i, v);
    } else {
      Variant n;
      Variant v;
      bool ret1 = name->getScalarValue(n);
      bool ret2 = val->getScalarValue(v);
      if (!(ret1 && ret2)) ASSERT(false);
      init.set(i, n, v);
    }
  }
  value = Array(init.create());
  return true;
}
예제 #4
0
unsigned int ExpressionList::checkIntegerKeys(int64 &max) const {
  ASSERT(m_arrayElements);
  max = 0;
  set<int64> keys;
  for (unsigned int i = 0; i < m_exps.size(); i++) {
    ArrayPairExpressionPtr ap =
      dynamic_pointer_cast<ArrayPairExpression>(m_exps[i]);
    ExpressionPtr name = ap->getName();
    if (!name) return 0;
    Variant value;
    bool ret = name->getScalarValue(value);
    if (!ret) return 0;
    if (!value.isInteger()) return 0;
    int64 v = value.toInt64();
    if (i == 0) {
      max = v;
    } else if (max < v) {
      max = v;
    }
    keys.insert(v);
  }
  if (max >= 0) {
    max++;
  } else {
    max = 0;
  }
  return keys.size();
}
예제 #5
0
ExpressionPtr ConstantExpression::preOptimize(AnalysisResultConstPtr ar) {
    if (ar->getPhase() < AnalysisResult::FirstPreOptimize) {
        return ExpressionPtr();
    }
    ConstructPtr decl;
    while (!isScalar() && !m_dynamic && !(m_context & LValue)) {
        const Symbol *sym = resolveNS(ar);
        if (sym &&
                (!const_cast<Symbol*>(sym)->checkDefined() || sym->isDynamic())) {
            sym = 0;
            m_dynamic = true;
        }
        if (!sym) break;
        if (!sym->isSystem()) BlockScope::s_constMutex.lock();
        ExpressionPtr value = dynamic_pointer_cast<Expression>(sym->getValue());
        if (!sym->isSystem()) BlockScope::s_constMutex.unlock();

        if (!value || !value->isScalar()) {
            if (!m_depsSet && sym->getDeclaration()) {
                sym->getDeclaration()->getScope()->addUse(
                    getScope(), BlockScope::UseKindConstRef);
                m_depsSet = true;
            }
            break;
        }

        Variant scalarValue;
        if (value->getScalarValue(scalarValue) &&
                !scalarValue.isAllowedAsConstantValue()) {
            // block further optimization
            const_cast<Symbol*>(sym)->setDynamic();
            m_dynamic = true;
            break;
        }

        if (sym->isSystem() && !value->is(KindOfScalarExpression)) {
            if (ExpressionPtr opt = value->preOptimize(ar)) {
                value = opt;
            }
        }
        ExpressionPtr rep = Clone(value, getScope());
        rep->setComment(getText());
        copyLocationTo(rep);
        return replaceValue(rep);
    }

    return ExpressionPtr();
}
예제 #6
0
unsigned int ExpressionList::checkLitstrKeys() const {
  ASSERT(m_arrayElements);
  std::set<string> keys;
  for (unsigned int i = 0; i < m_exps.size(); i++) {
    ArrayPairExpressionPtr ap =
      dynamic_pointer_cast<ArrayPairExpression>(m_exps[i]);
    ExpressionPtr name = ap->getName();
    if (!name) return 0;
    Variant value;
    bool ret = name->getScalarValue(value);
    if (!ret) return 0;
    if (!value.isString()) return 0;
    String str = value.toString();
    if (str->isInteger()) return 0;
    string s(str.data(), str.size());
    keys.insert(s);
  }
  return keys.size();
}
예제 #7
0
static bool isEquivRedecl(const std::string &name,
                          ExpressionPtr exp,
                          ModifierExpressionPtr modif,
                          Symbol * symbol) {
  assert(exp);
  assert(modif);
  assert(symbol);
  if (symbol->getName()     != name                 ||
      symbol->isProtected() != modif->isProtected() ||
      symbol->isPrivate()   != modif->isPrivate()   ||
      symbol->isPublic()    != modif->isPublic()    ||
      symbol->isStatic()    != modif->isStatic())
    return false;

  auto symDeclExp =
    dynamic_pointer_cast<Expression>(symbol->getDeclaration());
  if (!exp) return !symDeclExp;
  Variant v1, v2;
  auto s1 = exp->getScalarValue(v1);
  auto s2 = symDeclExp->getScalarValue(v2);
  if (s1 != s2) return false;
  if (s1) return same(v1, v2);
  return exp->getText() == symDeclExp->getText();
}
ExpressionPtr AssignmentExpression::preOptimize(AnalysisResultConstPtr ar) {
  if (Option::EliminateDeadCode &&
      ar->getPhase() >= AnalysisResult::FirstPreOptimize) {
    // otherwise used & needed flags may not be up to date yet
    ExpressionPtr rep = optimize(ar);
    if (rep) return rep;
  }
  if (m_variable->getContainedEffects() & ~(CreateEffect|AccessorEffect)) {
    return ExpressionPtr();
  }
  ExpressionPtr val = m_value;
  while (val) {
    if (val->is(KindOfExpressionList)) {
      ExpressionListPtr el(static_pointer_cast<ExpressionList>(val));
      val = el->listValue();
      continue;
    }
    if (val->is(KindOfAssignmentExpression)) {
      val = static_pointer_cast<AssignmentExpression>(val)->m_value;
      continue;
    }
    break;
  }
  if (val && val->isScalar()) {
    if (val != m_value) {
      ExpressionListPtr rep(new ExpressionList(
                              getScope(), getLocation(),
                              KindOfExpressionList,
                              ExpressionList::ListKindWrapped));
      rep->addElement(m_value);
      m_value = val->clone();
      rep->addElement(static_pointer_cast<Expression>(shared_from_this()));
      return replaceValue(rep);
    }
    if (!m_ref && m_variable->is(KindOfArrayElementExpression)) {
      ArrayElementExpressionPtr ae(
        static_pointer_cast<ArrayElementExpression>(m_variable));
      ExpressionPtr avar(ae->getVariable());
      ExpressionPtr aoff(ae->getOffset());
      if (!aoff || aoff->isScalar()) {
        avar = avar->getCanonLVal();
        while (avar) {
          if (avar->isScalar()) {
            Variant v,o,r;
            if (!avar->getScalarValue(v)) break;
            if (!val->getScalarValue(r)) break;
            try {
              g_context->setThrowAllErrors(true);
              if (aoff) {
                if (!aoff->getScalarValue(o)) break;
                v.set(o, r);
              } else {
                v.append(r);
              }
              g_context->setThrowAllErrors(false);
            } catch (...) {
              break;
            }
            ExpressionPtr rep(
              new AssignmentExpression(
                getScope(), getLocation(), KindOfAssignmentExpression,
                m_variable->replaceValue(Clone(ae->getVariable())),
                makeScalarExpression(ar, v), false));
            if (!isUnused()) {
              ExpressionListPtr el(
                new ExpressionList(
                  getScope(), getLocation(), KindOfExpressionList,
                  ExpressionList::ListKindWrapped));
              el->addElement(rep);
              el->addElement(val);
              rep = el;
            }
            return replaceValue(rep);
          }
          avar = avar->getCanonPtr();
        }
        g_context->setThrowAllErrors(false);
      }
    }
  }
  return ExpressionPtr();
}
예제 #9
0
void FunctionScope::outputCPPClassMap(CodeGenerator &cg, AnalysisResultPtr ar) {
  int attribute = ClassInfo::IsNothing;
  if (!isUserFunction()) attribute |= ClassInfo::IsSystem;
  if (isRedeclaring()) attribute |= ClassInfo::IsRedeclared;
  if (isVolatile()) attribute |= ClassInfo::IsVolatile;
  if (isRefReturn()) attribute |= ClassInfo::IsReference;

  if (isProtected()) {
    attribute |= ClassInfo::IsProtected;
  } else if (isPrivate()) {
    attribute |= ClassInfo::IsPrivate;
  } else {
    attribute |= ClassInfo::IsPublic;
  }
  if (isAbstract()) attribute |= ClassInfo::IsAbstract;
  if (isStatic() && !isStaticMethodAutoFixed()) {
    attribute |= ClassInfo::IsStatic;
  }
  if (isFinal()) attribute |= ClassInfo::IsFinal;
  if (!m_docComment.empty()) attribute |= ClassInfo::HasDocComment;

  // Use the original cased name, for reflection to work correctly.
  cg.printf("(const char *)0x%04X, \"%s\", NULL, NULL,\n", attribute,
            getOriginalName().c_str());

  if (!m_docComment.empty()) {
    char *dc = string_cplus_escape(m_docComment.c_str());
    cg.printf("\"%s\",\n", dc);
    free(dc);
  }

  Variant defArg;
  for (int i = 0; i < m_maxParam; i++) {
    int attr = ClassInfo::IsNothing;
    if (i >= m_minParam) attr |= ClassInfo::IsOptional;
    if (isRefParam(i)) attr |= ClassInfo::IsReference;

    cg.printf("(const char *)0x%04X, \"%s\", \"%s\", ",
              attr, m_paramNames[i].c_str(),
              Util::toLower(m_paramTypes[i]->getPHPName()).c_str());

    if (i >= m_minParam) {
      MethodStatementPtr m =
        dynamic_pointer_cast<MethodStatement>(getStmt());
      if (m) {
        ExpressionListPtr params = m->getParams();
        assert(i < params->getCount());
        ParameterExpressionPtr param =
          dynamic_pointer_cast<ParameterExpression>((*params)[i]);
        assert(param);
        ExpressionPtr def = param->defaultValue();
        if (!def->isScalar() || !def->getScalarValue(defArg)) {
          defArg = "1";
        }
      } else {
        defArg = "1";
      }
      char *s = string_cplus_escape(f_serialize(defArg).data());
      cg.printf("\"%s\",\n", s);
      free(s);
    } else {
      cg.printf("\"\",\n");
    }
  }
  cg.printf("NULL,\n");

  m_variables->outputCPPStaticVariables(cg, ar);
}
예제 #10
0
StatementPtr IfStatement::preOptimize(AnalysisResultPtr ar) {
  if (ar->getPhase() < AnalysisResult::FirstPreOptimize) {
    return StatementPtr();
  }

  // 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;
  int i;
  int j;
  Variant value;
  bool hoist = false;
  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) {
        if (!i &&
            ((getFunctionScope() && !getFunctionScope()->inPseudoMain()) ||
             !stmt->hasDecl())) {
          hoist = true;
          break;
        }
        if (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->isScalar() &&
               condition->getScalarValue(value)) {
      if (value.toBoolean()) {
        hoist = !i &&
          ((getFunctionScope() && !getFunctionScope()->inPseudoMain()) ||
           !branch->hasDecl());
        break;
      } else {
        m_stmts->removeElement(i--);
        changed = true;
      }
    }
  }

  if (!changed && i && 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 (hoist) {
    IfBranchStatementPtr branch =
      dynamic_pointer_cast<IfBranchStatement>((*m_stmts)[0]);
    return branch->getStmt() ? branch->getStmt() : NULL_STATEMENT();
  } else if (m_stmts->getCount() == 0) {
    return NULL_STATEMENT();
  } else {
    return changed ? static_pointer_cast<Statement>(shared_from_this())
                   : StatementPtr();
  }
}
예제 #11
0
void FunctionScope::outputCPPClassMap(CodeGenerator &cg, AnalysisResultPtr ar) {
  int attribute = ClassInfo::IsNothing;
  if (!isUserFunction()) attribute |= ClassInfo::IsSystem;
  if (isRedeclaring()) attribute |= ClassInfo::IsRedeclared;
  if (isVolatile()) attribute |= ClassInfo::IsVolatile;
  if (isRefReturn()) attribute |= ClassInfo::IsReference;

  if (isProtected()) {
    attribute |= ClassInfo::IsProtected;
  } else if (isPrivate()) {
    attribute |= ClassInfo::IsPrivate;
  } else {
    attribute |= ClassInfo::IsPublic;
  }
  if (isAbstract()) attribute |= ClassInfo::IsAbstract;
  if (isStatic()) {
    attribute |= ClassInfo::IsStatic;
  }
  if (isFinal()) attribute |= ClassInfo::IsFinal;

  if (isVariableArgument()) {
    attribute |= ClassInfo::VariableArguments;
  }
  if (isReferenceVariableArgument()) {
    attribute |= ClassInfo::RefVariableArguments;
  }
  if (isMixedVariableArgument()) {
    attribute |= ClassInfo::MixedVariableArguments;
  }

  attribute |= m_attributeClassInfo;
  if (!m_docComment.empty() && Option::GenerateDocComments) {
    attribute |= ClassInfo::HasDocComment;
  } else {
    attribute &= ~ClassInfo::HasDocComment;
  }

  // Use the original cased name, for reflection to work correctly.
  cg_printf("(const char *)0x%04X, \"%s\", \"%s\", (const char *)%d, "
            "(const char *)%d, NULL, NULL,\n", attribute,
            getOriginalName().c_str(),
            m_stmt ? m_stmt->getLocation()->file : "",
            m_stmt ? m_stmt->getLocation()->line0 : 0,
            m_stmt ? m_stmt->getLocation()->line1 : 0);

  if (!m_docComment.empty() && Option::GenerateDocComments) {
    char *dc = string_cplus_escape(m_docComment.c_str(), m_docComment.size());
    cg_printf("\"%s\",\n", dc);
    free(dc);
  }

  Variant defArg;
  for (int i = 0; i < m_maxParam; i++) {
    int attr = ClassInfo::IsNothing;
    if (i >= m_minParam) attr |= ClassInfo::IsOptional;
    if (isRefParam(i)) attr |= ClassInfo::IsReference;

    const std::string &tname = m_paramTypeSpecs[i] ?
      m_paramTypeSpecs[i]->getPHPName() : "";
    cg_printf("(const char *)0x%04X, \"%s\", \"%s\", ",
              attr, m_paramNames[i].c_str(),
              Util::toLower(tname).c_str());

    if (i >= m_minParam) {
      MethodStatementPtr m =
        dynamic_pointer_cast<MethodStatement>(getStmt());
      if (m) {
        ExpressionListPtr params = m->getParams();
        assert(i < params->getCount());
        ParameterExpressionPtr param =
          dynamic_pointer_cast<ParameterExpression>((*params)[i]);
        assert(param);
        ExpressionPtr def = param->defaultValue();
        string sdef = def->getText();
        char *esdef = string_cplus_escape(sdef.data(), sdef.size());
        if (!def->isScalar() || !def->getScalarValue(defArg)) {
          /**
           * Special value runtime/ext/ext_reflection.cpp can check and throw.
           * If we want to avoid seeing this so to make getDefaultValue()
           * work better for reflections, we will have to implement
           * getScalarValue() to greater extent under compiler/expressions.
           */
          cg_printf("\"\x01\", \"%s\",\n", esdef);
        } else {
          String str = f_serialize(defArg);
          char *s = string_cplus_escape(str.data(), str.size());
          cg_printf("\"%s\", \"%s\",\n", s, esdef);
          free(s);
        }
        free(esdef);
      } else {
        char *def = string_cplus_escape(m_paramDefaults[i].data(),
                                        m_paramDefaults[i].size());
        char *defText = string_cplus_escape(m_paramDefaultTexts[i].data(),
                                            m_paramDefaultTexts[i].size());
        cg_printf("\"%s\", \"%s\",\n", def, defText);
        free(def);
        free(defText);
      }
    } else {
      cg_printf("\"\", \"\",\n");
    }
  }
  cg_printf("NULL,\n");

  m_variables->outputCPPStaticVariables(cg, ar);
}