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

dmd.apply: Implement walkPreorder helper function #14883

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

ibuclaw
Copy link
Member

@ibuclaw ibuclaw commented Feb 15, 2023

Looking at putting #14830 into the front-end where it feels like it belongs (@kinke). I'll have to see whether what I'm using this for actually makes sense, this change only breaks out the boilerplate part into its own standalone PR.

Current expression/statement apply helper implements a post-order DFS traversal of the AST. This is fine when you want to descend and mark all children first before each connecting parent, but doesn't help when you want to traverse the AST in a more forwards direction as you'd expect the flow of user code to be executed in.

i.e: Given a stoppable visitor with override void visit(LabelStatement) { stop = true; } and marking every other statement/expression visited, for the following:

case 1:
    if (__ctfe)
    {
        {
            int[] foo = [1];
        }
L3:
        i += 2;
case 2:
        ++i;
    }

Traversing post-order will give you

case 1:
    if (__ctfe)
    {
        {                    // 2. mark
            int[] foo = [1]; // 1. mark
        }
L3:                          // 4. stop
        i += 2;              // 3. mark
case 2:
        ++i;
    }

Traversing pre-order will instead give you

case 1:                      // 1. mark
    if (__ctfe)              // 2. mark
    {                        // 3. mark
        {                    // 4. mark
            int[] foo = [1]; // 5. mark
        }
L3:                          // 6. stop
        i += 2;
case 2:
        ++i;
    }

Wait, if you want forward walking, shouldn't you be instead using a ParseTimeTransitiveVisitor?
Yes, maybe, well, not sure anymore the more I think about it. At the very least, one negative aspect of ParseTimeTransitiveVisitor is that it by default visits all connecting nodes, including types, constraints, and base class declarations. This would waste extra time walking the trees just to get to the nodes you actually want to visit.


Couldn't PostorderStatementVisitor and PreorderStatementVisitor just be folded into the same visitor, make it a template instead of 300 lines of almost (but not quite) identical code?
Yes, but would it be readable having both paths mixed together, ehh... maybe. We'll see how this goes first.

@ibuclaw ibuclaw added the Refactoring No semantic changes to code label Feb 15, 2023
@dlang-bot
Copy link
Contributor

Thanks for your pull request, @ibuclaw!

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + dmd#14883"

@RazvanN7
Copy link
Contributor

Yes, maybe, well, not sure anymore the more I think about it. At the very least, one negative aspect of ParseTimeTransitiveVisitor is that it by default visits all connecting nodes, including types, constraints, and base class declarations.

I think you can just exclude those nodes by overriding the most general visiting method (for example, just override visit(Type) with a do-nothing body to exclude the visitation of Type nodes). That being said, I don't have a problem with this PR going in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Rebase Refactoring No semantic changes to code stalled
Projects
None yet
3 participants