-- | short cut for: if b then empty else d
noPrint :: Bool -> Doc -> Doc
noPrint b d = if b then empty else d
noNullPrint :: [a] -> Doc -> Doc
noNullPrint = noPrint . null
semiDs :: Pretty a => [a] -> Doc
semiDs = fsep . punctuate semi . map pretty
semiAnnoted :: Pretty a => [Annoted a] -> Doc
semiAnnoted = vcat . map (printSemiAnno pretty True)
instance Pretty Variance where
pretty = sidDoc . mkSimpleId . show
instance Pretty a => Pretty (AnyKind a) where
ClassKind ci -> pretty ci
FunKind v k1 k2 _ -> fsep [pretty v <>
FunKind _ _ _ _ -> parens
varOfTypeArg :: TypeArg -> Id
varOfTypeArg (TypeArg i _ _ _ _ _ _) = i
instance Pretty TypePattern where
TypePattern name args _ -> pretty name
<+> fsep (map (pretty . varOfTypeArg) args)
TypePatternToken t -> pretty t
MixfixTypePattern ts -> fsep $ map pretty ts
BracketTypePattern k l _ -> bracket k $ ppWithCommas l
TypePatternArg t _ -> parens $ pretty t
-- | put proper brackets around a document
bracket :: BracketKind -> Doc -> Doc
-- | print a 'Kind' plus a preceding colon (or nothing)
printKind k = noPrint (k == universe) $ printVarKind InVar (VarKind k)
-- | print the kind of a variable with its variance and a preceding colon
printVarKind :: Variance -> VarKind -> Doc
printVarKind e vk = case vk of
space <> less <+> pretty t
VarKind k -> space <> colon <+>
data TypePrec = Outfix | Prefix | ProdInfix | FunInfix | Absfix
parenPrec :: TypePrec -> (TypePrec, Doc) -> Doc
parenPrec p1 (p2, d) = if p2 < p1 then d else parens d
printTypeToken :: Token -> Doc
l = ("*", cross) : map ( \ (a, d) -> (show a, d) )
in case lookup (tokStr t) l of
toMixType :: Type -> (TypePrec, Doc)
toMixType typ = case typ of
TypeName name _ _ -> (Outfix, pretty name)
TypeToken tt -> (Outfix, printTypeToken tt)
TypeAbs v t _ -> (Absfix, sep [ lambda <+> pretty v
, bullet <+> snd (toMixType t)])
ExpandedType t1 _ -> toMixType t1 -- here we print the unexpanded type
BracketType k l _ -> (Outfix, bracket k $ sepByCommas $ map
KindedType t kind _ -> (Prefix,
fsep [parenPrec Prefix $ toMixType t, colon, pretty kind])
MixfixType ts -> (Prefix, fsep $ map (snd . toMixType) ts)
_ -> let (topTy, tyArgs) = getTypeAppl typ
topDoc = snd $ toMixType topTy
dArgs = map toMixType tyArgs
pArgs = map (parenPrec Prefix) dArgs
aArgs = (Prefix, fsep $ topDoc : pArgs)
TypeName name@(Id ts cs _) _k _i ->
[e1, e2, e3] | not (isPlace e1) && isPlace e2
&& not (isPlace e3) && null cs ->
(Outfix, fsep [pretty e1, snd dArg, pretty e3])
[e1, e2, e3] | isPlace e1 && not (isPlace e2)
&& isPlace e3 && null cs ->
if tokStr e2 == prodS then
parenPrec ProdInfix dArg1, cross,
parenPrec ProdInfix dArg2])
parenPrec FunInfix dArg1, printTypeToken e2, snd dArg2])
_ -> if name == productId (length tyArgs) then
(ProdInfix, fsep $ punctuate (space <> cross) $
map (parenPrec ProdInfix) dArgs)
TypeAbs _ _ _ -> (Prefix, fsep $ parens topDoc : pArgs)
_ -> (Prefix, fsep $ parenPrec ProdInfix (toMixType topTy) : pArgs)
instance Pretty Type where
-- no curried notation for bound variables
instance Pretty TypeScheme where
pretty (TypeScheme vs t _) = let tdoc = pretty t in
if null vs then tdoc else
fsep [forallDoc, semiDs vs, bullet <+> tdoc]
instance Pretty Partiality where
instance Pretty Quantifier where
instance Pretty TypeQual where
instance Pretty Term where
pretty = printTerm . rmSomeTypes
isSimpleTerm :: Term -> Bool
isSimpleTerm trm = case trm of
ResolvedMixTerm _ _ _ -> True
BracketTerm _ _ _ -> True
-- | used only to produce CASL applications
isSimpleArgTerm :: Term -> Bool
isSimpleArgTerm trm = case trm of
QualVar vd -> not (isPatVarDecl vd)
ResolvedMixTerm n l _ -> placeCount n /= 0 || not (null l)
BracketTerm _ _ _ -> True
hasRightQuant :: Term -> Bool
hasRightQuant t = case t of
QuantifiedTerm {} -> True
LetTerm Let _ _ _ -> True
ResolvedMixTerm n ts _ | endPlace n && placeCount n == length ts
-> hasRightQuant (last ts)
ApplTerm (ResolvedMixTerm n [] _) t2 _ | endPlace n ->
TupleTerm ts _ | placeCount n == length ts -> hasRightQuant (last ts)
ApplTerm _ t2 _ -> hasRightQuant t2
zipArgs :: Id -> [Term] -> [Doc] -> [Doc]
zipArgs n ts ds = case (ts, ds) of
e = if hasRightQuant t then parens d else p
in if null r && null s && endPlace n then
[if hasRightQuant t then d else p]
isPatVarDecl :: VarDecl -> Bool
isPatVarDecl (VarDecl v ty _ _) = case ty of
TypeName t _ _ -> isSimpleId v && take 2 (show t) == "_v"
parenTermDoc :: Term -> Doc -> Doc
parenTermDoc trm = if isSimpleTerm trm then id else parens
printTermRec :: FoldRec Doc (Doc, Doc)
{ foldQualVar = \ _ vd@(VarDecl v _ _ _) ->
if isPatVarDecl vd then pretty v
else parens $ keyword varS <+> pretty vd
, foldQualOp = \ _ br n t _ ->
parens $ fsep [pretty br, pretty n, colon, pretty $
if isPred br then unPredTypeScheme t else t]
, foldResolvedMixTerm = \ (ResolvedMixTerm _ os _) n ts _ ->
if placeCount n == length ts || null ts then
idApplDoc n $ zipArgs n os ts
else idApplDoc applId [idDoc n, parens $ sepByCommas ts]
, foldApplTerm = \ (ApplTerm o1 o2 _) t1 t2 _ ->
-- comment out the following two guards for CASL applications
(ResolvedMixTerm n [] _, TupleTerm ts _) | placeCount n == length ts
-> idApplDoc n $ zipArgs n ts $ map printTerm ts
(ResolvedMixTerm n [] _, _) | placeCount n == 1
-> idApplDoc n $ zipArgs n [o2] [t2]
_ -> idApplDoc applId $ zipArgs applId [o1, o2] [t1, t2]
, foldTupleTerm = \ _ ts _ -> parens $ sepByCommas ts
, foldTypedTerm = \ (TypedTerm ot _ _ _) t q typ _ -> fsep [(case ot of
QuantifiedTerm {} -> parens
_ -> id) t, pretty q, pretty typ]
, foldQuantifiedTerm = \ _ q vs t _ ->
fsep [pretty q, printGenVarDecls vs, bullet <+> t]
, foldLambdaTerm = \ _ ps q t _ ->
_ -> fcat $ map parens ps
Total -> bullet <> text exMark) <+> t]
, foldCaseTerm = \ _ t es _ ->
fsep [text caseS, t, text ofS,
cat $ punctuate (space <> bar <> space) $
map (printEq0 funArrow) es]
, foldLetTerm = \ _ br es t _ ->
let des = sep $ punctuate semi $ map (printEq0 equals) es
Let -> fsep [sep [text letS <+> des, text inS], t]
Where -> fsep [sep [t, text whereS], des]
Program -> text programS <+> des
, foldTermToken = \ _ t -> pretty t
, foldMixTypeTerm = \ _ q t _ -> pretty q <+> pretty t
, foldMixfixTerm = \ _ ts -> fsep ts
, foldBracketTerm = \ _ k l _ -> bracket k $ sepByCommas l
, foldAsPattern = \ _ (VarDecl v _ _ _) p _ ->
fsep [pretty v, text asP, p]
, foldProgEq = \ _ p t _ -> (p, t)
printTerm = foldTerm printTermRec
{ foldQualOp = \ t _ (InstOpId i _ _) _ ps ->
if elem i $ map fst bList then
ResolvedMixTerm i [] ps else t
, foldTypedTerm = \ _ nt q ty ps ->
TypedTerm _ oq oty _ | oty == ty || oq == InType -> nt
QualVar (VarDecl _ oty _ _) | oty == ty -> nt
_ -> TypedTerm nt q ty ps
rmSomeTypes :: Term -> Term
rmSomeTypes = foldTerm rmTypeRec
-- | put parenthesis around applications
ResolvedMixTerm _ [] _ -> t
_ -> TupleTerm [t] nullRange
{ foldApplTerm = \ _ t1 t2 ps ->
ApplTerm (addParAppl t1) (addParAppl t2) ps
, foldResolvedMixTerm = \ _ n ts ps ->
ResolvedMixTerm n (map addParAppl ts) ps
, foldTypedTerm = \ _ t q typ ps ->
TypedTerm (addParAppl t) q typ ps
, foldMixfixTerm = \ _ ts -> MixfixTerm $ map addParAppl ts
, foldAsPattern = \ _ v p ps -> AsPattern v (addParAppl p) ps
parenTerm :: Term -> Term
parenTerm = foldTerm parenTermRec
-- | print an equation with different symbols between 'Pattern' and 'Term'
printEq0 :: Doc -> (Doc, Doc) -> Doc
printEq0 s (p, t) = sep [p, hsep [s, t]]
printGenVarDecls :: [GenVarDecl] -> Doc
printGenVarDecls = fsep . punctuate semi . map
GenVarDecl (VarDecl _ t _ _) : _ ->
ppWithCommas (map ( \ (GenVarDecl (VarDecl v _ _ _)) -> v) l)
GenTypeVarDecl (TypeArg _ e c _ _ _ _) : _ ->
ppWithCommas (map ( \ (GenTypeVarDecl v) -> varOfTypeArg v) l)
_ -> error "printGenVarDecls") . groupBy sameType
sameType :: GenVarDecl -> GenVarDecl -> Bool
sameType g1 g2 = case (g1, g2) of
(GenVarDecl (VarDecl _ t1 Comma _), GenVarDecl (VarDecl _ t2 _ _))
(GenTypeVarDecl (TypeArg _ e1 c1 _ _ Comma _),
GenTypeVarDecl (TypeArg _ e2 c2 _ _ _ _)) | e1 == e2 && c1 == c2 -> True
printVarDeclType :: Type -> Doc
printVarDeclType t = case t of
_ -> space <> colon <+> pretty t
instance Pretty VarDecl where
pretty (VarDecl v t _ _) = pretty v <> printVarDeclType t
instance Pretty GenVarDecl where
GenTypeVarDecl tv -> pretty tv
instance Pretty TypeArg where
pretty (TypeArg v e c _ _ _ _) =
pretty v <> printVarKind e c
-- | don't print an empty list and put parens around longer lists
printList0 :: (Pretty a) => [a] -> Doc
_ -> parens $ ppWithCommas l
instance Pretty InstOpId where
pretty (InstOpId n l _) = pretty n <> noNullPrint l
-- | print a 'TypeScheme' as a pseudo type
printPseudoType :: TypeScheme -> Doc
printPseudoType (TypeScheme l t _) = noNullPrint l (lambda
<+> (if null $ tail l then pretty $ head l
else fsep(map (parens . pretty) l))
<+> bullet <> space) <> pretty t
instance Pretty BasicSpec where
pretty (BasicSpec l) = if null l then specBraces empty else
changeGlobalAnnos addBuiltins . vcat $ map pretty l
instance Pretty ProgEq where
pretty = printEq0 equals . foldEq printTermRec
instance Pretty BasicItem where
ProgItems l _ -> sep [keyword programS, semiAnnoted l]
ClassItems i l _ -> let b = semiAnnos pretty l in case i of
Plain -> topSigKey classS <+> b
Instance -> sep [keyword classS <+> keyword instanceS, b]
GenVarItems l _ -> topSigKey (varS ++ case l of
_ -> "") <+> printGenVarDecls l
sep [keyword freeS <+> keyword (typeS ++ case l of
_ -> ""), semiAnnos pretty l]
GenItems l _ -> let gkw = keyword generatedS in
(if all (isDatatype . item) l then \ i -> gkw <+> rmTopKey i
else \ i -> sep [gkw, specBraces i])
$ vcat $ map (printAnnoted pretty) l
sep [ if null vs then empty else
forallDoc <+> printGenVarDecls vs
_ -> let pp = addBullet . pretty in
vcat $ map (printAnnoted pp) (init fs)
++ [printSemiAnno pp True $ last fs]]
Internal l _ -> sep [keyword internalS,
specBraces $ vcat $ map (printAnnoted pretty) l]
isDatatype :: SigItems -> Bool
isDatatype si = case si of
TypeItems _ l _ -> all ((\ t -> case t of
instance Pretty OpBrand where
pretty b = keyword $ show b
instance Pretty SigItems where
TypeItems i l _ -> let b = semiAnnos pretty l in case i of
Plain -> topSigKey ((if all (isSimpleTypeItem . item) l
then typeS else typeS) ++ plTypes l) <+> b
sep [keyword typeS <+> keyword (instanceS ++ plTypes l), b]
OpItems b l _ -> noNullPrint l $ topSigKey (show b ++ plOps l)
<+> let po = (prettyOpItem $ isPred b) in
OpDecl _ _ a@(_ : _) _ -> case last a of
then vcat (map (printSemiAnno po True) l)
plTypes :: [Annoted TypeItem] -> String
plTypes l = case map item l of
[TypeDecl (_ : _ : _) _ _] -> sS
[SubtypeDecl (_ : _ : _) _ _] -> sS
[IsoDecl (_ : _ : _) _] -> sS
plOps :: [Annoted OpItem] -> String
plOps l = case map item l of
[OpDecl (_ : _ : _) _ _ _] -> sS
isSimpleTypeItem :: TypeItem -> Bool
isSimpleTypeItem ti = case ti of
TypeDecl l k _ -> k == universe && all isSimpleTypePat l
SubtypeDecl l (TypeName i _ _) _ ->
not (isMixfix i) && all isSimpleTypePat l
SubtypeDefn p (Var _) t _ _ ->
isSimpleTypePat p && isSimpleType t
isSimpleTypePat :: TypePattern -> Bool
isSimpleTypePat tp = case tp of
TypePattern i [] _ -> not $ isMixfix i
isSimpleType :: Type -> Bool
isSimpleType t = case t of
TypeName i _ _ -> not $ isMixfix i
MixfixType[TypeToken _, BracketType Squares (_ : _) _] -> True
instance Pretty ClassItem where
pretty (ClassItem d l _) = pretty d $+$ noNullPrint l
(specBraces $ vcat $ map (printAnnoted pretty) l)
instance Pretty ClassDecl where
pretty (ClassDecl l k _) = fsep [ppWithCommas l, less, pretty k]
instance Pretty Vars where
VarTuple vs _ -> parens $ ppWithCommas vs
instance Pretty TypeItem where
TypeDecl l k _ -> ppWithCommas l <> printKind k
fsep [ppWithCommas l, less, pretty t]
IsoDecl l _ -> fsep $ punctuate (space <> equals) $ map pretty l
[pretty v, colon <+> pretty t, bullet <+> pretty f]]
AliasType p _ (TypeScheme l t _) _ ->
fsep $ pretty p : map (pretty . varOfTypeArg) l
++ [text assignS <+> pretty t]
prettyTypeScheme :: Bool -> TypeScheme -> Doc
prettyTypeScheme b = pretty . (if b then unPredTypeScheme else id)
prettyOpItem :: Bool -> OpItem -> Doc
prettyOpItem b oi = case oi of
OpDecl l t a _ -> fsep $ punctuate comma (map pretty l)
(if null a then id else (<> comma))(prettyTypeScheme b t)]
++ punctuate comma (map pretty a)
fcat $ ((if null ps then (<> space) else id) $ pretty n)
: map ((<> space) . parens . semiDs) ps
[colon <> pretty p <+> prettyTypeScheme b s <> space])
++ [(if b then equiv else equals) <> space, pretty t]
instance Pretty BinOpAttr where
pretty a = text $ case a of
instance Pretty OpAttr where
BinOpAttr a _ -> pretty a
UnitOpAttr t _ -> text unitS <+> pretty t
instance Pretty DatatypeDecl where
pretty (DatatypeDecl p k alts d _) =
fsep [ pretty p <> printKind k, defn
<+> cat (punctuate (space <> bar <> space)
_ -> keyword derivingS <+> ppWithCommas d]
instance Pretty Alternative where
Constructor n cs p _ -> pretty n <+> fsep
(map ( \ l -> case (l, p) of
-- comment out the following line to output real CASL
([NoSelector (TypeToken t)], Total) | isSimpleId n -> pretty t
_ -> parens $ semiDs l) cs) <> pretty p
Subtype l _ -> text (if all isSimpleType l then typeS else typeS)
instance Pretty Component where
Selector n p t _ _ -> sep [pretty n, colon <> pretty p <+> pretty t]
instance Pretty OpId where
sep $ pretty n : if null ts then [] else [brackets $ ppWithCommas ts]
instance Pretty Symb where
sep $ pretty i : case mt of
Just (SymbType t) -> [colon <+> pretty t]
instance Pretty SymbItems where
pretty (SymbItems k syms _ _) =
printSK k syms <> ppWithCommas syms
instance Pretty SymbOrMap where
pretty (SymbOrMap s mt _) =
sep $ pretty s : case mt of
Just t -> [mapsto <+> pretty t]
instance Pretty SymbMapItems where
pretty (SymbMapItems k syms _ _) =
printSK k syms <> ppWithCommas syms
printSK :: SymbKind -> [a] -> Doc
case k of Implicit -> empty
_ -> keyword (drop 3 (show k) ++ case l of