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("))");
}
Example #2
0
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 &params = *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));
  }
}
Example #4
0
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);
    }
  }
}
Example #6
0
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);
        }
    }
}
Example #7
0
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();
}
Example #8
0
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 &paramName = 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);
    }
  }
}
Example #9
0
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);
      }
    }
  }
}
Example #10
0
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);
  }

}
Example #12
0
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;
}
Example #13
0
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);
    }
  }
}
Example #14
0
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());
    }
  }
}
Example #15
0
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);
  }
}
Example #17
0
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");
}
Example #19
0
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);
}
Example #20
0
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);
      }
    }
  }
}
Example #25
0
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());
}
Example #26
0
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 &paramName = 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(")");
    }
  }
}
Example #28
0
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 &paramName = 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 &paramName = 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);
        }
      }
    }
  }
}
Example #30
0
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);
}