bmillwood / haskell-src-meta

Maintenance of Matt Morrow's package for parsing haskell source to a TH AST.
Other
27 stars 51 forks source link

Nested QuasiQuote Support #9

Open gbaz opened 12 years ago

gbaz commented 12 years ago

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 commented 12 years ago

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 commented 12 years ago

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

ddssff commented 11 years ago

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 commented 11 years ago

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 :)

Wizek commented 7 years ago

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 7 years ago

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 commented 7 years ago

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 7 years ago

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 commented 7 years ago

Yes, that is the essential problem.

JonasDuregard commented 6 years ago

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.