Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not expand all members of derived type variables unless explicitly requested #243

Open
reuterbal opened this issue Mar 12, 2024 · 0 comments

Comments

@reuterbal
Copy link
Collaborator

When creating Variable nodes for members of derived types, say in a subroutine's body, we use a mechanism to infer the parent symbol and then the type information from the parent:

if '%' in name and (not stored_type or stored_type.dtype is BasicType.DEFERRED):
name_parts = name.split('%')
if not parent:
# Build the parent if not given
parent_type = scope.symbol_attrs.lookup(name_parts[0])
parent = Variable(name=name_parts[0], scope=scope, type=parent_type)
for pname in name_parts[1:-1]:
if not parent:
return None
parent = parent.variable_map.get(pname) # pylint: disable=no-member
if parent:
# Lookup type in parent's typedef
tdef_var = parent.variable_map.get(name_parts[-1])
if tdef_var:
return tdef_var.type

This uses TypedSymbol.variable_map, which in turn invokes TypedSymbol.variables. The latter creates symbols for all variables declared in a derived type, with the correct scope (i.e., the parent's scope) attached. This ensures we have the correct type information in the local scope's type table for derived type members:

def variables(self):
"""
List of member variables in a derived type
Returns
-------
tuple of :any:`TypedSymbol` or :any:`MetaSymbol` if derived type variable, else `None`
List of member variables in a derived type
"""
_type = self.type
if _type and isinstance(_type.dtype, DerivedType):
if _type.dtype.typedef is BasicType.DEFERRED:
return ()
return tuple(
v.clone(name=f'{self.name}%{v.name}', scope=self.scope, type=v.type, parent=self)
for v in _type.dtype.typedef.variables
)
return None
@property
def variable_map(self):
"""
Member variables in a derived type variable as a map
Returns
-------
dict of (str, :any:`TypedSymbol` or :any:`MetaSymbol`)
Map of member variable basenames to variable objects
"""
return CaseInsensitiveDict((v.basename, v) for v in self.variables or ())

However, this can become costly for large nested derived types (e.g., my%very%deeply%nested%derived%type%var), where it will trigger this expansion for every intermediate symbol. While imho the mechanism of TypedSymbol.variables itself is correct and should remain as is, we should have a secondary mechanism which will allow to look up the relevant type information and instantiate only the required symbol.

This has been discovered as part of #242 and been flagged explicitly here: #242 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant