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

Nested QuasiQuote Support #9

Open
gbaz opened this Issue Oct 13, 2011 · 10 comments

Comments

Projects
None yet
7 participants
@gbaz

gbaz commented Oct 13, 2011

Currently, while haskell-src-exts supports quasiquotes, haskell-src-meta doesn't implement a translation for them. We can't straightforwardly implement quasiquote expansion as a prepass, because that means running them as a function of String -> HS.Exp, when quasiquoters are of type String -> TH.ExpQ. So on the one hand, we could write a TH -> HS converter (and thus roundtrip quasiquotes an extra time), or we could parameterize ToExp & friends over a dictionary, which includes a map of strings to quasiquoters at the least (and perhaps a few other things?). Alternately, rather than parameterizing directly over a dictionary of quasiquoters, we could add a more general "open recursion" style scheme where functions of type HS -> Maybe TH are passed around and tried first, and only failing their success are the standard cases tried.

Sorry if this is a bit dense -- I hope it explains the issues involved well enough.

@bmillwood

This comment has been minimized.

Show comment
Hide comment
@bmillwood

bmillwood Sep 7, 2012

Owner

This sounds like a lot of work and complication for a feature most people won't use. I'm not willing to write the code for it, and I'll probably only accept patches if I'm convinced people would actually use the feature.

Owner

bmillwood commented Sep 7, 2012

This sounds like a lot of work and complication for a feature most people won't use. I'm not willing to write the code for it, and I'll probably only accept patches if I'm convinced people would actually use the feature.

@bmillwood

This comment has been minimized.

Show comment
Hide comment
@bmillwood

bmillwood Sep 7, 2012

Owner

(although if you want to send a patch and then help maintain the package, you're welcome to :P )

Owner

bmillwood commented Sep 7, 2012

(although if you want to send a patch and then help maintain the package, you're welcome to :P )

@ddssff

This comment has been minimized.

Show comment
Hide comment
@ddssff

ddssff Aug 26, 2013

Contributor

I need this feature, and I'm willing to write code for it. I just need a little guidance about what the SpliceExp case in Translate.hs would look like. It seemed to me that it would be necessary to change the signature of ToExp to return ExpQ instead of Exp, so I did that. It also led to similar changes for ToType, ToPat, ToDec, ToDecs, and ToStmt. What I don't know is how to get at the template haskell bindings when I see an IdSplice. If anyone can educate me I would be grateful.

Contributor

ddssff commented Aug 26, 2013

I need this feature, and I'm willing to write code for it. I just need a little guidance about what the SpliceExp case in Translate.hs would look like. It seemed to me that it would be necessary to change the signature of ToExp to return ExpQ instead of Exp, so I did that. It also led to similar changes for ToType, ToPat, ToDec, ToDecs, and ToStmt. What I don't know is how to get at the template haskell bindings when I see an IdSplice. If anyone can educate me I would be grateful.

@bmillwood

This comment has been minimized.

Show comment
Hide comment
@bmillwood

bmillwood Aug 27, 2013

Owner

We can't get rid of HSE.Exp -> TH.Exp entirely (ExpQ can't be turned into Exp in general).

I can't help you much, to be honest. It's precisely that I don't know the right way of doing this that has stopped me from trying already :)

Owner

bmillwood commented Aug 27, 2013

We can't get rid of HSE.Exp -> TH.Exp entirely (ExpQ can't be turned into Exp in general).

I can't help you much, to be honest. It's precisely that I don't know the right way of doing this that has stopped me from trying already :)

aavogt added a commit to aavogt/haskell-src-meta that referenced this issue May 22, 2014

aavogt added a commit to aavogt/haskell-src-meta that referenced this issue May 22, 2014

@Wizek

This comment has been minimized.

Show comment
Hide comment
@Wizek

Wizek Sep 16, 2016

This question interests me too.
Is the problem the type of parseExp :: String -> Either String Exp?
And if so, couldn't we have an additional function of type parseExpQ :: String -> Either String (Q Exp)?

Wizek commented Sep 16, 2016

This question interests me too.
Is the problem the type of parseExp :: String -> Either String Exp?
And if so, couldn't we have an additional function of type parseExpQ :: String -> Either String (Q Exp)?

@Wizek

This comment has been minimized.

Show comment
Hide comment
@Wizek

Wizek Sep 16, 2016

I'd also like to provide a use-case as a response to "a feature most people won't use":

I have begun to write a simple assertion QuasiQuoter that I use to provide me with more information at a glance about which tests have failed, while allowing me to having to write less descriptions by hand:

Example:

[aa| ("aI b = 1" $> parseLineToDepsG $> f) `shouldBe` ("a", ["b"]) |]
[aa| ("aI b = \\ x -> 1" $> parseLineToDepsG $> f) `shouldBe` ("a", ["b"]) |]
[aa| ("aI = 1 > 1" $> parseLineToDepsG $> f) `shouldBe` ("a", []) |]

