project-m36-0.9.4: src/bin/TutorialD/Printer.hs
{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module TutorialD.Printer where
import ProjectM36.Base
import ProjectM36.Attribute as A hiding (null)
import Prettyprinter
import qualified Data.Set as S hiding (fromList)
import qualified Data.Vector as V
import qualified Data.Map.Strict as M
import Data.Time.Calendar
import Data.Time.Clock.POSIX
import qualified Data.ByteString.Base64 as B64
import qualified Data.Text.Encoding as TE
import Data.UUID hiding (null)
instance Pretty Atom where
pretty (IntegerAtom x) = pretty x
pretty (IntAtom x) = "int" <> parensList [pretty x]
pretty (DoubleAtom x) = pretty x
pretty (TextAtom x) = dquotes (pretty x)
pretty (DayAtom x) = "fromGregorian" <> parensList [pretty a, pretty b, pretty c]
where
(a,b,c) = toGregorian x
pretty (DateTimeAtom time) = "dateTimeFromEpochSeconds" <> parensList [pretty @Integer (round (utcTimeToPOSIXSeconds time))]
pretty (ByteStringAtom bs) = "bytestring" <> parensList [dquotes (pretty (TE.decodeUtf8 (B64.encode bs)))]
pretty (BoolAtom x) = if x then "t" else "f"
pretty (UUIDAtom u) = pretty u
pretty (RelationAtom x) = pretty x
pretty (RelationalExprAtom re) = pretty re
pretty (ConstructedAtom n _ as) = pretty n <+> prettyList as
instance Pretty AtomExpr where
pretty (AttributeAtomExpr attrName) = pretty attrName
pretty (NakedAtomExpr atom) = pretty atom
pretty (FunctionAtomExpr atomFuncName' atomExprs _) = pretty atomFuncName' <> prettyAtomExprsAsArguments atomExprs
pretty (RelationAtomExpr relExpr) = pretty relExpr
pretty (ConstructedAtomExpr dName [] _) = pretty dName
pretty (ConstructedAtomExpr dName atomExprs _) = pretty dName <+> hsep (map prettyAtomExpr atomExprs)
prettyAtomExpr :: AtomExpr -> Doc ann
prettyAtomExpr atomExpr =
case atomExpr of
AttributeAtomExpr attrName -> "@" <> pretty attrName
ConstructedAtomExpr dConsName [] () -> pretty dConsName
ConstructedAtomExpr dConsName atomExprs () -> parens (pretty dConsName <+> hsep (map prettyAtomExpr atomExprs))
_ -> pretty atomExpr
prettyAtomExprsAsArguments :: [AtomExpr] -> Doc ann
prettyAtomExprsAsArguments = align . parensList . map addAt
where addAt (atomExpr :: AtomExpr) =
case atomExpr of
AttributeAtomExpr attrName -> "@" <> pretty attrName
_ -> pretty atomExpr
instance Pretty UUID where
pretty = pretty . show
instance Pretty TupleExpr where
pretty (TupleExpr map') = "tuple" <> bracesList (Prelude.map (\(attrName,atom)-> pretty attrName <+> pretty atom) (M.toList map'))
instance Pretty RelationTuple where
pretty (RelationTuple attrs atoms) = "tuple" <> bracesList (zipWith (\x y-> pretty x <+> pretty y) (V.toList (attributeNames attrs)) (V.toList atoms))
instance Pretty Relation where
pretty (Relation attrs tupSet) | attrs == mempty && null (asList tupSet) = "false"
pretty (Relation attrs tupSet) | attrs == mempty && asList tupSet == [RelationTuple mempty mempty] = "true"
pretty (Relation attrs tupSet) = "relation" <> prettyBracesList (A.toList attrs) <> prettyBracesList (asList tupSet)
instance Pretty Attribute where
pretty (Attribute n aTy) = pretty n <+> pretty (show aTy) -- workaround
instance Pretty RelationalExpr where
pretty (RelationVariable n _) = pretty n
pretty (ExistingRelation r) = pretty r
pretty (NotEquals a b) = pretty' a <+> "!=" <+> pretty' b
pretty (Equals a b) = pretty' a <+> "==" <+> pretty' b
pretty (Project ns r) = pretty' (ignoreProjects r) <> pretty ns
pretty (Extend ext r) = collectExtends r <> pretty ext <> "}"
pretty (MakeRelationFromExprs Nothing (TupleExprs () tupExprs)) = "relation" <> prettyBracesList tupExprs
pretty (MakeRelationFromExprs (Just attrExprs) (TupleExprs () tupExprs)) = "relation" <> prettyBracesList attrExprs <> prettyBracesList tupExprs
pretty (MakeStaticRelation attrs tupSet) = "relation" <> prettyBracesList (A.toList attrs) <> prettyBracesList (asList tupSet)
pretty (Union a b) = parens $ pretty' a <+> "union" <+> pretty' b
pretty (Join a b) = parens $ pretty' a <+> "join" <+> pretty' b
pretty (Rename n1 n2 relExpr) = parens $ pretty relExpr <+> "rename" <+> braces (pretty n1 <+> "as" <+> pretty n2)
pretty (Difference a b) = parens $ pretty' a <+> "minus" <+> pretty' b
pretty (Group attrNames attrName relExpr) = parens $ pretty relExpr <+> "group" <+> parens (pretty attrNames <+> "as" <+> pretty attrName)
pretty (Ungroup attrName relExpr) = parens $ pretty' relExpr <+> "ungroup" <+> pretty attrName
pretty (Restrict resPreExpr relExpr) = parens $ pretty' relExpr <+> "where" <+> pretty resPreExpr
pretty (With pairs a) = "with" <+> parensList (map (\(name,expr)-> pretty name <+> "as" <+> pretty expr) pairs) <+> pretty' a
-- relvar:{a:=?}:{b:=?}:... in ADTs => relvar:{a:=?, b:=?, ...} in Doc ann
collectExtends :: RelationalExpr -> Doc ann
collectExtends (Extend ext r) = collectExtends r <> pretty ext <> ", "
collectExtends r = pretty r <> ":{"
--relvar{a,b,c,...}{a,b,...}..{a} => relvar{a}
ignoreProjects :: RelationalExpr -> RelationalExpr
ignoreProjects (Project _ r) = ignoreProjects r
ignoreProjects r = r
prettyRelationalExpr :: RelationalExpr -> Doc n
prettyRelationalExpr (RelationVariable n _) = pretty n
prettyRelationalExpr r = parens (pretty r)
pretty' :: RelationalExpr -> Doc n
pretty' = prettyRelationalExpr
instance Pretty AttributeNames where
pretty (AttributeNames attrNames) = prettyBracesList (S.toList attrNames)
pretty (InvertedAttributeNames attrNames) = braces $ "all but" <+> concatWith (surround ", ") (map pretty (S.toList attrNames))
pretty (RelationalExprAttributeNames relExpr) = braces $ "all from" <+> pretty relExpr
pretty (UnionAttributeNames aAttrNames bAttrNames) = braces ("union of" <+> pretty aAttrNames <+> pretty bAttrNames)
pretty (IntersectAttributeNames aAttrNames bAttrNames) = braces ("intersection of" <+> pretty aAttrNames <+> pretty bAttrNames)
instance Pretty AttributeExpr where
pretty (NakedAttributeExpr attr) = pretty attr
pretty (AttributeAndTypeNameExpr name typeCons _) = pretty name <+> pretty typeCons
instance Pretty TypeConstructor where
pretty (ADTypeConstructor tcName []) = pretty tcName
pretty (ADTypeConstructor tcName tConsArgs) = pretty tcName <+> hsep (map pretty tConsArgs)
pretty (PrimitiveTypeConstructor tcName atomType') = pretty tcName <+> pretty atomType'
pretty (RelationAtomTypeConstructor attrExprs) = "relation" <> prettyBracesList attrExprs
pretty (TypeVariable x) = pretty x
instance Pretty AtomType where
pretty IntAtomType = "Int"
pretty IntegerAtomType = "Integer"
pretty DoubleAtomType = "Double"
pretty TextAtomType = "Text"
pretty DayAtomType = "Day"
pretty DateTimeAtomType = "DateTime"
pretty ByteStringAtomType = "ByteString"
pretty BoolAtomType = "Bool"
pretty UUIDAtomType = "UUID"
pretty (RelationAtomType attrs) = "relation " <+> prettyBracesList (A.toList attrs)
pretty (ConstructedAtomType tcName tvMap) = pretty tcName <+> hsep (map pretty (M.toList tvMap)) --order matters
pretty RelationalExprAtomType = "RelationalExpr"
pretty (TypeVariableType x) = pretty x
instance Pretty ExtendTupleExpr where
pretty (AttributeExtendTupleExpr attrName atomExpr) = pretty attrName <> ":=" <> pretty atomExpr
instance Pretty RestrictionPredicateExpr where
pretty TruePredicate = "true"
pretty (AndPredicate a b) = pretty a <+> "and" <+> pretty b
pretty (OrPredicate a b) = pretty a <+> "or" <+> pretty b
pretty (NotPredicate a) = "not" <+> pretty a
pretty (RelationalExprPredicate relExpr) = pretty relExpr
pretty (AtomExprPredicate atomExpr) = pretty atomExpr
pretty (AttributeEqualityPredicate attrName atomExpr) = pretty attrName <> "=" <> pretty atomExpr
instance Pretty WithNameExpr where
pretty (WithNameExpr name _) = pretty name
bracesList :: [Doc ann] -> Doc ann
bracesList = group . encloseSep (flatAlt "{ " "{") (flatAlt " }" "}") ", "
prettyBracesList :: Pretty a => [a] -> Doc ann
prettyBracesList = align . bracesList . map pretty
parensList :: [Doc ann] -> Doc ann
parensList = group . encloseSep (flatAlt "( " "(") (flatAlt " )" ")") ", "
prettyParensList :: Pretty a => [a] -> Doc ann
prettyParensList = align . parensList . map pretty