Unknown syntactical construct: HsSpliceE{} #90

Closed
opened 2017-12-23 00:08:37 +01:00 by lpil · 15 comments
lpil commented 2017-12-23 00:08:37 +01:00 (Migrated from github.com)

Hello!

I've found some code that the formatter is unable to format:

let body = [json|
hello
|]

A single line XQuasiQuote seems to work as intended

Hello! I've found some code that the formatter is unable to format: ```haskell let body = [json| hello |] ``` A single line XQuasiQuote seems to work as intended
eborden commented 2018-06-26 21:33:27 +02:00 (Migrated from github.com)

@lspitzner Do you have any ideas about how best to support QuasiQuotes? There is no reliable way to correctly handle their contents, since their syntax rules are unknown. I seems correctly aligning the opening and ending splice are what matters.

@lspitzner Do you have any ideas about how best to support `QuasiQuotes`? There is no reliable way to correctly handle their contents, since their syntax rules are unknown. I seems correctly aligning the opening and ending splice are what matters.
lspitzner commented 2018-07-16 00:50:15 +02:00 (Migrated from github.com)

@eborden hum.. wait. is the initial comment's example even valid haskell? I would assume that

let body = [json|
hello -- interferes with layouting rule, because left of `body`
|]

Which also points to why we have to also take indentation into account in general. "retain indentation relative to opening parenthesis" might be sufficient, assuming those don't become negative. With negative indentations, instead "retain indentation relative to the inner-most layouting column". How whitespace-sensitive are common QQ blocks?

I think in general we cannot avoid re-indenting the whole block, but we cannot re-indent because it might change QQ semantics. Might become a question of which generality we sacrifice.

@eborden hum.. wait. is the initial comment's example even valid haskell? I would assume that ~~~~.sh let body = [json| hello -- interferes with layouting rule, because left of `body` |] ~~~~ Which also points to why we have to also take indentation into account in general. "retain indentation relative to opening parenthesis" might be sufficient, assuming those don't become negative. With negative indentations, instead "retain indentation relative to the inner-most layouting column". How whitespace-sensitive are common QQ blocks? I think in general we cannot avoid re-indenting the whole block, but we cannot re-indent because it might change QQ semantics. Might become a question of which generality we sacrifice.
tfausak commented 2018-07-16 15:12:22 +02:00 (Migrated from github.com)

That syntax is valid Haskell. Quasi quotes completely disregard any layout, I think.

$ stack --resolver lts-12.0 exec --package aeson-qq ghci
GHCi, version 8.4.3: http://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /Users/taylor/.ghc/ghci.conf
>>> :set -XQuasiQuotes
>>> import Data.Aeson.QQ
>>> :{
... let body = [aesonQQ|
... null
... |]
... :}
>>> body
Null
That syntax is valid Haskell. Quasi quotes completely disregard any layout, I think. ``` $ stack --resolver lts-12.0 exec --package aeson-qq ghci GHCi, version 8.4.3: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /Users/taylor/.ghc/ghci.conf >>> :set -XQuasiQuotes >>> import Data.Aeson.QQ >>> :{ ... let body = [aesonQQ| ... null ... |] ... :} >>> body Null ```
lspitzner commented 2018-07-16 17:39:12 +02:00 (Migrated from github.com)

Oh, interesting. Yeah, i tested on TH QQs, but those are not even HsSpliceEs in the AST. (If you do [t|Int|] with a similar linebreak after opening bracket, ghc barks, but that is irrelevant, unless/until we also want to support TH QQs.)

This.. might make basic support (without any re-indentation) much easier than I had assumed: We probably can defer directly to exactprint for any HsSpliceE, not just the single-line ones?

Oh, interesting. Yeah, i tested on TH QQs, but those are not even `HsSpliceE`s in the AST. (If you do `[t|Int|]` with a similar linebreak after opening bracket, ghc barks, but that is irrelevant, unless/until we also want to support TH QQs.) This.. might make basic support (without any re-indentation) much easier than I had assumed: We probably can defer directly to exactprint for _any_ `HsSpliceE`, not just the single-line ones?
eborden commented 2018-07-16 21:55:16 +02:00 (Migrated from github.com)

@lspitzner As far as I'm aware anything between the splice brackets is up to the quasi quoter itself. So white space sensitivity is defined by the given parser. With that in mind any white space alterations besides the alignment of the opening bracket could become destructive.

