2This module contains functions usefull to build scripts around the pyfortool library
6from multiprocessing
import cpu_count, Pool
7from multiprocessing.managers
import BaseManager
18from pyfortool
import __version__
23 Function to use on each file
24 :param clsPYFT: PYFT class to use
25 :param filename: file name
29 allArgs, orderedOptions = allFileArgs[filename]
32 with PYFT(filename, filename,
35 enableCache=allArgs.enableCache)
as pft:
38 for arg
in orderedOptions:
39 logging.debug(
'Applying %s on %s', arg, filename)
41 filename
if filename == allArgs.plotCentralFile
else None)
42 logging.debug(
' -> Done')
45 if not allArgs.dryRun:
51 except Exception
as exc:
52 logging.error(
"The following error has occurred in the file %s", filename)
53 traceback.print_exception(exc, file=sys.stdout)
60 Core of the pyfortool_parallel.py command
61 :param argv: list of arguments (including the 'programm' name in first position)
62 as would be obtained by sys.argv. Or None to use sys.argv
65 class MyManager(BaseManager):
67 Custom manager to deal with Tree instances
70 MyManager.register(
'Tree', Tree)
83 parser = argparse.ArgumentParser(description=
'Python FORTRAN tool', allow_abbrev=
False,
84 epilog=
"The argument order matters.")
86 updateParser(parser, withInput=
False, withOutput=
False, withXml=
False, withPlotCentralFile=
True,
87 treeIsOptional=
False, nbPar=
True, restrictScope=
False)
88 commonArgs, getFileArgs =
getArgs(parser, argv)
91 with MyManager()
as manager:
96 PYFT.setParallel(sharedTree)
99 allFileArgs = {file: getFileArgs(file)
for file
in sharedTree.getFiles()}
100 logging.info(
'Executing in parallel on %i files with a maximum of %i processes',
101 len(allFileArgs), commonArgs.nbPar)
102 with Pool(commonArgs.nbPar, initializer=init, initargs=(PYFT, allFileArgs))
as pool:
103 result = pool.map(task, sharedTree.getFiles())
106 sharedTree.toJson(commonArgs.descTree)
109 errors = [item[1]
for item
in result
if item[0] != 0]
112 logging.error(
'List of files with error:')
114 logging.error(
' - %s', error)
115 raise PYFTError(f
"Errors have been reported in {status} file(s).")
123 Core of the pyfortool.py command
124 :param argv: list of arguments (including the 'programm' name in first position)
125 as would be obtained by sys.argv. Or None to use sys.argv
127 parser = argparse.ArgumentParser(description=
'Python FORTRAN tool', allow_abbrev=
False,
128 epilog=
"The argument order matters.")
130 updateParser(parser, withInput=
True, withOutput=
True, withXml=
True, withPlotCentralFile=
False,
131 treeIsOptional=
True, nbPar=
False, restrictScope=
True)
132 args, orderedOptions =
getArgs(parser, argv)[1]()
139 pft =
PYFT(args.INPUT, args.OUTPUT, parserOptions=parserOptions,
140 verbosity=args.logLevel, wrapH=args.wrapH, tree=descTree,
141 enableCache=args.enableCache)
142 if args.restrictScope !=
'':
143 pft = pft.getScopeNode(args.restrictScope)
146 for arg
in orderedOptions:
147 logging.debug(
'Applying %s on %s', arg, args.INPUT)
148 applyTransfo(pft, arg, args, plotCentralFile=args.INPUT)
149 logging.debug(
' -> Done')
152 if descTree
is not None:
153 descTree.toJson(args.descTree)
154 if args.xml
is not None:
155 pft.mainScope.writeXML(args.xml)
157 pft.mainScope.write()
160 pft.mainScope.close()
164 logging.error(
"The following error has occurred in the file %s", args.INPUT)
168ARG_UPDATE_CNT = (
'--alignContinuation',
'--addBeginContinuation',
169 '--removeBeginContinuation',
170 '--emoveALLContinuation')
175 Parse arguments and interpret the --optsByEnv option
176 :param parser: argparse parser
177 :param argv: list of arguments (including the 'programm' name in first position)
178 as would be obtained by sys.argv. Or None to use sys.argv.
179 :return: a tuple with
180 - an argparse namespace containing common arguments (not using the --optsEnv option)
181 - a function taking a filename as input and returning
182 - an argparse namespace with the common arguments and the ones added by
183 interpreting the --optsEnv option
184 - an ordered list of arguments
188 args = parser.parse_args(argv[1:])
190 def getFileArgs(filename=args.INPUT if hasattr(args,
'INPUT')
else None):
192 :param filename: name of source code file
193 :return: argparse namespace to use with this file and
194 a list given the order in which the arguments were provided
198 if args.optsByEnv
is not None:
200 for line
in []
if args.optsByEnv
is None else os.environ[args.optsByEnv].split(
'\n'):
202 if re.match(line.split(
':=:')[0], filename):
203 extra = line.split(
':=:')[1]
206 index = arguments.index(
'--optsByEnv')
207 arguments = arguments[:index] + shlex.split(extra) + arguments[index + 2:]
212 for arg
in arguments:
213 if arg.startswith(
'--')
and arg
not in optList:
214 if arg
in ARG_UPDATE_CNT:
221 return parser.parse_args(arguments), optList
223 return args, getFileArgs
228 Get the options to use for the fxtran parser
229 :param args: arguments parsed by the argparse parser
231 if args.parserOption
is None:
232 parserOptions = PYFT.DEFAULT_FXTRAN_OPTIONS.copy()
234 parserOptions = [el
for elements
in args.parserOption
for el
in elements]
236 parserOptions = [opt
for opt
in parserOptions
if opt
not in (
'-no-include',
'-noinclude')]
242 get the Tree object built with the parsed arguments
243 :param args: arguments parsed by the argparse parser
244 :param cls: class to use (usefull for manager)
245 :return: a Tree instance
249 descTree = cls(tree=args.tree, descTreeFile=args.descTree,
250 parserOptions=parserOptions,
251 wrapH=args.wrapH, verbosity=args.logLevel)
257def updateParser(parser, withInput, withOutput, withXml, withPlotCentralFile, treeIsOptional,
258 nbPar, restrictScope):
260 Updates an argparse parser with arguments common to all the different tools
261 :param parser: parser in which arguments are added
262 :param withOutput: do we need the INPUT argument
263 :param withOutput: do we need the OUTPUT argument
264 :param withXml: do we need to be able to define an XML output file
265 :param withPlotCentralFile: to add the --plotCentralFile argument
266 :param treeIsOptional: is the --tree argument optional?
267 :param nbPar: number of parallel processes
268 :param restrictScope: can we specify the scope path
279 assert not parser.allow_abbrev,
'parser must be created with allow_abbrev=False'
281 parser.add_argument(
'--version', action=
'version',
282 version=
'%(prog)s {version}'.format(version=__version__))
283 parser.add_argument(
'--simplify', default=
False, action=
'store_true',
284 help=
'After a deletion, recursively deletes the code ' +
285 'and variables that have become useless')
286 parser.add_argument(
'--logLevel', default=
'warning',
287 help=
'Provide logging level. Example --logLevel debug (default is warning)')
288 parser.add_argument(
'--enableCache', default=
False, action=
'store_true',
289 help=
'Precompute parent of each xml node and store the result')
291 parser.add_argument(
'--nbPar', default=cpu_count(), type=int,
292 help=
'Number of parallel processes, 0 to get as many processes ' +
293 'as the number of cores (default=0)')
294 parser.add_argument(
'--optsByEnv', default=
None, type=str,
295 help=
'Name of the environment variable containing additional arguments ' +
296 'to use. These arguments are processed after all other arguments. ' +
297 'The variable can contain a multi-lines string. The ' +
298 'variable is read line by line and the last applicable line is ' +
299 'used. A line can take one of these two forms: ' +
300 '1) "FILE_DESCRIPTOR:=:OPTIONS" (where FILE_DESCRIPTOR is a ' +
301 'regular expression to test against the filename. If there ' +
302 'is a match, the OPTIONS can be used for the file) and ' +
303 '2) "OPTIONS" (if the line doesn\'t contain the FILE_DESCRIPTOR ' +
304 'part, it applies to all source code).')
307 parser.add_argument(
'--restrictScope', default=
'', type=str, metavar=
'SCOPEPATH',
308 help=
"Limit the action to this scope path (SUBROUTINE/FUNCTION/" +
309 "MODULE/TYPE). It is '/'-separated path with each element " +
310 "having the form 'module:<name of the module>', " +
311 "'sub:<name of the subroutine>', " +
312 "'func:<name of the function>' or 'type:<name of the type>'.")
350 Updates an argparse parser with input/output arguments
351 :param parser: parser in which arguments are added
352 :param withOutput: do we need the INPUT argument
353 :param withOutput: do we need the OUTPUT argument
354 :param withXml: do we need to be able to define an XML output file
356 gInOut = parser.add_argument_group(
'Input and output')
358 gInOut.add_argument(
'INPUT', help=
'FORTRAN input file')
360 gInOut.add_argument(
'OUTPUT', default=
None, help=
'FORTRAN output file', nargs=
'?')
361 gInOut.add_argument(
'--renamefF', default=
False, action=
'store_true',
362 help=
'Put file extension in upper case')
363 gInOut.add_argument(
'--renameFf', default=
False, action=
'store_true',
364 help=
'Put file extension in lower case')
366 gInOut.add_argument(
'--xml', default=
None, type=str,
367 help=
'Output file for xml')
368 gInOut.add_argument(
'--dryRun', default=
False, action=
'store_true',
369 help=
'Dry run without writing the FORTRAN file (the xml ' +
375 Updates an argparse parser with fxtran arguments
377 gParser = parser.add_argument_group(
'fxtran parser relative options')
378 gParser.add_argument(
'--parserOption', nargs=
'*', action=
'append',
379 help=
'Option to pass to fxtran, defaults ' +
380 f
'to {PYFT.DEFAULT_FXTRAN_OPTIONS}')
381 gParser.add_argument(
'--wrapH', default=
False, action=
'store_true',
382 help=
'Wrap .h file content into a MODULE to enable the reading')
387 Updates an argparse parser with variables arguments
389 gVariables = parser.add_argument_group(
'Options to deal with variables')
390 gVariables.add_argument(
'--showVariables', default=
False, action=
'store_true',
391 help=
'Show the declared variables')
392 gVariables.add_argument(
'--removeVariable', nargs=2, action=
'append',
393 metavar=(
'SCOPEPATH',
'VARNAME'),
394 help=
"Variable to remove from declaration. The first argument " +
395 "is the SUBROUTINE/FUNCTION/MODULE/TYPE where the variable " +
396 "is declared. It is '/'-separated path with each element having " +
397 "the form 'module:<name of the module>', " +
398 "'sub:<name of the subroutine>', " +
399 "'func:<name of the function>' or 'type:<name of the type>'. " +
400 "The second argument is the variable name")
401 gVariables.add_argument(
'--attachArraySpecToEntity', default=
False, action=
'store_true',
402 help=
'Find all T-decl-stmt elements that have a child element ' +
403 'attribute with attribute-N=DIMENSION and move the attribute ' +
404 'into EN-N elements')
405 gVariables.add_argument(
'--addVariable', nargs=4, action=
'append',
406 metavar=(
'SCOPEPATH',
'VARNAME',
'DECLARATION',
'POSITION'),
407 help=
'Add a variable. First argument is the scope path (as for ' +
408 'the --removeVariable option. The second is the variable ' +
409 'name, the third is the declarative statement to insert, ' +
410 'the fourth is the position (python indexing) the new ' +
411 'variable will have in the calling statment of the ' +
412 'routine (non-integer value for a local variable).')
413 gVariables.add_argument(
'--addModuleVariable', nargs=3, action=
'append',
414 metavar=(
'SCOPEPATH',
'MODULENAME',
'VARNAME'),
415 help=
'Add a USE statement. The first argument is the scope path ' +
416 '(as for the --removeVariable option). The second is the module ' +
417 'name; the third is the variable name.')
418 gVariables.add_argument(
'--showUnusedVariables', default=
False, action=
'store_true',
419 help=
'Show a list of unused variables.')
420 gVariables.add_argument(
'--removeUnusedLocalVariables',
421 help=
'Remove unused local variables, excluding some variables (comma-' +
422 'separated list or NONE to exclude nothing).')
423 gVariables.add_argument(
'--removePHYEXUnusedLocalVariables',
424 help=
'Remove unused local variables, excluding some variables (comma-' +
425 'separated list or NONE to exclude nothing). This option takes ' +
426 'into account the mnh_expand directives to prevent from ' +
427 'removing useful variables.')
428 gVariables.add_argument(
'--addExplicitArrayBounds', action=
'store_true',
429 help=
'Adds explicit bounds to arrays that already have parentheses.')
430 gVariables.add_argument(
'--addArrayParentheses', action=
'store_true',
431 help=
'Adds parentheses to arrays (A => A(:))')
432 gVariables.add_argument(
'--modifyAutomaticArrays', metavar=
"DECL#START#END",
433 help=
'Transform all automatic arrays declaration using the templates.' +
434 ' The DECL part of the template will replace the declaration ' +
435 'statement, the START part will be inserted as the first ' +
436 'executable statement while the END part will be inserted as ' +
437 'the last executable statement. Each part ' +
438 'of the template can use the following place holders: ' +
439 '"{doubledotshape}", "{shape}", "{lowUpList}", "{name}" and ' +
440 '"{type}" which are, respectively modified into ' +
441 '":, :, :", "I, I:J, 0:I", "1, I, I, J, 0, I", "A", "REAL" ' +
442 'if the original declaration statement ' +
443 'was "A(I, I:J, 0:I)". For example, the template ' +
444 '"{type}, DIMENSION({doubledotshape}), ALLOCATABLE :: ' +
445 '{name}#ALLOCATE({name}({shape}))#DEALLOCATE({name})"' +
446 'will replace automatic arrays by allocatables.')
447 gVariables.add_argument(
'--replaceAutomaticWithAllocatable', action=
'store_true',
448 help=
'Replace all automatic arrays with allocatable arrays.')
449 gVariables.add_argument(
'--addArgInTree', default=
None, action=
'append', nargs=3,
450 metavar=(
'VARNAME',
'DECLARATION',
'POSITION'),
451 help=
'Add an argument variable. The first argument is the variable ' +
452 'name, the second one is the declarative statement to insert, ' +
453 'the third one is the position (python indexing) the new ' +
454 'variable will have in the calling statement of the ' +
455 'routine. Needs the --stopScopes argument')
456 gVariables.add_argument(
'--addONLY', default=
False, action=
'store_true',
457 help=
'Add missing ONLY clause to USE statements.')
462 Updates an argparse parser with cosmetics arguments
464 gCosmetics = parser.add_argument_group(
'Cosmetics options')
465 gCosmetics.add_argument(
'--upperCase', default=
False, action=
'store_true',
466 help=
'Put FORTRAN code in upper case letters')
467 gCosmetics.add_argument(
'--lowerCase', default=
False, action=
'store_true',
468 help=
'Put FORTRAN code in lower case letters')
469 gCosmetics.add_argument(
'--changeIfStatementsInIfConstructs', default=
False,
471 help=
'Find all if-statement and convert it to if-then-statement')
472 gCosmetics.add_argument(
'--indent', default=
False, action=
'store_true',
473 help=
'Correct indentation')
474 gCosmetics.add_argument(
'--removeIndent', default=
False, action=
'store_true',
475 help=
'Remove indentation')
476 gCosmetics.add_argument(
'--removeEmptyLines', default=
False, action=
'store_true',
477 help=
'Remove empty lines')
478 gCosmetics.add_argument(
'--removeComments', default=
False, action=
'store_true',
479 help=
'Remove comments')
480 gCosmetics.add_argument(
'--updateSpaces', default=
False, action=
'store_true',
481 help=
'Updates spaces around operators, commas, parenthesis and ' +
482 'at the end of line')
483 gCosmetics.add_argument(
'--alignContinuation', default=
False, action=
'store_true',
484 help=
'Align the beginings of continued lines')
485 gCosmetics.add_argument(
'--addBeginContinuation', default=
False, action=
'store_true',
486 help=
'Add missing continuation characters (\'&\') at the ' +
488 gCosmetics.add_argument(
'--removeBeginContinuation', default=
False, action=
'store_true',
489 help=
'Remove continuation characters (\'&\') at the begining of lines')
490 gCosmetics.add_argument(
'--removeALLContinuation', default=
False, action=
'store_true',
491 help=
'Remove all continuation characters(\'&\')')
492 gCosmetics.add_argument(
'--prettify', default=
False, action=
'store_true',
493 help=
'Prettify the source code (indentation, spaces...)')
494 gCosmetics.add_argument(
'--minify', default=
False, action=
'store_true',
495 help=
'Simplify the source code (indentation, spaces...)')
496 gCosmetics.add_argument(
'--removeEmptyCONTAINS', default=
False, action=
'store_true',
497 help=
'Remove useless CONTAINS statements')
498 gCosmetics.add_argument(
'--formatModuleUse', default=
False, action=
'store_true',
499 help=
'Order USE declarations by module type (MODD_, MODE_, ' +
500 'MODI_, MODN_) and alphabetically within each group')
505 Updates an argparse parser with applications arguments
507 gApplications = parser.add_argument_group(
'Options to apply upper level transformation')
508 gApplications.add_argument(
'--deleteDrHook', default=
False, action=
'store_true',
509 help=
'Delete DR HOOK use')
510 gApplications.add_argument(
'--addDrHook', default=
False, action=
'store_true',
512 gApplications.add_argument(
'--deleteBudgetDDH', default=
False, action=
'store_true',
513 help=
'Delete Budget/DDH use')
514 gApplications.add_argument(
'--deleteRoutineCallsMesoNHGPU', default=
False, action=
'store_true',
515 help=
'Delete parts of the code not compatible with MesoNH-OpenACC' +
516 'such as OCND2 blocks')
517 gApplications.add_argument(
'--splitModuleRoutineFile', default=
False, action=
'store_true',
519 gApplications.add_argument(
'--deleteNonColumnCallsPHYEX', default=
False, action=
'store_true',
520 help=
'Delete call to PHYEX routines that needs information on ' +
521 'horizontal points (multiple column dependency')
522 gApplications.add_argument(
'--removeIJDim', default=
False, action=
'store_true',
523 help=
'Remove I and J dimensions (1, KLON). ' +
524 'Needs the --stopScopes argument.')
525 gApplications.add_argument(
'--expandAllArraysPHYEX', default=
False, action=
'store_true',
526 help=
'Expand all array syntax (computing and where block) ' +
527 'using PHYEX conventions')
528 gApplications.add_argument(
'--expandAllArraysPHYEXConcurrent', default=
False,
530 help=
'Expand all array syntax with DO CONCURRENT loops ' +
531 '(computing and where block) using PHYEX conventions')
532 gApplications.add_argument(
'--expandAllArrays', default=
False, action=
'store_true',
533 help=
'Expand all array syntax (computing and where block) ' +
534 'using mnh directives if present')
535 gApplications.add_argument(
'--expandAllArraysConcurrent', default=
False, action=
'store_true',
536 help=
'Expand all array syntax with DO CONCURRENT loops ' +
537 '(computing and where block) using mnh directives if present')
538 gApplications.add_argument(
'--inlineContainedSubroutinesPHYEX', default=
False,
540 help=
'Inline containted subroutines in main routine, using ' +
542 gApplications.add_argument(
'--addStack', metavar=
'MODEL', type=str,
543 help=
'Add local arrays to the stack. The argument is the ' +
544 'the model name in which stack must be added ("AROME" ' +
545 'or "MESONH"). Needs the --stopScopes argument for AROME.')
546 gApplications.add_argument(
'--addIncludes', default=
False, action=
'store_true',
547 help=
'Add .h includes in the file and remove the INCLUDE statement')
548 gApplications.add_argument(
'--addSubmodulePHYEX', default=
False, action=
'store_true',
549 help=
'Add SUBMODULE and INTERFACE of subroutines in PHYEX')
550 gApplications.add_argument(
'--mnhExpand', default=
False, action=
'store_true',
551 help=
'Apply the mnh_expand directives with DO loops')
552 gApplications.add_argument(
'--mnhExpandConcurrent', default=
False, action=
'store_true',
553 help=
'Apply the mnh_expand directives with DO CONCURRENT loops')
554 gApplications.add_argument(
'--addMPPDB_CHECKS', default=
False, action=
'store_true',
555 help=
'Add MPPDB_CHEKS bit-repro checking routines of MesoNH for ' +
556 'all in and inout arrays in subroutines')
557 gApplications.add_argument(
'--addPrints', default=
False, action=
'store_true',
558 help=
'Add Prints of min/maxval and shape of all in, out, inout ' +
559 'arguments of all scopes')
560 gApplications.add_argument(
'--shumanFUNCtoCALL', default=
False, action=
'store_true',
561 help=
'Transform shuman functions to call statements')
562 gApplications.add_argument(
'--mathFunctoBRFunc', default=
False, action=
'store_true',
563 help=
'Convert intrinsic math functions **, LOG, ATAN, **2, **3, ' +
564 '**4, EXP, COS, SIN, ATAN2 into a self defined function BR_ ' +
565 'for MesoNH bit-repro.')
566 gApplications.add_argument(
'--convertTypesInCompute', default=
False, action=
'store_true',
567 help=
'Use single variable instead of variable contained in ' +
568 'structure in compute statement for optimization issue ')
569 gApplications.add_argument(
'--buildModi', default=
False, action=
'store_true',
570 help=
'Builds the corresponding modi_ file')
571 gApplications.add_argument(
'--removeExtraDOinMnhDoConcurrent', default=
False,
573 help=
'Remove DO and ENDDO instructions inside !$mnh_do_concurrent')
574 gApplications.add_argument(
'--convertuseModuleToIncludes', default=
False,
576 help=
'Convert USE MODULE, ONLY: ROUTINE to #include routine.intfb.h')
581 Updates an argparse parser with openACC arguments
583 gOpenACC = parser.add_argument_group(
'OpenACC')
584 gOpenACC.add_argument(
'--addACCData', default=
False, action=
'store_true',
585 help=
'Add !$acc data present and !$acc end data directives')
586 gOpenACC.add_argument(
'--addACCRoutineSeq', default=
False, action=
'store_true',
587 help=
'Add "!$acc routine seq" to routines under stopScopes')
588 gOpenACC.add_argument(
'--craybyPassDOCONCURRENT', default=
False, action=
'store_true',
589 help=
'remove acc loop independant collapse for BR_ fonctions and ' +
590 'mnh_undef(OPENACC) macro' +
591 ' use DO CONCURRENT with mnh_undef(LOOP)')
592 gOpenACC.add_argument(
'--removeACC', default=
False, action=
'store_true',
593 help=
'remove all ACC directives')
594 gOpenACC.add_argument(
'--removebyPassDOCONCURRENT', default=
False, action=
'store_true',
595 help=
'remove macro !$mnh_(un)def(OPENACC) and !$mnh_(un)def(LOOP) ' +
597 gOpenACC.add_argument(
'--buildACCTypeHelpers', default=
False, action=
'store_true',
598 help=
'build module files containing helpers to copy user ' +
600 gOpenACC.add_argument(
'--allocatetoHIP', default=
False, action=
'store_true',
601 help=
'convert (DE)ALLOCATE to (DE)ALLOCATE_HIP on variables only sent ' +
602 'to the GPU via acc enter data copyin/create (for GPU AMD MI250X)')
607 Updates an argparse parser with checks arguments
610 gChecks = parser.add_argument_group(
'Check options')
611 gChecks.add_argument(
'--checkIMPLICIT', choices={
'Warn',
'Err'}, default=
None,
612 help=
'Send a warning or raise an error if the "IMPLICIT NONE" ' +
614 gChecks.add_argument(
'--checkINTENT', choices={
'Warn',
'Err'}, default=
None,
615 help=
'Send a warning or raise an error if the "INTENT" ' +
616 'attribute is missing for a dummy argument')
617 gChecks.add_argument(
'--checkOpInCall', choices={
'Warn',
'Err'}, default=
None,
618 help=
'Send a warning or raise an error if a call argument is an '
620 gChecks.add_argument(
'--checkUnusedLocalVar', choices={
'Warn',
'Err'}, default=
None,
621 help=
'Send a warning or raise an error if some local '
622 'variables are unused.')
623 gChecks.add_argument(
'--checkPHYEXUnusedLocalVar', choices={
'Warn',
'Err'}, default=
None,
624 help=
'Send a warning or raise an error if some local '
625 'variables are unused (excluding variables needed '
626 'for mnh_expand directives).')
627 gChecks.add_argument(
'--checkEmptyParensInCall', choices={
'Warn',
'Err'}, default=
None,
628 help=
'Send a warning or raise an error if a call argument is an '
629 'array with empty parens.')
630 gChecks.add_argument(
'--checkONLY', choices={
'Warn',
'Err'}, default=
None,
631 help=
'Send a warning or raise an error if a USE statement is not '
632 'followed by an ONLY clause.')
633 gChecks.add_argument(
'--checkKeyDim', choices={
'Warn',
'Err'}, default=
None,
634 help=
'Send a warning or raise an error if MERGE-based array '
635 'dimensions are inconsistent across scopes.')
640 Updates an argparse parser with statements arguments
643 gStatement = parser.add_argument_group(
'Statements options')
644 gStatement.add_argument(
'--removeCall', action=
'append',
645 help=
"Call to remove from the source code. The argument " +
646 "is the subprogram name")
647 gStatement.add_argument(
'--removePrints', default=
False, action=
'store_true',
648 help=
"Remove print statements from the source code.")
649 gStatement.add_argument(
'--inlineContainedSubroutines', default=
False, action=
'store_true',
650 help=
'Inline containted subroutines in main routine')
651 gStatement.add_argument(
'--setFalseIfStmt', default=
None,
652 help=
'Replace this value by .FALSE. in if statements')
657 Updates an argparse parser with misc arguments
659 gMisc = parser.add_argument_group(
'Miscellaneous')
660 gMisc.add_argument(
'--showScopes', default=
False, action=
'store_true',
661 help=
'Show the different scopes found in the source code')
662 gMisc.add_argument(
'--empty', default=
False, action=
'store_true',
663 help=
'Empty the different scopes')
668 Updates an argparse parser with statements arguments
669 :param withPlotCentralFile: to add the --plotCentralFile argumen
670 :param treeIsOptional: is the --tree argument optional?
672 gTree = parser.add_argument_group(
'Tree')
673 gTree.add_argument(
'--tree', default=
None, action=
'append', required=
not treeIsOptional,
674 help=
'Directories where source code must be searched for')
675 gTree.add_argument(
'--descTree', default=
None, required=
not treeIsOptional,
676 help=
'File to write and/or read the description of the tree.')
677 if withPlotCentralFile:
678 gTree.add_argument(
'--plotCentralFile', default=
None, type=str,
679 help=
'Central file of the plot')
680 gTree.add_argument(
'--plotCompilTree', default=
None,
681 help=
'File name for compilation dependency graph (.dot or image extension)')
682 gTree.add_argument(
'--plotExecTree', default=
None,
683 help=
'File name for execution dependency graph (.dot or image extension)')
684 gTree.add_argument(
'--plotMaxUpper', default=
None, type=int,
685 help=
'Maximum number of upper elements in the plot tree')
686 gTree.add_argument(
'--plotMaxLower', default=
None, type=int,
687 help=
'Maximum number of lower elements in the plot tree')
688 gTree.add_argument(
'--stopScopes', default=
None, type=str,
689 help=
'#-separated list of scopes ' +
690 'where the recursive inclusion of an argument variable ' +
691 'must stop (needed for some transformations).')
696 Updates an argparse parser with statements arguments
698 gCpp = parser.add_argument_group(
'Preprocessor')
699 gCpp.add_argument(
'--applyCPPifdef', nargs=
'*', action=
'append',
700 help=
"This option is followed by the list of defined or undefined " +
702 "All #ifdef and #ifndef concerning these keys are evaluated. " +
703 "Undefined keys are preceded by a percentage sign.")
708 Apply transformation on a PYFT instance
709 :param pft: PYFT instance
710 :param arg: argument to deal with
711 :param args: parsed argparsed arguments
712 :param plotCentralFile: central file for plots
714 simplify = {
'simplify': args.simplify}
716 stopScopes = args.stopScopes.split(
'#')
if args.stopScopes
is not None else None
751 Apply file name transformations on a PYFT instance
752 :param pft: PYFT instance
753 :param arg: argument to deal with
754 :param args: parsed argparsed arguments
758 if arg ==
'--renamefF':
760 elif arg ==
'--renameFf':
766 Apply variables transformations on a PYFT instance
767 :param pft: PYFT instance
768 :param arg: argument to deal with
769 :param args: parsed argparsed arguments
770 :param simplify: kwargs to simplify
771 :param parserOptions: fxtran parser options
772 :param stopScopes: upper limit in call tree for some transformations
774 if arg ==
'--showVariables':
775 pft.varList.showVarList()
776 elif arg ==
'--attachArraySpecToEntity':
777 pft.attachArraySpecToEntity()
778 elif arg ==
'--removeVariable':
779 pft.removeVar(args.removeVariable, **simplify)
780 elif arg ==
'--addVariable':
781 pft.addVar([[v[0], v[1], v[2], (int(v[3])
if isint(v[3])
else None)]
782 for v
in args.addVariable])
783 elif arg ==
'--addModuleVariable':
784 pft.addModuleVar([[v[0], v[1], v[2]]
for v
in args.addModuleVariable])
785 elif arg ==
'--showUnusedVariables':
787 elif arg ==
'--removeUnusedLocalVariables':
788 pft.removeUnusedLocalVar(
789 [item.strip()
for item
in args.removeUnusedLocalVariables.split(
',')]
790 if args.removeUnusedLocalVariables !=
'NONE' else None, **simplify)
791 elif arg ==
'--removePHYEXUnusedLocalVariables':
792 pft.removePHYEXUnusedLocalVar(
793 [item.strip()
for item
in args.removePHYEXUnusedLocalVariables.split(
',')]
794 if args.removePHYEXUnusedLocalVariables !=
'NONE' else None, **simplify)
795 elif arg ==
'--addExplicitArrayBounds':
796 pft.addExplicitArrayBounds()
797 elif arg ==
'--addArrayParentheses':
798 pft.addArrayParentheses()
799 elif arg ==
'--modifyAutomaticArrays':
800 pft.modifyAutomaticArrays(*(args.modifyAutomaticArrays.split(
'#')))
801 elif arg ==
'--replaceAutomaticWithAllocatable':
802 pft.modifyAutomaticArrays(
803 "{type}, DIMENSION({doubledotshape}), ALLOCATABLE :: {name}",
804 "ALLOCATE({name}({shape}))",
"DEALLOCATE({name})")
805 elif arg ==
'--addArgInTree':
806 for varName, declStmt, pos
in args.addArgInTree:
807 pft.addArgInTree(varName, declStmt, int(pos), stopScopes,
808 parserOptions=parserOptions,
810 elif arg ==
'--addONLY':
811 pft.addONLY(parserOptions=parserOptions, wrapH=args.wrapH)
816 Apply applications transformations on a PYFT instance
817 :param pft: PYFT instance
818 :param arg: argument to deal with
819 :param args: parsed argparsed arguments
820 :param simplify: kwargs to simplify
821 :param parserOptions: fxtran parser options
822 :param stopScopes: upper limit in call tree for some transformations
824 if arg ==
'--addStack':
825 pft.addStack(args.addStack, stopScopes,
826 parserOptions=parserOptions,
828 elif arg ==
'--deleteDrHook':
829 pft.deleteDrHook(**simplify)
830 elif arg ==
'--addDrHook':
832 elif arg ==
'--deleteBudgetDDH':
833 pft.deleteBudgetDDH(**simplify)
834 elif arg ==
'--deleteRoutineCallsMesoNHGPU':
835 pft.deleteRoutineCallsMesoNHGPU(**simplify)
836 elif arg ==
'--deleteNonColumnCallsPHYEX':
837 pft.deleteNonColumnCallsPHYEX(**simplify)
838 elif arg ==
'--addMPPDB_CHECKS':
839 pft.addMPPDB_CHECKS()
840 elif arg ==
'--addPrints':
841 pft.addMPPDB_CHECKS(printsMode=
True)
842 elif arg ==
'--addSubmodulePHYEX':
843 pft.addSubmodulePHYEX()
846 assert not (args.mnhExpand
and args.mnhExpandConcurrent), \
847 "Only one of --mnhExpand and --mnhExpandConcurrent"
848 if arg ==
'--mnhExpand':
849 pft.removeArraySyntax(everywhere=
False, addAccIndependentCollapse=
False)
850 elif arg ==
'--mnhExpandConcurrent':
851 pft.removeArraySyntax(concurrent=
True, everywhere=
False)
852 elif arg ==
'--inlineContainedSubroutines':
853 pft.inlineContainedSubroutines(**simplify)
854 elif arg ==
'--inlineContainedSubroutinesPHYEX':
855 pft.inlineContainedSubroutinesPHYEX(**simplify)
856 elif arg ==
'--expandAllArrays':
857 pft.removeArraySyntax()
858 elif arg ==
'--expandAllArraysConcurrent':
859 pft.removeArraySyntax(concurrent=
True)
860 elif arg ==
'--expandAllArraysPHYEX':
861 pft.expandAllArraysPHYEX()
862 elif arg ==
'--expandAllArraysPHYEXConcurrent':
863 pft.expandAllArraysPHYEX(concurrent=
True)
864 elif arg ==
'--removeIJDim':
865 pft.removeIJDim(stopScopes,
866 parserOptions=parserOptions,
867 wrapH=args.wrapH, **simplify)
868 elif arg ==
'--shumanFUNCtoCALL':
869 pft.shumanFUNCtoCALL()
870 elif arg ==
'--buildACCTypeHelpers':
871 pft.buildACCTypeHelpers()
872 elif arg ==
'--mathFunctoBRFunc':
873 pft.mathFunctoBRFunc()
874 elif arg ==
'--convertTypesInCompute':
875 pft.convertTypesInCompute()
876 elif arg ==
'--buildModi':
878 elif arg ==
'--splitModuleRoutineFile':
879 pft.splitModuleRoutineFile()
880 elif arg ==
'--removeExtraDOinMnhDoConcurrent':
881 pft.removeExtraDOinMnhDoConcurrent()
882 elif arg ==
'--convertuseModuleToIncludes':
883 pft.convertuseModuleToIncludes()
888 Apply openACC transformations on a PYFT instance
889 :param pft: PYFT instance
890 :param arg: argument to deal with
891 :param args: parsed argparsed arguments
892 :param stopScopes: upper limit in call tree for some transformations
894 if arg ==
'--addACCData':
896 elif arg ==
'--craybyPassDOCONCURRENT':
897 pft.craybyPassDOCONCURRENT()
898 elif arg ==
'--removebyPassDOCONCURRENT':
899 pft.removebyPassDOCONCURRENT()
900 elif arg ==
'--addACCRoutineSeq':
901 pft.addACCRoutineSeq(stopScopes)
902 elif arg ==
'--removeACC':
904 elif arg ==
'--allocatetoHIP':
910 Apply cosmetics transformations on a PYFT instance
911 :param pft: PYFT instance
912 :param arg: argument to deal with
913 :param args: parsed argparsed arguments
915 if arg ==
'--upperCase':
917 elif arg ==
'--lowerCase':
919 elif arg ==
'--changeIfStatementsInIfConstructs':
920 pft.changeIfStatementsInIfConstructs()
921 elif arg ==
'--indent':
923 elif arg ==
'--removeIndent':
924 pft.indent(indentProgramunit=0, indentBranch=0)
925 elif arg ==
'--removeEmptyLines':
926 pft.removeEmptyLines()
927 elif arg ==
'--removeComments':
929 elif arg ==
'--updateSpaces':
931 elif arg
in ARG_UPDATE_CNT:
932 pft.updateContinuation(align=args.alignContinuation,
933 addBegin=args.addBeginContinuation,
934 removeBegin=args.removeBeginContinuation,
935 removeALL=args.removeALLContinuation)
936 elif arg ==
'--prettify':
939 pft.removeEmptyLines()
941 pft.updateContinuation()
942 elif arg ==
'--minify':
943 pft.indent(indentProgramunit=0, indentBranch=0)
946 pft.removeEmptyLines()
948 pft.updateContinuation(align=
False, removeALL=
True, addBegin=
False)
949 elif arg ==
'--removeEmptyCONTAINS':
950 pft.removeEmptyCONTAINS()
951 elif arg ==
'--formatModuleUse':
952 pft.formatModuleUse()
957 Apply checks transformations on a PYFT instance
958 :param pft: PYFT instance
959 :param arg: argument to deal with
960 :param args: parsed argparsed arguments
961 :param stopScopes: list of scope paths or None
963 if arg ==
'--checkIMPLICIT':
964 pft.checkImplicitNone(args.checkIMPLICIT ==
'Err')
965 elif arg ==
'--checkINTENT':
966 pft.checkIntent(args.checkINTENT ==
'Err')
967 elif arg ==
'--checkOpInCall':
968 pft.checkOpInCall(args.checkOpInCall ==
'Err')
969 elif arg ==
'--checkUnusedLocalVar':
970 pft.checkUnusedLocalVar(args.checkUnusedLocalVar ==
'Err')
971 elif arg ==
'--checkPHYEXUnusedLocalVar':
972 pft.checkPHYEXUnusedLocalVar(args.checkPHYEXUnusedLocalVar ==
'Err')
973 elif arg ==
'--checkEmptyParensInCall':
974 pft.checkEmptyParensInCall(args.checkEmptyParensInCall ==
'Err')
975 elif arg ==
'--checkONLY':
976 pft.checkONLY(args.checkONLY ==
'Err')
977 elif arg ==
'--checkKeyDim':
978 pft.checkKeyDimConsistency(args.checkKeyDim ==
'Err',
979 stopScopes=stopScopes)
984 Apply statements transformations on a PYFT instance
985 :param pft: PYFT instance
986 :param arg: argument to deal with
987 :param args: parsed argparsed arguments
988 :param simplify: kwargs to simplify
990 if arg ==
'--removeCall':
991 for rc
in args.removeCall:
992 pft.removeCall(rc, **simplify)
993 elif arg ==
'--removePrints':
994 pft.removePrints(**simplify)
995 elif arg ==
'--setFalseIfStmt':
996 pft.setFalseIfStmt(args.setFalseIfStmt, **simplify)
1001 Apply misc transformations on a PYFT instance
1002 :param pft: PYFT instance
1003 :param arg: argument to deal with
1004 :param args: parsed argparsed arguments
1005 :param simplify: kwargs to simplify
1007 if arg ==
'--showScopes':
1008 pft.showScopesList()
1009 elif arg ==
'--empty':
1010 pft.empty(**simplify)
1015 Apply tree transformations on a PYFT instance
1016 :param pft: PYFT instance
1017 :param arg: argument to deal with
1018 :param args: parsed argparsed arguments
1019 :param plotCentralFile: central file for plots
1021 if arg ==
'--plotCompilTree' and plotCentralFile
is not None:
1022 pft.tree.plotCompilTreeFromFile(plotCentralFile, args.plotCompilTree,
1023 args.plotMaxUpper, args.plotMaxLower)
1024 elif arg ==
'--plotExecTree' and plotCentralFile
is not None:
1025 pft.tree.plotExecTreeFromFile(plotCentralFile, args.plotExecTree,
1026 args.plotMaxUpper, args.plotMaxLower)
1031 Apply preprocessor transformations on a PYFT instance
1032 :param pft: PYFT instance
1033 :param arg: argument to deal with
1034 :param args: parsed argparsed arguments
1036 if arg ==
'--applyCPPifdef':
1037 pft.applyCPPifdef([k
for aList
in args.applyCPPifdef
for k
in aList])
1040if __name__ ==
"__main__":