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