less prototype, less bad code implementation of CCHM type theory
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

233 lines
7.5 KiB

  1. {-# LANGUAGE LambdaCase #-}
  2. {-# OPTIONS_GHC -Wno-orphans #-}
  3. {-# LANGUAGE ViewPatterns #-}
  4. {-# LANGUAGE NamedFieldPuns #-}
  5. {-# LANGUAGE CPP #-}
  6. module Syntax.Pretty where
  7. import qualified Data.Map.Strict as Map
  8. import qualified Data.Text.Lazy as Lazy
  9. import qualified Data.Text as T
  10. import Data.Map.Strict (Map)
  11. import Presyntax.Presyntax (Plicity(..))
  12. import Prettyprinter.Render.Terminal
  13. import Prettyprinter
  14. import Syntax
  15. instance Pretty Name where
  16. pretty x = pretty (getNameText x) -- <> pretty '\'' <> pretty (getNameNum x)
  17. prettyTm' :: Bool -> Term -> Doc AnsiStyle
  18. prettyTm' implicits = go True 0 where
  19. go t p =
  20. \case
  21. Ref v -> pretty v
  22. Con v -> keyword $ pretty v
  23. PCon _ v -> keyword $ pretty v
  24. Data _ v -> keyword $ pretty v
  25. App Im f x
  26. | implicits -> parenIf (p >= arg_prec) $
  27. go False fun_prec f
  28. <+> braces (go False 0 x)
  29. | otherwise -> go t p f
  30. App Ex f x ->
  31. parenIf (p >= arg_prec) $
  32. go False fun_prec f
  33. <+> group (go False arg_prec x)
  34. Lam Ex v (App Ex f (Ref v')) | v == v' -> instead f
  35. Lam i v t ->
  36. let
  37. getArgs (Lam i v t) =
  38. let (as, b) = getArgs t in ((i, v):as, b)
  39. getArgs (PathIntro _ _ _ (Lam _ v t)) =
  40. let (as, b) = getArgs t in ((Ex, v):as, b)
  41. getArgs t = ([], t)
  42. (as, b) = getArgs (Lam i v t)
  43. in
  44. parenIf (p >= fun_prec) . group $
  45. pretty '\\' <> hsep (map (\(i, v) -> braceIf (i == Im) (pretty v)) as)
  46. <+> arrow
  47. <+> nest 2 (go False 0 b)
  48. Pi _ (T.unpack . getNameText -> "_") d r ->
  49. parenIf (p >= fun_prec) $
  50. group (go False dom_prec d)
  51. <> space <> arrow <> sp
  52. <> go t 0 r
  53. Pi i x d r ->
  54. let
  55. c = case r of
  56. Pi _ (getNameText -> x) _ _ | x /= T.pack "_" -> sp
  57. _ -> space <> arrow <> sp
  58. in
  59. parenIf (p >= fun_prec) $
  60. plic i (pretty x <+> colon <+> go False 0 d)
  61. <> c <> go t 0 r
  62. Let binds body ->
  63. parenIf (p >= fun_prec) $
  64. align $ keyword (pretty "let")
  65. <> line
  66. <> indent 2 (prettyBinds False binds)
  67. <> keyword (pretty "in")
  68. <+> go False 0 body
  69. Meta MV{mvName} -> keyword (pretty '?' <> pretty mvName)
  70. Type -> keyword (pretty "Type")
  71. Typeω -> keyword (pretty "Pretype")
  72. Sigma (T.unpack . getNameText -> "_") d r ->
  73. parenIf (p >= fun_prec) $
  74. go False dom_prec d
  75. <+> operator (pretty "*")
  76. <+> go False dom_prec r
  77. Sigma v d r ->
  78. parenIf (p >= fun_prec) . align $
  79. group (parens (pretty v <+> colon <+> go False 0 d))
  80. <+> operator (pretty "*") <+> go False dom_prec r
  81. Pair a b -> parens $ go False 0 a <> comma <+> go False 0 b
  82. Proj1 a -> parenIf (p >= arg_prec) $ go False 0 a <> keyword (pretty ".1")
  83. Proj2 a -> parenIf (p >= arg_prec) $ go False 0 a <> keyword (pretty ".2")
  84. I -> keyword (pretty "I")
  85. I0 -> keyword (pretty "i0")
  86. I1 -> keyword (pretty "i1")
  87. IAnd x y -> parenIf (True || p > and_prec) $
  88. go False and_prec x <+> operator (pretty "/\\") <+> go False and_prec y
  89. IOr x y -> parenIf (True || p > or_prec) $
  90. go False or_prec x <+> operator (pretty "\\/") <+> go False or_prec y
  91. INot x -> operator (pretty "~") <> go False p x
  92. PathP _ x y -> parenIf (p >= arg_prec) $
  93. go False 0 x <+> operator (pretty "") <+> go False 0 y
  94. IElim _a _x _y f i -> instead (App Ex f i)
  95. PathIntro _a _x _y f -> instead f
  96. Partial a p -> apps (con "Partial") [(Ex, a), (Ex, p)]
  97. PartialP a p -> apps (con "PartialP") [(Ex, a), (Ex, p)]
  98. System fs | Map.null fs -> brackets mempty
  99. System fs ->
  100. let
  101. face (f, t) = go False 0 f <+> operator (pretty "=>") <+> go False 0 t
  102. in
  103. brackets (line <> nest 2 (vsep (punctuate comma (map face (Map.toList fs)))) <> line)
  104. Sub a phi u -> apps (con "Sub") [(Ex, a), (Ex, phi), (Ex, u)]
  105. Inc a phi u -> apps (con "inS") [(Im, a), (Im, phi), (Ex, u)]
  106. Ouc a phi u a0 -> apps (con "outS") [(Im, a), (Im, phi), (Im, u), (Ex, a0)]
  107. GlueTy a phi t e -> apps (con "primGlue") [(Ex, a), (Ex, phi), (Ex, t), (Ex, e)]
  108. Glue _a _phi _ty _e t im -> apps (con "glue") [(Ex, t), (Ex, im)]
  109. Unglue _a _phi _ty _e t -> apps (con "unglue") [(Im, _a), (Im, _phi), (Im, _ty), (Im, _e), (Ex, t)]
  110. Comp a phi u a0 -> apps (con "comp") [(Ex, a), (Im, phi), (Ex, u), (Ex, a0)]
  111. HComp a phi u a0 -> apps (con "hcomp") [(Im, a), (Im, phi), (Ex, u), (Ex, a0)]
  112. Case _ t cs ->
  113. let
  114. oneCase (c, 0, l) = go False 0 c <+> operator (pretty "=>") <+> go False 0 l
  115. oneCase (c, i, l) =
  116. let (args, bd) = getLams i l
  117. in go False 0 c <+> hsep (map pretty args) <+> operator (pretty "=>") <+> go False 0 bd
  118. getLams 0 x = ([], x)
  119. getLams n (Lam _ v t) = let (as, b) = getLams (n - 1) t in (v:as, b)
  120. getLams _ x = ([], x)
  121. in
  122. parenIf (p >= fun_prec) $
  123. keyword (pretty "case") <+> go False 0 t <+> keyword (pretty "of")
  124. <> line
  125. <> indent 2 (vsep (map oneCase cs))
  126. EqS _ x y -> parenIf (p >= arg_prec) $
  127. go False 0 x <+> operator (pretty "≡S") <+> go False 0 y
  128. Syntax.Refl _ _ -> keyword (pretty "refl")
  129. Syntax.AxK _ _ bigp pr eq -> apps (con "K_s") [(Ex, bigp), (Ex, pr), (Ex, eq)]
  130. Syntax.AxJ _ _ bigp pr _ eq -> apps (con "J_s") [(Ex, bigp), (Ex, pr), (Ex, eq)]
  131. where
  132. sp | t = softline
  133. | otherwise = space
  134. parenIf p x | p = parens x
  135. | otherwise = x
  136. braceIf p x | p = braces x
  137. | otherwise = x
  138. con x = Con (Bound (T.pack x) 0)
  139. plic = \case
  140. Ex -> parens
  141. Im -> braces
  142. arrow = operator (pretty "->")
  143. instead = go t p
  144. apps :: Term -> [(Plicity, Term)] -> Doc AnsiStyle
  145. apps f xs = instead (foldl (\f (p, x) -> App p f x) f xs)
  146. prettyBinds :: Bool -> [(Name, Term, Term)] -> Doc AnsiStyle
  147. prettyBinds _ [] = mempty
  148. prettyBinds imp ((x, ty, tm):bs) =
  149. pretty x <+> colon <+> align (prettyTm' imp ty)
  150. <> line
  151. <> pretty x <+> equals <+> align (prettyTm' imp tm)
  152. <> line
  153. <> prettyBinds imp bs
  154. showFace :: Bool -> Map Head Bool -> Doc AnsiStyle
  155. showFace imp = hsep . map go . Map.toList where
  156. go (h, b) = parens $ prettyTm' imp (quoteWith False mempty (VNe h mempty)) <+> operator (pretty "=") <+> pretty (if b then "i1" else "i0")
  157. prettyVl' :: Bool -> Value -> Doc AnsiStyle
  158. prettyVl' b = prettyTm' b . quoteWith True mempty
  159. instance Pretty Term where
  160. pretty = unAnnotate . prettyTm
  161. prettyTm :: Term -> Doc AnsiStyle
  162. prettyTm = prettyTm' printImplicits
  163. instance Pretty Value where
  164. pretty = unAnnotate . prettyVl
  165. prettyVl :: Value -> Doc AnsiStyle
  166. prettyVl = prettyVl' printImplicits
  167. printImplicits :: Bool
  168. #if defined(RELEASE)
  169. printImplicits = False
  170. #else
  171. printImplicits = True
  172. #endif
  173. render :: Doc AnsiStyle -> Lazy.Text
  174. render = renderLazy . layoutSmart defaultLayoutOptions
  175. arg_prec, fun_prec, dom_prec, and_prec, or_prec :: Int
  176. dom_prec = succ fun_prec
  177. arg_prec = succ and_prec
  178. and_prec = succ or_prec
  179. or_prec = succ fun_prec
  180. fun_prec = 1
  181. keyword :: Doc AnsiStyle -> Doc AnsiStyle
  182. keyword = annotate (color Magenta)
  183. operator :: Doc AnsiStyle -> Doc AnsiStyle
  184. operator = annotate (color Yellow)