-
Notifications
You must be signed in to change notification settings - Fork 30
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
Adding strict order statements (closes #353) #358
base: master
Are you sure you want to change the base?
Conversation
I've fixed the 0 or 1 instance problem but now break the addition of comments so I think I'll need to add a comment loop before incrementing the class pointer. Note, there may be cases where it might be worth having a list of classes that are 0 or 1, as a subset of the classes might require this. I should look at this. |
There appears to be a noticable improvement in performance for the example benchmark ... master: Time taken for parse = 36.27s |
…arser into 353_strict_order
Codecov ReportBase: 91.48% // Head: 91.25% // Decreases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## master #358 +/- ##
==========================================
- Coverage 91.48% 91.25% -0.23%
==========================================
Files 37 37
Lines 13138 13134 -4
==========================================
- Hits 12019 11986 -33
- Misses 1119 1148 +29
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
When testing the latest version with LFRic algorithm code I am finding parse errors in code like ...
which is not correct (although PSyclone does not promise to support ifdef'ed code). I guess it is because we are incrementing the class match without dealing with comments and ifdefs. I need to look at how to fix this. This probably related to the change in location of comments that is observed in tests (which I convinced myself was OK). |
Interestingly comments between use statements seem to be OK but ifdef's are not. I thought we processed these in the same way. I guess there must be a difference somewhere. |
OK, I now realise that comment, include and preprocess rules are added to the general blockbase rules, so if we do them in order they will not be picked up at the right point. I think we need to not add them to the rules and then consume all of them as we go along (without incrementing the class reference), but it needs thinking about. |
Comment restructuring seems to be working. All tests pass, LFRic code is being parsed OK with psyclone and psyclone tests pass after finding and fixing another bug in one of the examples. Annoyingly, running psyclone on all the lfric algorithm codes does not seem to give any performance improvement. |
Hi @rupertford, do you think you could add in a test that I wrote for #366 into this PR:
|
Added test, which seems to work as expected, giving the following (which preserves comment locations) ...
|
I'm not sure why I didn't make this ready for review before so here we go ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All looks good apart from the fact that there seem to be no tests for the new once_only
flag - I'd expect to see some tests that we reject code that has more than one implicit none
in it for example.
Coverage is fine and Black means I don't have to worry much about style (although see inline for a couple of pylint things).
I don't think that the Dev Guide needs to be updated.
if not strict_order: | ||
# Return to start of classes list now that we've matched. | ||
i = 0 | ||
elif once_only: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest a comment: we had a match for this sub-class and once_only
is set so move on to the next sub-class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added comment.
@@ -714,9 +714,15 @@ def match( | |||
# We've found the enclosing end statement so break out | |||
found_end = True | |||
break | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not strictly yours but since we're here pylint complains that the elif
at L701 could be an if
. Probably the same goes for L705.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modified.
@@ -10157,6 +10159,7 @@ def match(reader): | |||
[Specification_Part, Module_Subprogram_Part], | |||
End_Module_Stmt, | |||
reader, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each sub-class can only match once for a valid module? (I initially got worried that this wouldn't work for multiple modules in a file but it's fine.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, a Module can only contain one Module_Stmt, one Specification_Part, one Module_Subprogram_Part and one End_Module_Stmt. Multiple modules are supported in 'higher level' rules, such as Program_Unit.
# |--> Execution_Part | ||
# | |--> Write_Stmt | ||
# | \--> Comment | ||
# | |--> Comment | ||
# . . | ||
# . | ||
# |--> Comment | ||
from fparser.two.Fortran2003 import Main_Program, Write_Stmt, End_Program_Stmt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move these imports to the top (and check for any subsequent repeats).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved all imports to the top.
assert isinstance(comment, Comment) | ||
assert "! First comment" in str(comment) | ||
comment = spec_part.content[2].content[0] | ||
spec_part = fn_unit.children[2] | ||
comment = spec_part.content[2] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/content/children/ since you use that on the previous line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point.
I started adding a test for strict_order and found that the implementation is not working correctly. For example
should not match with Specification_Part as The rule order is ...
However, |
Some of the rules using blockbase have a strict order. This PR enforces this where it was not already used. The parser runs a bit faster as a result.
However, there is an additional case where we only want blockbase to allow 0 or 1 instances of a particular rule to match. At the moment that is not enforced and we can end up with multiple Specification_Part entries within a Main_Program if, for example, an implicit none is incorrectly added before a use statement. This is not a good outcome as tools might rightly rely on there only being one of these and we end up with strange errors, rather than it being caught by fparser in the first place. Note that on master we only get one Specification_Part but the implicit none and use statements are allowed to be in the wrong order.