Skip to content

(#Closes 468) Added Directive node separated from comments #469

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

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

LonelyCat124
Copy link

Initial implementation of this feature.

Ready for a look from any of @arporter @sergisiso @hiker

@LonelyCat124
Copy link
Author

I've realised that this only works with 3.10 and above due to type declarations.

Copy link

codecov bot commented Jun 26, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 92.16%. Comparing base (370884f) to head (af58dde).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #469      +/-   ##
==========================================
+ Coverage   92.15%   92.16%   +0.01%     
==========================================
  Files          86       86              
  Lines       13734    13765      +31     
==========================================
+ Hits        12656    12687      +31     
  Misses       1078     1078              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@LonelyCat124
Copy link
Author

Pushed some changes now to fix some docs issues and coverage updates.

Copy link
Member

@arporter arporter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Aidan. Everything looks sensible but I do have a couple questions about inheritance and valid locations for directives.
In fact, now that I write that, please could you add a new section to the documentation - probably just before https://fparser.readthedocs.io/en/latest/fparser2.html#preprocessing-directives.
I'm wondering whether it would be wise for us to make this behaviour configurable somehow, just in case interpreting things as directives causes problems for downstream applications. I guess we could do this in the same way as we do for the support for non-standard extensions.

#
# SECTION 2
#
class Directive(Base):
"""
Represents a Directive.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Admittedly you've only copied what's done for Comment but this is a bit terse. Perhaps say that it's a leaf in the parse tree and contains a single item consisting of the whole directive (assuming I've got that right - I'm just guessing).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expanded it.

obj = object.__new__(cls)
obj.init(string)
return obj
elif isinstance(string, FortranReaderBase):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pylint will say that quite a few of these elif and else are unnecessary because they are immediately preceded by a return.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tidied this up for the directive.

"""
Initialise this Directive

:param comment: The comment object produced by the reader
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/comment/directive/ in the docstring, argument and body? (Although type of the comment argument is Comment?)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, because the input is a comment I kept this as "comment". I added a bit more saying we initialise from a comment object.

@@ -207,7 +284,8 @@ def match_comment_or_include(reader):
:py:class:`fparser.two.Fortran2003.Include_Stmt`

"""
obj = Comment(reader)
obj = Directive(reader)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring for this method needs to be updated now that it can also return a Directive.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

"""
return str(self.items[0])

def restore_reader(self, reader) -> None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I'm missing something, this is just a duplication of Base.restore_reader() and can therefore be removed?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, removed. Do you want me to remote it from Comment as well?

#
# SECTION 2
#
class Directive(Base):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering: since a directive is a comment, would it make sense to have Directive subclass Comment? Would that win us anything?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I think I dislike that. For parsing, having walk(..., Comment) and walk(..., Directive) return distinct sets makes more sense, especially since a lot of directives "do something" in real codes, wheras comments have no side effects.

if comment.items[0] != "":
assert comment.items[0] == "! A comment!"
comments = comments + 1
assert comments == 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert len(out) == 1 and then you don't have to count them? Please could you also add a check that !!$ is still a comment.
We also need a separate test with fixed-format source :-(

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No - for some reason fparser makes a bunch of empty comments in various locations in this tree (this behaviour happened before my changes), so I need to count how many non-empty comments there are.

Do directives exist in fixed-format? I've never really written fixed-format source - i guess I need to check what c $ does? But i'm also not sure what its meant to do.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also added a test for !!$

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Directive are not in the standard so each compiler may be different but cdir$ is understood by flang and gfortran, e.g. https://flang.llvm.org/docs/Directives.html#introduction

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't currently handle "!dir$" even, I'd assumed it would start !$ - I probably need to fix that then.

@@ -710,8 +712,8 @@ def match(
if match_names:
start_name = obj.get_start_name()

# Comments and Include statements are always valid sub-classes
classes = subclasses + [di.Comment, di.Include_Stmt]
# Directives, Comments and Include statements are always valid sub-classes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this definitely true? Are there examples of directives that can appear anywhere in a source file? i.e. outside a program or module unit?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assumed a directive could in theory appear anywhere a comment could (since it is a comment?). @sergisiso what do you7 think?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, since it is not standard it is difficult to say exactly. But I woudn't complicate things here. I would let Directive be anywhere, as Comments and Include_Stmts, and let the tooling reading the tree do the best effort to validate/interpret them.

@arporter arporter added reviewed with actions PR has been reviewed and is back with developer and removed under review labels Jun 26, 2025
@LonelyCat124
Copy link
Author

Addressed most of the comments.
Remaining questions about where directives can appear and fixed format directive test.

@sergisiso
Copy link
Collaborator

@LonelyCat124 I know we talked about that but I forgot. What is the benefit of differentiating in fparser between Comments and Directives? Are you planning to parse the body of the directive in the future?

@LonelyCat124
Copy link
Author

@LonelyCat124 I know we talked about that but I forgot. What is the benefit of differentiating in fparser between Comments and Directives? Are you planning to parse the body of the directive in the future?

@sergisiso yes - its to separate directives from comments to make handling them in PSyclone better in the future (which I plan to continue down that avenue now). It also cleans up even the current implementation I think.

@LonelyCat124
Copy link
Author

@arporter I think this is cleaned up and ready for another look now.

@LonelyCat124 LonelyCat124 added ready for review and removed reviewed with actions PR has been reviewed and is back with developer labels Jun 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants