Exemple #1
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();
  }
}
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;
}
void MethodStatement::inferFunctionTypes(AnalysisResultPtr ar) {
  IMPLEMENT_INFER_AND_CHECK_ASSERT(getFunctionScope());

  FunctionScopeRawPtr funcScope = getFunctionScope();
  bool pseudoMain = funcScope->inPseudoMain();

  if (m_stmt && funcScope->isFirstPass()) {
    if (pseudoMain ||
        funcScope->getReturnType() ||
        m_stmt->hasRetExp()) {
      bool lastIsReturn = false;
      if (m_stmt->getCount()) {
        StatementPtr lastStmt = (*m_stmt)[m_stmt->getCount()-1];
        if (lastStmt->is(Statement::KindOfReturnStatement)) {
          lastIsReturn = true;
        }
      }
      if (!lastIsReturn) {
        ExpressionPtr constant =
          makeScalarExpression(ar, funcScope->inPseudoMain() ?
                               Variant(1) :
                               Variant(Variant::NullInit()));
        ReturnStatementPtr returnStmt =
          ReturnStatementPtr(
            new ReturnStatement(getScope(), getLocation(), constant));
        m_stmt->addElement(returnStmt);
      }
    }
  }

  if (m_params) {
    m_params->inferAndCheck(ar, Type::Any, false);
  }

  // must also include params and use vars if this is a generator. note: we are
  // OK reading the params from the AST nodes of the original generator
  // function, since we have the dependency links set up
  if (funcScope->isGenerator()) {
    // orig function params
    MethodStatementRawPtr m = getOrigGeneratorFunc();
    assert(m);

    VariableTablePtr variables = funcScope->getVariables();
    ExpressionListPtr params = m->getParams();
    if (params) {
      for (int i = 0; i < params->getCount(); i++) {
        ParameterExpressionPtr param =
          dynamic_pointer_cast<ParameterExpression>((*params)[i]);
        const string &name = param->getName();
        assert(!param->isRef() || param->getType()->is(Type::KindOfVariant));
        variables->addParamLike(name, param->getType(), ar, param,
                                funcScope->isFirstPass());
      }
    }

    // use vars
    ExpressionListPtr useVars = m->getFunctionScope()->getClosureVars();
    if (useVars) {
      for (int i = 0; i < useVars->getCount(); i++) {
        ParameterExpressionPtr param =
          dynamic_pointer_cast<ParameterExpression>((*useVars)[i]);
        const string &name = param->getName();
        assert(!param->isRef() || param->getType()->is(Type::KindOfVariant));
        variables->addParamLike(name, param->getType(), ar, param,
                                funcScope->isFirstPass());
      }
    }
  }

  if (m_stmt) {
    m_stmt->inferTypes(ar);
  }
}