Source: https://github.com/Wizek/hs-di/blob/8cff246/test/MainSpec.hs#L258

Which when executed with hspec looks like this:
img

And I'd like to begin to support quasiquotes and splices inside too, like:

[aa| ([text|
  aI
    b
    = 1
|\] $> T.unpack $> parseLineToDepsG $> f) `shouldBe` ("a", ["b"]) |]

Do you think this could be possible?

Wizek commented Sep 16, 2016

I'd also like to provide a use-case as a response to "a feature most people won't use":

I have begun to write a simple assertion QuasiQuoter that I use to provide me with more information at a glance about which tests have failed, while allowing me to having to write less descriptions by hand:

Example:

[aa| ("aI b = 1" $> parseLineToDepsG $> f) `shouldBe` ("a", ["b"]) |]
[aa| ("aI b = \\ x -> 1" $> parseLineToDepsG $> f) `shouldBe` ("a", ["b"]) |]
[aa| ("aI = 1 > 1" $> parseLineToDepsG $> f) `shouldBe` ("a", []) |]

Source: https://github.com/Wizek/hs-di/blob/8cff246/test/MainSpec.hs#L258

Which when executed with hspec looks like this:
img

And I'd like to begin to support quasiquotes and splices inside too, like:

[aa| ([text|
  aI
    b
    = 1
|\] $> T.unpack $> parseLineToDepsG $> f) `shouldBe` ("a", ["b"]) |]

Do you think this could be possible?

@cumber

This comment has been minimized.

Show comment
Hide comment
@cumber

cumber Mar 8, 2017

I just hit a use case for this. I'm using quasiquotes to provide a nicer literal syntax for a length-indexed list, so I use haskell-src-meta to easily support any haskell expression for the items of the list.

But then I needed a "sum-indexed list" (an unknown number of Nat-indexed items whose indexes sum up to a statically known value), so I followed the same pattern and made a quasiquote for that too. But some of the key things you'd want to put in the sum-indexed list are length-indexed lists.

It's not a complete loss, as I can still use the constructors directly, or bind the individual lists to variables ahead of time. But the failure is a bit jarring.

cumber commented Mar 8, 2017

I just hit a use case for this. I'm using quasiquotes to provide a nicer literal syntax for a length-indexed list, so I use haskell-src-meta to easily support any haskell expression for the items of the list.

But then I needed a "sum-indexed list" (an unknown number of Nat-indexed items whose indexes sum up to a statically known value), so I followed the same pattern and made a quasiquote for that too. But some of the key things you'd want to put in the sum-indexed list are length-indexed lists.

It's not a complete loss, as I can still use the constructors directly, or bind the individual lists to variables ahead of time. But the failure is a bit jarring.

@cumber

This comment has been minimized.

Show comment
Hide comment
@cumber

cumber Mar 9, 2017

Am I right in thinking that the essential problem is that there's no template haskell representation of template haskell syntax (like quasiquotes), so to produce a TH.Exp we have to run the quasi quotes?

cumber commented Mar 9, 2017

Am I right in thinking that the essential problem is that there's no template haskell representation of template haskell syntax (like quasiquotes), so to produce a TH.Exp we have to run the quasi quotes?

@mainland

This comment has been minimized.

Show comment
Hide comment
@mainland

mainland Mar 10, 2017

Collaborator

Yes, that is the essential problem.

Collaborator

mainland commented Mar 10, 2017

Yes, that is the essential problem.

@JonasDuregard

This comment has been minimized.

Show comment
Hide comment
@JonasDuregard

JonasDuregard Jun 20, 2018

Collaborator

IMO this is outside the scope of haskell-src-meta (it would require more than just a translation).

However if the code only needs to support a given set of quasi-quoters, it could perhaps be done by preprocessing. A function something like this:
processQQ :: [(String,QuasiQuoter)] -> HSE.Module -> Q HSE.Module
The idea is that processQQ [("text",text)] would preprocess all uses of the text QuasiQuoter.
For each QuaiQuote found in the HSE AST: Lookup the name of the quasiquoter in the list, apply the appropriate function from the QuasiQuoter, pretty-print the resulting TH AST and parse it back into a HSE AST, replacing the quote. Then the HSE AST can be translated using haskell-src-meta.

Collaborator

JonasDuregard commented Jun 20, 2018

IMO this is outside the scope of haskell-src-meta (it would require more than just a translation).

However if the code only needs to support a given set of quasi-quoters, it could perhaps be done by preprocessing. A function something like this:
processQQ :: [(String,QuasiQuoter)] -> HSE.Module -> Q HSE.Module
The idea is that processQQ [("text",text)] would preprocess all uses of the text QuasiQuoter.
For each QuaiQuote found in the HSE AST: Lookup the name of the quasiquoter in the list, apply the appropriate function from the QuasiQuoter, pretty-print the resulting TH AST and parse it back into a HSE AST, replacing the quote. Then the HSE AST can be translated using haskell-src-meta.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment