Commit c9a0c5d0 authored by sparonuz's avatar sparonuz
Browse files

# This is a combination of 5 commits.

[FixMerge]: Sources were not red in order ...

[FixMerge]: Find use statement inside functions or sbr, now get variables use the introduces info
parent 1c972920
......@@ -33,7 +33,6 @@ class Procedure(object):
self.interface = None
self.dummy_arguments = None
self.uses = []
self._accessible_variables = None
def add_variable(self, _variable):
try:
......@@ -115,12 +114,15 @@ class ModuleMain(Procedure):
class Routine(Procedure):
def __init__(self, _name, module):
super(Routine, self).__init__(_name, module)
# Case in which a use statement is found inside a subroutine definition
self.use_only_variables = []
class Function(Procedure):
def __init__(self, _name, module):
super(Function, self).__init__(_name, module)
self.type = None
self.use_only_variables = []
class Interface:
......
......@@ -256,7 +256,8 @@ def get_structure_member(contents, routine, vault):
contents = contents.lower()
# Let's check if the structure has been declared in this same routine
variable_name = contents.split("%")[0]
variable = [v for v in routine.variables + routine.module.variables if v.name.lower() == variable_name]
variable = [v for v in
routine.variables + routine.module.variables + routine.use_only_variables if v.name.lower() == variable_name]
if not variable:
try:
variable = [[var for var in m.accessible_var if var.name.lower() == variable_name][0]
......@@ -313,8 +314,17 @@ def get_member_from_tail(contents, routine, vault):
def get_member_from_root(contents, routine, vault):
# Retrieve variable corresponding to a structure member
root = contents.split("%")[0]
root_variable = [v for v in routine.variables + routine.module.variables if v.name.lower() == root][0]
try:
root_variable = [v for v in
routine.variables + routine.module.variables
if v.name.lower() == root][0]
except IndexError:
# Case of routine or function with a use module, only var statement
root_variable = [v for v in
routine.use_only_variables
if v.name.lower() == root][0]
try:
root_derived_type = [dt for dt in vault.derived_types if dt.name.lower() == root_variable.type.lower()][0]
except IndexError:
......
......@@ -132,8 +132,7 @@ class ObtainSourcefileInfo(ReadSourceFile):
# -_routine_start: integer with line number where the routine starts
# -_routine_end: integer with line number where the routine ends
# Output: list of strings containing declarations
def find_routine_declarations(self, _routine_start, _routine_end):
def find_routine_declarations(self, _routine_start, _routine_end, obj_to_find="::"):
# Check if there is some statement inside
# TODO find a better way of parsing this: actually we can take advantage of the fact that
# Cases in which a routine contains other functions declarations.
......@@ -148,7 +147,7 @@ class ObtainSourcefileInfo(ReadSourceFile):
_routine_lines = self.lines[_routine_start:_routine_end + 1]
# Lines that are variable declarations
_all_declaration = [_l.strip() for _l in _routine_lines if _l.count("::")]
_all_declaration = [_l.strip() for _l in _routine_lines if _l.count(obj_to_find)]
return _all_declaration
......@@ -171,31 +170,25 @@ class ObtainSourcefileInfo(ReadSourceFile):
except UnboundLocalError:
print("Main not found for structure %s", structure.name)
def find_procedure_variables(self, routine_name, dummy_arguments, declarations, header):
if header.count("function"):
routine_or_function = "function"
def find_procedure_variables(self, header, routine_name, dummy_arguments, var_declarations, obj_type, used_modules):
if obj_type == Function:
# Retrieve the ret_val name
ret_type, ret_val = Finder.find_function_type_from_header(header)
if not ret_val:
ret_val = routine_name
elif header.count("subroutine"):
elif obj_type == Routine:
ret_val = None
routine_or_function = "routine"
else:
raise ValueError("Header does not correspond to function or routine")
if routine_or_function == "routine":
obj_type = Routine
elif routine_or_function == "function":
obj_type = Function
else:
raise ValueError("routine_or_function must be 'routine' or 'function'")
ob = obj_type(routine_name, self.module)
# ob.used_modules = [m.split("use")[1].split("only")[0].replace(",", "").strip() for m in used_modules]
if len(used_modules):
ob.use_only_variables = [m.split("use")[1].strip() for m in used_modules]
# Reverse approach
dummy_arguments = [x.lower() for x in dummy_arguments]
for declaration in declarations:
for declaration in var_declarations:
pattern = "(.*)::(.*)"
m = re.search(pattern, declaration)
# In this case is not a variable declaration
......@@ -218,6 +211,7 @@ class ObtainSourcefileInfo(ReadSourceFile):
# If the variable name is the same of the function or is return statement
if ret_val is not None and _v.name.lower() == ret_val.lower():
_v.is_retval = True
ob.type = _var_type
_v.is_pointer = is_pointer
if variable_name.lower() in dummy_arguments:
_v.intent = _intent
......@@ -248,20 +242,17 @@ class ObtainSourcefileInfo(ReadSourceFile):
_v.position = index
_v.is_parameter = False
ob.add_variable(_v)
# Save object
if routine_or_function == "function":
if obj_type == Function:
# In case of function declaration like INTEGER FUNCTION name() without variables declaration
if not [var for var in ob.variables if var.is_retval == True]:
if not [var for var in ob.variables if var.is_retval==True]:
# Add the return value to functions variables
_v = Variable(ob, ret_val, ret_type, 0, self.module)
_v.is_retval = True
ob.add_variable(_v)
if ret_type:
# Specify the type of the function
ob.type = ret_type
else:
for variable in ob.variables:
if variable.name.lower() == ret_val.lower():
ob.type = variable.type
break
# Save object
self.objects.append(ob)
# Definition: Looks into the sourcefile for routine declarations, storing the name, type,
......@@ -281,10 +272,12 @@ class ObtainSourcefileInfo(ReadSourceFile):
# Find name and dummy arguments
routine_name, dummy_arguments = self.get_dummy_arguments(_index)
# Find declarations
declarations = self.find_routine_declarations(routine_start, routine_end)
var_declarations = self.find_routine_declarations(routine_start, routine_end, obj_to_find="::")
used_modules = self.find_routine_declarations(routine_start, routine_end, obj_to_find="use ")
header = self.lines[routine_start].lower()
# Parse everything and store
self.find_procedure_variables(routine_name.lower(), dummy_arguments, declarations, header)
self.find_procedure_variables(header, routine_name.lower(), dummy_arguments, var_declarations,
obj_type=Routine, used_modules=used_modules)
# ERROR: Definition: Looks into the sourcefile for routine declarations, storing the name, type,
# dimensions and optionality of the arguments.
......@@ -339,7 +332,7 @@ class ObtainSourcefileInfo(ReadSourceFile):
v.is_dummy_argument = True
v.allocatable = allocatable
v.is_parameter = is_parameter
v.pointer = is_pointer
v.is_pointer = is_pointer
v.is_member_of = type_name
ob.add_variable(v)
variable_counter += 1
......@@ -381,7 +374,7 @@ class ObtainSourcefileInfo(ReadSourceFile):
for variable in variables:
v = Variable(main_routine, variable, var_type, dimension, self.module)
v.allocatable = allocatable
v.pointer = is_pointer
v.is_pointer = is_pointer
v.is_parameter = is_parameter
main_routine.add_variable(v)
......@@ -398,10 +391,12 @@ class ObtainSourcefileInfo(ReadSourceFile):
# Find name and dummy arguments
function_name, dummy_arguments = self.get_dummy_arguments(_index)
# Find declarations
declarations = self.find_routine_declarations(function_start, function_end)
variables_declarations = self.find_routine_declarations(function_start, function_end)
used_modules = self.find_routine_declarations(function_start, function_end, obj_to_find="use")
# Parse everything and store
header = self.lines[function_start].lower()
self.find_procedure_variables(function_name.lower(), dummy_arguments, declarations, header)
self.find_procedure_variables(header, function_name.lower(), dummy_arguments, variables_declarations,
obj_type=Function, used_modules=used_modules)
def find_implicit_functions(self, vault):
try:
......
......@@ -11,18 +11,18 @@ import re
def process_pointers(vault):
for var in vault.variables:
if var.pointer:
if var.pointer.count("type"):
pointer_name = var.pointer.replace("type", "")
if var.is_pointer:
if var.is_pointer.count("type"):
pointer_name = var.is_pointer.replace("type", "")
pointer_name = Cleaner.remove_outer_brackets(pointer_name)
search_array = vault.derived_types
elif var.pointer.count("class"):
elif var.is_pointer.count("class"):
# Same of type, but for compiler reason they have to be declared as classes
pointer_name = var.pointer.replace("class", "")
pointer_name = var.is_pointer.replace("class", "")
pointer_name = Cleaner.remove_outer_brackets(pointer_name)
search_array = vault.derived_types
elif var.type == "procedure":
pointer_name = var.pointer
pointer_name = var.is_pointer
search_array = vault.procedures
else:
# It is a pointer to real or a pointer to integer
......@@ -31,7 +31,7 @@ def process_pointers(vault):
if len(pointed_obj) > 1:
raise Error.DuplicatedObject
else:
var.pointer = pointed_obj
var.is_pointer = pointed_obj
continue
......
......@@ -11,13 +11,13 @@ import AutoRPE.UtilsRPE.Error as Error
import AutoRPE.UtilsRPE.PointerDealer as PointerDealer
import warnings
import networkx as nx
from os import listdir
from os.path import isfile, join
def track_dependencies(path_to_model_sources, vault, graph):
from AutoRPE.UtilsRPE.SourceManager import listdir_ord
# Find files in sources
all_sources = [f for f in listdir(path_to_model_sources) if
all_sources = [f for f in listdir_ord(path_to_model_sources) if
isfile(join(path_to_model_sources, f)) and f.count(".f90")]
# Process Sources
total = len(all_sources)
......
......@@ -115,11 +115,18 @@ class Vault:
return variables[0]
elif len(variables) > 1 and routine is not None:
var = [c for c in variables if c in routine.module.accessible_var +
routine.module.variables +
routine.variables]
routine.module.variables +
routine.variables]
if len(var) == 1:
return var[0]
if not len(var):
try:
# Check if a use module, only var has been made
var = [c for c in variables if c in routine.use_only_variables]
if len(var) == 1:
return var[0]
except AttributeError:
pass
# Import are not done in a proper way, but use some sort of inheritance, I am not happy
var = [c for c in variables if c in routine.module.indirect_accessible_var]
if len(var) == 1:
......@@ -246,6 +253,28 @@ class Vault:
for var in used_module.variables:
module.indirect_accessible_var.append(var)
# Add info when a Func or a Sbr is using a use statement:
for procedure in self.functions + self.routines:
list_of_accessible_variables = []
if len(procedure.use_only_variables):
for index, module in enumerate(procedure.use_only_variables):
if module.count("only"):
used_var = module.split("only")[1].replace(":", "").strip()
module = module.split("only")[0].replace(",", "").strip()
for var in used_var.split(","):
used_module = [m for m in self.modules if m.name == module][0]
variable = [v for v in used_module.variables if v.name == var.strip()]
if variable:
list_of_accessible_variables.append(variable[0])
else:
used_module = [m for m in self.modules if m.name == module]
if used_module:
list_of_accessible_variables.extend(used_module[0].variables)
if list_of_accessible_variables:
procedure.use_only_variables = list_of_accessible_variables
else:
procedure.use_only_variables = []
def expand_derived_types(self):
for derived_type in self.derived_types:
if derived_type.extended_structure is not None:
......
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