compiler/AST/foralls.cpp
/*
When we are dealing with a recursive parallel iterator, we call
fsIterYieldType() while resolving it. At that time, IteratorInfo
has not been created yet. Also the yield type is not yet available
anywhere, because it is the type of a tuple of the original return type
plus one component per shadow variable.

Ex. standalone iter walkdirs() in FileSystem module, as tested by:
  test/library/standard/FileSystem/filerator/bradc/findfiles-par.chpl

Therefore we compute this extended yield type manually.
*/
When we are dealing with a recursive parallel iterator, we call
fsIterYieldType() while resolving it. At that time, IteratorInfo
has not been created yet. Also the yield type is not yet available
anywhere, because it is the type of a tuple of the original return type
plus one component per shadow variable.

Ex.

Therefore we compute this extended yield type manually.
When we are dealing with a recursive parallel iterator we call fsIterYieldType () while resolving it . At that time IteratorInfo has not been created yet . Also the yield type is not yet available anywhere because it is the type of a tuple of the original return type plus one component per shadow variable . Ex . Therefore we compute this extended yield type manually .
static QualifiedType buildIterYieldType(ForallStmt* fs, FnSymbol* iterFn, FnSymbol* origIterFn) {
  if (fs->numShadowVars() == 0) {
    QualifiedType result(iterFn->getReturnSymbol()->type);
    return result;
  }
  CallExpr* constup = new CallExpr("_type_construct__tuple");
  bool alreadyResolved = origIterFn->isResolved();
  QualifiedType origQt = fsIterYieldType(fs, origIterFn, NULL, alreadyResolved);
  Type* origYieldedType = origQt.type();
  INT_ASSERT(origYieldedType && origYieldedType != dtUnknown);
  constup->insertAtTail(origYieldedType->symbol);
  for_shadow_vars(svar, temp, fs) {
    Symbol* ovar = NULL;
    switch (svar->intent) {
      case TFI_DEFAULT:
      case TFI_CONST:
      case TFI_IN_PARENT:
      case TFI_IN:
      case TFI_CONST_IN:
      case TFI_REF:
      case TFI_CONST_REF:
        ovar = svar->outerVarSym();
        break;
      case TFI_REDUCE:
        USR_FATAL_CONT(svar, "Reduce intents are currently not implemented"
          " for forall- or for-loops over recursive parallel iterators");
        USR_PRINT(iterFn, "the parallel iterator is here");
        USR_STOP();
        break;
      case TFI_REDUCE_OP:
      case TFI_REDUCE_PARENT_AS:
      case TFI_REDUCE_PARENT_OP:
        break;
      case TFI_TASK_PRIVATE:
        USR_FATAL_CONT(svar,
          "Task-private variables are currently not implemented"
          " for forall- or for-loops over recursive parallel iterators");
        USR_PRINT(iterFn, "the parallel iterator is here");
        USR_STOP();
        break;
    }
    INT_ASSERT(ovar != NULL);
    INT_ASSERT(ovar->type != dtUnknown);
    constup->insertAtTail(ovar->type->getRefType()->symbol);
  }
  int numComponents = constup->numActuals();
  constup->insertAtHead(new_IntSymbol(numComponents));
  fs->insertBefore(constup);
  resolveCall(constup);
  constup->remove();
  QualifiedType result(constup->qualType().type());
  return result;
}
static QualifiedType buildIterYieldType ( ForallStmt * fs , FnSymbol * iterFn , FnSymbol * origIterFn ) { if ( fs -> numShadowVars ( ) == 0 ) { QualifiedType result ( iterFn -> getReturnSymbol ( ) -> type ) ; return result ; } CallExpr * constup = new CallExpr ( " " ) ; bool alreadyResolved = origIterFn -> isResolved ( ) ; QualifiedType origQt = fsIterYieldType ( fs , origIterFn , NULL , alreadyResolved ) ; Type * origYieldedType = origQt . type ( ) ; INT_ASSERT ( origYieldedType && origYieldedType != dtUnknown ) ; constup -> insertAtTail ( origYieldedType -> symbol ) ; for_shadow_vars ( svar , temp , fs ) { Symbol * ovar = NULL ; switch ( svar -> intent ) { case TFI_DEFAULT : case TFI_CONST : case TFI_IN_PARENT : case TFI_IN : case TFI_CONST_IN : case TFI_REF : case TFI_CONST_REF : ovar = svar -> outerVarSym ( ) ; break ; case TFI_REDUCE : USR_FATAL_CONT ( svar , " " " " ) ; USR_PRINT ( iterFn , " " ) ; USR_STOP ( ) ; break ; case TFI_REDUCE_OP : case TFI_REDUCE_PARENT_AS : case TFI_REDUCE_PARENT_OP : break ; case TFI_TASK_PRIVATE : USR_FATAL_CONT ( svar , " " " " ) ; USR_PRINT ( iterFn , " " ) ; USR_STOP ( ) ; break ; } INT_ASSERT ( ovar != NULL ) ; INT_ASSERT ( ovar -> type != dtUnknown ) ; constup -> insertAtTail ( ovar -> type -> getRefType ( ) -> symbol ) ; } int numComponents = constup -> numActuals ( ) ; constup -> insertAtHead ( new_IntSymbol ( numComponents ) ) ; fs -> insertBefore ( constup ) ; resolveCall ( constup ) ; constup -> remove ( ) ; QualifiedType result ( constup -> qualType ( ) . type ( ) ) ; return result ; }
When we are dealing with a recursive parallel iterator, we call
fsIterYieldType() while resolving it.
When we are dealing with a recursive parallel iterator we call fsIterYieldType () while resolving it .
// The iterator has not undergone extendLeader(). // It still yields whatever the user wrote. // Its return symbol is still in tact. // What is the right qualifier? // Otherwise, build the tuple mocking what iterFn yields, supposedly. // Yield type must have been declared by user for recursive iterator, // and the function that declaration is attached to is origIterFn. // The other tuple components are refs to shadow variables, // so their types come from respective outer variables. // ... except for reduce intents - they are TODO. // The error should have been issued above upon TFI_REDUCE. // task-private variables are TODO too. // Resolve it now. // What is the right qualifier?