-- | Helpers for pretty-printing sslang, including common ASCII tokens.
module Common.Pretty (
  module Prettyprinter,
  typeAnn,
  drarrow,
  larrow,
  rarrow,
  dbar,
  bar,
  amp,
  block,
  indentNo,
  spaghetti,
  Dumpy (dumpy),
) where

import Prettyprinter
import Prettyprinter.Render.String


{- | @typeAnn t d@ annotates document @d@ with type annotation @t@.

Only used by spaghetti so constrained by Dumpy instead of Pretty for now.
-}
typeAnn :: Dumpy t => t -> Doc ann -> Doc ann
typeAnn :: t -> Doc ann -> Doc ann
typeAnn t
t Doc ann
d = Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
parens (Doc ann -> Doc ann) -> Doc ann -> Doc ann
forall a b. (a -> b) -> a -> b
$ Doc ann
d Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Doc ann
forall ann. Doc ann
colon Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> t -> Doc ann
forall a ann. Dumpy a => a -> Doc ann
dumpy t
t


-- | @=>@
drarrow :: Doc ann
drarrow :: Doc ann
drarrow = [Char] -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty [Char]
"=>"


-- | @<-@
larrow :: Doc ann
larrow :: Doc ann
larrow = [Char] -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty [Char]
"<-"


-- | @->@
rarrow :: Doc ann
rarrow :: Doc ann
rarrow = [Char] -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty [Char]
"->"


-- | @||@
dbar :: Doc ann
dbar :: Doc ann
dbar = [Char] -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty [Char]
"||"


-- | @|@
bar :: Doc ann
bar :: Doc ann
bar = [Char] -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty [Char]
"|"


-- | @&@
amp :: Doc ann
amp :: Doc ann
amp = [Char] -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty [Char]
"&"


-- | Number of spaces to indent
indentNo :: Int
indentNo :: Int
indentNo = Int
2


-- | Constructs a separator-delimited block 'Doc' out of a list of 'Doc's.
block :: Doc ann -> [Doc ann] -> Doc ann
block :: Doc ann -> [Doc ann] -> Doc ann
block Doc ann
separator = Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
braces (Doc ann -> Doc ann)
-> ([Doc ann] -> Doc ann) -> [Doc ann] -> Doc ann
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Doc ann] -> Doc ann
forall ann. [Doc ann] -> Doc ann
sep ([Doc ann] -> Doc ann)
-> ([Doc ann] -> [Doc ann]) -> [Doc ann] -> Doc ann
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc ann -> [Doc ann] -> [Doc ann]
forall ann. Doc ann -> [Doc ann] -> [Doc ann]
punctuate Doc ann
separator


-- | Format with a document of infinite width, preventing wraparound.
spaghetti :: Dumpy t => t -> String
spaghetti :: t -> [Char]
spaghetti = SimpleDocStream Any -> [Char]
forall ann. SimpleDocStream ann -> [Char]
renderString (SimpleDocStream Any -> [Char])
-> (t -> SimpleDocStream Any) -> t -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LayoutOptions -> Doc Any -> SimpleDocStream Any
forall ann. LayoutOptions -> Doc ann -> SimpleDocStream ann
layoutPretty LayoutOptions
opts (Doc Any -> SimpleDocStream Any)
-> (t -> Doc Any) -> t -> SimpleDocStream Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. t -> Doc Any
forall a ann. Dumpy a => a -> Doc ann
dumpy
 where
  opts :: LayoutOptions
opts = LayoutOptions :: PageWidth -> LayoutOptions
LayoutOptions{layoutPageWidth :: PageWidth
layoutPageWidth = PageWidth
Unbounded}


{- | Dumpy Typeclass: print an ugly but parseable representation of the AST

* Translates from IR to Doc representation in one-to-one fashion
* No simplifications
* No whitespace formatting
* Type annotates everything
-}
class Dumpy a where
  dumpy :: a -> Doc ann