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
63 class MyManager(BaseManager):
65 Custom manager to deal with Tree instances
68 MyManager.register(
'Tree', Tree)
81 parser = argparse.ArgumentParser(description=
'Python FORTRAN tool', allow_abbrev=
False,
82 epilog=
"The argument order matters.")
84 updateParser(parser, withInput=
False, withOutput=
False, withXml=
False, withPlotCentralFile=
True,
85 treeIsOptional=
False, nbPar=
True, restrictScope=
False)
86 commonArgs, getFileArgs =
getArgs(parser)
89 with MyManager()
as manager:
94 PYFT.setParallel(sharedTree)
97 allFileArgs = {file: getFileArgs(file)
for file
in sharedTree.getFiles()}
98 logging.info(
'Executing in parallel on %i files with a maximum of %i processes',
99 len(allFileArgs), commonArgs.nbPar)
100 with Pool(commonArgs.nbPar, initializer=init, initargs=(PYFT, allFileArgs))
as pool:
101 result = pool.map(task, sharedTree.getFiles())
104 sharedTree.toJson(commonArgs.descTree)
107 errors = [item[1]
for item
in result
if item[0] != 0]
110 logging.error(
'List of files with error:')
112 logging.error(
' - %s', error)
113 raise PYFTError(f
"Errors have been reported in {status} file(s).")
118 Core of the pyfortool.py command
120 parser = argparse.ArgumentParser(description=
'Python FORTRAN tool', allow_abbrev=
False,
121 epilog=
"The argument order matters.")
123 updateParser(parser, withInput=
True, withOutput=
True, withXml=
True, withPlotCentralFile=
False,
124 treeIsOptional=
True, nbPar=
False, restrictScope=
True)
125 args, orderedOptions =
getArgs(parser)[1]()
132 pft =
PYFT(args.INPUT, args.OUTPUT, parserOptions=parserOptions,
133 verbosity=args.logLevel, wrapH=args.wrapH, tree=descTree,
134 enableCache=args.enableCache)
135 if args.restrictScope !=
'':
136 pft = pft.getScopeNode(args.restrictScope)
139 for arg
in orderedOptions:
140 logging.debug(
'Applying %s on %s', arg, args.INPUT)
141 applyTransfo(pft, arg, args, plotCentralFile=args.INPUT)
142 logging.debug(
' -> Done')
145 if descTree
is not None:
146 descTree.toJson(args.descTree)
147 if args.xml
is not None:
148 pft.mainScope.writeXML(args.xml)
150 pft.mainScope.write()
153 pft.mainScope.close()
157 logging.error(
"The following error has occurred in the file %s", args.INPUT)
161ARG_UPDATE_CNT = (
'--alignContinuation',
'--addBeginContinuation',
162 '--removeBeginContinuation',
163 '--emoveALLContinuation')
168 Parse arguments and interpret the --optsByEnv option
169 :param parser: argparse parser
170 :return: a tuple with
171 - an argparse namespace containing common arguments (not using the --optsEnv option)
172 - a function taking a filename as input and returning
173 - an argparse namespace with the common arguments and the ones added by
174 interpreting the --optsEnv option
175 - an ordered list of arguments
177 args = parser.parse_args()
179 def getFileArgs(filename=args.INPUT if hasattr(args,
'INPUT')
else None):
181 :param filename: name of source code file
182 :return: argparse namespace to use with this file and
183 a list given the order in which the arguments were provided
186 arguments = sys.argv[1:]
187 if args.optsByEnv
is not None:
189 for line
in []
if args.optsByEnv
is None else os.environ[args.optsByEnv].split(
'\n'):
191 if re.match(line.split(
':=:')[0], filename):
192 extra = line.split(
':=:')[1]
195 index = arguments.index(
'--optsByEnv')
196 arguments = arguments[:index] + shlex.split(extra) + arguments[index + 2:]
201 for arg
in arguments:
202 if arg.startswith(
'--')
and arg
not in optList:
203 if arg
in ARG_UPDATE_CNT:
210 return parser.parse_args(arguments), optList
212 return args, getFileArgs
217 Get the options to use for the fxtran parser
218 :param args: arguments parsed by the argparse parser
220 if args.parserOption
is None:
221 parserOptions = PYFT.DEFAULT_FXTRAN_OPTIONS.copy()
223 parserOptions = [el
for elements
in args.parserOption
for el
in elements]
225 parserOptions = [opt
for opt
in parserOptions
if opt
not in (
'-no-include',
'-noinclude')]
231 get the Tree object built with the parsed arguments
232 :param args: arguments parsed by the argparse parser
233 :param cls: class to use (usefull for manager)
234 :return: a Tree instance
238 descTree = cls(tree=args.tree, descTreeFile=args.descTree,
239 parserOptions=parserOptions,
240 wrapH=args.wrapH, verbosity=args.logLevel)
246def updateParser(parser, withInput, withOutput, withXml, withPlotCentralFile, treeIsOptional,
247 nbPar, restrictScope):
249 Updates an argparse parser with arguments common to all the different tools
250 :param parser: parser in which arguments are added
251 :param withOutput: do we need the INPUT argument
252 :param withOutput: do we need the OUTPUT argument
253 :param withXml: do we need to be able to define an XML output file
254 :param withPlotCentralFile: to add the --plotCentralFile argument
255 :param treeIsOptional: is the --tree argument optional?
256 :param nbPar: number of parallel processes
257 :param restrictScope: can we specify the scope path
268 assert not parser.allow_abbrev,
'parser must be created with allow_abbrev=False'
270 parser.add_argument(
'--version', action=
'version',
271 version=
'%(prog)s {version}'.format(version=__version__))
272 parser.add_argument(
'--simplify', default=
False, action=
'store_true',
273 help=
'After a deletion, recursively deletes the code ' +
274 'and variables that have become useless')
275 parser.add_argument(
'--logLevel', default=
'warning',
276 help=
'Provide logging level. Example --logLevel debug (default is warning)')
277 parser.add_argument(
'--enableCache', default=
False, action=
'store_true',
278 help=
'Precompute parent of each xml node and store the result')
280 parser.add_argument(
'--nbPar', default=cpu_count(), type=int,
281 help=
'Number of parallel processes, 0 to get as many processes ' +
282 'as the number of cores (default=0)')
283 parser.add_argument(
'--optsByEnv', default=
None, type=str,
284 help=
'Name of the environment variable containing additional arguments ' +
285 'to use. These arguments are processed after all other arguments. ' +
286 'The variable can contain a multi-lines string. The ' +
287 'variable is read line by line and the last applicable line is ' +
288 'used. A line can take one of these two forms: ' +
289 '1) "FILE_DESCRIPTOR:=:OPTIONS" (where FILE_DESCRIPTOR is a ' +
290 'regular expression to test against the filename. If there ' +
291 'is a match, the OPTIONS can be used for the file) and ' +
292 '2) "OPTIONS" (if the line doesn\'t contain the FILE_DESCRIPTOR ' +
293 'part, it applies to all source code).')
296 parser.add_argument(
'--restrictScope', default=
'', type=str, metavar=
'SCOPEPATH',
297 help=
"Limit the action to this scope path (SUBROUTINE/FUNCTION/" +
298 "MODULE/TYPE). It is '/'-separated path with each element " +
299 "having the form 'module:<name of the module>', " +
300 "'sub:<name of the subroutine>', " +
301 "'func:<name of the function>' or 'type:<name of the type>'.")
339 Updates an argparse parser with input/output arguments
340 :param parser: parser in which arguments are added
341 :param withOutput: do we need the INPUT argument
342 :param withOutput: do we need the OUTPUT argument
343 :param withXml: do we need to be able to define an XML output file
345 gInOut = parser.add_argument_group(
'Input and output')
347 gInOut.add_argument(
'INPUT', help=
'FORTRAN input file')
349 gInOut.add_argument(
'OUTPUT', default=
None, help=
'FORTRAN output file', nargs=
'?')
350 gInOut.add_argument(
'--renamefF', default=
False, action=
'store_true',
351 help=
'Put file extension in upper case')
352 gInOut.add_argument(
'--renameFf', default=
False, action=
'store_true',
353 help=
'Put file extension in lower case')
355 gInOut.add_argument(
'--xml', default=
None, type=str,
356 help=
'Output file for xml')
357 gInOut.add_argument(
'--dryRun', default=
False, action=
'store_true',
358 help=
'Dry run without writing the FORTRAN file (the xml ' +
364 Updates an argparse parser with fxtran arguments
366 gParser = parser.add_argument_group(
'fxtran parser relative options')
367 gParser.add_argument(
'--parserOption', nargs=
'*', action=
'append',
368 help=
'Option to pass to fxtran, defaults ' +
369 f
'to {PYFT.DEFAULT_FXTRAN_OPTIONS}')
370 gParser.add_argument(
'--wrapH', default=
False, action=
'store_true',
371 help=
'Wrap .h file content into a MODULE to enable the reading')
376 Updates an argparse parser with variables arguments
378 gVariables = parser.add_argument_group(
'Options to deal with variables')
379 gVariables.add_argument(
'--showVariables', default=
False, action=
'store_true',
380 help=
'Show the declared variables')
381 gVariables.add_argument(
'--removeVariable', nargs=2, action=
'append',
382 metavar=(
'SCOPEPATH',
'VARNAME'),
383 help=
"Variable to remove from declaration. The first argument " +
384 "is the SUBROUTINE/FUNCTION/MODULE/TYPE where the variable " +
385 "is declared. It is '/'-separated path with each element having " +
386 "the form 'module:<name of the module>', " +
387 "'sub:<name of the subroutine>', " +
388 "'func:<name of the function>' or 'type:<name of the type>'. " +
389 "The second argument is the variable name")
390 gVariables.add_argument(
'--attachArraySpecToEntity', default=
False, action=
'store_true',
391 help=
'Find all T-decl-stmt elements that have a child element ' +
392 'attribute with attribute-N=DIMENSION and move the attribute ' +
393 'into EN-N elements')
394 gVariables.add_argument(
'--addVariable', nargs=4, action=
'append',
395 metavar=(
'SCOPEPATH',
'VARNAME',
'DECLARATION',
'POSITION'),
396 help=
'Add a variable. First argument is the scope path (as for ' +
397 'the --removeVariable option. The second is the variable ' +
398 'name, the third is the declarative statement to insert, ' +
399 'the fourth is the position (python indexing) the new ' +
400 'variable will have in the calling statment of the ' +
401 'routine (non-integer value for a local variable).')
402 gVariables.add_argument(
'--addModuleVariable', nargs=3, action=
'append',
403 metavar=(
'SCOPEPATH',
'MODULENAME',
'VARNAME'),
404 help=
'Add a USE statement. The first argument is the scope path ' +
405 '(as for the --removeVariable option). The second is the module ' +
406 'name; the third is the variable name.')
407 gVariables.add_argument(
'--showUnusedVariables', default=
False, action=
'store_true',
408 help=
'Show a list of unused variables.')
409 gVariables.add_argument(
'--removeUnusedLocalVariables',
410 help=
'Remove unused local variables, excluding some variables (comma-' +
411 'separated list or NONE to exclude nothing).')
412 gVariables.add_argument(
'--removePHYEXUnusedLocalVariables',
413 help=
'Remove unused local variables, excluding some variables (comma-' +
414 'separated list or NONE to exclude nothing). This option takes ' +
415 'into account the mnh_expand directives to prevent from ' +
416 'removing useful variables.')
417 gVariables.add_argument(
'--addExplicitArrayBounds', action=
'store_true',
418 help=
'Adds explicit bounds to arrays that already have parentheses.')
419 gVariables.add_argument(
'--addArrayParentheses', action=
'store_true',
420 help=
'Adds parentheses to arrays (A => A(:))')
421 gVariables.add_argument(
'--modifyAutomaticArrays', metavar=
"DECL#START#END",
422 help=
'Transform all automatic arrays declaration using the templates.' +
423 ' The DECL part of the template will replace the declaration ' +
424 'statement, the START part will be inserted as the first ' +
425 'executable statement while the END part will be inserted as ' +
426 'the last executable statement. Each part ' +
427 'of the template can use the following place holders: ' +
428 '"{doubledotshape}", "{shape}", "{lowUpList}", "{name}" and ' +
429 '"{type}" which are, respectively modified into ' +
430 '":, :, :", "I, I:J, 0:I", "1, I, I, J, 0, I", "A", "REAL" ' +
431 'if the original declaration statement ' +
432 'was "A(I, I:J, 0:I)". For example, the template ' +
433 '"{type}, DIMENSION({doubledotshape}), ALLOCATABLE :: ' +
434 '{name}#ALLOCATE({name}({shape}))#DEALLOCATE({name})"' +
435 'will replace automatic arrays by allocatables.')
436 gVariables.add_argument(
'--replaceAutomaticWithAllocatable', action=
'store_true',
437 help=
'Replace all automatic arrays with allocatable arrays.')
438 gVariables.add_argument(
'--addArgInTree', default=
None, action=
'append', nargs=3,
439 metavar=(
'VARNAME',
'DECLARATION',
'POSITION'),
440 help=
'Add an argument variable. The first argument is the variable ' +
441 'name, the second one is the declarative statement to insert, ' +
442 'the third one is the position (python indexing) the new ' +
443 'variable will have in the calling statement of the ' +
444 'routine. Needs the --stopScopes argument')
445 gVariables.add_argument(
'--addONLY', default=
False, action=
'store_true',
446 help=
'Add missing ONLY clause to USE statements.')
451 Updates an argparse parser with cosmetics arguments
453 gCosmetics = parser.add_argument_group(
'Cosmetics options')
454 gCosmetics.add_argument(
'--upperCase', default=
False, action=
'store_true',
455 help=
'Put FORTRAN code in upper case letters')
456 gCosmetics.add_argument(
'--lowerCase', default=
False, action=
'store_true',
457 help=
'Put FORTRAN code in lower case letters')
458 gCosmetics.add_argument(
'--changeIfStatementsInIfConstructs', default=
False,
460 help=
'Find all if-statement and convert it to if-then-statement')
461 gCosmetics.add_argument(
'--indent', default=
False, action=
'store_true',
462 help=
'Correct indentation')
463 gCosmetics.add_argument(
'--removeIndent', default=
False, action=
'store_true',
464 help=
'Remove indentation')
465 gCosmetics.add_argument(
'--removeEmptyLines', default=
False, action=
'store_true',
466 help=
'Remove empty lines')
467 gCosmetics.add_argument(
'--removeComments', default=
False, action=
'store_true',
468 help=
'Remove comments')
469 gCosmetics.add_argument(
'--updateSpaces', default=
False, action=
'store_true',
470 help=
'Updates spaces around operators, commas, parenthesis and ' +
471 'at the end of line')
472 gCosmetics.add_argument(
'--alignContinuation', default=
False, action=
'store_true',
473 help=
'Align the beginings of continued lines')
474 gCosmetics.add_argument(
'--addBeginContinuation', default=
False, action=
'store_true',
475 help=
'Add missing continuation characters (\'&\') at the ' +
477 gCosmetics.add_argument(
'--removeBeginContinuation', default=
False, action=
'store_true',
478 help=
'Remove continuation characters (\'&\') at the begining of lines')
479 gCosmetics.add_argument(
'--removeALLContinuation', default=
False, action=
'store_true',
480 help=
'Remove all continuation characters(\'&\')')
481 gCosmetics.add_argument(
'--prettify', default=
False, action=
'store_true',
482 help=
'Prettify the source code (indentation, spaces...)')
483 gCosmetics.add_argument(
'--minify', default=
False, action=
'store_true',
484 help=
'Simplify the source code (indentation, spaces...)')
485 gCosmetics.add_argument(
'--removeEmptyCONTAINS', default=
False, action=
'store_true',
486 help=
'Remove useless CONTAINS statements')
491 Updates an argparse parser with applications arguments
493 gApplications = parser.add_argument_group(
'Options to apply upper level transformation')
494 gApplications.add_argument(
'--deleteDrHook', default=
False, action=
'store_true',
495 help=
'Delete DR HOOK use')
496 gApplications.add_argument(
'--addDrHook', default=
False, action=
'store_true',
498 gApplications.add_argument(
'--deleteBudgetDDH', default=
False, action=
'store_true',
499 help=
'Delete Budget/DDH use')
500 gApplications.add_argument(
'--deleteRoutineCallsMesoNHGPU', default=
False, action=
'store_true',
501 help=
'Delete parts of the code not compatible with MesoNH-OpenACC' +
502 'such as OCND2 blocks')
503 gApplications.add_argument(
'--splitModuleRoutineFile', default=
False, action=
'store_true',
505 gApplications.add_argument(
'--deleteNonColumnCallsPHYEX', default=
False, action=
'store_true',
506 help=
'Delete call to PHYEX routines that needs information on ' +
507 'horizontal points (multiple column dependency')
508 gApplications.add_argument(
'--removeIJDim', default=
False, action=
'store_true',
509 help=
'Remove I and J dimensions (1, KLON). ' +
510 'Needs the --stopScopes argument.')
511 gApplications.add_argument(
'--expandAllArraysPHYEX', default=
False, action=
'store_true',
512 help=
'Expand all array syntax (computing and where block) ' +
513 'using PHYEX conventions')
514 gApplications.add_argument(
'--expandAllArraysPHYEXConcurrent', default=
False,
516 help=
'Expand all array syntax with DO CONCURRENT loops ' +
517 '(computing and where block) using PHYEX conventions')
518 gApplications.add_argument(
'--expandAllArrays', default=
False, action=
'store_true',
519 help=
'Expand all array syntax (computing and where block) ' +
520 'using mnh directives if present')
521 gApplications.add_argument(
'--expandAllArraysConcurrent', default=
False, action=
'store_true',
522 help=
'Expand all array syntax with DO CONCURRENT loops ' +
523 '(computing and where block) using mnh directives if present')
524 gApplications.add_argument(
'--inlineContainedSubroutinesPHYEX', default=
False,
526 help=
'Inline containted subroutines in main routine, using ' +
528 gApplications.add_argument(
'--addStack', metavar=
'MODEL', type=str,
529 help=
'Add local arrays to the stack. The argument is the ' +
530 'the model name in which stack must be added ("AROME" ' +
531 'or "MESONH"). Needs the --stopScopes argument for AROME.')
532 gApplications.add_argument(
'--addIncludes', default=
False, action=
'store_true',
533 help=
'Add .h includes in the file and remove the INCLUDE statement')
534 gApplications.add_argument(
'--addSubmodulePHYEX', default=
False, action=
'store_true',
535 help=
'Add SUBMODULE and INTERFACE of subroutines in PHYEX')
536 gApplications.add_argument(
'--mnhExpand', default=
False, action=
'store_true',
537 help=
'Apply the mnh_expand directives with DO loops')
538 gApplications.add_argument(
'--mnhExpandConcurrent', default=
False, action=
'store_true',
539 help=
'Apply the mnh_expand directives with DO CONCURRENT loops')
540 gApplications.add_argument(
'--addMPPDB_CHECKS', default=
False, action=
'store_true',
541 help=
'Add MPPDB_CHEKS bit-repro checking routines of MesoNH for ' +
542 'all in and inout arrays in subroutines')
543 gApplications.add_argument(
'--addPrints', default=
False, action=
'store_true',
544 help=
'Add Prints of min/maxval and shape of all in, out, inout ' +
545 'arguments of all scopes')
546 gApplications.add_argument(
'--shumanFUNCtoCALL', default=
False, action=
'store_true',
547 help=
'Transform shuman functions to call statements')
548 gApplications.add_argument(
'--mathFunctoBRFunc', default=
False, action=
'store_true',
549 help=
'Convert intrinsic math functions **, LOG, ATAN, **2, **3, ' +
550 '**4, EXP, COS, SIN, ATAN2 into a self defined function BR_ ' +
551 'for MesoNH bit-repro.')
552 gApplications.add_argument(
'--convertTypesInCompute', default=
False, action=
'store_true',
553 help=
'Use single variable instead of variable contained in ' +
554 'structure in compute statement for optimization issue ')
555 gApplications.add_argument(
'--buildModi', default=
False, action=
'store_true',
556 help=
'Builds the corresponding modi_ file')
557 gApplications.add_argument(
'--removeExtraDOinMnhDoConcurrent', default=
False,
559 help=
'Remove DO and ENDDO instructions inside !$mnh_do_concurrent')
560 gApplications.add_argument(
'--convertuseModuleToIncludes', default=
False,
562 help=
'Convert USE MODULE, ONLY: ROUTINE to #include routine.intfb.h')
567 Updates an argparse parser with openACC arguments
569 gOpenACC = parser.add_argument_group(
'OpenACC')
570 gOpenACC.add_argument(
'--addACCData', default=
False, action=
'store_true',
571 help=
'Add !$acc data present and !$acc end data directives')
572 gOpenACC.add_argument(
'--addACCRoutineSeq', default=
False, action=
'store_true',
573 help=
'Add "!$acc routine seq" to routines under stopScopes')
574 gOpenACC.add_argument(
'--craybyPassDOCONCURRENT', default=
False, action=
'store_true',
575 help=
'remove acc loop independant collapse for BR_ fonctions and ' +
576 'mnh_undef(OPENACC) macro' +
577 ' use DO CONCURRENT with mnh_undef(LOOP)')
578 gOpenACC.add_argument(
'--removeACC', default=
False, action=
'store_true',
579 help=
'remove all ACC directives')
580 gOpenACC.add_argument(
'--removebyPassDOCONCURRENT', default=
False, action=
'store_true',
581 help=
'remove macro !$mnh_(un)def(OPENACC) and !$mnh_(un)def(LOOP) ' +
583 gOpenACC.add_argument(
'--buildACCTypeHelpers', default=
False, action=
'store_true',
584 help=
'build module files containing helpers to copy user ' +
586 gOpenACC.add_argument(
'--allocatetoHIP', default=
False, action=
'store_true',
587 help=
'convert (DE)ALLOCATE to (DE)ALLOCATE_HIP on variables only sent ' +
588 'to the GPU via acc enter data copyin/create (for GPU AMD MI250X)')
593 Updates an argparse parser with checks arguments
596 gChecks = parser.add_argument_group(
'Check options')
597 gChecks.add_argument(
'--checkIMPLICIT', choices={
'Warn',
'Err'}, default=
None,
598 help=
'Send a warning or raise an error if the "IMPLICIT NONE" ' +
600 gChecks.add_argument(
'--checkINTENT', choices={
'Warn',
'Err'}, default=
None,
601 help=
'Send a warning or raise an error if the "INTENT" ' +
602 'attribute is missing for a dummy argument')
603 gChecks.add_argument(
'--checkOpInCall', choices={
'Warn',
'Err'}, default=
None,
604 help=
'Send a warning or raise an error if a call argument is an '
606 gChecks.add_argument(
'--checkUnusedLocalVar', choices={
'Warn',
'Err'}, default=
None,
607 help=
'Send a warning or raise an error if some local '
608 'variables are unused.')
609 gChecks.add_argument(
'--checkPHYEXUnusedLocalVar', choices={
'Warn',
'Err'}, default=
None,
610 help=
'Send a warning or raise an error if some local '
611 'variables are unused (excluding variables needed '
612 'for mnh_expand directives).')
613 gChecks.add_argument(
'--checkEmptyParensInCall', choices={
'Warn',
'Err'}, default=
None,
614 help=
'Send a warning or raise an error if a call argument is an '
615 'array with empty parens.')
616 gChecks.add_argument(
'--checkONLY', choices={
'Warn',
'Err'}, default=
None,
617 help=
'Send a warning or raise an error if a USE statement is not '
618 'followed by an ONLY clause.')
623 Updates an argparse parser with statements arguments
626 gStatement = parser.add_argument_group(
'Statements options')
627 gStatement.add_argument(
'--removeCall', action=
'append',
628 help=
"Call to remove from the source code. The argument " +
629 "is the subprogram name")
630 gStatement.add_argument(
'--removePrints', default=
False, action=
'store_true',
631 help=
"Remove print statements from the source code.")
632 gStatement.add_argument(
'--inlineContainedSubroutines', default=
False, action=
'store_true',
633 help=
'Inline containted subroutines in main routine')
634 gStatement.add_argument(
'--setFalseIfStmt', default=
None,
635 help=
'Replace this value by .FALSE. in if statements')
640 Updates an argparse parser with misc arguments
642 gMisc = parser.add_argument_group(
'Miscellaneous')
643 gMisc.add_argument(
'--showScopes', default=
False, action=
'store_true',
644 help=
'Show the different scopes found in the source code')
645 gMisc.add_argument(
'--empty', default=
False, action=
'store_true',
646 help=
'Empty the different scopes')
651 Updates an argparse parser with statements arguments
652 :param withPlotCentralFile: to add the --plotCentralFile argumen
653 :param treeIsOptional: is the --tree argument optional?
655 gTree = parser.add_argument_group(
'Tree')
656 gTree.add_argument(
'--tree', default=
None, action=
'append', required=
not treeIsOptional,
657 help=
'Directories where source code must be searched for')
658 gTree.add_argument(
'--descTree', default=
None, required=
not treeIsOptional,
659 help=
'File to write and/or read the description of the tree.')
660 if withPlotCentralFile:
661 gTree.add_argument(
'--plotCentralFile', default=
None, type=str,
662 help=
'Central file of the plot')
663 gTree.add_argument(
'--plotCompilTree', default=
None,
664 help=
'File name for compilation dependency graph (.dot or image extension)')
665 gTree.add_argument(
'--plotExecTree', default=
None,
666 help=
'File name for execution dependency graph (.dot or image extension)')
667 gTree.add_argument(
'--plotMaxUpper', default=
None, type=int,
668 help=
'Maximum number of upper elements in the plot tree')
669 gTree.add_argument(
'--plotMaxLower', default=
None, type=int,
670 help=
'Maximum number of lower elements in the plot tree')
671 gTree.add_argument(
'--stopScopes', default=
None, type=str,
672 help=
'#-separated list of scopes ' +
673 'where the recursive inclusion of an argument variable ' +
674 'must stop (needed for some transformations).')
679 Updates an argparse parser with statements arguments
681 gCpp = parser.add_argument_group(
'Preprocessor')
682 gCpp.add_argument(
'--applyCPPifdef', nargs=
'*', action=
'append',
683 help=
"This option is followed by the list of defined or undefined " +
685 "All #ifdef and #ifndef concerning these keys are evaluated. " +
686 "Undefined keys are preceded by a percentage sign.")
691 Apply transformation on a PYFT instance
692 :param pft: PYFT instance
693 :param arg: argument to deal with
694 :param args: parsed argparsed arguments
695 :param plotCentralFile: central file for plots
697 simplify = {
'simplify': args.simplify}
699 stopScopes = args.stopScopes.split(
'#')
if args.stopScopes
is not None else None
734 Apply file name transformations on a PYFT instance
735 :param pft: PYFT instance
736 :param arg: argument to deal with
737 :param args: parsed argparsed arguments
741 if arg ==
'--renamefF':
743 elif arg ==
'--renameFf':
749 Apply variables transformations on a PYFT instance
750 :param pft: PYFT instance
751 :param arg: argument to deal with
752 :param args: parsed argparsed arguments
753 :param simplify: kwargs to simplify
754 :param parserOptions: fxtran parser options
755 :param stopScopes: upper limit in call tree for some transformations
757 if arg ==
'--showVariables':
758 pft.varList.showVarList()
759 elif arg ==
'--attachArraySpecToEntity':
760 pft.attachArraySpecToEntity()
761 elif arg ==
'--removeVariable':
762 pft.removeVar(args.removeVariable, **simplify)
763 elif arg ==
'--addVariable':
764 pft.addVar([[v[0], v[1], v[2], (int(v[3])
if isint(v[3])
else None)]
765 for v
in args.addVariable])
766 elif arg ==
'--addModuleVariable':
767 pft.addModuleVar([[v[0], v[1], v[2]]
for v
in args.addModuleVariable])
768 elif arg ==
'--showUnusedVariables':
770 elif arg ==
'--removeUnusedLocalVariables':
771 pft.removeUnusedLocalVar(
772 [item.strip()
for item
in args.removeUnusedLocalVariables.split(
',')]
773 if args.removeUnusedLocalVariables !=
'NONE' else None, **simplify)
774 elif arg ==
'--removePHYEXUnusedLocalVariables':
775 pft.removePHYEXUnusedLocalVar(
776 [item.strip()
for item
in args.removePHYEXUnusedLocalVariables.split(
',')]
777 if args.removePHYEXUnusedLocalVariables !=
'NONE' else None, **simplify)
778 elif arg ==
'--addExplicitArrayBounds':
779 pft.addExplicitArrayBounds()
780 elif arg ==
'--addArrayParentheses':
781 pft.addArrayParentheses()
782 elif arg ==
'--modifyAutomaticArrays':
783 pft.modifyAutomaticArrays(*(args.modifyAutomaticArrays.split(
'#')))
784 elif arg ==
'--replaceAutomaticWithAllocatable':
785 pft.modifyAutomaticArrays(
786 "{type}, DIMENSION({doubledotshape}), ALLOCATABLE :: {name}",
787 "ALLOCATE({name}({shape}))",
"DEALLOCATE({name})")
788 elif arg ==
'--addArgInTree':
789 for varName, declStmt, pos
in args.addArgInTree:
790 pft.addArgInTree(varName, declStmt, int(pos), stopScopes,
791 parserOptions=parserOptions,
793 elif arg ==
'--addONLY':
794 pft.addONLY(parserOptions=parserOptions, wrapH=args.wrapH)
799 Apply applications transformations on a PYFT instance
800 :param pft: PYFT instance
801 :param arg: argument to deal with
802 :param args: parsed argparsed arguments
803 :param simplify: kwargs to simplify
804 :param parserOptions: fxtran parser options
805 :param stopScopes: upper limit in call tree for some transformations
807 if arg ==
'--addStack':
808 pft.addStack(args.addStack, stopScopes,
809 parserOptions=parserOptions,
811 elif arg ==
'--deleteDrHook':
812 pft.deleteDrHook(**simplify)
813 elif arg ==
'--addDrHook':
815 elif arg ==
'--deleteBudgetDDH':
816 pft.deleteBudgetDDH(**simplify)
817 elif arg ==
'--deleteRoutineCallsMesoNHGPU':
818 pft.deleteRoutineCallsMesoNHGPU(**simplify)
819 elif arg ==
'--deleteNonColumnCallsPHYEX':
820 pft.deleteNonColumnCallsPHYEX(**simplify)
821 elif arg ==
'--addMPPDB_CHECKS':
822 pft.addMPPDB_CHECKS()
823 elif arg ==
'--addPrints':
824 pft.addMPPDB_CHECKS(printsMode=
True)
825 elif arg ==
'--addSubmodulePHYEX':
826 pft.addSubmodulePHYEX()
829 assert not (args.mnhExpand
and args.mnhExpandConcurrent), \
830 "Only one of --mnhExpand and --mnhExpandConcurrent"
831 if arg ==
'--mnhExpand':
832 pft.removeArraySyntax(everywhere=
False, addAccIndependentCollapse=
False)
833 elif arg ==
'--mnhExpandConcurrent':
834 pft.removeArraySyntax(concurrent=
True, everywhere=
False)
835 elif arg ==
'--inlineContainedSubroutines':
836 pft.inlineContainedSubroutines(**simplify)
837 elif arg ==
'--inlineContainedSubroutinesPHYEX':
838 pft.inlineContainedSubroutinesPHYEX(**simplify)
839 elif arg ==
'--expandAllArrays':
840 pft.removeArraySyntax()
841 elif arg ==
'--expandAllArraysConcurrent':
842 pft.removeArraySyntax(concurrent=
True)
843 elif arg ==
'--expandAllArraysPHYEX':
844 pft.expandAllArraysPHYEX()
845 elif arg ==
'--expandAllArraysPHYEXConcurrent':
846 pft.expandAllArraysPHYEX(concurrent=
True)
847 elif arg ==
'--removeIJDim':
848 pft.removeIJDim(stopScopes,
849 parserOptions=parserOptions,
850 wrapH=args.wrapH, **simplify)
851 elif arg ==
'--shumanFUNCtoCALL':
852 pft.shumanFUNCtoCALL()
853 elif arg ==
'--buildACCTypeHelpers':
854 pft.buildACCTypeHelpers()
855 elif arg ==
'--mathFunctoBRFunc':
856 pft.mathFunctoBRFunc()
857 elif arg ==
'--convertTypesInCompute':
858 pft.convertTypesInCompute()
859 elif arg ==
'--buildModi':
861 elif arg ==
'--splitModuleRoutineFile':
862 pft.splitModuleRoutineFile()
863 elif arg ==
'--removeExtraDOinMnhDoConcurrent':
864 pft.removeExtraDOinMnhDoConcurrent()
865 elif arg ==
'--convertuseModuleToIncludes':
866 pft.convertuseModuleToIncludes()
871 Apply openACC transformations on a PYFT instance
872 :param pft: PYFT instance
873 :param arg: argument to deal with
874 :param args: parsed argparsed arguments
875 :param stopScopes: upper limit in call tree for some transformations
877 if arg ==
'--addACCData':
879 elif arg ==
'--craybyPassDOCONCURRENT':
880 pft.craybyPassDOCONCURRENT()
881 elif arg ==
'--removebyPassDOCONCURRENT':
882 pft.removebyPassDOCONCURRENT()
883 elif arg ==
'--addACCRoutineSeq':
884 pft.addACCRoutineSeq(stopScopes)
885 elif arg ==
'--removeACC':
887 elif arg ==
'--allocatetoHIP':
893 Apply cosmetics transformations on a PYFT instance
894 :param pft: PYFT instance
895 :param arg: argument to deal with
896 :param args: parsed argparsed arguments
898 if arg ==
'--upperCase':
900 elif arg ==
'--lowerCase':
902 elif arg ==
'--changeIfStatementsInIfConstructs':
903 pft.changeIfStatementsInIfConstructs()
904 elif arg ==
'--indent':
906 elif arg ==
'--removeIndent':
907 pft.indent(indentProgramunit=0, indentBranch=0)
908 elif arg ==
'--removeEmptyLines':
909 pft.removeEmptyLines()
910 elif arg ==
'--removeComments':
912 elif arg ==
'--updateSpaces':
914 elif arg
in ARG_UPDATE_CNT:
915 pft.updateContinuation(align=args.alignContinuation,
916 addBegin=args.addBeginContinuation,
917 removeBegin=args.removeBeginContinuation,
918 removeALL=args.removeALLContinuation)
919 elif arg ==
'--prettify':
922 pft.removeEmptyLines()
924 pft.updateContinuation()
925 elif arg ==
'--minify':
926 pft.indent(indentProgramunit=0, indentBranch=0)
929 pft.removeEmptyLines()
931 pft.updateContinuation(align=
False, removeALL=
True, addBegin=
False)
932 elif arg ==
'--removeEmptyCONTAINS':
933 pft.removeEmptyCONTAINS()
938 Apply checks transformations on a PYFT instance
939 :param pft: PYFT instance
940 :param arg: argument to deal with
941 :param args: parsed argparsed arguments
943 if arg ==
'--checkIMPLICIT':
944 pft.checkImplicitNone(args.checkIMPLICIT ==
'Err')
945 elif arg ==
'--checkINTENT':
946 pft.checkIntent(args.checkINTENT ==
'Err')
947 elif arg ==
'--checkOpInCall':
948 pft.checkOpInCall(args.checkOpInCall ==
'Err')
949 elif arg ==
'--checkUnusedLocalVar':
950 pft.checkUnusedLocalVar(args.checkUnusedLocalVar ==
'Err')
951 elif arg ==
'--checkPHYEXUnusedLocalVar':
952 pft.checkPHYEXUnusedLocalVar(args.checkPHYEXUnusedLocalVar ==
'Err')
953 elif arg ==
'--checkEmptyParensInCall':
954 pft.checkEmptyParensInCall(args.checkEmptyParensInCall ==
'Err')
955 elif arg ==
'--checkONLY':
956 pft.checkONLY(args.checkONLY ==
'Err')
961 Apply statements transformations on a PYFT instance
962 :param pft: PYFT instance
963 :param arg: argument to deal with
964 :param args: parsed argparsed arguments
965 :param simplify: kwargs to simplify
967 if arg ==
'--removeCall':
968 for rc
in args.removeCall:
969 pft.removeCall(rc, **simplify)
970 elif arg ==
'--removePrints':
971 pft.removePrints(**simplify)
972 elif arg ==
'--setFalseIfStmt':
973 pft.setFalseIfStmt(args.setFalseIfStmt, **simplify)
978 Apply misc transformations on a PYFT instance
979 :param pft: PYFT instance
980 :param arg: argument to deal with
981 :param args: parsed argparsed arguments
982 :param simplify: kwargs to simplify
984 if arg ==
'--showScopes':
986 elif arg ==
'--empty':
987 pft.empty(**simplify)
992 Apply tree transformations on a PYFT instance
993 :param pft: PYFT instance
994 :param arg: argument to deal with
995 :param args: parsed argparsed arguments
996 :param plotCentralFile: central file for plots
998 if arg ==
'--plotCompilTree' and plotCentralFile
is not None:
999 pft.tree.plotCompilTreeFromFile(plotCentralFile, args.plotCompilTree,
1000 args.plotMaxUpper, args.plotMaxLower)
1001 elif arg ==
'--plotExecTree' and plotCentralFile
is not None:
1002 pft.tree.plotExecTreeFromFile(plotCentralFile, args.plotExecTree,
1003 args.plotMaxUpper, args.plotMaxLower)
1008 Apply preprocessor transformations on a PYFT instance
1009 :param pft: PYFT instance
1010 :param arg: argument to deal with
1011 :param args: parsed argparsed arguments
1013 if arg ==
'--applyCPPifdef':
1014 pft.applyCPPifdef([k
for aList
in args.applyCPPifdef
for k
in aList])
1017if __name__ ==
"__main__":