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')
449 Updates an argparse parser with cosmetics arguments
451 gCosmetics = parser.add_argument_group(
'Cosmetics options')
452 gCosmetics.add_argument(
'--upperCase', default=
False, action=
'store_true',
453 help=
'Put FORTRAN code in upper case letters')
454 gCosmetics.add_argument(
'--lowerCase', default=
False, action=
'store_true',
455 help=
'Put FORTRAN code in lower case letters')
456 gCosmetics.add_argument(
'--changeIfStatementsInIfConstructs', default=
False,
458 help=
'Find all if-statement and convert it to if-then-statement')
459 gCosmetics.add_argument(
'--indent', default=
False, action=
'store_true',
460 help=
'Correct indentation')
461 gCosmetics.add_argument(
'--removeIndent', default=
False, action=
'store_true',
462 help=
'Remove indentation')
463 gCosmetics.add_argument(
'--removeEmptyLines', default=
False, action=
'store_true',
464 help=
'Remove empty lines')
465 gCosmetics.add_argument(
'--removeComments', default=
False, action=
'store_true',
466 help=
'Remove comments')
467 gCosmetics.add_argument(
'--updateSpaces', default=
False, action=
'store_true',
468 help=
'Updates spaces around operators, commas, parenthesis and ' +
469 'at the end of line')
470 gCosmetics.add_argument(
'--alignContinuation', default=
False, action=
'store_true',
471 help=
'Align the beginings of continued lines')
472 gCosmetics.add_argument(
'--addBeginContinuation', default=
False, action=
'store_true',
473 help=
'Add missing continuation characters (\'&\') at the ' +
475 gCosmetics.add_argument(
'--removeBeginContinuation', default=
False, action=
'store_true',
476 help=
'Remove continuation characters (\'&\') at the begining of lines')
477 gCosmetics.add_argument(
'--removeALLContinuation', default=
False, action=
'store_true',
478 help=
'Remove all continuation characters(\'&\')')
479 gCosmetics.add_argument(
'--prettify', default=
False, action=
'store_true',
480 help=
'Prettify the source code (indentation, spaces...)')
481 gCosmetics.add_argument(
'--minify', default=
False, action=
'store_true',
482 help=
'Simplify the source code (indentation, spaces...)')
483 gCosmetics.add_argument(
'--removeEmptyCONTAINS', default=
False, action=
'store_true',
484 help=
'Remove useless CONTAINS statements')
489 Updates an argparse parser with applications arguments
491 gApplications = parser.add_argument_group(
'Options to apply upper level transformation')
492 gApplications.add_argument(
'--deleteDrHook', default=
False, action=
'store_true',
493 help=
'Delete DR HOOK use')
494 gApplications.add_argument(
'--addDrHook', default=
False, action=
'store_true',
496 gApplications.add_argument(
'--deleteBudgetDDH', default=
False, action=
'store_true',
497 help=
'Delete Budget/DDH use')
498 gApplications.add_argument(
'--deleteRoutineCallsMesoNHGPU', default=
False, action=
'store_true',
499 help=
'Delete parts of the code not compatible with MesoNH-OpenACC' +
500 'such as OCND2 blocks')
501 gApplications.add_argument(
'--splitModuleRoutineFile', default=
False, action=
'store_true',
503 gApplications.add_argument(
'--deleteNonColumnCallsPHYEX', default=
False, action=
'store_true',
504 help=
'Delete call to PHYEX routines that needs information on ' +
505 'horizontal points (multiple column dependency')
506 gApplications.add_argument(
'--removeIJDim', default=
False, action=
'store_true',
507 help=
'Remove I and J dimensions (1, KLON). ' +
508 'Needs the --stopScopes argument.')
509 gApplications.add_argument(
'--expandAllArraysPHYEX', default=
False, action=
'store_true',
510 help=
'Expand all array syntax (computing and where block) ' +
511 'using PHYEX conventions')
512 gApplications.add_argument(
'--expandAllArraysPHYEXConcurrent', default=
False,
514 help=
'Expand all array syntax with DO CONCURRENT loops ' +
515 '(computing and where block) using PHYEX conventions')
516 gApplications.add_argument(
'--expandAllArrays', default=
False, action=
'store_true',
517 help=
'Expand all array syntax (computing and where block) ' +
518 'using mnh directives if present')
519 gApplications.add_argument(
'--expandAllArraysConcurrent', default=
False, action=
'store_true',
520 help=
'Expand all array syntax with DO CONCURRENT loops ' +
521 '(computing and where block) using mnh directives if present')
522 gApplications.add_argument(
'--inlineContainedSubroutinesPHYEX', default=
False,
524 help=
'Inline containted subroutines in main routine, using ' +
526 gApplications.add_argument(
'--addStack', metavar=
'MODEL', type=str,
527 help=
'Add local arrays to the stack. The argument is the ' +
528 'the model name in which stack must be added ("AROME" ' +
529 'or "MESONH"). Needs the --stopScopes argument for AROME.')
530 gApplications.add_argument(
'--addIncludes', default=
False, action=
'store_true',
531 help=
'Add .h includes in the file and remove the INCLUDE statement')
532 gApplications.add_argument(
'--mnhExpand', default=
False, action=
'store_true',
533 help=
'Apply the mnh_expand directives with DO loops')
534 gApplications.add_argument(
'--mnhExpandConcurrent', default=
False, action=
'store_true',
535 help=
'Apply the mnh_expand directives with DO CONCURRENT loops')
536 gApplications.add_argument(
'--addMPPDB_CHECKS', default=
False, action=
'store_true',
537 help=
'Add MPPDB_CHEKS bit-repro checking routines of MesoNH for ' +
538 'all in and inout arrays in subroutines')
539 gApplications.add_argument(
'--addPrints', default=
False, action=
'store_true',
540 help=
'Add Prints of min/maxval and shape of all in, out, inout ' +
541 'arguments of all scopes')
542 gApplications.add_argument(
'--shumanFUNCtoCALL', default=
False, action=
'store_true',
543 help=
'Transform shuman functions to call statements')
544 gApplications.add_argument(
'--mathFunctoBRFunc', default=
False, action=
'store_true',
545 help=
'Convert intrinsic math functions **, LOG, ATAN, **2, **3, ' +
546 '**4, EXP, COS, SIN, ATAN2 into a self defined function BR_ ' +
547 'for MesoNH bit-repro.')
548 gApplications.add_argument(
'--convertTypesInCompute', default=
False, action=
'store_true',
549 help=
'Use single variable instead of variable contained in ' +
550 'structure in compute statement for optimization issue ')
551 gApplications.add_argument(
'--buildModi', default=
False, action=
'store_true',
552 help=
'Builds the corresponding modi_ file')
557 Updates an argparse parser with openACC arguments
559 gOpenACC = parser.add_argument_group(
'OpenACC')
560 gOpenACC.add_argument(
'--addACCData', default=
False, action=
'store_true',
561 help=
'Add !$acc data present and !$acc end data directives')
562 gOpenACC.add_argument(
'--addACCRoutineSeq', default=
False, action=
'store_true',
563 help=
'Add "!$acc routine seq" to routines under stopScopes')
564 gOpenACC.add_argument(
'--craybyPassDOCONCURRENT', default=
False, action=
'store_true',
565 help=
'remove acc loop independant collapse for BR_ fonctions and ' +
566 'mnh_undef(OPENACC) macro' +
567 ' use DO CONCURRENT with mnh_undef(LOOP)')
568 gOpenACC.add_argument(
'--removeACC', default=
False, action=
'store_true',
569 help=
'remove all ACC directives')
570 gOpenACC.add_argument(
'--removebyPassDOCONCURRENT', default=
False, action=
'store_true',
571 help=
'remove macro !$mnh_(un)def(OPENACC) and !$mnh_(un)def(LOOP) ' +
573 gOpenACC.add_argument(
'--buildACCTypeHelpers', default=
False, action=
'store_true',
574 help=
'build module files containing helpers to copy user ' +
580 Updates an argparse parser with checks arguments
583 gChecks = parser.add_argument_group(
'Check options')
584 gChecks.add_argument(
'--checkIMPLICIT', choices={
'Warn',
'Err'}, default=
None,
585 help=
'Send a warning or raise an error if the "IMPLICIT NONE" ' +
587 gChecks.add_argument(
'--checkINTENT', choices={
'Warn',
'Err'}, default=
None,
588 help=
'Send a warning or raise an error if the "INTENT" ' +
589 'attribute is missing for a dummy argument')
590 gChecks.add_argument(
'--checkOpInCall', choices={
'Warn',
'Err'}, default=
None,
591 help=
'Send a warning or raise an error if a call argument is an '
597 Updates an argparse parser with statements arguments
600 gStatement = parser.add_argument_group(
'Statements options')
601 gStatement.add_argument(
'--removeCall', action=
'append',
602 help=
"Call to remove from the source code. The argument " +
603 "is the subprogram name")
604 gStatement.add_argument(
'--removePrints', default=
False, action=
'store_true',
605 help=
"Remove print statements from the source code.")
606 gStatement.add_argument(
'--inlineContainedSubroutines', default=
False, action=
'store_true',
607 help=
'Inline containted subroutines in main routine')
608 gStatement.add_argument(
'--setFalseIfStmt', default=
None,
609 help=
'Replace this value by .FALSE. in if statements')
614 Updates an argparse parser with misc arguments
616 gMisc = parser.add_argument_group(
'Miscellaneous')
617 gMisc.add_argument(
'--showScopes', default=
False, action=
'store_true',
618 help=
'Show the different scopes found in the source code')
619 gMisc.add_argument(
'--empty', default=
False, action=
'store_true',
620 help=
'Empty the different scopes')
625 Updates an argparse parser with statements arguments
626 :param withPlotCentralFile: to add the --plotCentralFile argumen
627 :param treeIsOptional: is the --tree argument optional?
629 gTree = parser.add_argument_group(
'Tree')
630 gTree.add_argument(
'--tree', default=
None, action=
'append', required=
not treeIsOptional,
631 help=
'Directories where source code must be searched for')
632 gTree.add_argument(
'--descTree', default=
None, required=
not treeIsOptional,
633 help=
'File to write and/or read the description of the tree.')
634 if withPlotCentralFile:
635 gTree.add_argument(
'--plotCentralFile', default=
None, type=str,
636 help=
'Central file of the plot')
637 gTree.add_argument(
'--plotCompilTree', default=
None,
638 help=
'File name for compilation dependency graph (.dot or image extension)')
639 gTree.add_argument(
'--plotExecTree', default=
None,
640 help=
'File name for execution dependency graph (.dot or image extension)')
641 gTree.add_argument(
'--plotMaxUpper', default=
None, type=int,
642 help=
'Maximum number of upper elements in the plot tree')
643 gTree.add_argument(
'--plotMaxLower', default=
None, type=int,
644 help=
'Maximum number of lower elements in the plot tree')
645 gTree.add_argument(
'--stopScopes', default=
None, type=str,
646 help=
'#-separated list of scopes ' +
647 'where the recursive inclusion of an argument variable ' +
648 'must stop (needed for some transformations).')
653 Updates an argparse parser with statements arguments
655 gCpp = parser.add_argument_group(
'Preprocessor')
656 gCpp.add_argument(
'--applyCPPifdef', nargs=
'*', action=
'append',
657 help=
"This option is followed by the list of defined or undefined " +
659 "All #ifdef and #ifndef concerning these keys are evaluated. " +
660 "Undefined keys are preceded by a percentage sign.")
665 Apply transformation on a PYFT instance
666 :param pft: PYFT instance
667 :param arg: argument to deal with
668 :param args: parsed argparsed arguments
669 :param plotCentralFile: central file for plots
671 simplify = {
'simplify': args.simplify}
673 stopScopes = args.stopScopes.split(
'#')
if args.stopScopes
is not None else None
708 Apply file name transformations on a PYFT instance
709 :param pft: PYFT instance
710 :param arg: argument to deal with
711 :param args: parsed argparsed arguments
715 if arg ==
'--renamefF':
717 elif arg ==
'--renameFf':
723 Apply variables transformations on a PYFT instance
724 :param pft: PYFT instance
725 :param arg: argument to deal with
726 :param args: parsed argparsed arguments
727 :param simplify: kwargs to simplify
728 :param parserOptions: fxtran parser options
729 :param stopScopes: upper limit in call tree for some transformations
731 if arg ==
'--showVariables':
732 pft.varList.showVarList()
733 elif arg ==
'--attachArraySpecToEntity':
734 pft.attachArraySpecToEntity()
735 elif arg ==
'--removeVariable':
736 pft.removeVar(args.removeVariable, **simplify)
737 elif arg ==
'--addVariable':
738 pft.addVar([[v[0], v[1], v[2], (int(v[3])
if isint(v[3])
else None)]
739 for v
in args.addVariable])
740 elif arg ==
'--addModuleVariable':
741 pft.addModuleVar([[v[0], v[1], v[2]]
for v
in args.addModuleVariable])
742 elif arg ==
'--showUnusedVariables':
744 elif arg ==
'--removeUnusedLocalVariables':
745 pft.removeUnusedLocalVar(
746 [item.strip()
for item
in args.removeUnusedLocalVariables.split(
',')]
747 if args.removeUnusedLocalVariables !=
'NONE' else None, **simplify)
748 elif arg ==
'--removePHYEXUnusedLocalVariables':
749 pft.removePHYEXUnusedLocalVar(
750 [item.strip()
for item
in args.removePHYEXUnusedLocalVariables.split(
',')]
751 if args.removePHYEXUnusedLocalVariables !=
'NONE' else None, **simplify)
752 elif arg ==
'--addExplicitArrayBounds':
753 pft.addExplicitArrayBounds()
754 elif arg ==
'--addArrayParentheses':
755 pft.addArrayParentheses()
756 elif arg ==
'--modifyAutomaticArrays':
757 pft.modifyAutomaticArrays(*(args.modifyAutomaticArrays.split(
'#')))
758 elif arg ==
'--replaceAutomaticWithAllocatable':
759 pft.modifyAutomaticArrays(
760 "{type}, DIMENSION({doubledotshape}), ALLOCATABLE :: {name}",
761 "ALLOCATE({name}({shape}))",
"DEALLOCATE({name})")
762 elif arg ==
'--addArgInTree':
763 for varName, declStmt, pos
in args.addArgInTree:
764 pft.addArgInTree(varName, declStmt, int(pos), stopScopes,
765 parserOptions=parserOptions,
771 Apply applications transformations on a PYFT instance
772 :param pft: PYFT instance
773 :param arg: argument to deal with
774 :param args: parsed argparsed arguments
775 :param simplify: kwargs to simplify
776 :param parserOptions: fxtran parser options
777 :param stopScopes: upper limit in call tree for some transformations
779 if arg ==
'--addStack':
780 pft.addStack(args.addStack, stopScopes,
781 parserOptions=parserOptions,
783 elif arg ==
'--deleteDrHook':
784 pft.deleteDrHook(**simplify)
785 elif arg ==
'--addDrHook':
787 elif arg ==
'--deleteBudgetDDH':
788 pft.deleteBudgetDDH(**simplify)
789 elif arg ==
'--deleteRoutineCallsMesoNHGPU':
790 pft.deleteRoutineCallsMesoNHGPU(**simplify)
791 elif arg ==
'--deleteNonColumnCallsPHYEX':
792 pft.deleteNonColumnCallsPHYEX(**simplify)
793 elif arg ==
'--addMPPDB_CHECKS':
794 pft.addMPPDB_CHECKS()
795 elif arg ==
'--addPrints':
796 pft.addMPPDB_CHECKS(printsMode=
True)
799 assert not (args.mnhExpand
and args.mnhExpandConcurrent), \
800 "Only one of --mnhExpand and --mnhExpandConcurrent"
801 if arg ==
'--mnhExpand':
802 pft.removeArraySyntax(everywhere=
False, addAccIndependentCollapse=
False)
803 elif arg ==
'--mnhExpandConcurrent':
804 pft.removeArraySyntax(concurrent=
True, everywhere=
False)
805 elif arg ==
'--inlineContainedSubroutines':
806 pft.inlineContainedSubroutines(**simplify)
807 elif arg ==
'--inlineContainedSubroutinesPHYEX':
808 pft.inlineContainedSubroutinesPHYEX(**simplify)
809 elif arg ==
'--expandAllArrays':
810 pft.removeArraySyntax()
811 elif arg ==
'--expandAllArraysConcurrent':
812 pft.removeArraySyntax(concurrent=
True)
813 elif arg ==
'--expandAllArraysPHYEX':
814 pft.expandAllArraysPHYEX()
815 elif arg ==
'--expandAllArraysPHYEXConcurrent':
816 pft.expandAllArraysPHYEX(concurrent=
True)
817 elif arg ==
'--removeIJDim':
818 pft.removeIJDim(stopScopes,
819 parserOptions=parserOptions,
820 wrapH=args.wrapH, **simplify)
821 elif arg ==
'--shumanFUNCtoCALL':
822 pft.shumanFUNCtoCALL()
823 elif arg ==
'--buildACCTypeHelpers':
824 pft.buildACCTypeHelpers()
825 elif arg ==
'--mathFunctoBRFunc':
826 pft.mathFunctoBRFunc()
827 elif arg ==
'--convertTypesInCompute':
828 pft.convertTypesInCompute()
829 elif arg ==
'--buildModi':
831 elif arg ==
'--splitModuleRoutineFile':
832 pft.splitModuleRoutineFile()
837 Apply openACC transformations on a PYFT instance
838 :param pft: PYFT instance
839 :param arg: argument to deal with
840 :param args: parsed argparsed arguments
841 :param stopScopes: upper limit in call tree for some transformations
843 if arg ==
'--addACCData':
845 elif arg ==
'--craybyPassDOCONCURRENT':
846 pft.craybyPassDOCONCURRENT()
847 elif arg ==
'--removebyPassDOCONCURRENT':
848 pft.removebyPassDOCONCURRENT()
849 elif arg ==
'--addACCRoutineSeq':
850 pft.addACCRoutineSeq(stopScopes)
851 elif arg ==
'--removeACC':
857 Apply cosmetics transformations on a PYFT instance
858 :param pft: PYFT instance
859 :param arg: argument to deal with
860 :param args: parsed argparsed arguments
862 if arg ==
'--upperCase':
864 elif arg ==
'--lowerCase':
866 elif arg ==
'--changeIfStatementsInIfConstructs':
867 pft.changeIfStatementsInIfConstructs()
868 elif arg ==
'--indent':
870 elif arg ==
'--removeIndent':
871 pft.indent(indentProgramunit=0, indentBranch=0)
872 elif arg ==
'--removeEmptyLines':
873 pft.removeEmptyLines()
874 elif arg ==
'--removeComments':
876 elif arg ==
'--updateSpaces':
878 elif arg
in ARG_UPDATE_CNT:
879 pft.updateContinuation(align=args.alignContinuation,
880 addBegin=args.addBeginContinuation,
881 removeBegin=args.removeBeginContinuation,
882 removeALL=args.removeALLContinuation)
883 elif arg ==
'--prettify':
886 pft.removeEmptyLines()
888 pft.updateContinuation()
889 elif arg ==
'--minify':
890 pft.indent(indentProgramunit=0, indentBranch=0)
893 pft.removeEmptyLines()
895 pft.updateContinuation(align=
False, removeALL=
True, addBegin=
False)
896 elif arg ==
'--removeEmptyCONTAINS':
897 pft.removeEmptyCONTAINS()
902 Apply checks transformations on a PYFT instance
903 :param pft: PYFT instance
904 :param arg: argument to deal with
905 :param args: parsed argparsed arguments
907 if arg ==
'--checkIMPLICIT':
908 pft.checkImplicitNone(args.checkIMPLICIT ==
'Err')
909 elif arg ==
'--checkINTENT':
910 pft.checkIntent(args.checkINTENT ==
'Err')
911 elif arg ==
'--checkOpInCall':
912 pft.checkOpInCall(args.checkOpInCall ==
'Err')
917 Apply statements transformations on a PYFT instance
918 :param pft: PYFT instance
919 :param arg: argument to deal with
920 :param args: parsed argparsed arguments
921 :param simplify: kwargs to simplify
923 if arg ==
'--removeCall':
924 for rc
in args.removeCall:
925 pft.removeCall(rc, **simplify)
926 elif arg ==
'--removePrints':
927 pft.removePrints(**simplify)
928 elif arg ==
'--setFalseIfStmt':
929 pft.setFalseIfStmt(args.setFalseIfStmt, **simplify)
934 Apply misc transformations on a PYFT instance
935 :param pft: PYFT instance
936 :param arg: argument to deal with
937 :param args: parsed argparsed arguments
938 :param simplify: kwargs to simplify
940 if arg ==
'--showScopes':
942 elif arg ==
'--empty':
943 pft.empty(**simplify)
948 Apply tree transformations on a PYFT instance
949 :param pft: PYFT instance
950 :param arg: argument to deal with
951 :param args: parsed argparsed arguments
952 :param plotCentralFile: central file for plots
954 if arg ==
'--plotCompilTree' and plotCentralFile
is not None:
955 pft.tree.plotCompilTreeFromFile(plotCentralFile, args.plotCompilTree,
956 args.plotMaxUpper, args.plotMaxLower)
957 elif arg ==
'--plotExecTree' and plotCentralFile
is not None:
958 pft.tree.plotExecTreeFromFile(plotCentralFile, args.plotExecTree,
959 args.plotMaxUpper, args.plotMaxLower)
964 Apply preprocessor transformations on a PYFT instance
965 :param pft: PYFT instance
966 :param arg: argument to deal with
967 :param args: parsed argparsed arguments
969 if arg ==
'--applyCPPifdef':
970 pft.applyCPPifdef([k
for aList
in args.applyCPPifdef
for k
in aList])