Repository navigation
Updates for expansion of array dimensions - #3620
schreiberx wants to merge 39 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3620 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 403 403
Lines 57394 57437 +43
=========================================
+ Hits 57394 57437 +43 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Thanks @schreiberx - please could you fix the coverage problems and then I'll review. |
|
100% coverage. Your turn. |
|
back to you |
|
Rather than to-and-fro on this Martin, I've taken it on. |
|
I've checked the three files where we do this transformation and the results of running PSyclone with this branch are identical to those on master: |
|
I'm having a lot of trouble getting NEMO built so that I can test locally. I therefore propose that this is ready for review and I can try again later (or perhaps a re-run of the ITs will resolve it). |
| f"inside a Routine.") | ||
|
|
||
| # Convert to list of symbols, if provided as strings | ||
| arrays_symbols: list[DataSymbol] = [] |
There was a problem hiding this comment.
Maybe rename it to "arrays_symbols_to_increase" ?
| # This checks for assignments of the form `a = ...` where 'a' | ||
| # is requested to have its rank increased. | ||
| if assignment.lhs.symbol not in arrays_symbols: | ||
| continue | ||
|
|
||
| if assignment.is_descendant_of(target_loop): | ||
| continue | ||
|
|
||
| if not assignment.rhs.walk(Call): | ||
| continue | ||
|
|
||
| if isinstance(assignment.lhs.datatype, | ||
| (ArrayType, UnresolvedType)): | ||
| # Reject because such an assignment needs to change | ||
| # the function as well (or introduce one or more | ||
| # additional loops), e.g.: | ||
| # a(1,:) = 1 + dummy_func() | ||
| info_str = assignment.debug_string().strip() | ||
| raise TransformationError( | ||
| f"{self.name} No call on r.h.s. of an assignment" | ||
| " to an array range is allowed as this would" | ||
| " imply a change to the return type of the call" | ||
| f" ({info_str})." | ||
| ) |
There was a problem hiding this comment.
At the first glance I don't see why this is needed, the function does not need to change because in Fortran the rhs rank does not need to match the lhs rank, the value is expanded to all the missing range, it's the same as:
a(1,:) = 1
converted to:
a(1,:,:) = 1
There was a problem hiding this comment.
Ok, I see it is not valid if dummy_func() returns an array, but this is not what is being tested, maybe we could do:
if not isinstance(assignment.rhs.datatype, ScalarType): ? and remove the walk(Call) as this is also true without the calls?
| f"{self.name} can't be applied to character arrays.") | ||
|
|
||
| if (not array.is_automatic or not array.is_array or | ||
| isinstance(sym.datatype.intrinsic, DataTypeSymbol)): |
There was a problem hiding this comment.
I suppose its array.datatype....., sym should not be used anymore
| f"{self.name} provided array '{sym_or_name}' does not " | ||
| f"exist in this scope." | ||
| ) from err | ||
| arrays_symbols.append(sym) |
There was a problem hiding this comment.
Careful here we can insert non-DataSymbols in what we said it is a arrays_symbols: list[DataSymbol] = [], this means that the type checker is happy with some operations below, like array.datatype in line 252, but it will fail at runtime with an AttributeError.
I think we want to do is first the lookups then the DataSym validation:
if isinstance(sym_or_name, str):
try:
sym = target_loop.scope.symbol_table.lookup(array)
except:
# Error
else
sym = sym_or_name
if isinstance(sym, DataSymbol):
arrays_symbols.append(sym)
else:
# Error
| # We iterate here over the arrays since it's more efficient | ||
| # than in the outer. |
There was a problem hiding this comment.
No need for this comment
There was a problem hiding this comment.
In fact we don't do anything with array, why don't we simply do:
for ref in target_loop.walk(Reference):
if ref in array_symbols:
if type(ref) ...
| f"for arrays accessed without indices. Found " | ||
| f"'{ref.ancestor(Statement).debug_string().strip()}'.") | ||
|
|
||
| array_ref: ArrayReference = ref |
There was a problem hiding this comment.
I am a bit scared of this type statements, are we sure ref is always an ArrayReference here? If it should be, why not make it explicit by using:
if not isinstance(ref, ArrayReference):
if the condition above, then the typechecker already infers that "ref" is ArrayReference without a manual annotation that could lie.
| integer :: i, j, k | ||
|
|
||
| ! Reject because of such an assignment | ||
| a(1,:) = 1 + dummy_func() |
There was a problem hiding this comment.
I have added the same comment in my review :) but in my case I cannot see why we reject this yet
| integer :: i, j, k | ||
|
|
||
| ! Reject because of such an assignment | ||
| a = 1 + dummy_func() |
There was a problem hiding this comment.
Same here, why reject this?

It rejects expanding array dimensions for return values of functions.