-- | Linearisation
{-# LANGUAGE RecordWildCards #-}
module Induction.Structural.Linearise
(
-- * Linearising (pretty-printing) obligations and terms
linObligations,
linObligation,
linTerm,
Style(..),
strStyle,
-- ** Convenience re-export
render,
text
) where
import Induction.Structural.Types
import Text.PrettyPrint hiding (Style)
-- | Functions for linearising constructors (`linc`), variables (`linv`) and
-- types (`lint`).
data Style c v t = Style
{ linc :: c -> Doc
, linv :: v -> Doc
, lint :: t -> Doc
}
-- | An example style where constructors, variables and types are represented as `String`.
strStyle :: Style String String String
strStyle = Style
{ linc = text
, linv = text
, lint = text
}
-- | Linearises a list of `Obligation`, using a given `Style`.
linObligations :: Style c v t -> [Obligation c v t] -> Doc
linObligations s = vcat . map ((<> dot) . linObligation s)
-- | Linearises an `Obligation` using a given `Style`. The output format is
-- inspired by TPTP, but with typed quantifiers.
linObligation :: Style c v t -> Obligation c v t -> Doc
linObligation s@Style{..} x = case x of
Obligation sks [] concl -> linForall sks <+> linPred concl
Obligation sks hyps concl -> hang (linForall sks) 4 $
cat $ parList $
punctuate (fluff ampersand) (map linHyp hyps) ++
[space <> darrow <+> linPred concl]
where
linTypedVar v t = linv v <+> colon <+> lint t
linForall [] = empty
linForall qs =
bang <+> brackets (csv (map (uncurry linTypedVar) qs)) <+> colon
linPred xs = char 'P' <> parens (csv (map (linTerm s) xs))
linHyp ([],hyp) = linPred hyp
linHyp (qs,hyp) = parens (linForall qs <+> linPred hyp)
-- | Linearises a `Term` using a given `Style`.
linTerm :: Style c v t -> Term c v -> Doc
linTerm Style{..} = go where
go tm = case tm of
Var v -> linv v
Con c [] -> linc c
Con c ts -> linc c <> parens (csv (map go ts))
Fun v ts -> linv v <> parens (csv (map go ts))
csv :: [Doc] -> Doc
csv = hcat . punctuate comma
parList :: [Doc] -> [Doc]
parList [] = [parens empty]
parList [x] = [x]
parList (x:xs) = (lparen <> x) : init xs ++ [last xs <> rparen]
ampersand :: Doc
ampersand = char '&'
bang :: Doc
bang = char '!'
fluff :: Doc -> Doc
fluff d = space <> d <> space
darrow :: Doc
darrow = text "=>"
dot :: Doc
dot = char '.'