0 | module Compiler.ES.Doc
  1 |
  2 | import Data.List
  3 |
  4 | public export
  5 | data Doc
  6 |   = Nil
  7 |   | LineBreak
  8 |   | SoftSpace -- this will be ignored in compact printing
  9 |   | Comment Doc -- this will be ignored in compact printing
 10 |   | Text String
 11 |   | Nest Nat Doc
 12 |   | Seq Doc Doc
 13 |
 14 | export
 15 | Semigroup Doc where
 16 |   Nil <+> y = y
 17 |   x <+> Nil = x
 18 |   x <+> y = Seq x y
 19 |
 20 | export
 21 | Monoid Doc where
 22 |   neutral = Nil
 23 |
 24 | public export %inline
 25 | shown : Show a => a -> Doc
 26 | shown a = Text (show a)
 27 |
 28 | export %inline
 29 | comment : Doc -> Doc
 30 | comment = Comment
 31 |
 32 | export
 33 | FromString Doc where
 34 |   fromString = Text
 35 |
 36 | export
 37 | isMultiline : Doc -> Bool
 38 | isMultiline []         = False
 39 | isMultiline LineBreak  = True
 40 | isMultiline SoftSpace  = False
 41 | isMultiline (Text x)   = False
 42 | isMultiline (Comment x) = isMultiline x
 43 | isMultiline (Nest k x) = isMultiline x
 44 | isMultiline (Seq x y)  = isMultiline x || isMultiline y
 45 |
 46 | export
 47 | (<++>) : Doc -> Doc -> Doc
 48 | (<++>) a b = a <+> " " <+> b
 49 |
 50 | export
 51 | vcat : List Doc -> Doc
 52 | vcat = concat . intersperse LineBreak
 53 |
 54 | export
 55 | hcat : List Doc -> Doc
 56 | hcat = concat
 57 |
 58 | export
 59 | hsep : List Doc -> Doc
 60 | hsep = concat . intersperse " "
 61 |
 62 | export
 63 | block : Doc -> Doc
 64 | block b = concat ["{", Nest 1 (LineBreak <+> b), LineBreak, "}"]
 65 |
 66 | export
 67 | paren : Doc -> Doc
 68 | paren d = "(" <+> d <+> ")"
 69 |
 70 | export
 71 | lambdaArrow : Doc
 72 | lambdaArrow = SoftSpace <+> "=>" <+> SoftSpace
 73 |
 74 | export
 75 | softComma : Doc
 76 | softComma = "," <+> SoftSpace
 77 |
 78 | export
 79 | softColon : Doc
 80 | softColon = ":" <+> SoftSpace
 81 |
 82 | export
 83 | softEq : Doc
 84 | softEq = SoftSpace <+> "=" <+> SoftSpace
 85 |
 86 | export
 87 | compact : Doc -> String
 88 | compact = fastConcat . go
 89 |   where go : Doc -> List String
 90 |         go Nil        = []
 91 |         go LineBreak  = []
 92 |         go SoftSpace  = []
 93 |         go (Comment _) = []
 94 |         go (Text x)   = [x]
 95 |         go (Nest _ y) = go y
 96 |         go (Seq x y)  = go x ++ go y
 97 |
 98 | export
 99 | pretty : Doc -> String
100 | pretty = fastConcat . go ""
101 |   where nSpaces : Nat -> String
102 |         nSpaces n = fastPack $ replicate n ' '
103 |
104 |         go : (spaces : String) -> Doc -> List String
105 |         go _ Nil        = []
106 |         go s LineBreak  = ["\n",s]
107 |         go _ SoftSpace  = [" "]
108 |         go s (Comment x) = "/* " :: go s x ++ [" */"]
109 |         go _ (Text x)   = [x]
110 |         go s (Nest x y) = go (s ++ nSpaces x) y
111 |         go s (Seq x y)  = go s x ++ go s y
112 |