1 {-# LANGUAGE PolyKinds #-}
2 {-# OPTIONS_GHC -fno-warn-orphans #-}
3 module Language.Symantic.Typing.Show where
5 import Data.Map.Strict (Map)
6 import Data.Semigroup ((<>))
8 import Data.Text (Text)
10 import qualified Data.List as List
11 import qualified Data.Map.Strict as Map
12 import qualified Data.Set as Set
13 import qualified Data.Text as Text
15 import Language.Symantic.Grammar
16 import Language.Symantic.Typing.Kind
17 import Language.Symantic.Typing.Variable
18 import Language.Symantic.Typing.Type
20 instance Source src => Show (Type src vs t) where
22 let (v2n, _) = varNames mempty typ in
23 go v2n (infixB SideL pr, SideL) typ
27 (Map IndexVar Name) -> -- names of variables
32 | Just HRefl <- proj_ConstKiTy @Constraint @() c = showString "()"
33 go _v2n _po (TyConst _src _vs c) = showsPrec 11 c
34 go v2n _po (TyVar _src _n v) =
35 let iv = indexVar v in
36 case Map.lookup iv v2n of
37 Nothing -> error "[BUG] showsPrec @Type: variable name missing"
38 Just n -> showString $ Text.unpack n
39 go v2n po (TyApp _ (TyApp _ (TyConst _ _ f@Const{}) a) b)
40 | Just HRefl <- proj_ConstKiTy @Constraint @(()::Constraint) a
41 , Just HRefl <- proj_ConstKi @(K (#>)) @(#>) f =
43 | Fixity2 op <- fixityOf f =
44 showParen (needsParenInfix po op) $
45 go v2n (op, SideL) a .
46 showString (prettyConst f) .
49 prettyConst :: forall k c. Const src (c::k) -> String
50 prettyConst c | Just HRefl <- proj_ConstKi @(K (#>)) @(#>) c = " => "
51 prettyConst c | Just HRefl <- proj_ConstKi @(K (#)) @(#) c = ", "
53 | r <- typeRepTyCon (typeRep c)
55 , tyConModule r =="Language.Symantic.Typing.Type"
56 -- XXX: module name must be in sync with where (#~) is defined.
57 -- NOTE: cannot use 'proj_ConstKi' here
58 -- because (#~) has a polymorphic kind.
60 | otherwise = ' ' : unParen (show c) ++ " "
61 unParen ('(':s) | ')':s' <- reverse s = reverse s'
63 go v2n po (TyApp _src f a) =
65 showParen (needsParenInfix po op) $
66 go v2n (op, SideL) f .
69 go v2n po (TyFam _src _len fam args) =
71 showParen (needsParenInfix po op) $
74 showChar ' ' . go v2n (op, SideL) t . acc
77 -- | Return a 'Map' associating a distinct 'Name'
78 -- for all the variables of the given 'Type'.
81 (Map IndexVar Name, Names) ->
83 (Map IndexVar Name, Names)
84 varNames st TyConst{} = st
85 varNames st@(v2n, ns) (TyVar _src (NameVar n) v) =
86 let iv = indexVar v in
87 case Map.lookup iv v2n of
90 -- let n' = freshifyName ns n in
91 let n' = n <> Text.pack (show iv) in
92 let v2n' = Map.insert iv n' v2n in
93 let ns' = Set.insert n' ns in
95 varNames st (TyApp _src f a) = varNames (varNames st f) a
96 varNames st (TyFam _src _len _fam as) = foldlTys (flip varNames) as st
97 instance Source src => Show (TypeK src vs kt) where
98 showsPrec p (TypeK t) = showsPrec p t
99 instance Source src => Show (TypeVT src) where
100 showsPrec p (TypeVT t) = showsPrec p t
101 instance Source src => Show (TypeT src vs) where
102 showsPrec p (TypeT t) = showsPrec p t
103 instance Source src => Show (Types src vs ts) where
104 showsPrec _p tys = showString "[" . go tys . showString "]"
106 go :: forall xs. Types src vs xs -> ShowS
107 go TypesZ = showString ""
108 go (TypesS t0 (TypesS t1 ts)) = showsPrec 10 t0 . showString ", " . showsPrec 10 t1 . go ts
109 go (TypesS t ts) = showsPrec 10 t . go ts
111 showBracket :: Bool -> ShowS -> ShowS
112 showBracket b p = if b then showChar '{' . p . showChar '}' else p
117 type Names = Set Name
119 -- | Return given 'Name' renamed a bit to avoid
120 -- conflicting with any given 'Names'.
121 freshifyName :: Names -> Name -> Name
122 freshifyName ns "" = freshName ns
124 let ints = [1..] :: [Int] in
127 | suffix <- "" : (show <$> ints)
128 , fresh <- [n <> Text.pack suffix]
129 , fresh `Set.notMember` ns
132 freshName :: Names -> Name
133 freshName ns = List.head $ poolNames List.\\ Set.toList ns
135 -- | Infinite list of unique 'Name's:
136 -- @a, b, .., z, a1, b1 .., z1, a2, ..@
139 [ Text.singleton n | n <- ['a'..'z'] ] <>
140 [ Text.pack (n:show i) | n <- ['a'..'z']
141 , i <- [1 :: Int ..] ]