@lspitzner As far as I'm aware anything between the splice brackets is up to the quasi quoter itself. So white space sensitivity is defined by the given parser. With that in mind any white space alterations besides the alignment of the opening bracket could become destructive.
lspitzner commented 2018-07-16 23:34:00 +02:00 (Migrated from github.com)

right. you can disregard my re-indentation idea.

unfortunately exactprinting does not work, it turns

{-# LANGUAGE QuasiQuotes #-}
func = [blub|
  asd
  qwe
  |]

into

{-# LANGUAGE QuasiQuotes #-}
func =
   [blub|
      asd
      qwe
      |]

so we need to manually not-transform the splice contents.

@eborden why does the closing position matter? only if there is stuff in the same line after it?

right. you can disregard my re-indentation idea. unfortunately exactprinting does not work, it turns ~~~~.hs {-# LANGUAGE QuasiQuotes #-} func = [blub| asd qwe |] ~~~~ into ~~~~.hs {-# LANGUAGE QuasiQuotes #-} func = [blub| asd qwe |] ~~~~ so we need to manually not-transform the splice contents. @eborden why does the closing position matter? only if there is stuff in the same line after it?
tfausak commented 2018-07-16 23:48:01 +02:00 (Migrated from github.com)

If I'm understanding you correctly, the closing position matters because it's still part of the splice:

$ stack --resolver ghc-8.4.3 exec -- ghci -XQuasiQuotes
GHCi, version 8.4.3: http://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /Users/taylor/.ghc/ghci.conf
>>> :m + Language.Haskell.TH.Quote Language.Haskell.TH.Syntax
>>> string = QuasiQuoter (pure . LitE . StringL) undefined undefined undefined
>>> :{
... [string| one
... two
... three |]
... :}
" one\ntwo\nthree "
If I'm understanding you correctly, the closing position matters because it's still part of the splice: ``` $ stack --resolver ghc-8.4.3 exec -- ghci -XQuasiQuotes GHCi, version 8.4.3: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /Users/taylor/.ghc/ghci.conf >>> :m + Language.Haskell.TH.Quote Language.Haskell.TH.Syntax >>> string = QuasiQuoter (pure . LitE . StringL) undefined undefined undefined >>> :{ ... [string| one ... two ... three |] ... :} " one\ntwo\nthree " ```
lspitzner commented 2018-07-16 23:55:40 +02:00 (Migrated from github.com)

right, i see.
I think this aspect can be handled just by appending "|]" to the splice contents. This narrows it down to the one task of exactly reproducing the splice contents, including any newline/whitespace.

right, i see. I think this aspect can be handled just by appending "|]" to the splice contents. This narrows it down to the one task of exactly reproducing the splice contents, including any newline/whitespace.
eborden commented 2018-07-17 02:35:46 +02:00 (Migrated from github.com)

I'd certainly prefer if the opening and closing brackets were aligned in form we'd expect with indentation alignment. Maybe brittany should do this and just assume that trailing whitespace doesn't matter in a parser since in the 99.9999% case it shouldn't.

let longidentifierthatbrittanywantstoindent = [qq|
my
 whitespace
language
     booya
      |]

into

let
 longidentifierthatbrittanywantstoindent = [qq|
my
 whitespace
language
     booya
  |]

I'd certainly prefer if the opening and closing brackets were aligned in form we'd expect with indentation alignment. Maybe `brittany` should do this and just assume that trailing whitespace doesn't matter in a parser since in the 99.9999% case it shouldn't. ``` let longidentifierthatbrittanywantstoindent = [qq| my whitespace language booya |] ``` into ``` let longidentifierthatbrittanywantstoindent = [qq| my whitespace language booya |] ```
domenkozar commented 2018-08-03 11:14:38 +02:00 (Migrated from github.com)

Maybe the starting point could be to just preserve everything between quasiquoting? Right now I have to filter out files with quasiquotes when using Brittany, which means those files don't get the same love :)

Maybe the starting point could be to just preserve everything between quasiquoting? Right now I have to filter out files with quasiquotes when using Brittany, which means those files don't get the same love :)
fisx commented 2018-09-27 17:00:54 +02:00 (Migrated from github.com)

I just encountered this behavior, and I'm not sure it's covered by this issue, so I'll add it as an extra data point. Let me know if I should open a separate issue!

$ brittany --version
brittany version 0.11.0.0
Copyright (C) 2016-2018 Lennart Spitzner
There is NO WARRANTY, to the extent permitted by law.
$ export SOME_MODULE="{-# LANGUAGE QuasiQuotes #-}\nimport URI.ByteString.QQ\nlonglonglonglonglonglonglonglonglonglonglonglonglonglonglong = [uri|http://alsolonglonglonglonglonglonglonglong.io/|]"
$ echo -e "$SOME_MODULE" | brittany
{-# LANGUAGE QuasiQuotes #-}
import           URI.ByteString.QQ
longlonglonglonglonglonglonglonglonglonglonglonglonglonglong =
  [uri|http://alsolonglonglonglonglonglonglonglong.io/|]
$ echo -e "$SOME_MODULE" | brittany | brittany
ERROR: brittany pretty printer returned syntactically invalid result.
ERROR: encountered unknown syntactical constructs:
HsSpliceE{} at stdin:4:3-56
I just encountered this behavior, and I'm not sure it's covered by this issue, so I'll add it as an extra data point. Let me know if I should open a separate issue! ```sh $ brittany --version brittany version 0.11.0.0 Copyright (C) 2016-2018 Lennart Spitzner There is NO WARRANTY, to the extent permitted by law. $ export SOME_MODULE="{-# LANGUAGE QuasiQuotes #-}\nimport URI.ByteString.QQ\nlonglonglonglonglonglonglonglonglonglonglonglonglonglonglong = [uri|http://alsolonglonglonglonglonglonglonglong.io/|]" $ echo -e "$SOME_MODULE" | brittany {-# LANGUAGE QuasiQuotes #-} import URI.ByteString.QQ longlonglonglonglonglonglonglonglonglonglonglonglonglonglong = [uri|http://alsolonglonglonglonglonglonglonglong.io/|] $ echo -e "$SOME_MODULE" | brittany | brittany ERROR: brittany pretty printer returned syntactically invalid result. ERROR: encountered unknown syntactical constructs: HsSpliceE{} at stdin:4:3-56 ```
domenkozar commented 2018-11-29 21:00:38 +01:00 (Migrated from github.com)

We are using git ls-files | grep 'hs$' | xargs grep -L QuasiQuotes | xargs brittany --write-mode inplace to avoid this issue (and keep those quasiquoted modules small).

We are using `git ls-files | grep 'hs$' | xargs grep -L QuasiQuotes | xargs brittany --write-mode inplace` to avoid this issue (and keep those quasiquoted modules small).
domenkozar commented 2019-04-11 09:26:58 +02:00 (Migrated from github.com)

Note that grep -L will exit with 123 if no files in the input contain the script, so best to use ack -L.

Note that `grep -L` will exit with 123 if no files in the input contain the script, so best to use `ack -L`.
tfausak commented 2019-06-18 15:52:49 +02:00 (Migrated from github.com)
$ stack exec -- brittany --version
brittany version 0.12.0.0
Copyright (C) 2016-2018 Lennart Spitzner
There is NO WARRANTY, to the extent permitted by law.

$ cat ~/Desktop/example.hs 
{-# language QuasiQuotes #-}
import Data.String.Interpolate
main = putStrLn
  [i|
    hello from a quasi quote
  |]

$ stack exec -- brittany ~/Desktop/example.hs
{-# language QuasiQuotes #-}
import Data.String.Interpolate
main = putStrLn [i|
    hello from a quasi quote
  |]
``` sh $ stack exec -- brittany --version brittany version 0.12.0.0 Copyright (C) 2016-2018 Lennart Spitzner There is NO WARRANTY, to the extent permitted by law. $ cat ~/Desktop/example.hs {-# language QuasiQuotes #-} import Data.String.Interpolate main = putStrLn [i| hello from a quasi quote |] $ stack exec -- brittany ~/Desktop/example.hs {-# language QuasiQuotes #-} import Data.String.Interpolate main = putStrLn [i| hello from a quasi quote |] ```
LennartSpitzner commented 2019-06-19 17:11:21 +02:00 (Migrated from github.com)

For the TH equivalent there is #206.

For the TH equivalent there is #206.
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: hexagoxel/brittany#90
There is no content yet.