void ClosureExpression::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { cg_printf("%sClosure((NEWOBJ(%sClosure)())->create(\"%s\", ", Option::SmartPtrPrefix, Option::ClassPrefix, m_func->getOriginalName().c_str()); if (m_vars && m_vars->getCount()) { cg_printf("Array(ArrayInit(%d, false, true)", m_vars->getCount()); for (int i = 0; i < m_vars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); ExpressionPtr value = (*m_values)[i]; cg_printf(".set%s(\"%s\", ", param->isRef() ? "Ref" : "", param->getName().c_str()); value->outputCPP(cg, ar); cg_printf(")"); } cg_printf(".create())"); } else { cg_printf("Array()"); } cg_printf("))"); }
bool AliasManager::optimize(AnalysisResultPtr ar, MethodStatementPtr m) { m_arp = ar; m_variables = ar->getScope()->getVariables(); if (!m_variables->isPseudoMainTable()) { m_variables->clearUsed(); } if (ExpressionListPtr pPtr = m->getParams()) { ExpressionList ¶ms = *pPtr; for (int i = params.getCount(); i--; ) { ParameterExpressionPtr p = spc(ParameterExpression, params[i]); AliasInfo &ai = m_aliasInfo[p->getName()]; if (p->isRef()) { ai.setIsRefTo(); } } } collectAliasInfoRecur(m->getStmts()); for (AliasInfoMap::iterator it = m_aliasInfo.begin(), end = m_aliasInfo.end(); it != end; ++it) { if (m_variables->isGlobal(it->first) || m_variables->isStatic(it->first)) { it->second.setIsGlobal(); } } canonicalizeRecur(m->getStmts()); return m_changed; }
void FunctionStatement::onParse(AnalysisResultConstPtr ar, FileScopePtr scope) { // Correctness checks are normally done before adding function to scope. if (m_params) { for (int i = 0; i < m_params->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); if (param->hasTypeHint() && param->defaultValue()) { param->compatibleDefault(); } } } // note it's important to add to scope, not a pushed FunctionContainer, // as a function may be declared inside a class's method, yet this function // is a global function, not a class method. FunctionScopePtr fs = onInitialParse(ar, scope); FunctionScope::RecordFunctionInfo(m_name, fs); if (!scope->addFunction(ar, fs)) { m_ignored = true; return; } if (Option::PersistenceHook) { fs->setPersistent(Option::PersistenceHook(fs, scope)); } }
void InterfaceStatement::checkArgumentsToPromote( FileScopeRawPtr scope, ExpressionListPtr promotedParams, int type) { if (!m_stmt) { return; } for (int i = 0; i < m_stmt->getCount(); i++) { MethodStatementPtr meth = dynamic_pointer_cast<MethodStatement>((*m_stmt)[i]); if (meth && meth->isNamed("__construct")) { ExpressionListPtr params = meth->getParams(); if (params) { for (int i = 0; i < params->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); if (param->getModifier() != 0) { if (type == T_TRAIT || type == T_INTERFACE) { param->parseTimeFatal(scope, Compiler::InvalidAttribute, "Constructor parameter promotion " "not allowed on traits or interfaces"); } if (promotedParams) { promotedParams->addElement(param); } } } } return; // nothing else to look at } } }
ClosureExpression::ClosureExpression (EXPRESSION_CONSTRUCTOR_PARAMETERS, FunctionStatementPtr func, ExpressionListPtr vars) : Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES), m_func(func), m_vars(vars) { if (m_vars) { m_values = ExpressionListPtr (new ExpressionList(m_vars->getScope(), m_vars->getLocation(), KindOfExpressionList)); for (int i = 0; i < m_vars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); string name = param->getName(); SimpleVariablePtr var(new SimpleVariable(param->getScope(), param->getLocation(), KindOfSimpleVariable, name)); if (param->isRef()) { var->setContext(RefValue); } m_values->addElement(var); } } }
void FunctionScope::setParamCounts(AnalysisResultConstPtr ar, int minParam, int numDeclParam) { if (minParam >= 0) { m_minParam = minParam; m_numDeclParams = numDeclParam; } else { assert(numDeclParam == minParam); } assert(m_minParam >= 0 && m_numDeclParams >= m_minParam); assert(IMPLIES(hasVariadicParam(), m_numDeclParams > 0)); if (m_numDeclParams > 0) { m_paramNames.resize(m_numDeclParams); m_refs.resize(m_numDeclParams); if (m_stmt) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); ExpressionListPtr params = stmt->getParams(); for (int i = 0; i < m_numDeclParams; i++) { if (stmt->isRef(i)) m_refs[i] = true; ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); m_paramNames[i] = param->getName(); } assert(m_paramNames.size() == m_numDeclParams); } } }
bool MethodStatement::isRef(int index /* = -1 */) const { if (index == -1) return m_ref; assert(index >= 0 && index < m_params->getCount()); ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[index]); return param->isRef(); }
void MethodStatement::addParamRTTI(AnalysisResultPtr ar) { FunctionScopePtr func = dynamic_pointer_cast<FunctionScope>(ar->getScope()); VariableTablePtr variables = func->getVariables(); if (variables->getAttribute(VariableTable::ContainsDynamicVariable) || variables->getAttribute(VariableTable::ContainsExtract)) { return; } for (int i = 0; i < m_params->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); const string ¶mName = param->getName(); if (variables->isLvalParam(paramName)) continue; TypePtr paramType = param->getActualType(); if ((paramType->is(Type::KindOfVariant) || paramType->is(Type::KindOfSome)) && !param->isRef()) { param->setHasRTTI(); ClassScopePtr cls = ar->getClassScope(); ar->addParamRTTIEntry(cls, func, paramName); const string funcId = ar->getFuncId(cls, func); ar->addRTTIFunction(funcId); } } }
void FunctionScope::setParamCounts(AnalysisResultPtr ar, int minParam, int maxParam) { m_minParam = minParam; m_maxParam = maxParam; ASSERT(m_minParam >= 0 && m_maxParam >= m_minParam); if (m_maxParam > 0) { m_paramNames.resize(m_maxParam); m_paramTypes.resize(m_maxParam); m_paramTypeSpecs.resize(m_maxParam); m_refs.resize(m_maxParam); if (m_stmt) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); ExpressionListPtr params = stmt->getParams(); for (int i = 0; i < m_maxParam; i++) { if (stmt->isRef(i)) m_refs[i] = true; ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); m_paramNames[i] = param->getName(); m_paramTypeSpecs[i] = param->getTypeSpec(ar); } } } }
void Symbol::beginLocal(BlockScopeRawPtr scope) { m_prevCoerced = m_coerced; if (isClosureVar()) { ExpressionListPtr useVars = scope->getContainingFunction()->getClosureVars(); assert(useVars); // linear scan for now, since most use var lists are // fairly short bool found = false; for (int i = 0; i < useVars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*useVars)[i]); if (m_name == param->getName()) { // bootstrap use var with parameter type m_coerced = param->getType(); found = true; break; } } if (!found) assert(false); assert(!isRefClosureVar() || (m_coerced && m_coerced->is(Type::KindOfVariant))); } else { m_coerced.reset(); } }
void ClosureExpression::analyzeProgram(AnalysisResultPtr ar) { m_func->analyzeProgram(ar); if (m_vars) { m_values->analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeAll) { getFunctionScope()->addUse(m_func->getFunctionScope(), BlockScope::UseKindClosure); m_func->getFunctionScope()->setClosureVars(m_vars); // closure function's variable table (not containing function's) VariableTablePtr variables = m_func->getFunctionScope()->getVariables(); VariableTablePtr containing = getFunctionScope()->getVariables(); for (int i = 0; i < m_vars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); const string &name = param->getName(); { Symbol *containingSym = containing->addDeclaredSymbol(name, param); containingSym->setPassClosureVar(); Symbol *sym = variables->addDeclaredSymbol(name, param); sym->setClosureVar(); sym->setDeclaration(ConstructPtr()); if (param->isRef()) { sym->setRefClosureVar(); sym->setUsed(); } else { sym->clearRefClosureVar(); sym->clearUsed(); } } } return; } if (ar->getPhase() == AnalysisResult::AnalyzeFinal) { // closure function's variable table (not containing function's) VariableTablePtr variables = m_func->getFunctionScope()->getVariables(); for (int i = 0; i < m_vars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); const string &name = param->getName(); // so we can assign values to them, instead of seeing CVarRef Symbol *sym = variables->getSymbol(name); if (sym && sym->isParameter()) { sym->setLvalParam(); } } } } FunctionScopeRawPtr container = getFunctionScope()->getContainingNonClosureFunction(); if (container && container->isStatic()) { m_func->getModifiers()->add(T_STATIC); } }
bool MethodStatement::hasRefParam() { for (int i = 0; i < m_params->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); if (param->isRef()) return true; } return false; }
void MethodStatement::fixupSelfAndParentTypehints(ClassScopePtr scope) { if (m_params) { for (int i = 0; i < m_params->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); param->fixupSelfAndParentTypehints(scope); } } }
ClosureExpression::ClosureExpression (EXPRESSION_CONSTRUCTOR_PARAMETERS, FunctionStatementPtr func, ExpressionListPtr vars) : Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(ClosureExpression)), m_func(func) { if (vars) { m_vars = ExpressionListPtr (new ExpressionList(vars->getScope(), vars->getLocation())); // push the vars in reverse order, not retaining duplicates std::set<string> seenBefore; // Because PHP is insane you can have a use variable with the same // name as a param name. // In that case, params win (which is different than zend but much easier) ExpressionListPtr bodyParams = m_func->getParams(); if (bodyParams) { int nParams = bodyParams->getCount(); for (int i = 0; i < nParams; i++) { ParameterExpressionPtr par( static_pointer_cast<ParameterExpression>((*bodyParams)[i])); seenBefore.insert(par->getName()); } } for (int i = vars->getCount() - 1; i >= 0; i--) { ParameterExpressionPtr param( dynamic_pointer_cast<ParameterExpression>((*vars)[i])); assert(param); if (seenBefore.find(param->getName().c_str()) == seenBefore.end()) { seenBefore.insert(param->getName().c_str()); m_vars->insertElement(param); } } if (m_vars) { m_values = ExpressionListPtr (new ExpressionList(m_vars->getScope(), m_vars->getLocation())); for (int i = 0; i < m_vars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); const string &name = param->getName(); SimpleVariablePtr var(new SimpleVariable(param->getScope(), param->getLocation(), name)); if (param->isRef()) { var->setContext(RefValue); } m_values->addElement(var); } assert(m_vars->getCount() == m_values->getCount()); } } }
void FunctionScope::outputCPPParamsCall(CodeGenerator &cg, AnalysisResultPtr ar, bool aggregateParams) { if (isVariableArgument()) { cg.printf("num_args, "); } bool userFunc = isUserFunction(); ExpressionListPtr params; if (userFunc) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); params = stmt->getParams(); } if (aggregateParams) { cg.printf("Array("); if (m_maxParam) { // param arrays are always vectors cg.printf("ArrayInit(%d, true).", m_maxParam); } } for (int i = 0; i < m_maxParam; i++) { if (i > 0) cg.printf(aggregateParams ? "." : ", "); bool isRef; if (userFunc) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); isRef = param->isRef(); if (aggregateParams) { cg.printf("set%s(%d, v_%s", isRef ? "Ref" : "", i, param->getName().c_str()); } else { cg.printf("%sv_%s%s", isRef ? "ref(" : "", param->getName().c_str(), isRef ? ")" : ""); } } else { isRef = isRefParam(i); if (aggregateParams) { cg.printf("set%s(%d, a%d", isRef ? "Ref" : "", i, i); } else { cg.printf("%sa%d%s", isRef ? "ref(" : "", i, isRef ? ")" : ""); } } if (aggregateParams) cg.printf(")"); } if (aggregateParams) { if (m_maxParam) cg.printf(".create()"); cg.printf(")"); } if (isVariableArgument()) { if (aggregateParams || m_maxParam > 0) cg.printf(","); cg.printf("args"); } }
void MethodStatement::outputCPPStaticMethodWrapper(CodeGenerator &cg, AnalysisResultPtr ar, const char *cls) { if (!m_modifiers->isStatic() || !m_stmt) return; CodeGenerator::Context context = cg.getContext(); FunctionScopePtr funcScope = m_funcScope.lock(); bool isWrapper = context == CodeGenerator::CppTypedParamsWrapperDecl || context == CodeGenerator::CppTypedParamsWrapperImpl; bool needsWrapper = isWrapper || (Option::HardTypeHints && funcScope->needsTypeCheckWrapper()); m_modifiers->outputCPP(cg, ar); TypePtr type = funcScope->getReturnType(); if (type) { type->outputCPPDecl(cg, ar); } else { cg_printf("void"); } cg_printf(" %s%s(", needsWrapper && !isWrapper ? Option::TypedMethodPrefix : Option::MethodPrefix, cg.formatLabel(m_name).c_str()); if (!isWrapper) cg.setContext(CodeGenerator::CppStaticMethodWrapper); funcScope->outputCPPParamsDecl(cg, ar, m_params, true); cg_printf(") { %s%s%s(", type ? "return " : "", needsWrapper && !isWrapper ? Option::TypedMethodImplPrefix : Option::MethodImplPrefix, cg.formatLabel(m_name).c_str()); cg_printf("%s%s::s_class_name", Option::ClassPrefix, cls); cg.setContext(context); if (funcScope->isVariableArgument()) { cg_printf(", num_args"); } if (m_params) { for (int i = 0; i < m_params->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); ASSERT(param); cg_printf(", %s%s", Option::VariablePrefix, param->getName().c_str()); } } if (funcScope->isVariableArgument()) { cg_printf(", args"); } cg_printf("); }\n"); if (!isWrapper && needsWrapper) { cg.setContext(CodeGenerator::CppTypedParamsWrapperDecl); outputCPPStaticMethodWrapper(cg, ar, cls); cg.setContext(context); } }
void FunctionStatement::onParse(AnalysisResultConstPtr ar, FileScopePtr scope) { // Correctness checks are normally done before adding function to scope. if (m_params) { for (int i = 0; i < m_params->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); if (param->hasTypeHint() && param->defaultValue()) { param->compatibleDefault(); } } } // note it's important to add to scope, not a pushed FunctionContainer, // as a function may be declared inside a class's method, yet this function // is a global function, not a class method. FunctionScopePtr fs = onInitialParse(ar, scope); FunctionScope::RecordFunctionInfo(m_name, fs); if (!scope->addFunction(ar, fs)) { m_ignored = true; return; } if (Option::PersistenceHook) { fs->setPersistent(Option::PersistenceHook(fs, scope)); } if (fs->isNative()) { if (getStmts()) { parseTimeFatal(Compiler::InvalidAttribute, "Native functions must not have an implementation body"); } if (m_params) { int nParams = m_params->getCount(); for (int i = 0; i < nParams; ++i) { auto param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); if (!param->hasUserType()) { parseTimeFatal(Compiler::InvalidAttribute, "Native function calls must have type hints " "on all args"); } } } if (getReturnTypeConstraint().empty()) { parseTimeFatal(Compiler::InvalidAttribute, "Native function %s() must have a return type hint", getOriginalName().c_str()); } } else if (!getStmts()) { parseTimeFatal(Compiler::InvalidAttribute, "Global function %s() must contain a body", getOriginalName().c_str()); } }
void MethodStatement::outputCPPTypeCheckWrapper(CodeGenerator &cg, AnalysisResultPtr ar) { FunctionScopePtr funcScope = getFunctionScope(); TypePtr type = funcScope->getReturnType(); bool isMethod = getClassScope(); string fname = isMethod ? funcScope->getName() : funcScope->getId(cg); funcScope->outputCPP(cg, ar); cg_printf("%s%s%s(", type ? "return " : "", (isMethod ? (m_modifiers->isStatic() ? Option::TypedMethodImplPrefix : Option::TypedMethodPrefix) : Option::TypedFunctionPrefix), fname.c_str()); if (getClassScope() && m_modifiers->isStatic()) { cg_printf("cls, "); } if (funcScope->isVariableArgument()) { cg_printf("num_args, "); } assert(m_params); for (int i = 0; i < m_params->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); ASSERT(param); if (i) cg_printf(", "); cg_printf("%s%s", Option::VariablePrefix, param->getName().c_str()); if (TypePtr spec = funcScope->getParamTypeSpec(i)) { if (Type::SameType(spec, funcScope->getParamType(i))) { if (spec->is(Type::KindOfArray)) { cg_printf(".getArrayData()"); } else { ClassScopePtr cls = ar->findClass(spec->getName()); assert(cls && !cls->isRedeclaring()); cg_printf(".getObjectData()"); } } } } if (funcScope->isVariableArgument()) { cg_printf(", args"); } cg_printf(");\n"); }
void FunctionScope::outputCPP(CodeGenerator &cg, AnalysisResultPtr ar) { for (int i = 0; i < m_callTempCountMax; i++) { cg_printf("Variant %s%d;\n", Option::EvalOrderTempPrefix, i); } ExpressionListPtr params = dynamic_pointer_cast<MethodStatement>(getStmt())->getParams(); /* Typecheck parameters */ for (size_t i = 0; i < m_paramTypes.size(); i++) { TypePtr specType = m_paramTypeSpecs[i]; if (!specType) continue; if (specType->is(Type::KindOfSome) || specType->is(Type::KindOfAny) || specType->is(Type::KindOfVariant)) continue; /* If there's any possible runtime conflict, this will be turned into * a Variant; if it hasn't been, then we don't need to worry */ if (!getParamType(i)->is(Type::KindOfVariant)) continue; ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); /* Insert runtime checks. */ if (specType->is(Type::KindOfArray)) { cg_printf("if(!%s%s.isArray())\n", Option::VariablePrefix, param->getName().c_str()); cg_printf(" throw_unexpected_argument_type" "(%d,\"%s\",\"array\",%s%s);\n", i, m_name.c_str(), Option::VariablePrefix, param->getName().c_str()); } else if (specType->is(Type::KindOfObject)) { cg_printf("if(!%s%s.instanceof(\"%s\"))\n", Option::VariablePrefix, param->getName().c_str(), specType->getName().c_str()); cg_printf(" throw_unexpected_argument_type(%d,\"%s\",\"%s\",%s%s);\n", i, m_name.c_str(), specType->getName().c_str(), Option::VariablePrefix, param->getName().c_str()); } else { Logger::Error("parameter %d of %s: improper type hint %s", i, m_name.c_str(), specType->toString().c_str()); return; } } BlockScope::outputCPP(cg, ar); }
void FunctionScope::getClosureUseVars( ParameterExpressionPtrIdxPairVec &useVars, bool filterUsed /* = true */) { useVars.clear(); if (!m_closureVars) return; assert(isClosure()); VariableTablePtr variables = getVariables(); for (int i = 0; i < m_closureVars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_closureVars)[i]); auto const& name = param->getName(); if (!filterUsed || variables->isUsed(name)) { useVars.push_back(ParameterExpressionPtrIdxPair(param, i)); } } }
ClosureExpression::ClosureExpression (EXPRESSION_CONSTRUCTOR_PARAMETERS, FunctionStatementPtr func, ExpressionListPtr vars) : Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(ClosureExpression)), m_func(func) { if (vars) { m_vars = ExpressionListPtr (new ExpressionList(vars->getScope(), vars->getLocation())); // push the vars in reverse order, not retaining duplicates std::set<string> seenBefore; for (int i = vars->getCount() - 1; i >= 0; i--) { ParameterExpressionPtr param( dynamic_pointer_cast<ParameterExpression>((*vars)[i])); assert(param); if (param->getName() == "this") { // "this" is automatically included. // Once we get rid of all the callsites, make this an error continue; } if (seenBefore.find(param->getName().c_str()) == seenBefore.end()) { seenBefore.insert(param->getName().c_str()); m_vars->insertElement(param); } } if (m_vars) { m_values = ExpressionListPtr (new ExpressionList(m_vars->getScope(), m_vars->getLocation())); for (int i = 0; i < m_vars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); const string &name = param->getName(); SimpleVariablePtr var(new SimpleVariable(param->getScope(), param->getLocation(), name)); if (param->isRef()) { var->setContext(RefValue); } m_values->addElement(var); } assert(m_vars->getCount() == m_values->getCount()); } } }
TypePtr ClosureExpression::inferTypes(AnalysisResultPtr ar, TypePtr type, bool coerce) { m_func->inferTypes(ar); if (m_values) m_values->inferAndCheck(ar, Type::Some, false); if (m_vars) { // containing function's variable table (not closure function's) VariableTablePtr variables = getScope()->getVariables(); for (int i = 0; i < m_vars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); string name = param->getName(); if (param->isRef()) { variables->forceVariant(ar, name, VariableTable::AnyVars); } } } return Type::CreateObjectType("Closure"); }
void ClosureExpression::analyzeProgram(AnalysisResultPtr ar) { m_func->analyzeProgram(ar); if (m_vars) { m_values->analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeAll) { m_func->getFunctionScope()->setClosureVars(m_vars); // closure function's variable table (not containing function's) VariableTablePtr variables = m_func->getFunctionScope()->getVariables(); for (int i = 0; i < m_vars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); string name = param->getName(); { Symbol *sym = variables->addSymbol(name); sym->setClosureVar(); if (param->isRef()) { sym->setRefClosureVar(); } else { sym->clearRefClosureVar(); } } } return; } if (ar->getPhase() == AnalysisResult::AnalyzeFinal) { // closure function's variable table (not containing function's) VariableTablePtr variables = m_func->getFunctionScope()->getVariables(); for (int i = 0; i < m_vars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); string name = param->getName(); // so we can assign values to them, instead of seeing CVarRef Symbol *sym = variables->getSymbol(name); if (sym && sym->isParameter()) { sym->setLvalParam(); } } } } }
ClosureExpression::ClosureExpression (EXPRESSION_CONSTRUCTOR_PARAMETERS, FunctionStatementPtr func, ExpressionListPtr vars) : Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES), m_func(func) { if (vars) { m_vars = ExpressionListPtr (new ExpressionList(vars->getScope(), vars->getLocation(), KindOfExpressionList)); // push the vars in reverse order, not retaining duplicates set<string> seenBefore; for (int i = vars->getCount() - 1; i >= 0; i--) { ParameterExpressionPtr param( dynamic_pointer_cast<ParameterExpression>((*vars)[i])); ASSERT(param); if (seenBefore.find(param->getName().c_str()) == seenBefore.end()) { seenBefore.insert(param->getName().c_str()); m_vars->insertElement(param); } } if (m_vars) { m_values = ExpressionListPtr (new ExpressionList(m_vars->getScope(), m_vars->getLocation(), KindOfExpressionList)); for (int i = 0; i < m_vars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); string name = param->getName(); SimpleVariablePtr var(new SimpleVariable(param->getScope(), param->getLocation(), KindOfSimpleVariable, name)); if (param->isRef()) { var->setContext(RefValue); } m_values->addElement(var); } } } }
void ClosureExpression::initializeValuesFromVars() { if (!m_vars) return; m_values = ExpressionListPtr (new ExpressionList(m_vars->getScope(), m_vars->getLocation())); for (int i = 0; i < m_vars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); const string &name = param->getName(); SimpleVariablePtr var(new SimpleVariable(param->getScope(), param->getLocation(), name)); if (param->isRef()) { var->setContext(RefValue); } m_values->addElement(var); } assert(m_vars->getCount() == m_values->getCount()); }
void FunctionScope::setParamSpecs(AnalysisResultPtr ar) { if (m_maxParam > 0 && m_stmt) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); ExpressionListPtr params = stmt->getParams(); for (int i = 0; i < m_maxParam; i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); TypePtr specType = param->getTypeSpec(ar, false); if (specType && !specType->is(Type::KindOfSome) && !specType->is(Type::KindOfVariant)) { m_paramTypeSpecs[i] = specType; } ExpressionPtr exp = param->defaultValue(); if (exp) { m_paramDefaults[i] = exp->getText(false, false, ar); } } } }
void MethodStatement::outputParamArrayCreate(CodeGenerator &cg, bool checkRef) { int n = m_params->getCount(); ASSERT(n > 0); cg_printf("array_create%d(%d, ", n, n); for (int i = 0; i < n; i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); const string ¶mName = param->getName(); cg_printf("%d, ", i); if (checkRef && param->isRef()) { ASSERT(false); cg_printf("ref(%s%s)", Option::VariablePrefix, paramName.c_str()); } else { cg_printf("%s%s", Option::VariablePrefix, paramName.c_str()); } if (i < n - 1) { cg_printf(", "); } else { cg_printf(")"); } } }
void MethodStatement::outputCPPStaticMethodWrapper(CodeGenerator &cg, AnalysisResultPtr ar, const char *cls) { if (!m_modifiers->isStatic() || !m_stmt) return; FunctionScopePtr funcScope = m_funcScope.lock(); ar->pushScope(funcScope); m_modifiers->outputCPP(cg, ar); TypePtr type = funcScope->getReturnType(); if (type) { type->outputCPPDecl(cg, ar); } else { cg.printf("void"); } cg.printf(" %s%s(", Option::MethodPrefix, m_name.c_str()); CodeGenerator::Context old = cg.getContext(); cg.setContext(CodeGenerator::CppStaticMethodWrapper); funcScope->outputCPPParamsDecl(cg, ar, m_params, true); cg.setContext(old); cg.printf(") { %s%s%s(\"%s\"", type ? "return " : "", Option::MethodImplPrefix, m_name.c_str(), cls); if (funcScope->isVariableArgument()) { cg.printf(", num_args"); } if (m_params) { for (int i = 0; i < m_params->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); ASSERT(param); cg.printf(", %s%s", Option::VariablePrefix, param->getName().c_str()); } } if (funcScope->isVariableArgument()) { cg.printf(", args"); } cg.printf("); }\n"); ar->popScope(); }
void MethodStatement::outputCPPArgInjections(CodeGenerator &cg, AnalysisResultPtr ar, const char *name, ClassScopePtr cls, FunctionScopePtr funcScope) { if (cg.getOutput() != CodeGenerator::SystemCPP) { if (m_params) { int n = m_params->getCount(); cg_printf("INTERCEPT_INJECTION(\"%s\", ", name); if (Option::GenArrayCreate && !hasRefParam()) { ar->m_arrayIntegerKeySizes.insert(n); outputParamArrayCreate(cg, true); cg_printf(", %s);\n", funcScope->isRefReturn() ? "ref(r)" : "r"); } else { cg_printf("(Array(ArrayInit(%d, true)", n); for (int i = 0; i < n; i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); const string ¶mName = param->getName(); cg_printf(".set%s(%d, %s%s)", param->isRef() ? "Ref" : "", i, Option::VariablePrefix, paramName.c_str()); } cg_printf(".create())), %s);\n", funcScope->isRefReturn() ? "ref(r)" : "r"); } } else { cg_printf("INTERCEPT_INJECTION(\"%s\", null_array, %s);\n", name, funcScope->isRefReturn() ? "ref(r)" : "r"); } } if (Option::GenRTTIProfileData && m_params) { for (int i = 0; i < m_params->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); if (param->hasRTTI()) { const string ¶mName = param->getName(); int id = ar->getParamRTTIEntryId(cls, funcScope, paramName); if (id != -1) { cg_printf("RTTI_INJECTION(%s%s, %d);\n", Option::VariablePrefix, paramName.c_str(), id); } } } } }
ExpressionPtr FunctionCall::inliner(AnalysisResultConstPtr ar, ExpressionPtr obj, std::string localThis) { FunctionScopePtr fs = getFunctionScope(); if (m_noInline || !fs || fs == m_funcScope || !m_funcScope->getStmt()) { return ExpressionPtr(); } BlockScope::s_jobStateMutex.lock(); if (m_funcScope->getMark() == BlockScope::MarkProcessing) { fs->setForceRerun(true); BlockScope::s_jobStateMutex.unlock(); return ExpressionPtr(); } ReadLock lock(m_funcScope->getInlineMutex()); BlockScope::s_jobStateMutex.unlock(); if (!m_funcScope->getInlineAsExpr()) { return ExpressionPtr(); } if (m_funcScope->getInlineSameContext() && m_funcScope->getContainingClass() && m_funcScope->getContainingClass() != getClassScope()) { /* The function contains a context sensitive construct such as call_user_func (context sensitive because it could call array('parent', 'foo')) so its not safe to inline it into a different context. */ return ExpressionPtr(); } MethodStatementPtr m (dynamic_pointer_cast<MethodStatement>(m_funcScope->getStmt())); VariableTablePtr vt = fs->getVariables(); int nAct = m_params ? m_params->getCount() : 0; int nMax = m_funcScope->getMaxParamCount(); if (nAct < m_funcScope->getMinParamCount() || !m->getStmts()) { return ExpressionPtr(); } InlineCloneInfo info(m_funcScope); info.elist = ExpressionListPtr(new ExpressionList( getScope(), getLocation(), ExpressionList::ListKindWrapped)); std::ostringstream oss; oss << fs->nextInlineIndex() << "_" << m_name << "_"; std::string prefix = oss.str(); if (obj) { info.callWithThis = true; if (!obj->isThis()) { SimpleVariablePtr var (new SimpleVariable(getScope(), obj->getLocation(), prefix + "this")); var->updateSymbol(SimpleVariablePtr()); var->getSymbol()->setHidden(); var->getSymbol()->setUsed(); var->getSymbol()->setReferenced(); AssignmentExpressionPtr ae (new AssignmentExpression(getScope(), obj->getLocation(), var, obj, false)); info.elist->addElement(ae); info.sepm[var->getName()] = var; info.localThis = var->getName(); } } else { if (m_classScope) { if (!m_funcScope->isStatic()) { ClassScopeRawPtr oCls = getOriginalClass(); FunctionScopeRawPtr oFunc = getOriginalFunction(); if (oCls && !oFunc->isStatic() && (oCls == m_classScope || oCls->derivesFrom(ar, m_className, true, false))) { info.callWithThis = true; info.localThis = localThis; } } if (!isSelf() && !isParent() && !isStatic()) { info.staticClass = m_className; } } } ExpressionListPtr plist = m->getParams(); int i; for (i = 0; i < nMax || i < nAct; i++) { ParameterExpressionPtr param (i < nMax ? dynamic_pointer_cast<ParameterExpression>((*plist)[i]) : ParameterExpressionPtr()); ExpressionPtr arg = i < nAct ? (*m_params)[i] : Clone(param->defaultValue(), getScope()); SimpleVariablePtr var (new SimpleVariable(getScope(), (i < nAct ? arg.get() : this)->getLocation(), prefix + (param ? param->getName() : lexical_cast<string>(i)))); var->updateSymbol(SimpleVariablePtr()); var->getSymbol()->setHidden(); var->getSymbol()->setUsed(); var->getSymbol()->setReferenced(); bool ref = (i < nMax && m_funcScope->isRefParam(i)) || arg->hasContext(RefParameter); arg->clearContext(RefParameter); AssignmentExpressionPtr ae (new AssignmentExpression(getScope(), arg->getLocation(), var, arg, ref)); info.elist->addElement(ae); if (i < nAct && (ref || !arg->isScalar())) { info.sepm[var->getName()] = var; } } if (cloneStmtsForInline(info, m->getStmts(), prefix, ar, getFunctionScope()) <= 0) { info.elist->addElement(makeConstant(ar, "null")); } if (info.sepm.size()) { ExpressionListPtr unset_list (new ExpressionList(getScope(), getLocation())); for (StringToExpressionPtrMap::iterator it = info.sepm.begin(), end = info.sepm.end(); it != end; ++it) { ExpressionPtr var = it->second->clone(); var->clearContext((Context)(unsigned)-1); unset_list->addElement(var); } ExpressionPtr unset( new UnaryOpExpression(getScope(), getLocation(), unset_list, T_UNSET, true)); i = info.elist->getCount(); ExpressionPtr ret = (*info.elist)[--i]; if (ret->isScalar()) { info.elist->insertElement(unset, i); } else { ExpressionListPtr result_list (new ExpressionList(getScope(), getLocation(), ExpressionList::ListKindLeft)); if (ret->hasContext(LValue)) { result_list->setContext(LValue); result_list->setContext(ReturnContext); } result_list->addElement(ret); result_list->addElement(unset); (*info.elist)[i] = result_list; } } recomputeEffects(); return replaceValue(info.elist); }