Commit fde33a06 authored by erodrigu's avatar erodrigu
Browse files

Fixed imports and moved command arguments to a function

parent fe0d0158
# Script that automatically creates different versions of a routine with different precisions
# Import classes and functions from RPE_Utils
from AutoRPE.UtilsRPE.MainFunctions import parse_sources, postprocess_sources, assign_sbits_to_rpe_variables, \
create_read_precisions_module_and_add_to_file, preprocess_sources
from AutoRPE.UtilsRPE.Functions import load_vault, remove_comments
from AutoRPE.UtilsRPE.CurrentBlock import Current_block
# from AutoRPE.UtilsRPE.MainFunctions import parse_sources, postprocess_sources, assign_sbits_to_rpe_variables, \
# create_read_precisions_module_and_add_to_file, preprocess_sources
# from AutoRPE.UtilsRPE.Functions import load_vault, remove_comments
from AutoRPE.UtilsRPE.CurrentBlock import CurrentBlock
from AutoRPE.UtilsRPE.Inserter import replace_real_declaration
from AutoRPE.UtilsRPE.SourceManager import preprocess_sources, parse_sources, load_vault
from AutoRPE.UtilsRPE.Cleaner import remove_comments
from os import listdir, mkdir
from os.path import join, isdir, isfile
from shutil import rmtree
......@@ -14,9 +18,31 @@ from math import factorial
import itertools
def get_command_line_arguments():
from argparse import ArgumentParser
help_text = """
This script takes as arguments the input source (-s/--input-source)
and the name of a routine (-r/--routine) and creates different versions
of this routine accouting for all different precision combinations that can happen.
An additional argument for the vault (-v/--vault) allows to skip the
creation of the vault if this is provided.
"""
parser = ArgumentParser(usage=help_text)
parser.add_argument("-v", "--vault", dest="vault", required=False, help="Path to the vault")
parser.add_argument("-s", "--input-source", dest="input_source", required=True,
help="Path to the processed sources")
parser.add_argument("-r", "--routine", dest="routine_name", required=True,
help="Name of the routine to create different interfaces")
args = parser.parse_args()
return args.vault, args.input_source, args.routine_name
# Few functions
def merge_declaration_lines(code_text):
lines = [ l for l in code_text.split("\n")]
lines = [l for l in code_text.split("\n")]
for _index, _line in enumerate(lines):
line = remove_comments(_line).strip()
if line.count("&") and line.count("::"):
......@@ -40,80 +66,65 @@ def replace_subroutine_name(old_name, new_name, code_text):
pat = re.compile(pattern, re.I)
replacement = r"\1 %s" % new_name
return pat.sub(replacement, code_text)
def find_declaration_line(variable, routine_code):
def find_declaration_line(variable, routine_lines):
import re
from AutoRPE.UtilsRPE.Functions import in_which_block, remove_comments
import warnings
# Declaration pattern
# TODO: This might have issues with split lines
pattern = r"::.*\b%s\b" % variable.name
exception_pattern = r"&*\b%s\b" % variable.name
real_pattern = r"real.*::"
lines = [l for l in routine_code.split("\n")]
current_block = Current_block(vault[variable.procedure.module.name].main())
current_block = CurrentBlock(vault[variable.procedure.module.name].main())
for _index, _line in enumerate(routine_lines):
# _line = remove_comments(_line).strip()
for _index, _line in enumerate(lines):
_line = remove_comments(_line).strip()
if re.search(pattern, _line):
if current_block.procedure == variable.procedure:
if current_block.procedure.name == variable.procedure.name:
return _index
else:
current_block = in_which_block(_line, current_block, vault=vault)
current_block = current_block.in_which_block(_line, vault=vault)
print("Declaration of variable %s with id %i not found in module %s" % (variable.name,variable.id, variable.procedure.module.name))
print("Declaration of variable %s with id %s not found in module %s" % (variable.name, variable.id, variable.procedure.module.name))
return None
def obtain_rotine_source(routine, sources_path):
def obtain_routine_source(routine, sources_path):
source_file = join(sources_path, "%s.f90" % routine.module.name)
with open(source_file) as f:
pattern = r"routine.*\b%s\b" % routine.name
lines = [l for l in f]
indices = []
for index, line in enumerate(lines):
line = remove_comments(line).strip()
if re.search(pattern, line, re.I):
indices.append(index)
routine_code = "".join(lines[indices[0]:indices[1]+1])
# Routine name pattern
pattern = r"routine.*\b%s\b" % routine.name
lines = [l for l in f]
indices = []
for index, line in enumerate(lines):
line = remove_comments(line).strip()
# Search for the start/end of the routine
if re.search(pattern, line, re.I):
indices.append(index)
routine_code = "".join(lines[indices[0]:indices[1] + 1])
routine_code = merge_declaration_lines(routine_code)
return routine_code
if __name__ == "__main__":
# Getting Command line options
from optparse import OptionParser
help_text = """
This script takes as arguments the input source (-s/--input-source)
and the name of a routine (-r/--routine) and creates different versions
of this routine accouting for all different precision combinations that can happen.
An additional argument for the vault (-v/--vault) allows to skip the
creation of the vault if this is provided.
"""
parser = OptionParser(usage=help_text)
parser.add_option("-v", "--vault", dest="vault", default=None, metavar="FILE")
parser.add_option("-s", "--input-source", dest="input_source", default=None, metavar="FILE")
parser.add_option("-r", "--routine", dest="routine_name", default=None)
(options, args) = parser.parse_args()
vault_path = options.vault
path_to_input_sources = options.input_source
routine_name = options.routine_name
def replace_routine_name(old_name, new_name, code_text):
pattern = r"(subroutine +\b)%s\b" % old_name
pat = re.compile(pattern, re.I)
replacement = r"\1 %s" % new_name
return pat.sub(replacement, code_text)
if path_to_input_sources is None:
print("\nArgument -s/--input-source and -r/--routine are mandatory\n")
parser.print_help()
exit(1)
if __name__ == "__main__":
if routine_name is None:
print("\nArgument -r/--routine is mandatory\n")
parser.print_help()
exit(1)
# Get command line arguments
vault_path, path_to_input_sources, routine_name = get_command_line_arguments()
path_to_preprocessed_sources = "./tmp_processedsources/"
# In case no vault has been provided it will create it from the sources in the input sources folder
......@@ -121,12 +132,10 @@ if __name__ == "__main__":
# Paths to source folders
# Path_to_input_sources
if not isdir(path_to_preprocessed_sources):
mkdir(path_to_preprocessed_sources)
# List of files that should not be processed, as red from "list_of_files_to_keep_unmodified.txt"
preprocess_blacklist = listdir(path_to_input_sources)
mkdir(path_to_preprocessed_sources)
# Format text + replace real declarations with type(rpe_var)
preprocess_sources(path_to_input_sources, path_to_preprocessed_sources, blacklist=preprocess_blacklist)
preprocess_sources(path_to_input_sources, path_to_preprocessed_sources)
# Obtain source information
vault = parse_sources(path_to_preprocessed_sources, save_vault=True)
......@@ -135,43 +144,43 @@ if __name__ == "__main__":
routine = None
for procedure in vault.procedures:
if procedure.name == routine_name:
routine = procedure
break
if procedure.name == routine_name:
routine = procedure
break
if routine is None:
print("Routine %s not found in vault." % routine_name)
exit(0)
routine_code = obtain_rotine_source(routine, path_to_input_sources)
routine_code = obtain_routine_source(routine, path_to_input_sources)
routine_lines = routine_code.split("\n")
sensitive_variables = [v for v in routine.variables if v.is_dummy_argument and v.type == "real"]
sensitive_variables = [v for v in routine.variables if v.is_dummy_argument and v.type == "double"]
# All possible combinations of precisions
precision_combinations = list(itertools.product(["dp","sp"], repeat=len(sensitive_variables)))
precision_combinations = list(itertools.product(["dp", "sp"], repeat=len(sensitive_variables)))
code_versions = {}
interface = "module procedure "
for c_index, combination in enumerate(precision_combinations):
version_lines = routine_lines[:]
new_routine_name = "%s_%04i" % (routine.name, c_index)
for index, variable in enumerate(sensitive_variables):
variable_precision = combination[index]
dec_line = find_declaration_line(variable, routine_code)
original_line = version_lines[dec_line]
new_line = replace_real_declaration(variable, original_line, variable_precision)
version_lines[dec_line] = new_line
version_text = "\n".join(version_lines).strip()
version_text = replace_routine_name(routine.name, new_routine_name,version_text)
code_versions[c_index] = version_text
if c_index == 0:
interface += "%s" % new_routine_name
else:
interface += ", %s" % new_routine_name
version_lines = routine_lines[:]
new_routine_name = "%s_%04i" % (routine.name, c_index)
for index, variable in enumerate(sensitive_variables):
variable_precision = combination[index]
dec_line = find_declaration_line(variable, routine_lines)
original_line = version_lines[dec_line]
new_line = replace_real_declaration(variable, original_line, variable_precision)
version_lines[dec_line] = new_line
version_text = "\n".join(version_lines).strip()
version_text = replace_routine_name(routine.name, new_routine_name, version_text)
code_versions[c_index] = version_text
if c_index == 0:
interface += "%s" % new_routine_name
else:
interface += ", %s" % new_routine_name
interface = "interface %s\n %s\nend interface %s" % (routine.name, interface, routine.name)
print(interface)
for key, code in code_versions.items():
print(code)
print(code)
# Deleting temporary folders
if isdir(path_to_preprocessed_sources):
rmtree(path_to_preprocessed_sources)
rmtree(path_to_preprocessed_sources)
......@@ -11,6 +11,7 @@ import AutoRPE.UtilsRPE.Getter as Getter
import AutoRPE.UtilsRPE.Counter as Counter
import AutoRPE.UtilsRPE.Error as Error
import AutoRPE.UtilsRPE.VariablePrecision as VariablePrecision
import AutoRPE.UtilsRPE.AttributeParser as AttributeParser
import warnings
import re
import itertools
......@@ -613,10 +614,10 @@ def change_code(list_filename, source_path, vault_path, target_precision="dp"):
# This function takes a declaration line (string) and updates it with the new type
# If the declaration contains more variables it keeps the other variables with the original attributes.
def replace_real_declaration(variable, declaration_line, target_precision="dp", filename=None):
declaration_line_without_comments = BasicFunctions.remove_comments(declaration_line).strip()
declaration_line_without_comments = Cleaner.remove_comments(declaration_line).strip()
attributes, arguments = declaration_line_without_comments.split("::")
variable_name = Getter.get_variable_name(arguments)
variable_name = AttributeParser.get_variable_name(arguments)
# Real statement pattern
pattern = "real *\(([^\)]*)\)"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment