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

Add pointwise command to the metaprogram parser #1921

Merged
merged 3 commits into from Jun 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 23 additions & 0 deletions plugins/hls-tactics-plugin/COMMANDS.md
Expand Up @@ -389,6 +389,29 @@ running `obvious` will produce:
```haskell
[]
```
## pointwise

arguments: tactic.
deterministic.

> Restrict the hypothesis in the holes of the given tactic to align up with the top-level bindings. This will ensure, eg, that the first hole can see only terms that came from the first position in any terms destructed from the top-level bindings.


### Example

> In the context of `f (a1, b1) (a2, b2) = _`. The resulting first hole can see only 'a1' and 'a2', and the second, only 'b1' and 'b2'.

Given:

```haskell
_
```

running `pointwise (use mappend)` will produce:

```haskell
mappend _ _
```
## recursion

arguments: none.
Expand Down
2 changes: 0 additions & 2 deletions plugins/hls-tactics-plugin/src/Wingman/KnownStrategies.hs
@@ -1,8 +1,6 @@
module Wingman.KnownStrategies where

import Control.Applicative (empty)
import Control.Monad.Error.Class
import Control.Monad.Reader.Class (asks)
import Data.Foldable (for_)
import OccName (mkVarOcc)
import Refinery.Tactic
Expand Down
11 changes: 11 additions & 0 deletions plugins/hls-tactics-plugin/src/Wingman/Metaprogramming/Parser.hs
Expand Up @@ -176,6 +176,17 @@ commands =
"f (_ :: a)"
]

, command "pointwise" Deterministic Tactic
"Restrict the hypothesis in the holes of the given tactic to align up with the top-level bindings. This will ensure, eg, that the first hole can see only terms that came from the first position in any terms destructed from the top-level bindings."
(pure . flip restrictPositionForApplication (pure ()))
[ Example
(Just "In the context of `f (a1, b1) (a2, b2) = _`. The resulting first hole can see only 'a1' and 'a2', and the second, only 'b1' and 'b2'.")
["(use mappend)"]
[]
Nothing
"mappend _ _"
]

, command "apply" Deterministic (Ref One)
"Apply the given function from *local* scope."
(pure . useNameFromHypothesis apply)
Expand Down
@@ -0,0 +1,7 @@
module Wingman.Metaprogramming.Parser where

import Wingman.Metaprogramming.Lexer
import Wingman.Types

tactic :: Parser (TacticsM ())

Expand Up @@ -6,13 +6,15 @@ import Data.Functor ((<&>))
import Data.List (sortOn)
import Data.String (IsString)
import Data.Text (Text)
import Data.Text.Prettyprint.Doc
import Data.Text.Prettyprint.Doc hiding (parens)
import Data.Text.Prettyprint.Doc.Render.String (renderString)
import GhcPlugins (OccName)
import qualified Text.Megaparsec as P
import Wingman.Metaprogramming.Lexer (Parser, identifier, variable)
import Wingman.Metaprogramming.Lexer (Parser, identifier, variable, parens)
import Wingman.Types (TacticsM)

import {-# SOURCE #-} Wingman.Metaprogramming.Parser (tactic)


------------------------------------------------------------------------------
-- | Is a tactic deterministic or not?
Expand Down Expand Up @@ -46,11 +48,13 @@ data Syntax a where
Nullary :: Syntax (Parser (TacticsM ()))
Ref :: Count a -> Syntax (a -> Parser (TacticsM ()))
Bind :: Count a -> Syntax (a -> Parser (TacticsM ()))
Tactic :: Syntax (TacticsM () -> Parser (TacticsM ()))

prettySyntax :: Syntax a -> Doc b
prettySyntax Nullary = "none"
prettySyntax (Ref co) = prettyCount co <+> "reference"
prettySyntax (Bind co) = prettyCount co <+> "binding"
prettySyntax Tactic = "tactic"


------------------------------------------------------------------------------
Expand Down Expand Up @@ -108,21 +112,24 @@ data SomeMetaprogramCommand where
------------------------------------------------------------------------------
-- | Run the 'Parser' of a 'MetaprogramCommand'
makeMPParser :: MetaprogramCommand a -> Parser (TacticsM ())
makeMPParser (MC name Nullary _ _ tactic _) = do
makeMPParser (MC name Nullary _ _ t _) = do
identifier name
t
makeMPParser (MC name (Ref One) _ _ t _) = do
identifier name
tactic
makeMPParser (MC name (Ref One) _ _ tactic _) = do
variable >>= t
makeMPParser (MC name (Ref Many) _ _ t _) = do
identifier name
variable >>= tactic
makeMPParser (MC name (Ref Many) _ _ tactic _) = do
P.many variable >>= t
makeMPParser (MC name (Bind One) _ _ t _) = do
identifier name
P.many variable >>= tactic
makeMPParser (MC name (Bind One) _ _ tactic _) = do
variable >>= t
makeMPParser (MC name (Bind Many) _ _ t _) = do
identifier name
variable >>= tactic
makeMPParser (MC name (Bind Many) _ _ tactic _) = do
P.many variable >>= t
makeMPParser (MC name Tactic _ _ t _) = do
identifier name
P.many variable >>= tactic
parens tactic >>= t


------------------------------------------------------------------------------
Expand Down
Expand Up @@ -33,5 +33,5 @@ spec = do
metaTest 11 11 "MetaUseMethod"
metaTest 9 38 "MetaCataCollapse"
metaTest 7 16 "MetaCataCollapseUnary"
metaTest 6 46 "MetaPointwise"
metaTest 4 28 "MetaUseSymbol"

@@ -0,0 +1,8 @@
import Data.Monoid

data Foo = Foo (Sum Int) (Sum Int)

mappend2 :: Foo -> Foo -> Foo
mappend2 (Foo sum sum') (Foo sum2 sum3)
= Foo (mappend sum sum2) (mappend sum' sum3)

7 changes: 7 additions & 0 deletions plugins/hls-tactics-plugin/test/golden/MetaPointwise.hs
@@ -0,0 +1,7 @@
import Data.Monoid

data Foo = Foo (Sum Int) (Sum Int)

mappend2 :: Foo -> Foo -> Foo
mappend2 = [wingman| intros f1 f2, destruct_all, ctor Foo; pointwise (use mappend); assumption|]