compiler/resolution/wrappers.cpp
// info is used to handle out-of-order named arguments
// if there aren't any out-of-order arguments (as with promotion)
// it can be NULL.
info is used to handle out-of-order named arguments
if there aren't any out-of-order arguments (as with promotion)
it can be NULL.
info is used to handle out - of - order named arguments if there aren ' t any out - of - order arguments ( as with promotion ) it can be NULL .
static void addDefaultsAndReorder(FnSymbol *fn,
                                CallExpr* call,
                                CallInfo* info,
                                std::vector<ArgSymbol*>& actualFormals,
                                bool resolveNewCode) {
  int numFormals = fn->numFormals();
  std::vector<Symbol*> newActuals(numFormals);
  std::vector<int8_t> newActualDefaulted(numFormals);
  int i = 0;
  for_formals(formal, fn) {
    bool actualProvidedForFormal = false;
    Symbol* actualSym = NULL;
    if (info) {
      int j = 0;
      for_vector(ArgSymbol, arg, actualFormals) {
        if (arg == formal) {
          actualSym = info->actuals.v[j];
        }
        j++;
      }
    } else {
      int j = 0;
      for_actuals(actual, call) {
        if (actualFormals[j] == formal) {
          actualProvidedForFormal = true;
          if (SymExpr* se = toSymExpr(actual))
            actualSym = se->symbol();
        }
        j++;
      }
    }
    newActuals[i] = actualSym;
    newActualDefaulted[i] = !actualProvidedForFormal;
    i++;
  }
  for_actuals(actual, call) {
    actual->remove();
  }
  SymbolMap copyMap;
  BlockStmt* body = new BlockStmt(BLOCK_SCOPELESS);
  call->getStmtExpr()->insertBefore(body);
  i = 0;
  for_formals(formal, fn) {
    if (newActuals[i] == NULL) {
      newActuals[i] = createDefaultedActual(fn, formal, call, body, copyMap);
    } else if (formal->intent & INTENT_FLAG_IN &&
               formal->getValType()->symbol->hasFlag(FLAG_HAS_RUNTIME_TYPE) &&
               mustUseRuntimeTypeDefault(formal) &&
               isNestedNewOrDefault(fn, call) == false) {
      Symbol* newDef = insertRuntimeTypeDefault(fn, formal, call, body, copyMap, newActuals[i]);
      newActuals[i] = newDef;
    }
    copyMap.put(formal, newActuals[i]);
    i++;
  }
  update_symbols(body, &copyMap);
  normalize(body);
  if (resolveNewCode) {
    resolveBlockStmt(body);
    for (i = 0; i < numFormals; i++) {
      if (newActualDefaulted[i])
        if (Symbol* param = paramMap.get(newActuals[i]))
          newActuals[i] = param;
    }
    i = 0;
    for_formals(formal, fn) {
      if (newActualDefaulted[i]) {
        Symbol* actual = newActuals[i];
        bool actualIsTypeAlias = actual->hasFlag(FLAG_TYPE_VARIABLE);
        bool formalIsTypeAlias = formal->hasFlag(FLAG_TYPE_VARIABLE);
        bool formalIsParam     = formal->hasFlag(FLAG_INSTANTIATED_PARAM) ||
                                 formal->intent == INTENT_PARAM;
        Type* actualValType = actual->getValType();
        Type* formalValType = formal->getValType();
        bool promotes = false;
        bool dispatches = canDispatch(actualValType, actual,
                                      formalValType, fn,
                                      &promotes, NULL, formalIsParam);
        if (actualIsTypeAlias != formalIsTypeAlias ||
            dispatches == false ||
            promotes == true) {
          USR_FATAL_CONT(formal, "Default expression not convertible to formal type");
        }
      }
      i++;
    }
  }
  for_vector(Symbol, actual, newActuals) {
    call->insertAtTail(actual);
  }
  reset_ast_loc(body, call);
  body->flattenAndRemove();
}
static void addDefaultsAndReorder ( FnSymbol * fn , CallExpr * call , CallInfo * info , std :: vector < ArgSymbol * > & actualFormals , bool resolveNewCode ) { int numFormals = fn -> numFormals ( ) ; std :: vector < Symbol * > newActuals ( numFormals ) ; std :: vector < int8_t > newActualDefaulted ( numFormals ) ; int i = 0 ; for_formals ( formal , fn ) { bool actualProvidedForFormal = false ; Symbol * actualSym = NULL ; if ( info ) { int j = 0 ; for_vector ( ArgSymbol , arg , actualFormals ) { if ( arg == formal ) { actualSym = info -> actuals . v [ j ] ; } j ++ ; } } else { int j = 0 ; for_actuals ( actual , call ) { if ( actualFormals [ j ] == formal ) { actualProvidedForFormal = true ; if ( SymExpr * se = toSymExpr ( actual ) ) actualSym = se -> symbol ( ) ; } j ++ ; } } newActuals [ i ] = actualSym ; newActualDefaulted [ i ] = ! actualProvidedForFormal ; i ++ ; } for_actuals ( actual , call ) { actual -> remove ( ) ; } SymbolMap copyMap ; BlockStmt * body = new BlockStmt ( BLOCK_SCOPELESS ) ; call -> getStmtExpr ( ) -> insertBefore ( body ) ; i = 0 ; for_formals ( formal , fn ) { if ( newActuals [ i ] == NULL ) { newActuals [ i ] = createDefaultedActual ( fn , formal , call , body , copyMap ) ; } else if ( formal -> intent & INTENT_FLAG_IN && formal -> getValType ( ) -> symbol -> hasFlag ( FLAG_HAS_RUNTIME_TYPE ) && mustUseRuntimeTypeDefault ( formal ) && isNestedNewOrDefault ( fn , call ) == false ) { Symbol * newDef = insertRuntimeTypeDefault ( fn , formal , call , body , copyMap , newActuals [ i ] ) ; newActuals [ i ] = newDef ; } copyMap . put ( formal , newActuals [ i ] ) ; i ++ ; } update_symbols ( body , & copyMap ) ; normalize ( body ) ; if ( resolveNewCode ) { resolveBlockStmt ( body ) ; for ( i = 0 ; i < numFormals ; i ++ ) { if ( newActualDefaulted [ i ] ) if ( Symbol * param = paramMap . get ( newActuals [ i ] ) ) newActuals [ i ] = param ; } i = 0 ; for_formals ( formal , fn ) { if ( newActualDefaulted [ i ] ) { Symbol * actual = newActuals [ i ] ; bool actualIsTypeAlias = actual -> hasFlag ( FLAG_TYPE_VARIABLE ) ; bool formalIsTypeAlias = formal -> hasFlag ( FLAG_TYPE_VARIABLE ) ; bool formalIsParam = formal -> hasFlag ( FLAG_INSTANTIATED_PARAM ) || formal -> intent == INTENT_PARAM ; Type * actualValType = actual -> getValType ( ) ; Type * formalValType = formal -> getValType ( ) ; bool promotes = false ; bool dispatches = canDispatch ( actualValType , actual , formalValType , fn , & promotes , NULL , formalIsParam ) ; if ( actualIsTypeAlias != formalIsTypeAlias || dispatches == false || promotes == true ) { USR_FATAL_CONT ( formal , " " ) ; } } i ++ ; } } for_vector ( Symbol , actual , newActuals ) { call -> insertAtTail ( actual ) ; } reset_ast_loc ( body , call ) ; body -> flattenAndRemove ( ) ; }
info is used to handle out-of-order named arguments
if there aren't any out-of-order arguments (as with promotion)
it can be NULL.
info is used to handle out - of - order named arguments if there aren ' t any out - of - order arguments ( as with promotion ) it can be NULL .
// Gather the actuals into newActuals with NULLs where // we need to fill in a default. This also happens // to address the need to reorder the actuals. // Remove the actuals from the call // (we'll add them back again in a moment) // Create a copyMap to handle cases like //   proc f(a, b=a) // where a formal argument's default value refers to a previous formal // Create a Block to store the default values // We'll flatten this back out again in a minute. // Fill in the NULLs in newActuals with the appropriate default argument. // Fill it in with a default argument. // In-intent formals with runtime types need to be handled carefully in // order to preserve the correct runtime type. // TODO -- should this be adding a reference to the original actual? // Apply the map copyMap to the block storing defaults // Normalize and resolve the new code in the BlockStmt. // Resolve the new code // This is important in the usual case where we are adding // some calls before a call that is being resolved. The rest // of resolution will assume that this new code is already // resolved, since it is before what is currently being handled. // resolveBlockStmt might remove DefExprs for params // in that event, we need to update them here. // Check that newActuals are coercible to the formals // Use the value types to work around issues with string literals. // Value types should be sufficient for the check needed here, though. // Add the actuals back to the call. // Adjust AST location to be call site // Flatten body