Exemple #1
0
void Parser::onStaticMember(Token &out, Token &className, Token &name) {
  out.reset();
  TempExpressionListPtr texp = name->getExp<TempExpressionList>();
  ArrayElementExpressionPtr arr = name->getExp<ArrayElementExpression>();
  if (!arr && texp) {
    arr = texp->getLast()->unsafe_cast<ArrayElementExpression>();
  }
  NamePtr cn = procStaticClassName(className, false);
  if (arr) {
    arr->sinkStaticMember(this, cn);
    out->exp() = name->exp();
  } else {
    NamePtr n;
    VariableExpressionPtr var = name->getExp<VariableExpression>();
    if (var) {
      n = var->getName();
      ASSERT(n);
      out->exp() = NEW_EXP(StaticMember, cn, n);
    } else {
      ASSERT(texp);
      var = texp->getLast()->unsafe_cast<VariableExpression>();
      ASSERT(var);
      n = var->getName();
      ASSERT(n);
      out->exp() = NEW_EXP(StaticMember, cn, n);
      texp->setLast(out->exp());
      out->exp() = texp;
    }
  }
}
bool BinaryOpExpression::outputCPPImplOpEqual(CodeGenerator &cg,
                                              AnalysisResultPtr ar) {
  if (m_exp1->is(Expression::KindOfArrayElementExpression)) {
    ArrayElementExpressionPtr exp =
      dynamic_pointer_cast<ArrayElementExpression>(m_exp1);
    if (exp->isSuperGlobal() || exp->isDynamicGlobal()) return false;
    if (TypePtr t = exp->getVariable()->getActualType()) {
      if (t->is(Type::KindOfArray) &&
          (!exp->getVariable()->getImplementedType() ||
           exp->getVariable()->getImplementedType()->is(Type::KindOfArray))) {
        return false;
      }
    }
    // turning $a['elem'] Op= $b into $a.setOpEqual('elem', $b);
    exp->getVariable()->outputCPP(cg, ar);
    if (exp->getOffset()) {
      cg_printf(".setOpEqual(%d, ", m_op);
      exp->getOffset()->outputCPP(cg, ar);
      cg_printf(", (");
    } else {
      cg_printf(".appendOpEqual(%d, (", m_op);
    }
    m_exp2->outputCPP(cg, ar);
    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 true;
  }
  if (m_exp1->is(Expression::KindOfObjectPropertyExpression)) {
    ObjectPropertyExpressionPtr var(
      dynamic_pointer_cast<ObjectPropertyExpression>(m_exp1));
    if (var->isValid()) return false;
    var->outputCPPObject(cg, ar);
    cg_printf("o_assign_op<%s,%d>(",
              isUnused() ? "void" : "Variant", m_op);
    var->outputCPPProperty(cg, ar);
    cg_printf(", ");
    m_exp2->outputCPP(cg, ar);
    cg_printf("%s)", originalClassName(cg, true).c_str());
    return true;
  }

  return false;
}
void ReturnStatement::analyzeProgram(AnalysisResultPtr ar) {
  if (m_exp) {
    FunctionScopePtr funcScope = getFunctionScope();
    if (funcScope) {
      if (funcScope->isRefReturn()) {
        m_exp->setContext(Expression::RefValue);
      }
    }
    m_exp->analyzeProgram(ar);
  }
  if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
    if (m_exp) {
      TypePtr retType = m_exp->getCPPType();
      bool needsCheck = !retType->isPrimitive();
      if (m_exp->is(Expression::KindOfSimpleFunctionCall) ||
          m_exp->is(Expression::KindOfDynamicFunctionCall) ||
          m_exp->is(Expression::KindOfObjectMethodExpression)) {
        // return a value from another function call
        needsCheck = false;
      }
      ExpressionPtr tmp = m_exp;
      while (tmp &&
             (tmp->is(Expression::KindOfObjectPropertyExpression) ||
              tmp->is(Expression::KindOfArrayElementExpression))) {
        if (ObjectPropertyExpressionPtr opExp =
            dynamic_pointer_cast<ObjectPropertyExpression>(tmp)) {
          tmp = opExp->getObject();
        } else {
          ArrayElementExpressionPtr aeExp =
            dynamic_pointer_cast<ArrayElementExpression>(tmp);
          ASSERT(aeExp);
          tmp = aeExp->getVariable();
        }
      }
      if (SimpleVariablePtr svExp = dynamic_pointer_cast<SimpleVariable>(tmp)) {
        if (svExp->isThis()) {
          // returning something from $this
          needsCheck = false;
        } else {
          Symbol *sym = svExp->getSymbol();
          if (sym && sym->isParameter() && !sym->isLvalParam()) {
            // returning something from non-lval parameter
            needsCheck = false;
          }
        }
      }
      if (needsCheck) {
        FunctionScopePtr funcScope = getFunctionScope();
        if (funcScope) funcScope->setNeedsCheckMem();
      }
    }
  }
}
Exemple #4
0
void Parser::onStaticMember(Token &out, Token &className, Token &name) {
  out.reset();
  ArrayElementExpressionPtr arr = name->getExp<ArrayElementExpression>();
  NamePtr cn = procStaticClassName(className, false);
  if (arr) {
    arr->sinkStaticMember(this, cn);
    out->exp() = name->exp();
  } else {
    NamePtr n;
    VariableExpressionPtr var = name->getExp<VariableExpression>();
    if (var) {
      n = var->getName();
    }
    ASSERT(n);
    out->exp() = NEW_EXP(StaticMember, cn, n);
  }
}
void ArrayElementExpression::sinkStaticMember(Parser *parser,
                                              const NamePtr &className) {
  ArrayElementExpressionPtr arr = m_arr->unsafe_cast<ArrayElementExpression>();
  if (arr) {
    arr->sinkStaticMember(parser, className);
    return;
  }

  VariableExpressionPtr var = m_arr->unsafe_cast<VariableExpression>();
  if (var) {
    m_arr =
      StaticMemberExpressionPtr(new StaticMemberExpression(parser,
                                                           className,
                                                           var->getName()));
    return;
  }
  ASSERT(false);
}
Exemple #6
0
void Parser::onStaticMember(Token &out, Token &className, Token &name) {
  out.reset();
  ArrayElementExpressionPtr arr = name->getExp<ArrayElementExpression>();
  string cn = className.getText();
  if (haveClass()) {
    if (cn == "self") {
      cn = peekClass()->name();
    } else if (cn == "parent") {
      cn = peekClass()->parent();
    }
  }
  if (arr) {
    arr->sinkStaticMember(this, cn);
    out->exp() = name->exp();
  } else {
    NamePtr n;
    VariableExpressionPtr var = name->getExp<VariableExpression>();
    if (var) {
      n = var->getName();
    }
    ASSERT(n);
    out->exp() = NEW_EXP(StaticMember, cn, n);
  }
}
void ListAssignment::outputCPPAssignment(CodeGenerator &cg,
    AnalysisResultPtr ar, const string &arrTmp) {
  if (!m_variables) return;

  for (int i = m_variables->getCount() - 1; i >= 0; --i) {
    ExpressionPtr exp = (*m_variables)[i];
    if (exp) {
      if (exp->is(Expression::KindOfListAssignment)) {
        ListAssignmentPtr sublist = dynamic_pointer_cast<ListAssignment>(exp);
        string subTmp = genCPPTemp(cg, ar);
        cg_printf("Variant %s((ref(%s[%d])));\n", subTmp.c_str(),
                  arrTmp.c_str(), i);
        sublist->outputCPPAssignment(cg, ar, subTmp);
      } else {
        bool done = false;
        if (exp->is(Expression::KindOfArrayElementExpression)) {
          ArrayElementExpressionPtr arrExp =
            dynamic_pointer_cast<ArrayElementExpression>(exp);
          if (!arrExp->isSuperGlobal() && !arrExp->isDynamicGlobal()) {
            arrExp->getVariable()->outputCPP(cg, ar);
            if (arrExp->getOffset()) {
              cg_printf(".set(");
              arrExp->getOffset()->outputCPP(cg, ar);
              cg_printf(", ");
            } else {
              cg_printf(".append(");
            }
            cg_printf("%s[%d]);\n", arrTmp.c_str(), i);
            done = true;
          }
        } else if (exp->is(Expression::KindOfObjectPropertyExpression)) {
          ObjectPropertyExpressionPtr var(
            dynamic_pointer_cast<ObjectPropertyExpression>(exp));
          if (!var->isValid()) {
            var->outputCPPObject(cg, ar);
            cg_printf("o_set(");
            var->outputCPPProperty(cg, ar);
            cg_printf(", %s[%d], %s);\n",
                      arrTmp.c_str(), i,
                      getClassScope() ? "s_class_name" : "empty_string");
            done = true;
          }
        }
        if (!done) {
          exp->outputCPP(cg, ar);
          if (arrTmp == "null") {
            cg_printf(" = null;\n");
          } else {
            cg_printf(" = %s[%d];\n", arrTmp.c_str(), i);
          }
        }
      }
    }
  }
}
bool BinaryOpExpression::outputCPPImplOpEqual(CodeGenerator &cg,
                                              AnalysisResultPtr ar) {
  if (!m_exp1->is(Expression::KindOfArrayElementExpression)) return false;
  ArrayElementExpressionPtr exp =
    dynamic_pointer_cast<ArrayElementExpression>(m_exp1);
  if (exp->isSuperGlobal() || exp->isDynamicGlobal()) return false;
  bool linemap = outputLineMap(cg, ar);

  // turning $a['elem'] Op= $b into $a.setOpEqual('elem', $b);
  exp->getVariable()->outputCPP(cg, ar);
  if (exp->getOffset()) {
    cg_printf(".setOpEqual(%d, ", m_op);
    exp->getOffset()->outputCPP(cg, ar);
    cg_printf(", (");
  } else {
    cg_printf(".appendOpEqual(%d, (", m_op);
  }
  m_exp2->outputCPP(cg, ar);
  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(")");

  if (linemap) cg_printf(")");
  return true;
}
void ListAssignment::outputCPPAssignment(CodeGenerator &cg,
    AnalysisResultPtr ar, const string &arrTmp) {
  if (!m_variables) return;

  for (int i = m_variables->getCount() - 1; i >= 0; --i) {
    ExpressionPtr exp = (*m_variables)[i];
    if (exp) {
      if (exp->is(Expression::KindOfListAssignment)) {
        ListAssignmentPtr sublist = dynamic_pointer_cast<ListAssignment>(exp);
        string subTmp = genCPPTemp(cg, ar);
        cg.printf("Variant %s((ref(%s.rvalAt(%d))));\n", subTmp.c_str(),
                  arrTmp.c_str(), i);
        sublist->outputCPPAssignment(cg, ar, subTmp);
      } else {
        bool done = false;
        if (exp->is(Expression::KindOfArrayElementExpression)) {
          ArrayElementExpressionPtr arrExp =
            dynamic_pointer_cast<ArrayElementExpression>(exp);
          if (!arrExp->isSuperGlobal() && !arrExp->isDynamicGlobal()) {
            arrExp->getVariable()->outputCPP(cg, ar);
            if (arrExp->getOffset()) {
              cg.printf(".set(");
              arrExp->getOffset()->outputCPP(cg, ar);
              cg.printf(", ");
            } else {
              cg.printf(".append(");
            }
            cg.printf("%s.rvalAt(%d));\n", arrTmp.c_str(), i);
            done = true;
          }
        }
        if (!done) {
          exp->outputCPP(cg, ar);
          if (arrTmp == "null") {
            cg.printf(" = null;\n");
          } else {
            cg.printf(" = %s.rvalAt(%d);\n", arrTmp.c_str(), i);
          }
        }
      }
    }
  }
}
bool AssignmentExpression::SpecialAssignment(CodeGenerator &cg,
                                             AnalysisResultPtr ar,
                                             ExpressionPtr lval,
                                             ExpressionPtr rval,
                                             const char *rvalStr, bool ref) {
  if (lval->is(KindOfArrayElementExpression)) {
    ArrayElementExpressionPtr exp =
      dynamic_pointer_cast<ArrayElementExpression>(lval);
    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 (rval) {
        wrapValue(cg, ar, rval, ref,
                  (exp->getVariable()->is(KindOfArrayElementExpression) ||
                   exp->getVariable()->is(KindOfObjectPropertyExpression)) &&
                  (exp->getVariable()->getContainedEffects() &&
                   (CreateEffect|AccessorEffect)));
      } else {
        cg_printf(ref ? "ref(%s)" : "%s", rvalStr);
      }
      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 true;
    }
  } else if (lval->is(KindOfObjectPropertyExpression)) {
    ObjectPropertyExpressionPtr var(
      dynamic_pointer_cast<ObjectPropertyExpression>(lval));
    if (!var->isValid()) {
      bool nonPrivate = var->isNonPrivate(ar);
      var->outputCPPObject(cg, ar);
      if (nonPrivate) {
        cg_printf("o_setPublic(");
      } else {
        cg_printf("o_set(");
      }
      var->outputCPPProperty(cg, ar);
      cg_printf(", %s", ref ? "ref(" : "");
      if (rval) {
        rval->outputCPP(cg, ar);
      } else {
        cg_printf(ref ? "ref(%s)" : "%s", rvalStr);
      }
      if (nonPrivate) {
        cg_printf("%s)", ref ? ")" : "");
      }
      else {
        cg_printf("%s%s)",
                  ref ? ")" : "",
                  lval->originalClassName(cg, true).c_str());
      }
      return true;
    }
  }
  return false;
}
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(")");
  }
}