예제 #1
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);
    }
  }
}
TypePtr ClosureExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
                                      bool coerce) {
  if (m_vars) {
    assert(m_values && m_values->getCount() == m_vars->getCount());

    // containing function's variable table (not closure function's)
    VariableTablePtr variables = getScope()->getVariables();

    // closure function's variable table
    VariableTablePtr cvariables = m_func->getFunctionScope()->getVariables();

    // force all reference use vars into variant for this function scope
    for (int i = 0; i < m_vars->getCount(); i++) {
      ParameterExpressionPtr param =
        dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
      const string &name = param->getName();
      if (param->isRef()) {
        variables->forceVariant(ar, name, VariableTable::AnyVars);
      }
    }

    // infer the types of the values
    m_values->inferAndCheck(ar, Type::Some, false);

    // coerce the types inferred from m_values into m_vars
    for (int i = 0; i < m_vars->getCount(); i++) {
      ExpressionPtr value = (*m_values)[i];
      ParameterExpressionPtr var =
        dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
      assert(!var->getExpectedType());
      assert(!var->getImplementedType());
      if (var->isRef()) {
        var->setActualType(Type::Variant);
      } else {
        TypePtr origVarType(var->getActualType() ?
                            var->getActualType() : Type::Some);
        var->setActualType(Type::Coerce(ar, origVarType, value->getType()));
      }
    }

    {
      // this lock isn't technically needed for thread-safety, since
      // the dependencies are all set up. however, the lock assertions
      // will fail if we don't acquire it.
      GET_LOCK(m_func->getFunctionScope());

      // bootstrap the closure function's variable table with
      // the types from m_vars
      for (int i = 0; i < m_vars->getCount(); i++) {
        ParameterExpressionPtr param =
          dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
        const string &name = param->getName();
        cvariables->addParamLike(name, param->getType(), ar,
                                 shared_from_this(),
                                 getScope()->isFirstPass());
      }
    }
  }
  return s_ClosureType;
}