quox/lib/Quox/Syntax/Term/Pretty.idr

198 lines
6.6 KiB
Idris
Raw Normal View History

2022-04-23 18:21:30 -04:00
module Quox.Syntax.Term.Pretty
import Quox.Syntax.Term.Base
import Quox.Syntax.Term.Split
import Quox.Syntax.Term.Subst
import Quox.Pretty
import Data.Vect
2022-05-02 16:38:37 -04:00
%default total
2022-04-23 18:21:30 -04:00
2023-01-20 20:34:28 -05:00
private %inline
typeD, arrowD, timesD, lamD, eqndD, dlamD, annD :
2023-01-26 13:54:46 -05:00
Pretty.HasEnv m => m (Doc HL)
2023-02-25 13:14:26 -05:00
typeD = hlF Syntax $ ifUnicode "" "Type"
2023-02-25 13:14:11 -05:00
arrowD = hlF Syntax $ ifUnicode "" "->"
timesD = hlF Syntax $ ifUnicode "×" "**"
lamD = hlF Syntax $ ifUnicode "λ" "fun"
eqndD = hlF Syntax $ ifUnicode "" "=="
dlamD = hlF Syntax $ ifUnicode "δ" "dfun"
annD = hlF Syntax $ ifUnicode "" "::"
2022-04-23 18:21:30 -04:00
2023-01-20 20:34:28 -05:00
private %inline
eqD, colonD, commaD, dotD, caseD, returnD, ofD : Doc HL
2023-01-26 13:54:46 -05:00
eqD = hl Syntax "Eq"
colonD = hl Syntax ":"
commaD = hl Syntax ","
dotD = hl Delim "."
2023-01-26 13:54:46 -05:00
caseD = hl Syntax "case"
ofD = hl Syntax "of"
returnD = hl Syntax "return"
2022-04-23 18:21:30 -04:00
2023-02-22 01:40:19 -05:00
export covering
prettyBindType : PrettyHL a => PrettyHL b => PrettyHL q =>
Pretty.HasEnv m =>
2023-02-22 01:40:19 -05:00
List q -> BaseName -> a -> Doc HL -> b -> m (Doc HL)
prettyBindType qtys x s arr t =
parensIfM Outer $ hang 2 $
parens (hang 2 $ !(prettyQtyBinds qtys (TV x)) <++> colonD
<//> !(prettyM s)) <++> arr
2023-02-22 01:40:19 -05:00
<//> !(under T x $ prettyM t)
export covering
prettyLams : PrettyHL a => Pretty.HasEnv m =>
2023-02-22 01:40:19 -05:00
BinderSort -> List BaseName -> a -> m (Doc HL)
prettyLams sort names body = do
lam <- case sort of T => lamD; D => dlamD
header <- sequence $ [hl TVar <$> prettyM x | x <- names]
2023-02-22 01:40:19 -05:00
body <- unders sort names $ prettyM body
parensIfM Outer $ (sep (lam :: header) <+> dotD) <//> body
2023-02-22 01:40:19 -05:00
export covering
prettyApps : PrettyHL f => PrettyHL a => Pretty.HasEnv m =>
2023-02-26 05:22:44 -05:00
Maybe (Doc HL) -> f -> List a -> m (Doc HL)
prettyApps pfx fun args =
2023-02-22 01:40:19 -05:00
parensIfM App =<< withPrec Arg
2023-02-26 05:22:44 -05:00
[|prettyM fun <//> (align . sep <$> traverse prettyArg args)|]
where
prettyArg : a -> m (Doc HL)
prettyArg x = maybe id (\p => map (hl Delim p <+>)) pfx $ prettyM x
2023-02-22 01:40:19 -05:00
export covering
prettyTuple : PrettyHL a => Pretty.HasEnv m => List a -> m (Doc HL)
2023-02-22 01:40:19 -05:00
prettyTuple = map (parens . align . separate commaD) . traverse prettyM
export covering
prettyArm : PrettyHL a => Pretty.HasEnv m =>
2023-02-22 01:40:19 -05:00
(List BaseName, Doc HL, a) -> m (Doc HL)
prettyArm (xs, pat, body) =
pure $ hang 2 $ sep
[pat <+> dotD, !(withPrec Outer $ unders T xs $ prettyM body)]
2023-02-22 01:40:19 -05:00
export covering
prettyArms : PrettyHL a => Pretty.HasEnv m =>
2023-02-22 01:40:19 -05:00
List (List BaseName, Doc HL, a) -> m (Doc HL)
prettyArms = map (braces . align . sep) . traverse prettyArm
export covering
prettyCase : PrettyHL a => PrettyHL b => PrettyHL c => PrettyHL q =>
Pretty.HasEnv m =>
2023-02-22 01:40:19 -05:00
q -> a -> BaseName -> b -> List (List BaseName, Doc HL, c) ->
m (Doc HL)
prettyCase pi elim r ret arms =
pure $ align $ sep $
[hsep [caseD, !(prettyQtyBinds [pi] elim)],
hsep [returnD, !(prettyM r) <+> dotD, !(under T r $ prettyM ret)],
2023-02-22 01:40:19 -05:00
hsep [ofD, !(prettyArms arms)]]
-- [fixme] put delimiters around tags that aren't simple names
export
prettyTag : TagVal -> Doc HL
prettyTag t = hl Tag $ "`" <+> fromString t
2023-02-22 01:40:19 -05:00
2023-02-26 05:25:11 -05:00
parameters (showSubsts : Bool)
mutual
2022-04-23 18:21:30 -04:00
export covering
2023-02-26 05:25:11 -05:00
[TermSubst] PrettyHL q => PrettyHL (Term q d n) using TermSubst ElimSubst
where
2022-04-23 18:21:30 -04:00
prettyM (TYPE l) =
parensIfM App $ !typeD <+> hl Syntax !(prettyUnivSuffix l)
2023-02-22 01:40:19 -05:00
prettyM (Pi qty s (S [x] t)) =
2023-02-26 05:25:11 -05:00
prettyBindType [qty] x s !arrowD t.term
2023-02-22 01:40:19 -05:00
prettyM (Lam (S x t)) =
let GotLams {names, body, _} = getLams' x t.term Refl in
2023-01-20 20:34:28 -05:00
prettyLams T (toList names) body
2023-02-22 01:40:19 -05:00
prettyM (Sig s (S [x] t)) =
2023-02-26 05:25:11 -05:00
prettyBindType {q} [] x s !timesD t.term
2023-01-26 13:54:46 -05:00
prettyM (Pair s t) =
let GotPairs {init, last, _} = getPairs' [< s] t in
prettyTuple $ toList $ init :< last
prettyM (Enum tags) =
2023-02-26 05:23:30 -05:00
pure $ delims "`{" "}" . aseparate comma $ map prettyTag $
Prelude.toList tags
prettyM (Tag t) =
pure $ prettyTag t
2023-02-22 01:40:19 -05:00
prettyM (Eq (S _ (N ty)) l r) =
2023-01-20 20:34:28 -05:00
parensIfM Eq !(withPrec InEq $ pure $
2023-02-22 01:40:19 -05:00
sep [!(prettyM l) <++> !eqndD,
!(prettyM r) <++> colonD, !(prettyM ty)])
prettyM (Eq (S [i] (Y ty)) l r) =
2023-01-20 20:34:28 -05:00
parensIfM App $
eqD <++>
sep [bracks !(withPrec Outer $ pure $ hang 2 $
sep [hl DVar !(prettyM i) <+> dotD,
2023-01-20 20:34:28 -05:00
!(under D i $ prettyM ty)]),
!(withPrec Arg $ prettyM l),
!(withPrec Arg $ prettyM r)]
2023-02-22 01:40:19 -05:00
prettyM (DLam (S i t)) =
let GotDLams {names, body, _} = getDLams' i t.term Refl in
2023-01-20 20:34:28 -05:00
prettyLams D (toList names) body
prettyM (E e) = bracks <$> prettyM e
2022-04-23 18:21:30 -04:00
prettyM (CloT s th) =
2023-02-26 05:25:11 -05:00
if showSubsts then
parensIfM SApp . hang 2 =<<
[|withPrec SApp (prettyM s) </> prettyTSubst th|]
else
prettyM $ pushSubstsWith' id th s
2022-04-23 18:21:30 -04:00
prettyM (DCloT s th) =
2023-02-26 05:25:11 -05:00
if showSubsts then
parensIfM SApp . hang 2 =<<
[|withPrec SApp (prettyM s) </> prettyDSubst th|]
else
prettyM $ pushSubstsWith' th id s
2022-04-23 18:21:30 -04:00
export covering
2023-02-26 05:25:11 -05:00
[ElimSubst] PrettyHL q => PrettyHL (Elim q d n) using TermSubst ElimSubst
where
2022-04-23 18:21:30 -04:00
prettyM (F x) =
hl' Free <$> prettyM x
prettyM (B i) =
prettyVar TVar TVarErr (!ask).tnames i
prettyM (e :@ s) =
2023-01-20 20:34:28 -05:00
let GotArgs {fun, args, _} = getArgs' e [s] in
2023-02-26 05:22:44 -05:00
prettyApps Nothing fun args
2023-02-22 01:40:19 -05:00
prettyM (CasePair pi p (S [r] ret) (S [x, y] body)) = do
2023-01-26 13:54:46 -05:00
pat <- (parens . separate commaD . map (hl TVar)) <$>
traverse prettyM [x, y]
2023-02-26 05:25:11 -05:00
prettyCase pi p r ret.term [([x, y], pat, body.term)]
prettyM (CaseEnum pi t (S [r] ret) arms) =
2023-02-26 05:25:11 -05:00
prettyCase pi t r ret.term
[([], prettyTag t, b) | (t, b) <- SortedMap.toList arms]
2023-01-20 20:34:28 -05:00
prettyM (e :% d) =
let GotDArgs {fun, args, _} = getDArgs' e [d] in
2023-02-26 05:22:44 -05:00
prettyApps (Just "@") fun args
2022-04-23 18:21:30 -04:00
prettyM (s :# a) =
parensIfM Ann $ hang 2 $
!(withPrec AnnL $ prettyM s) <++> !annD
<//> !(withPrec Ann $ prettyM a)
prettyM (CloE e th) =
2023-02-26 05:25:11 -05:00
if showSubsts then
parensIfM SApp . hang 2 =<<
[|withPrec SApp (prettyM e) </> prettyTSubst th|]
else
prettyM $ pushSubstsWith' id th e
2022-04-23 18:21:30 -04:00
prettyM (DCloE e th) =
2023-02-26 05:25:11 -05:00
if showSubsts then
parensIfM SApp . hang 2 =<<
[|withPrec SApp (prettyM e) </> prettyDSubst th|]
else
prettyM $ pushSubstsWith' th id e
2022-04-23 18:21:30 -04:00
export covering
2023-01-08 14:44:25 -05:00
prettyTSubst : Pretty.HasEnv m => PrettyHL q =>
TSubst q d from to -> m (Doc HL)
2023-02-26 05:25:11 -05:00
prettyTSubst s =
prettySubstM (prettyM @{ElimSubst}) (!ask).tnames TVar "[" "]" s
export covering %inline
PrettyHL q => PrettyHL (Term q d n) where
prettyM = prettyM @{TermSubst False}
export covering %inline
PrettyHL q => PrettyHL (Elim q d n) where
prettyM = prettyM @{ElimSubst False}