2023-09-14 19:43:13 +03:00
# include "../Utils/leak_detector.h"
# include <cstdio>
# include <map>
# include <string>
# include <algorithm>
# include "dvm.h"
# include "verifications.h"
# include "../ParallelizationRegions/ParRegions.h"
# include "../Utils/utils.h"
# include "../Utils/SgUtils.h"
# include "../Utils/errors.h"
using std : : vector ;
using std : : map ;
using std : : pair ;
using std : : string ;
using std : : wstring ;
using std : : make_pair ;
using std : : set ;
bool EndDoLoopChecker ( SgFile * file , vector < Messages > & currMessages )
{
int funcNum = file - > numberOfFunctions ( ) ;
bool checkOK = true ;
for ( int i = 0 ; i < funcNum ; + + i )
{
SgStatement * st = file - > functions ( i ) ;
SgStatement * lastNode = st - > lastNodeOfStmt ( ) ;
while ( st ! = lastNode )
{
if ( st = = NULL )
{
__spf_print ( 1 , " internal error in analysis, parallel directives will not be generated for this file! \n " ) ;
break ;
}
if ( st - > variant ( ) = = CONTAINS_STMT )
break ;
if ( st - > variant ( ) = = FOR_NODE )
{
SgForStmt * currSt = ( SgForStmt * ) st ;
if ( currSt - > isEnddoLoop ( ) = = 0 )
{
__spf_print ( 1 , " ERROR: Loop on line %d does not have END DO \n " , st - > lineNumber ( ) ) ;
currMessages . push_back ( Messages ( ERROR , st - > lineNumber ( ) , R51 , L " This loop does not have END DO format " , 1018 ) ) ;
checkOK = false ;
}
}
if ( st - > variant ( ) = = FORALL_NODE | | st - > variant ( ) = = FORALL_STAT | |
st - > variant ( ) = = WHERE_BLOCK_STMT | | st - > variant ( ) = = WHERE_NODE )
{
__spf_print ( 1 , " ERROR: Loop on line %d does not have END DO \n " , st - > lineNumber ( ) ) ;
currMessages . push_back ( Messages ( ERROR , st - > lineNumber ( ) , R50 , L " This loop does not have END DO format " , 1018 ) ) ;
checkOK = false ;
}
if ( st - > variant ( ) = = WHILE_NODE )
{
auto last = st - > lastNodeOfStmt ( ) ;
auto str = string ( last - > unparse ( ) ) ;
convertToLower ( str ) ;
if ( last - > variant ( ) ! = CONTROL_END | | str . find ( " enddo " ) = = string : : npos )
{
__spf_print ( 1 , " ERROR: Loop on line %d does not have END DO \n " , st - > lineNumber ( ) ) ;
currMessages . push_back ( Messages ( ERROR , st - > lineNumber ( ) , R50 , L " This loop does not have END DO format " , 1018 ) ) ;
checkOK = false ;
}
}
st = st - > lexNext ( ) ;
}
}
return checkOK ;
}
bool DvmDirectiveChecker ( SgFile * file , map < string , vector < int > > & errors , const int keepDvmDirectives , const int ignoreDvmChecker )
{
if ( keepDvmDirectives ! = 0 )
return true ;
int funcNum = file - > numberOfFunctions ( ) ;
bool checkOK = true ;
__spf_print ( 1 , " ignoreDvmChecker = %d \n " , ignoreDvmChecker ) ;
for ( int i = 0 ; i < funcNum ; + + i )
{
SgStatement * st = file - > functions ( i ) ;
SgStatement * lastNode = st - > lastNodeOfStmt ( ) ;
for ( ; st ! = lastNode ; st = st - > lexNext ( ) )
{
if ( st - > variant ( ) = = CONTAINS_STMT )
break ;
if ( isDVM_stat ( st ) & & ( st - > variant ( ) ! = DVM_INTERVAL_DIR & & st - > variant ( ) ! = DVM_ENDINTERVAL_DIR ) )
{
errors [ st - > fileName ( ) ] . push_back ( st - > lineNumber ( ) ) ;
checkOK = false ;
}
}
}
return checkOK ;
}
bool EquivalenceChecker ( SgFile * file , const string & fileName , const vector < ParallelRegion * > & regions , map < string , vector < Messages > > & currMessages )
{
int funcNum = file - > numberOfFunctions ( ) ;
bool checkOK = true ;
for ( int i = 0 ; i < funcNum ; + + i )
{
SgStatement * st = file - > functions ( i ) ;
SgStatement * lastNode = st - > lastNodeOfStmt ( ) ;
int lastLine = 1 ;
while ( st ! = lastNode )
{
lastLine = st - > lineNumber ( ) ;
if ( st = = NULL )
{
__spf_print ( 1 , " internal error in analysis, parallel directives will not be generated for this file! \n " ) ;
break ;
}
if ( st - > variant ( ) = = EQUI_STAT )
{
auto eqList = isSgNestedVarListDeclStmt ( st ) ;
if ( eqList = = NULL )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
bool needToReport = false ;
bool checkTmp = true ;
//TODO: need to check variables in region
if ( getRegionByLine ( regions , st - > fileName ( ) , lastLine ) )
{
checkTmp = false ;
needToReport = true ;
}
else
needToReport = true ;
bool onlyVars = true ;
for ( int z = 0 ; z < eqList - > numberOfLists ( ) ; + + z )
{
auto list = eqList - > list ( z ) ;
while ( list )
{
SgSymbol * symb = list - > lhs ( ) - > symbol ( ) ;
checkNull ( symb , convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
if ( isArrayRef ( list - > lhs ( ) ) | |
symb - > type ( ) & & symb - > type ( ) - > variant ( ) = = T_ARRAY )
{
SgStatement * decl = declaratedInStmt ( symb ) ;
DIST : : Array * array = getArrayFromDeclarated ( decl , symb - > identifier ( ) ) ;
if ( array & & ! array - > IsNotDistribute ( ) )
onlyVars = false ;
}
list = list - > rhs ( ) ;
}
}
if ( onlyVars )
{
needToReport = false ;
checkTmp = true ;
}
checkOK & = checkTmp ;
if ( needToReport )
{
__spf_print ( 1 , " The equivalence operator is not supported yet at line %d of file %s \n " , st - > lineNumber ( ) , st - > fileName ( ) ) ;
currMessages [ st - > fileName ( ) ] . push_back ( Messages ( checkOK ? WARR : ERROR , st - > lineNumber ( ) , R70 , L " An equivalence operator is not supported yet " , 1038 ) ) ;
}
}
if ( st - > variant ( ) = = PAUSE_NODE )
{
checkOK & = false ;
__spf_print ( 1 , " The PAUSE operator is not supported yet at line %d of file %s \n " , st - > lineNumber ( ) , st - > fileName ( ) ) ;
currMessages [ st - > fileName ( ) ] . push_back ( Messages ( ERROR , st - > lineNumber ( ) , R69 , L " An PAUSE operator is deprecated to parallel " , 1038 ) ) ;
}
st = st - > lexNext ( ) ;
}
}
return checkOK ;
}
bool CommonBlockChecker ( SgFile * file , const string & fileName , const map < string , CommonBlock * > & commonBlocks , map < string , vector < Messages > > & messages )
{
bool checkOK = true ;
for ( auto & block : commonBlocks )
{
auto vars = block . second - > getVariables ( ) ;
for ( int i = 0 ; i < vars . size ( ) ; i + + )
{
int pos = vars [ i ] - > getPosition ( ) ;
varType type = vars [ i ] - > getType ( ) ;
//only this file
bool needToSkip = true ;
const CommonVariableUse * currUse = NULL ;
for ( auto & elem : vars [ i ] - > getAllUse ( ) )
{
if ( elem . getFile ( ) = = file )
{
needToSkip = false ;
currUse = & elem ;
}
}
if ( needToSkip )
continue ;
for ( int j = i + 1 ; j < vars . size ( ) ; j + + )
{
bool needToReport = false ;
auto typeMessage = NOTE ;
if ( ( vars [ j ] - > getPosition ( ) = = pos ) & &
( ( vars [ j ] - > getType ( ) = = ARRAY & & type ! = ARRAY ) | | ( vars [ j ] - > getType ( ) ! = ARRAY & & type = = ARRAY ) ) )
{
DIST : : Array * array = NULL ;
if ( vars [ j ] - > getType ( ) = = ARRAY )
array = getArrayFromDeclarated ( vars [ j ] - > getDeclarated ( ) , vars [ j ] - > getName ( ) ) ;
else
array = getArrayFromDeclarated ( vars [ i ] - > getDeclarated ( ) , vars [ i ] - > getName ( ) ) ;
if ( array = = NULL )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
if ( array - > IsNotDistribute ( ) )
typeMessage = WARR ;
else
{
checkOK = false ;
typeMessage = ERROR ;
}
needToReport = true ;
}
else if ( vars [ j ] - > getPosition ( ) = = pos & & vars [ j ] - > getType ( ) ! = type )
{
typeMessage = WARR ;
needToReport = true ;
}
if ( needToReport )
{
wstring messageE , messageR ;
__spf_printToLongBuf ( messageE , L " Variables '%s' and '%s' in one storage association (common block '%s') have different types (files - %s:%d and %s:%d) " ,
to_wstring ( vars [ i ] - > getName ( ) ) . c_str ( ) , to_wstring ( vars [ j ] - > getName ( ) ) . c_str ( ) , to_wstring ( block . first ) . c_str ( ) ,
to_wstring ( vars [ i ] - > getDeclarated ( ) - > fileName ( ) ) . c_str ( ) , vars [ i ] - > getDeclarated ( ) - > lineNumber ( ) ,
to_wstring ( vars [ j ] - > getDeclarated ( ) - > fileName ( ) ) . c_str ( ) , vars [ j ] - > getDeclarated ( ) - > lineNumber ( ) ) ;
__spf_printToLongBuf ( messageR , R71 ,
to_wstring ( vars [ i ] - > getName ( ) ) . c_str ( ) , to_wstring ( vars [ j ] - > getName ( ) ) . c_str ( ) , to_wstring ( block . first ) . c_str ( ) ,
to_wstring ( vars [ i ] - > getDeclarated ( ) - > fileName ( ) ) . c_str ( ) , vars [ i ] - > getDeclarated ( ) - > lineNumber ( ) ,
to_wstring ( vars [ j ] - > getDeclarated ( ) - > fileName ( ) ) . c_str ( ) , vars [ j ] - > getDeclarated ( ) - > lineNumber ( ) ) ;
messages [ vars [ i ] - > getDeclarated ( ) - > fileName ( ) ] . push_back ( Messages ( typeMessage , vars [ i ] - > getDeclarated ( ) - > lineNumber ( ) , messageR , messageE , 1039 ) ) ;
messages [ vars [ j ] - > getDeclarated ( ) - > fileName ( ) ] . push_back ( Messages ( typeMessage , vars [ j ] - > getDeclarated ( ) - > lineNumber ( ) , messageR , messageE , 1039 ) ) ;
}
}
}
}
return checkOK ;
}
bool FunctionsChecker ( SgFile * file , map < string , pair < string , int > > & funcNames , map < string , vector < Messages > > & currMessages )
{
int funcNum = file - > numberOfFunctions ( ) ;
bool checkOK = true ;
for ( int i = 0 ; i < funcNum ; + + i )
{
SgStatement * st = file - > functions ( i ) ;
SgStatement * lastNode = st - > lastNodeOfStmt ( ) ;
if ( st - > controlParent ( ) - > variant ( ) = = GLOBAL )
{
string funcName = st - > symbol ( ) - > identifier ( ) ;
auto it = funcNames . find ( funcName ) ;
if ( it = = funcNames . end ( ) )
funcNames [ funcName ] = make_pair ( file - > filename ( ) , st - > lineNumber ( ) ) ;
else
{
__spf_print ( 1 , " the same function name in different places was found: func %s, places %s:%d and %s:%d \n " ,
it - > first . c_str ( ) , it - > second . first . c_str ( ) , it - > second . second , file - > filename ( ) , st - > lineNumber ( ) ) ;
wstring messageE , messageR ;
__spf_printToLongBuf ( messageE , L " Function '%s' was declared in more than one place: '%s':%d and '%s':%d " ,
to_wstring ( funcName ) . c_str ( ) , to_wstring ( it - > second . first ) . c_str ( ) ,
it - > second . second , to_wstring ( file - > filename ( ) ) . c_str ( ) , st - > lineNumber ( ) ) ;
__spf_printToLongBuf ( messageR , R92 ,
to_wstring ( funcName ) . c_str ( ) , to_wstring ( it - > second . first ) . c_str ( ) ,
it - > second . second , to_wstring ( file - > filename ( ) ) . c_str ( ) , st - > lineNumber ( ) ) ;
currMessages [ st - > fileName ( ) ] . push_back ( Messages ( ERROR , st - > lineNumber ( ) , messageR , messageE , 1048 ) ) ;
currMessages [ it - > second . first ] . push_back ( Messages ( ERROR , it - > second . second , messageR , messageE , 1048 ) ) ;
checkOK = false ;
}
2024-05-02 11:05:56 +03:00
if ( isIntrinsicFunctionName ( funcName . c_str ( ) ) )
{
__spf_print ( 1 , " the same function name in different places was found: func %s, places %s:%d and %s:%d \n " ,
funcName . c_str ( ) , file - > filename ( ) , st - > lineNumber ( ) , " intrinsic " , 0 ) ;
wstring messageE , messageR ;
__spf_printToLongBuf ( messageE , L " Function '%s' was declared in more than one place: '%s':%d and '%s':%d " ,
to_wstring ( funcName ) . c_str ( ) , to_wstring ( file - > filename ( ) ) . c_str ( ) , st - > lineNumber ( ) , to_wstring ( " intrinsic " ) . c_str ( ) , 0 ) ;
__spf_printToLongBuf ( messageR , R92 ,
to_wstring ( funcName ) . c_str ( ) , to_wstring ( file - > filename ( ) ) . c_str ( ) , st - > lineNumber ( ) , to_wstring ( " intrinsic " ) . c_str ( ) , 0 ) ;
currMessages [ st - > fileName ( ) ] . push_back ( Messages ( ERROR , st - > lineNumber ( ) , messageR , messageE , 1048 ) ) ;
checkOK = false ;
}
2023-09-14 19:43:13 +03:00
}
}
return checkOK ;
}
void fillFunctionInfo ( SgFile * file , map < string , vector < Function > > & funcInfo )
{
const int funcNum = file - > numberOfFunctions ( ) ;
const string fileName = file - > filename ( ) ;
for ( int i = 0 ; i < funcNum ; + + i )
{
SgStatement * st = file - > functions ( i ) ;
SgStatement * lastNode = st - > lastNodeOfStmt ( ) ;
if ( st - > fileName ( ) ! = fileName )
continue ;
Function newFunc ;
newFunc . name = st - > symbol ( ) - > identifier ( ) ;
newFunc . line = st - > lineNumber ( ) ;
newFunc . file = file - > filename ( ) ;
newFunc . point = st ;
if ( isSgProgHedrStmt ( st ) = = NULL )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
newFunc . parametersCount = ( ( SgProgHedrStmt * ) st ) - > numberOfParameters ( ) ;
auto cp = st - > controlParent ( ) ;
if ( cp - > variant ( ) = = GLOBAL )
newFunc . type = 1 ;
else if ( cp - > variant ( ) = = MODULE_STMT )
{
if ( string ( cp - > fileName ( ) ) ! = file - > filename ( ) )
continue ; // add module functions only once
newFunc . type = 0 ;
newFunc . parentName = cp - > symbol ( ) - > identifier ( ) ;
}
else
{
auto cpcp = cp - > controlParent ( ) ;
if ( cpcp - > variant ( ) = = GLOBAL )
{
newFunc . type = 2 ;
newFunc . parentName = cp - > symbol ( ) - > identifier ( ) ;
}
else
{
newFunc . type = 3 ;
newFunc . parentName = cp - > symbol ( ) - > identifier ( ) ;
newFunc . globalName = cpcp - > symbol ( ) - > identifier ( ) ;
}
}
funcInfo [ newFunc . name ] . push_back ( newFunc ) ;
}
}
//TODO: for the same parameters count
// add support of optilnal parameters
static SgSymbol * resolveName ( SgFile * file , SgStatement * context , SgExpression * parameters , const vector < Function > & functions , const string & name )
{
SgSymbol * corrected = NULL ;
int parCount = 0 ;
while ( parameters )
{
parCount + + ;
parameters = parameters - > rhs ( ) ;
}
auto cp = getFuncStat ( context , { MODULE_STMT } ) ;
auto cpcp = cp - > controlParent ( ) ;
auto globalP = cpcp - > controlParent ( ) ;
const string cpName = cp - > symbol ( ) - > identifier ( ) ;
const string cpcpName = ( cpcp - > variant ( ) = = GLOBAL ) ? " " : cpcp - > symbol ( ) - > identifier ( ) ;
const string global = globalP ? ( ( globalP - > variant ( ) ! = GLOBAL ) ? globalP - > symbol ( ) - > identifier ( ) : " " ) : " " ;
//try to resolve by parameters count
vector < Function > firstStep , candidates ;
for ( auto & func : functions )
if ( func . parametersCount = = parCount )
firstStep . push_back ( func ) ;
if ( firstStep . size ( ) ! = 1 )
{
for ( auto & func : firstStep )
{
if ( func . type = = 3 )
{
if ( func . parentName = = cpName & & func . globalName = = cpcpName | |
func . parentName = = cpcpName & & func . globalName = = global )
{
candidates . push_back ( func ) ;
}
}
else if ( func . type = = 0 )
{
if ( func . parentName = = cpcpName )
candidates . push_back ( func ) ;
}
else if ( func . type = = 2 )
{
if ( func . parentName = = cpName | | func . parentName = = cpcpName ) // contains
candidates . push_back ( func ) ;
}
else
{
//TODO:
candidates . push_back ( func ) ;
}
}
}
else
candidates = firstStep ;
if ( candidates . size ( ) = = 0 )
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
//TODO: added candidate filtration by context
if ( candidates . size ( ) = = 1 )
{
Function target = candidates [ 0 ] ;
auto itF = target . resolved . find ( file ) ;
if ( itF ! = target . resolved . end ( ) )
corrected = itF - > second ;
else
{
if ( target . type = = 1 | | target . type = = 2 ) // global or internal
{
if ( target . file = = file - > filename ( ) )
{
corrected = target . point - > symbol ( ) ;
target . resolved [ file ] = corrected ;
}
/*else //TODO: create needed symbol?
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ; */
}
else if ( target . type = = 0 ) // module
{
if ( target . file = = file - > filename ( ) )
{
corrected = target . point - > symbol ( ) ;
target . resolved [ file ] = corrected ;
}
else
; //TODO: find module symbol clone in current file
}
}
}
else // TODO
{
__spf_print ( 1 , " can not resolve of CALL '%s' function, candidates count %d, file %s and line %d \n " , name . c_str ( ) , functions . size ( ) , current_file - > filename ( ) , context - > lineNumber ( ) ) ;
for ( auto & func : functions )
__spf_print ( 1 , " --> from file file %s and line %d, parameter count - %d \n " , func . file . c_str ( ) , func . line , func . parametersCount ) ;
printInternalError ( convertFileName ( __FILE__ ) . c_str ( ) , __LINE__ ) ;
}
return corrected ;
}
static void resolveFunctionCalls ( SgFile * file , SgStatement * context , SgExpression * ex , const set < string > & toResolve , const map < string , vector < Function > > & funcInfo )
{
if ( ex )
{
if ( ex - > variant ( ) = = FUNC_CALL )
{
string name = ex - > symbol ( ) - > identifier ( ) ;
if ( toResolve . find ( name ) ! = toResolve . end ( ) )
{
auto newS = resolveName ( file , context , ex - > lhs ( ) , funcInfo . at ( name ) , name ) ;
if ( newS & & ex - > symbol ( ) - > id ( ) ! = newS - > id ( ) )
ex - > setSymbol ( * newS ) ;
}
}
resolveFunctionCalls ( file , context , ex - > lhs ( ) , toResolve , funcInfo ) ;
resolveFunctionCalls ( file , context , ex - > rhs ( ) , toResolve , funcInfo ) ;
}
}
void resolveFunctionCalls ( SgFile * file , const set < string > & toResolve , const map < string , vector < Function > > & funcInfo )
{
if ( toResolve . size ( ) = = 0 )
return ;
int funcNum = file - > numberOfFunctions ( ) ;
for ( int z = 0 ; z < funcNum ; + + z )
{
SgStatement * st = file - > functions ( z ) ;
SgStatement * lastNode = st - > lastNodeOfStmt ( ) ;
while ( st ! = lastNode )
{
if ( st - > variant ( ) = = CONTAINS_STMT )
break ;
if ( st - > variant ( ) = = PROC_STAT )
{
string name = st - > symbol ( ) - > identifier ( ) ;
if ( toResolve . find ( name ) ! = toResolve . end ( ) )
{
auto newS = resolveName ( file , st , st - > expr ( 0 ) , funcInfo . at ( name ) , name ) ;
if ( newS & & st - > symbol ( ) - > id ( ) ! = newS - > id ( ) )
st - > setSymbol ( * newS ) ;
}
}
for ( int z = 0 ; z < 3 ; + + z )
resolveFunctionCalls ( file , st , st - > expr ( z ) , toResolve , funcInfo ) ;
st = st - > lexNext ( ) ;
}
}
}
bool OperatorChecker ( SgFile * file , map < string , vector < Messages > > & currMessages )
{
bool checkOK = true ;
set < int > usedLines ;
SgStatement * st = file - > firstStatement ( ) ;
string currF = file - > filename ( ) ;
2024-08-30 12:17:35 +03:00
2024-09-30 20:24:34 +03:00
const set < int > cpOnSameLine = { ARITHIF_NODE , LOGIF_NODE , GOTO_NODE , IF_NODE , FORALL_STAT } ;
2023-09-14 19:43:13 +03:00
while ( st )
{
int line = st - > lineNumber ( ) ;
2024-08-30 12:17:35 +03:00
if ( line > 0 & & st - > variant ( ) = = PROG_HEDR & & st - > symbol ( ) - > identifier ( ) = = string ( " _MAIN " ) )
; // skip
else if ( line > 0 & & st - > fileName ( ) = = currF )
2023-09-14 19:43:13 +03:00
{
int var = st - > controlParent ( ) - > variant ( ) ;
2024-09-30 20:24:34 +03:00
bool cpWasAdded = cpOnSameLine . find ( var ) ! = cpOnSameLine . end ( ) & & ( usedLines . find ( line ) ! = usedLines . end ( ) ) ;
2023-09-14 19:43:13 +03:00
if ( usedLines . find ( line ) ! = usedLines . end ( ) & & ! cpWasAdded )
{
wstring messageE , messageR ;
__spf_printToLongBuf ( messageE , L " More than one operator found on a line, try to run Code correction pass " ) ;
__spf_printToLongBuf ( messageR , R179 ) ;
currMessages [ st - > fileName ( ) ] . push_back ( Messages ( ERROR , line , messageR , messageE , 1027 ) ) ;
checkOK = false ;
}
usedLines . insert ( line ) ;
}
st = st - > lexNext ( ) ;
}
return checkOK ;
}
bool checkAndMoveFormatOperators ( SgFile * file , vector < Messages > & currMessages , bool withError )
{
bool checkOK = true ;
const int funcNum = file - > numberOfFunctions ( ) ;
for ( int i = 0 ; i < funcNum ; + + i )
{
SgStatement * st = file - > functions ( i ) ;
SgStatement * lastNode = st - > lastNodeOfStmt ( ) ;
vector < SgStatement * > toMove ;
while ( st ! = lastNode )
{
if ( st = = NULL )
{
__spf_print ( 1 , " internal error in analysis, parallel directives will not be generated for this file! \n " ) ;
break ;
}
if ( st - > variant ( ) = = CONTAINS_STMT )
break ;
2024-05-15 17:54:18 +03:00
if ( isSgExecutableStatement ( st ) & & ! isDVM_stat ( st ) & & ! isSPF_stat ( st ) )
2023-09-14 19:43:13 +03:00
break ;
if ( st - > variant ( ) = = FORMAT_STAT )
{
if ( withError )
{
toMove . push_back ( st ) ;
st = st - > lexNext ( ) ;
}
else
{
SgStatement * needed = st ;
st = st - > lexNext ( ) ;
toMove . push_back ( needed - > extractStmt ( ) ) ;
}
}
else
st = st - > lexNext ( ) ;
}
if ( toMove . size ( ) > 0 )
{
if ( ! withError )
{
for ( auto & format : toMove )
2024-05-15 17:54:18 +03:00
lastNode - > insertStmtBefore ( * format , * lastNode - > controlParent ( ) ) ;
2023-09-14 19:43:13 +03:00
}
else
{
for ( auto & format : toMove )
{
wstring messageE , messageR ;
__spf_printToLongBuf ( messageE , L " FORMAT operators cannot be placed in the declaration scope in the SAPFOR, try to run Code correction pass " ) ;
__spf_printToLongBuf ( messageR , R183 ) ;
currMessages . push_back ( Messages ( ERROR , format - > lineNumber ( ) , messageR , messageE , 1060 ) ) ;
}
checkOK = false ;
}
}
}
return checkOK ;
}