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

Agda-style case splitting for tactics #1379

Merged
merged 32 commits into from
Feb 17, 2021
Merged

Conversation

isovector
Copy link
Collaborator

@isovector isovector commented Feb 15, 2021

This PR lets tactics manipulate Match nodes in the AST when the solved goal is at the top level. It shifts a top-level lambda into function arguments, and then splits top-level case statements into multiple Matches. It looks like this:

fmapBoth

fmapEither

The underlying tactic search isn't changed, this is all just implemented as a final transformation step in I.P.T.CaseSplit.

Most of the work in this PR is grafting the new matches into the old ValD, which is a surprisingly tricky thing. @alanz --- is there an easier way to do this in ExactPrint?

I've tagged @konn and @alanz to take a look at my ExactPrint changes. I'm not particularly proud of them, but this works and I don't know how to do it better.

@jneira you're my go-to person for changes to the tactics codebase. And @pepeiborra , github suggested I tag you, so feel free to review any bits that interest you (the null set is acceptable too!)

Fixes #582

@Ailrun
Copy link
Member

Ailrun commented Feb 16, 2021

I'm not sure about that, but it would be better if we can move the cursor to the first generated sub-hole. (and preferably to the "next" hole if it generates none, but that's considerably harder, I guess.)

@isovector
Copy link
Collaborator Author

@Ailrun good idea! It won't happen in this PR, but feel free to file an issue, and I'll get around to it at some point :)

@isovector isovector changed the title [WIP] Agda-style case splitting for tactics Agda-style case splitting for tactics Feb 16, 2021
@isovector isovector marked this pull request as ready for review February 16, 2021 05:38
Copy link
Collaborator

@alanz alanz left a comment

Choose a reason for hiding this comment

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

I gave some feedback on ghc-exactprint related items.

@@ -358,7 +471,7 @@ annotateDecl :: DynFlags -> LHsDecl GhcPs -> TransformT (Either String) (Anns, L
annotateDecl dflags ast = do
uniq <- show <$> uniqueSrcSpanT
let rendered = render dflags ast
(anns, expr') <- lift $ mapLeft show $ parseDecl dflags uniq rendered
(anns, expr') <- lift $ mapLeft show $ parseDecls dflags uniq rendered
Copy link
Collaborator

Choose a reason for hiding this comment

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

Your parseDecls function seems to be an alternative version of addAnnotationsForPretty, which is specifically designed to add annotations to an AST element so that it is guaranteed to then parse again as the same AST. It may change layout in the process, but there are extensive tests to ensure that it does work for all ASTs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Unfortunately addAnnotationsForPretty doesn't work for newly generated code: alanz/ghc-exactprint#91

-- | We can't compare 'RdrName' for equality directly. Instead, compare them by
-- their 'OccName's.
eqRdrName :: RdrName -> RdrName -> Bool
eqRdrName = (==) `on` occNameString . occName
Copy link
Collaborator

Choose a reason for hiding this comment

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

Each RdrName is Located. The locations can be used as an index between the identifier location in the Parsed AST and the Renamed one, to get the exact identity, via the unique associated with a Name.

We used to construct this name map in HIE, it may still be in HLS. If not, here is it's source.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sorry, I'm not sure what you mean by this. The problem I was running into is that the RdrNames that come from VarPats have different locations than the RdrNames from HsVars.

Copy link
Collaborator

Choose a reason for hiding this comment

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

For each Located RdrName, if you look it up in the nameMap you will get the corresponding Name. If they are the same, as identified by the renaming phase, they will both have the same nameUnique value.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Upon further thought, I'm not sure this will work for me. This is all a pass over parsed trees, before the renamer has had a chance to run. Since we're simplifying tactics' code, which doesn't ever shadow variables, I don't think this is a concern.

@pepeiborra pepeiborra removed the request for review from jneira February 16, 2021 17:45
@isovector
Copy link
Collaborator Author

Please take another look. I think this is ready to be merged.

@pepeiborra pepeiborra added the merge me Label to trigger pull request merge label Feb 17, 2021
@mergify mergify bot merged commit 430ba2d into haskell:master Feb 17, 2021
@Ailrun Ailrun mentioned this pull request Feb 17, 2021
@isovector isovector deleted the agda-case-split branch May 21, 2021 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merge me Label to trigger pull request merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Tactics: case split as several declarations
4 participants