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 ' +
563 gApplications.add_argument(
'--shugradTransfo', default=
False, action=
'store_true',
564 help=
'Transform shuman functions to call statements')
565 gApplications.add_argument(
'--mathFunctoBRFunc', default=
False, action=
'store_true',
566 help=
'Convert intrinsic math functions **, LOG, ATAN, **2, **3, ' +
567 '**4, EXP, COS, SIN, ATAN2 into a self defined function BR_ ' +
568 'for MesoNH bit-repro.')
569 gApplications.add_argument(
'--convertTypesInCompute', default=
False, action=
'store_true',
570 help=
'Use single variable instead of variable contained in ' +
571 'structure in compute statement for optimization issue ')
572 gApplications.add_argument(
'--buildModi', default=
False, action=
'store_true',
573 help=
'Builds the corresponding modi_ file')
574 gApplications.add_argument(
'--removeExtraDOinMnhDoConcurrent', default=
False,
576 help=
'Remove DO and ENDDO instructions inside !$mnh_do_concurrent')
577 gApplications.add_argument(
'--convertuseModuleToIncludes', default=
False,
579 help=
'Convert USE MODULE, ONLY: ROUTINE to #include routine.intfb.h')
584 Updates an argparse parser with openACC arguments
586 gOpenACC = parser.add_argument_group(
'OpenACC')
587 gOpenACC.add_argument(
'--addACCData', default=
False, action=
'store_true',
588 help=
'Add !$acc data present and !$acc end data directives')
589 gOpenACC.add_argument(
'--addACCRoutineSeq', default=
False, action=
'store_true',
590 help=
'Add "!$acc routine seq" to routines under stopScopes')
591 gOpenACC.add_argument(
'--craybyPassDOCONCURRENT', default=
False, action=
'store_true',
592 help=
'remove acc loop independant collapse for BR_ fonctions and ' +
593 'mnh_undef(OPENACC) macro' +
594 ' use DO CONCURRENT with mnh_undef(LOOP)')
595 gOpenACC.add_argument(
'--removeACC', default=
False, action=
'store_true',
596 help=
'remove all ACC directives')
597 gOpenACC.add_argument(
'--removebyPassDOCONCURRENT', default=
False, action=
'store_true',
598 help=
'remove macro !$mnh_(un)def(OPENACC) and !$mnh_(un)def(LOOP) ' +
600 gOpenACC.add_argument(
'--buildACCTypeHelpers', default=
False, action=
'store_true',
601 help=
'build module files containing helpers to copy user ' +
603 gOpenACC.add_argument(
'--allocatetoHIP', default=
False, action=
'store_true',
604 help=
'convert (DE)ALLOCATE to (DE)ALLOCATE_HIP on variables only sent ' +
605 'to the GPU via acc enter data copyin/create (for GPU AMD MI250X)')
610 Updates an argparse parser with checks arguments
613 gChecks = parser.add_argument_group(
'Check options')
614 gChecks.add_argument(
'--checkIMPLICIT', choices={
'Warn',
'Err'}, default=
None,
615 help=
'Send a warning or raise an error if the "IMPLICIT NONE" ' +
617 gChecks.add_argument(
'--checkINTENT', choices={
'Warn',
'Err'}, default=
None,
618 help=
'Send a warning or raise an error if the "INTENT" ' +
619 'attribute is missing for a dummy argument')
620 gChecks.add_argument(
'--checkOpInCall', choices={
'Warn',
'Err'}, default=
None,
621 help=
'Send a warning or raise an error if a call argument is an '
623 gChecks.add_argument(
'--checkUnusedLocalVar', choices={
'Warn',
'Err'}, default=
None,
624 help=
'Send a warning or raise an error if some local '
625 'variables are unused.')
626 gChecks.add_argument(
'--checkPHYEXUnusedLocalVar', choices={
'Warn',
'Err'}, default=
None,
627 help=
'Send a warning or raise an error if some local '
628 'variables are unused (excluding variables needed '
629 'for mnh_expand directives).')
630 gChecks.add_argument(
'--checkEmptyParensInCall', choices={
'Warn',
'Err'}, default=
None,
631 help=
'Send a warning or raise an error if a call argument is an '
632 'array with empty parens.')
633 gChecks.add_argument(
'--checkONLY', choices={
'Warn',
'Err'}, default=
None,
634 help=
'Send a warning or raise an error if a USE statement is not '
635 'followed by an ONLY clause.')
636 gChecks.add_argument(
'--checkKeyDim', choices={
'Warn',
'Err'}, default=
None,
637 help=
'Send a warning or raise an error if MERGE-based array '
638 'dimensions are inconsistent across scopes.')
639 gChecks.add_argument(
'--checkTopLevelUSE', choices={
'Warn',
'Err'}, default=
None,
640 help=
'Send a warning or raise an error if a USE statement in '
641 'top-level module is present')
646 Updates an argparse parser with statements arguments
649 gStatement = parser.add_argument_group(
'Statements options')
650 gStatement.add_argument(
'--removeCall', action=
'append',
651 help=
"Call to remove from the source code. The argument " +
652 "is the subprogram name")
653 gStatement.add_argument(
'--removePrints', default=
False, action=
'store_true',
654 help=
"Remove print statements from the source code.")
655 gStatement.add_argument(
'--inlineContainedSubroutines', default=
False, action=
'store_true',
656 help=
'Inline containted subroutines in main routine')
657 gStatement.add_argument(
'--setFalseIfStmt', default=
None,
658 help=
'Replace this value by .FALSE. in if statements')
659 gStatement.add_argument(
'--checkEmptyParensInMnhExpand', choices={
'Warn',
'Err'}, default=
None,
660 help=
'Send a warning or raise an error if an empty parens ' +
661 'is found in an mnh_expand directive.')
666 Updates an argparse parser with misc arguments
668 gMisc = parser.add_argument_group(
'Miscellaneous')
669 gMisc.add_argument(
'--showScopes', default=
False, action=
'store_true',
670 help=
'Show the different scopes found in the source code')
671 gMisc.add_argument(
'--empty', default=
False, action=
'store_true',
672 help=
'Empty the different scopes')
677 Updates an argparse parser with statements arguments
678 :param withPlotCentralFile: to add the --plotCentralFile argumen
679 :param treeIsOptional: is the --tree argument optional?
681 gTree = parser.add_argument_group(
'Tree')
682 gTree.add_argument(
'--tree', default=
None, action=
'append', required=
not treeIsOptional,
683 help=
'Directories where source code must be searched for')
684 gTree.add_argument(
'--descTree', default=
None, required=
not treeIsOptional,
685 help=
'File to write and/or read the description of the tree.')
686 if withPlotCentralFile:
687 gTree.add_argument(
'--plotCentralFile', default=
None, type=str,
688 help=
'Central file of the plot')
689 gTree.add_argument(
'--plotCompilTree', default=
None,
690 help=
'File name for compilation dependency graph (.dot or image extension)')
691 gTree.add_argument(
'--plotExecTree', default=
None,
692 help=
'File name for execution dependency graph (.dot or image extension)')
693 gTree.add_argument(
'--plotMaxUpper', default=
None, type=int,
694 help=
'Maximum number of upper elements in the plot tree')
695 gTree.add_argument(
'--plotMaxLower', default=
None, type=int,
696 help=
'Maximum number of lower elements in the plot tree')
697 gTree.add_argument(
'--stopScopes', default=
None, type=str,
698 help=
'#-separated list of scopes ' +
699 'where the recursive inclusion of an argument variable ' +
700 'must stop (needed for some transformations).')
705 Updates an argparse parser with statements arguments
707 gCpp = parser.add_argument_group(
'Preprocessor')
708 gCpp.add_argument(
'--applyCPPifdef', nargs=
'*', action=
'append',
709 help=
"This option is followed by the list of defined or undefined " +
711 "All #ifdef and #ifndef concerning these keys are evaluated. " +
712 "Undefined keys are preceded by a percentage sign.")
717 Apply transformation on a PYFT instance
718 :param pft: PYFT instance
719 :param arg: argument to deal with
720 :param args: parsed argparsed arguments
721 :param plotCentralFile: central file for plots
723 simplify = {
'simplify': args.simplify}
725 stopScopes = args.stopScopes.split(
'#')
if args.stopScopes
is not None else None
760 Apply file name transformations on a PYFT instance
761 :param pft: PYFT instance
762 :param arg: argument to deal with
763 :param args: parsed argparsed arguments
767 if arg ==
'--renamefF':
769 elif arg ==
'--renameFf':
775 Apply variables transformations on a PYFT instance
776 :param pft: PYFT instance
777 :param arg: argument to deal with
778 :param args: parsed argparsed arguments
779 :param simplify: kwargs to simplify
780 :param parserOptions: fxtran parser options
781 :param stopScopes: upper limit in call tree for some transformations
783 if arg ==
'--showVariables':
784 pft.varList.showVarList()
785 elif arg ==
'--attachArraySpecToEntity':
786 pft.attachArraySpecToEntity()
787 elif arg ==
'--removeVariable':
788 pft.removeVar(args.removeVariable, **simplify)
789 elif arg ==
'--addVariable':
790 pft.addVar([[v[0], v[1], v[2], (int(v[3])
if isint(v[3])
else None)]
791 for v
in args.addVariable])
792 elif arg ==
'--addModuleVariable':
793 pft.addModuleVar([[v[0], v[1], v[2]]
for v
in args.addModuleVariable])
794 elif arg ==
'--showUnusedVariables':
796 elif arg ==
'--removeUnusedLocalVariables':
797 pft.removeUnusedLocalVar(
798 [item.strip()
for item
in args.removeUnusedLocalVariables.split(
',')]
799 if args.removeUnusedLocalVariables !=
'NONE' else None, **simplify)
800 elif arg ==
'--removePHYEXUnusedLocalVariables':
801 pft.removePHYEXUnusedLocalVar(
802 [item.strip()
for item
in args.removePHYEXUnusedLocalVariables.split(
',')]
803 if args.removePHYEXUnusedLocalVariables !=
'NONE' else None, **simplify)
804 elif arg ==
'--addExplicitArrayBounds':
805 pft.addExplicitArrayBounds()
806 elif arg ==
'--addArrayParentheses':
807 pft.addArrayParentheses()
808 elif arg ==
'--modifyAutomaticArrays':
809 pft.modifyAutomaticArrays(*(args.modifyAutomaticArrays.split(
'#')))
810 elif arg ==
'--replaceAutomaticWithAllocatable':
811 pft.modifyAutomaticArrays(
812 "{type}, DIMENSION({doubledotshape}), ALLOCATABLE :: {name}",
813 "ALLOCATE({name}({shape}))",
"DEALLOCATE({name})")
814 elif arg ==
'--addArgInTree':
815 for varName, declStmt, pos
in args.addArgInTree:
816 pft.addArgInTree(varName, declStmt, int(pos), stopScopes,
817 parserOptions=parserOptions,
819 elif arg ==
'--addONLY':
820 pft.addONLY(parserOptions=parserOptions, wrapH=args.wrapH)
825 Apply applications transformations on a PYFT instance
826 :param pft: PYFT instance
827 :param arg: argument to deal with
828 :param args: parsed argparsed arguments
829 :param simplify: kwargs to simplify
830 :param parserOptions: fxtran parser options
831 :param stopScopes: upper limit in call tree for some transformations
833 if arg ==
'--addStack':
834 pft.addStack(args.addStack, stopScopes,
835 parserOptions=parserOptions,
837 elif arg ==
'--deleteDrHook':
838 pft.deleteDrHook(**simplify)
839 elif arg ==
'--addDrHook':
841 elif arg ==
'--deleteBudgetDDH':
842 pft.deleteBudgetDDH(**simplify)
843 elif arg ==
'--deleteRoutineCallsMesoNHGPU':
844 pft.deleteRoutineCallsMesoNHGPU(**simplify)
845 elif arg ==
'--deleteNonColumnCallsPHYEX':
846 pft.deleteNonColumnCallsPHYEX(**simplify)
847 elif arg ==
'--addMPPDB_CHECKS':
848 pft.addMPPDB_CHECKS()
849 elif arg ==
'--addPrints':
850 pft.addMPPDB_CHECKS(printsMode=
True)
851 elif arg ==
'--addSubmodulePHYEX':
852 pft.addSubmodulePHYEX()
855 assert not (args.mnhExpand
and args.mnhExpandConcurrent), \
856 "Only one of --mnhExpand and --mnhExpandConcurrent"
857 if arg ==
'--mnhExpand':
858 pft.removeArraySyntax(everywhere=
False, addAccIndependentCollapse=
False)
859 elif arg ==
'--mnhExpandConcurrent':
860 pft.removeArraySyntax(concurrent=
True, everywhere=
False)
861 elif arg ==
'--inlineContainedSubroutines':
862 pft.inlineContainedSubroutines(**simplify)
863 elif arg ==
'--inlineContainedSubroutinesPHYEX':
864 pft.inlineContainedSubroutinesPHYEX(**simplify)
865 elif arg ==
'--expandAllArrays':
866 pft.removeArraySyntax()
867 elif arg ==
'--expandAllArraysConcurrent':
868 pft.removeArraySyntax(concurrent=
True)
869 elif arg ==
'--expandAllArraysPHYEX':
870 pft.expandAllArraysPHYEX()
871 elif arg ==
'--expandAllArraysPHYEXConcurrent':
872 pft.expandAllArraysPHYEX(concurrent=
True)
873 elif arg ==
'--removeIJDim':
874 pft.removeIJDim(stopScopes,
875 parserOptions=parserOptions,
876 wrapH=args.wrapH, **simplify)
877 elif arg ==
'--shumanFUNCtoCALL':
878 pft.shumanFUNCtoCALL()
879 elif arg ==
'--shugradTransfo':
881 elif arg ==
'--buildACCTypeHelpers':
882 pft.buildACCTypeHelpers()
883 elif arg ==
'--mathFunctoBRFunc':
884 pft.mathFunctoBRFunc()
885 elif arg ==
'--convertTypesInCompute':
886 pft.convertTypesInCompute()
887 elif arg ==
'--buildModi':
889 elif arg ==
'--splitModuleRoutineFile':
890 pft.splitModuleRoutineFile()
891 elif arg ==
'--removeExtraDOinMnhDoConcurrent':
892 pft.removeExtraDOinMnhDoConcurrent()
893 elif arg ==
'--convertuseModuleToIncludes':
894 pft.convertuseModuleToIncludes()
899 Apply openACC transformations on a PYFT instance
900 :param pft: PYFT instance
901 :param arg: argument to deal with
902 :param args: parsed argparsed arguments
903 :param stopScopes: upper limit in call tree for some transformations
905 if arg ==
'--addACCData':
907 elif arg ==
'--craybyPassDOCONCURRENT':
908 pft.craybyPassDOCONCURRENT()
909 elif arg ==
'--removebyPassDOCONCURRENT':
910 pft.removebyPassDOCONCURRENT()
911 elif arg ==
'--addACCRoutineSeq':
912 pft.addACCRoutineSeq(stopScopes)
913 elif arg ==
'--removeACC':
915 elif arg ==
'--allocatetoHIP':
921 Apply cosmetics transformations on a PYFT instance
922 :param pft: PYFT instance
923 :param arg: argument to deal with
924 :param args: parsed argparsed arguments
926 if arg ==
'--upperCase':
928 elif arg ==
'--lowerCase':
930 elif arg ==
'--changeIfStatementsInIfConstructs':
931 pft.changeIfStatementsInIfConstructs()
932 elif arg ==
'--indent':
934 elif arg ==
'--removeIndent':
935 pft.indent(indentProgramunit=0, indentBranch=0)
936 elif arg ==
'--removeEmptyLines':
937 pft.removeEmptyLines()
938 elif arg ==
'--removeComments':
940 elif arg ==
'--updateSpaces':
942 elif arg
in ARG_UPDATE_CNT:
943 pft.updateContinuation(align=args.alignContinuation,
944 addBegin=args.addBeginContinuation,
945 removeBegin=args.removeBeginContinuation,
946 removeALL=args.removeALLContinuation)
947 elif arg ==
'--prettify':
950 pft.removeEmptyLines()
952 pft.updateContinuation()
953 elif arg ==
'--minify':
954 pft.indent(indentProgramunit=0, indentBranch=0)
957 pft.removeEmptyLines()
959 pft.updateContinuation(align=
False, removeALL=
True, addBegin=
False)
960 elif arg ==
'--removeEmptyCONTAINS':
961 pft.removeEmptyCONTAINS()
962 elif arg ==
'--formatModuleUse':
963 pft.formatModuleUse()
968 Apply checks transformations on a PYFT instance
969 :param pft: PYFT instance
970 :param arg: argument to deal with
971 :param args: parsed argparsed arguments
972 :param stopScopes: list of scope paths or None
974 if arg ==
'--checkIMPLICIT':
975 pft.checkImplicitNone(args.checkIMPLICIT ==
'Err')
976 elif arg ==
'--checkINTENT':
977 pft.checkIntent(args.checkINTENT ==
'Err')
978 elif arg ==
'--checkOpInCall':
979 pft.checkOpInCall(args.checkOpInCall ==
'Err')
980 elif arg ==
'--checkUnusedLocalVar':
981 pft.checkUnusedLocalVar(args.checkUnusedLocalVar ==
'Err')
982 elif arg ==
'--checkPHYEXUnusedLocalVar':
983 pft.checkPHYEXUnusedLocalVar(args.checkPHYEXUnusedLocalVar ==
'Err')
984 elif arg ==
'--checkEmptyParensInCall':
985 pft.checkEmptyParensInCall(args.checkEmptyParensInCall ==
'Err')
986 elif arg ==
'--checkONLY':
987 pft.checkONLY(args.checkONLY ==
'Err')
988 elif arg ==
'--checkKeyDim':
989 pft.checkKeyDimConsistency(args.checkKeyDim ==
'Err',
990 stopScopes=stopScopes)
991 elif arg ==
'--checkTopLevelUSE':
992 pft.checkTopLevelUSE(args.checkTopLevelUSE ==
'Err')
993 elif arg ==
'--checkEmptyParensInMnhExpand':
994 pft.checkEmptyParensInMnhExpand(args.checkEmptyParensInMnhExpand ==
'Err')
999 Apply statements transformations on a PYFT instance
1000 :param pft: PYFT instance
1001 :param arg: argument to deal with
1002 :param args: parsed argparsed arguments
1003 :param simplify: kwargs to simplify
1005 if arg ==
'--removeCall':
1006 for rc
in args.removeCall:
1007 pft.removeCall(rc, **simplify)
1008 elif arg ==
'--removePrints':
1009 pft.removePrints(**simplify)
1010 elif arg ==
'--setFalseIfStmt':
1011 pft.setFalseIfStmt(args.setFalseIfStmt, **simplify)
1016 Apply misc transformations on a PYFT instance
1017 :param pft: PYFT instance
1018 :param arg: argument to deal with
1019 :param args: parsed argparsed arguments
1020 :param simplify: kwargs to simplify
1022 if arg ==
'--showScopes':
1023 pft.showScopesList()
1024 elif arg ==
'--empty':
1025 pft.empty(**simplify)
1030 Apply tree transformations on a PYFT instance
1031 :param pft: PYFT instance
1032 :param arg: argument to deal with
1033 :param args: parsed argparsed arguments
1034 :param plotCentralFile: central file for plots
1036 if arg ==
'--plotCompilTree' and plotCentralFile
is not None:
1037 pft.tree.plotCompilTreeFromFile(plotCentralFile, args.plotCompilTree,
1038 args.plotMaxUpper, args.plotMaxLower)
1039 elif arg ==
'--plotExecTree' and plotCentralFile
is not None:
1040 pft.tree.plotExecTreeFromFile(plotCentralFile, args.plotExecTree,
1041 args.plotMaxUpper, args.plotMaxLower)
1046 Apply preprocessor transformations on a PYFT instance
1047 :param pft: PYFT instance
1048 :param arg: argument to deal with
1049 :param args: parsed argparsed arguments
1051 if arg ==
'--applyCPPifdef':
1052 pft.applyCPPifdef([k
for aList
in args.applyCPPifdef
for k
in aList])
1055if __name__ ==
"__main__":