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(); } } } }
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); }
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(")"); } }