futhark-0.20.2: src/Futhark/IR/Pretty.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
-- | Futhark prettyprinter. This module defines 'Pretty' instances
-- for the AST defined in "Futhark.IR.Syntax",
-- but also a number of convenience functions if you don't want to use
-- the interface from 'Pretty'.
module Futhark.IR.Pretty
( prettyTuple,
pretty,
PrettyRep (..),
ppTuple',
)
where
import Data.Foldable (toList)
import Data.Maybe
import Futhark.IR.Syntax
import Futhark.Util.Pretty
-- | The class of representations whose annotations can be prettyprinted.
class
( RepTypes rep,
Pretty (RetType rep),
Pretty (BranchType rep),
Pretty (FParamInfo rep),
Pretty (LParamInfo rep),
Pretty (LetDec rep),
Pretty (Op rep)
) =>
PrettyRep rep
where
ppExpDec :: ExpDec rep -> Exp rep -> Maybe Doc
ppExpDec _ _ = Nothing
instance Pretty VName where
ppr (VName vn i) = ppr vn <> text "_" <> text (show i)
instance Pretty Commutativity where
ppr Commutative = text "commutative"
ppr Noncommutative = text "noncommutative"
instance Pretty NoUniqueness where
ppr _ = mempty
instance Pretty Shape where
ppr = mconcat . map (brackets . ppr) . shapeDims
instance Pretty a => Pretty (Ext a) where
ppr (Free e) = ppr e
ppr (Ext x) = text "?" <> text (show x)
instance Pretty ExtShape where
ppr = mconcat . map (brackets . ppr) . shapeDims
instance Pretty Space where
ppr DefaultSpace = mempty
ppr (Space s) = text "@" <> text s
ppr (ScalarSpace d t) = text "@" <> mconcat (map (brackets . ppr) d) <> ppr t
instance Pretty u => Pretty (TypeBase Shape u) where
ppr (Prim t) = ppr t
ppr (Acc acc ispace ts u) =
ppr u <> text "acc" <> apply [ppr acc, ppr ispace, ppTuple' ts]
ppr (Array et (Shape ds) u) =
ppr u <> mconcat (map (brackets . ppr) ds) <> ppr et
ppr (Mem s) = text "mem" <> ppr s
instance Pretty u => Pretty (TypeBase ExtShape u) where
ppr (Prim t) = ppr t
ppr (Acc acc ispace ts u) =
ppr u <> text "acc" <> apply [ppr acc, ppr ispace, ppTuple' ts]
ppr (Array et (Shape ds) u) =
ppr u <> mconcat (map (brackets . ppr) ds) <> ppr et
ppr (Mem s) = text "mem" <> ppr s
instance Pretty u => Pretty (TypeBase Rank u) where
ppr (Prim t) = ppr t
ppr (Acc acc ispace ts u) =
ppr u <> text "acc" <> apply [ppr acc, ppr ispace, ppTuple' ts]
ppr (Array et (Rank n) u) =
ppr u <> mconcat (replicate n $ brackets mempty) <> ppr et
ppr (Mem s) = text "mem" <> ppr s
instance Pretty Ident where
ppr ident = ppr (identType ident) <+> ppr (identName ident)
instance Pretty SubExp where
ppr (Var v) = ppr v
ppr (Constant v) = ppr v
instance Pretty Certs where
ppr (Certs []) = empty
ppr (Certs cs) = text "#" <> braces (commasep (map ppr cs))
instance PrettyRep rep => Pretty (Stms rep) where
ppr = stack . map ppr . stmsToList
instance Pretty SubExpRes where
ppr (SubExpRes cs se) = spread $ certAnnots cs ++ [ppr se]
instance PrettyRep rep => Pretty (Body rep) where
ppr (Body _ stms res)
| null stms = braces (commasep $ map ppr res)
| otherwise =
stack (map ppr $ stmsToList stms)
</> text "in" <+> braces (commasep $ map ppr res)
instance Pretty Attr where
ppr (AttrAtom v) = ppr v
ppr (AttrComp f attrs) = ppr f <> parens (commasep $ map ppr attrs)
attrAnnots :: Attrs -> [Doc]
attrAnnots = map f . toList . unAttrs
where
f v = text "#[" <> ppr v <> text "]"
stmAttrAnnots :: Stm rep -> [Doc]
stmAttrAnnots = attrAnnots . stmAuxAttrs . stmAux
certAnnots :: Certs -> [Doc]
certAnnots cs
| cs == mempty = []
| otherwise = [ppr cs]
stmCertAnnots :: Stm rep -> [Doc]
stmCertAnnots = certAnnots . stmAuxCerts . stmAux
instance Pretty Attrs where
ppr = spread . attrAnnots
instance Pretty (PatElemT dec) => Pretty (PatT dec) where
ppr (Pat xs) = braces $ commastack $ map ppr xs
instance Pretty t => Pretty (PatElemT t) where
ppr (PatElem name t) = ppr name <+> colon <+> align (ppr t)
instance Pretty t => Pretty (Param t) where
ppr (Param name t) = ppr name <+> colon <+> align (ppr t)
instance PrettyRep rep => Pretty (Stm rep) where
ppr stm@(Let pat aux e) =
align . hang 2 $
text "let" <+> align (ppr pat)
<+> case (linebreak, stmannot) of
(True, []) -> equals </> ppr e
(False, []) -> equals <+/> ppr e
(_, ann) -> equals </> (stack ann </> ppr e)
where
linebreak = case e of
BasicOp BinOp {} -> False
BasicOp CmpOp {} -> False
BasicOp ConvOp {} -> False
BasicOp UnOp {} -> False
BasicOp SubExp {} -> False
_ -> True
stmannot =
concat
[ maybeToList (ppExpDec (stmAuxDec aux) e),
stmAttrAnnots stm,
stmCertAnnots stm
]
instance Pretty a => Pretty (Slice a) where
ppr (Slice xs) = brackets (commasep (map ppr xs))
instance Pretty d => Pretty (FlatDimIndex d) where
ppr (FlatDimIndex n s) = ppr n <+> text ":" <+> ppr s
instance Pretty a => Pretty (FlatSlice a) where
ppr (FlatSlice offset xs) = brackets (ppr offset <> text ";" <+> commasep (map ppr xs))
instance Pretty BasicOp where
ppr (SubExp se) = ppr se
ppr (Opaque OpaqueNil e) = text "opaque" <> apply [ppr e]
ppr (Opaque (OpaqueTrace s) e) = text "trace" <> apply [ppr (show s), ppr e]
ppr (ArrayLit es rt) =
case rt of
Array {} -> brackets $ commastack $ map ppr es
_ -> brackets $ commasep $ map ppr es
<+> colon
<+> text "[]" <> ppr rt
ppr (BinOp bop x y) = ppr bop <> parens (ppr x <> comma <+> ppr y)
ppr (CmpOp op x y) = ppr op <> parens (ppr x <> comma <+> ppr y)
ppr (ConvOp conv x) =
text (convOpFun conv) <+> ppr fromtype <+> ppr x <+> text "to" <+> ppr totype
where
(fromtype, totype) = convOpType conv
ppr (UnOp op e) = ppr op <+> pprPrec 9 e
ppr (Index v slice) = ppr v <> ppr slice
ppr (Update safety src slice se) =
ppr src <+> with <+> ppr slice <+> text "=" <+> ppr se
where
with = case safety of
Unsafe -> text "with"
Safe -> text "with?"
ppr (FlatIndex v slice) = ppr v <> ppr slice
ppr (FlatUpdate src slice se) =
ppr src <+> text "with" <+> ppr slice <+> text "=" <+> ppr se
ppr (Iota e x s et) = text "iota" <> et' <> apply [ppr e, ppr x, ppr s]
where
et' = text $ show $ primBitSize $ IntType et
ppr (Replicate ne ve) =
text "replicate" <> apply [ppr ne, align (ppr ve)]
ppr (Scratch t shape) =
text "scratch" <> apply (ppr t : map ppr shape)
ppr (Reshape shape e) =
text "reshape" <> apply [apply (map ppr shape), ppr e]
ppr (Rearrange perm e) =
text "rearrange" <> apply [apply (map ppr perm), ppr e]
ppr (Rotate es e) =
text "rotate" <> apply [apply (map ppr es), ppr e]
ppr (Concat i x ys w) =
text "concat" <> text "@" <> ppr i <> apply (ppr w : ppr x : map ppr ys)
ppr (Copy e) = text "copy" <> parens (ppr e)
ppr (Manifest perm e) = text "manifest" <> apply [apply (map ppr perm), ppr e]
ppr (Assert e msg (loc, _)) =
text "assert" <> apply [ppr e, ppr msg, text $ show $ locStr loc]
ppr (UpdateAcc acc is v) =
text "update_acc" <> apply [ppr acc, ppTuple' is, ppTuple' v]
instance Pretty a => Pretty (ErrorMsg a) where
ppr (ErrorMsg parts) = braces $ align $ commasep $ map p parts
where
p (ErrorString s) = text $ show s
p (ErrorVal t x) = ppr x <+> colon <+> ppr t
instance PrettyRep rep => Pretty (Exp rep) where
ppr (If c t f (IfDec ret ifsort)) =
text "if" <+> info' <+> ppr c
</> text "then"
<+> maybeNest t
<+> text "else"
<+> maybeNest f
</> colon
<+> ppTuple' ret
where
info' = case ifsort of
IfNormal -> mempty
IfFallback -> text "<fallback>"
IfEquiv -> text "<equiv>"
maybeNest b
| null $ bodyStms b = ppr b
| otherwise = nestedBlock "{" "}" $ ppr b
ppr (BasicOp op) = ppr op
ppr (Apply fname args ret (safety, _, _)) =
applykw
<+> text (nameToString fname)
<> apply (map (align . pprArg) args)
</> colon
<+> braces (commasep $ map ppr ret)
where
pprArg (arg, Consume) = text "*" <> ppr arg
pprArg (arg, _) = ppr arg
applykw = case safety of
Unsafe -> text "apply <unsafe>"
Safe -> text "apply"
ppr (Op op) = ppr op
ppr (DoLoop merge form loopbody) =
text "loop" <+> braces (commastack $ map ppr params)
<+> equals
<+> ppTuple' args
</> ( case form of
ForLoop i it bound [] ->
text "for"
<+> align
( ppr i <> text ":" <> ppr it
<+> text "<"
<+> align (ppr bound)
)
ForLoop i it bound loop_vars ->
text "for"
<+> align
( ppr i <> text ":" <> ppr it
<+> text "<"
<+> align (ppr bound)
</> stack (map pprLoopVar loop_vars)
)
WhileLoop cond ->
text "while" <+> ppr cond
)
<+> text "do"
<+> nestedBlock "{" "}" (ppr loopbody)
where
(params, args) = unzip merge
pprLoopVar (p, a) = ppr p <+> text "in" <+> ppr a
ppr (WithAcc inputs lam) =
text "with_acc"
<> parens (braces (commastack $ map ppInput inputs) <> comma </> ppr lam)
where
ppInput (shape, arrs, op) =
parens
( ppr shape <> comma <+> ppTuple' arrs
<> case op of
Nothing -> mempty
Just (op', nes) ->
comma </> parens (ppr op' <> comma </> ppTuple' (map ppr nes))
)
instance PrettyRep rep => Pretty (Lambda rep) where
ppr (Lambda [] (Body _ stms []) []) | stms == mempty = text "nilFn"
ppr (Lambda params body rettype) =
text "\\" <+> ppTuple' params
<+/> colon <+> ppTuple' rettype <+> text "->"
</> indent 2 (ppr body)
instance Pretty EntryPointType where
ppr (TypeDirect u) = ppr u <> "direct"
ppr (TypeUnsigned u) = ppr u <> "unsigned"
ppr (TypeOpaque u desc n) = ppr u <> "opaque" <> apply [ppr (show desc), ppr n]
instance PrettyRep rep => Pretty (FunDef rep) where
ppr (FunDef entry attrs name rettype fparams body) =
annot (attrAnnots attrs) $
fun
</> indent 2 (text (nameToString name))
<+> apply (map ppr fparams)
</> indent 2 (colon <+> align (ppTuple' rettype))
<+> equals
<+> nestedBlock "{" "}" (ppr body)
where
fun = case entry of
Nothing -> "fun"
Just (p_name, p_entry, ret_entry) ->
"entry"
<> parens
( "\"" <> ppr p_name <> "\"" <> comma
</> ppTuple' p_entry <> comma
</> ppTuple' ret_entry
)
instance PrettyRep rep => Pretty (Prog rep) where
ppr (Prog consts funs) =
stack $ punctuate line $ ppr consts : map ppr funs
instance Pretty d => Pretty (DimChange d) where
ppr (DimCoercion se) = text "~" <> ppr se
ppr (DimNew se) = ppr se
instance Pretty d => Pretty (DimIndex d) where
ppr (DimFix i) = ppr i
ppr (DimSlice i n s) = ppr i <+> text ":+" <+> ppr n <+> text "*" <+> ppr s
-- | Like 'prettyTuple', but produces a 'Doc'.
ppTuple' :: Pretty a => [a] -> Doc
ppTuple' ets = braces $ commasep $ map (align . ppr) ets