------------------------------------------------------------------------- -- CDoc AST interface to Haskell ------------------------------------------------------------------------- MODULE {UHC.Shuffle.CDoc} {} { import UHC.Shuffle.Common import System.IO import qualified Data.Map as Map } INCLUDE "CDocAbsSyn.ag" ------------------------------------------------------------------------- -- Make CDoc ------------------------------------------------------------------------- { type FromVariantReqm a = VariantReqm -> a type MkCDoc = FromVariantReqm (Maybe CDoc) instance Show MkCDoc where show _ = "MkCDoc" } ------------------------------------------------------------------------- -- Chunk doc utils ------------------------------------------------------------------------- { cdHor :: CD a => [a] -> CDoc cdHor = foldr CDoc_Hor CDoc_Emp . map cd cdVer :: CD a => [a] -> CDoc cdVer = foldr CDoc_Ver CDoc_Emp . map cd {- cdLines :: CDoc -> [String] cdLines d = lns d where ln l CDoc_Emp = (l,CDoc_Emp) ln l (CDoc_Str s) = (s:l,CDoc_Emp) ln l (CDoc_Hor d1 d2) = case ln l d1 of (l1,CDoc_Emp) -> ln l1 d2 r -> r ln l (CDoc_Ver d1 d2) = case ln l d1 of (l1,CDoc_Emp) -> (l1,d2) (l1,dr) -> (l1,CDoc_Ver dr d2) lns CDoc_Emp = [] lns d = let (l,d') = ln [] d in concat (reverse l) : lns d' cdPut' :: Handle -> CDoc -> IO () cdPut' h = mapM_ (hPutStrLn h) . cdLines -} cdPut :: Handle -> CDoc -> IO () cdPut h d = do p d hPutStrLn h "" where p d = case d of CDoc_Emp -> return () CDoc_Str s -> hPutStr h s CDoc_Ref r s d -> hPutStr h (showUndef r) CDoc_Hor d1 d2 -> do p d1 p d2 CDoc_Ver CDoc_Emp d2 -> p d2 CDoc_Ver d1 CDoc_Emp -> p d1 CDoc_Ver d1 d2 -> do p d1 hPutStrLn h "" p d2 CDoc_Pos _ d -> p d class CD a where cd :: a -> CDoc instance CD String where cd "" = CDoc_Emp cd s = CDoc_Str s instance CD Int where cd = CDoc_Str . show instance CD CDoc where cd = id instance CD Nm where cd = cdDots . nmToL instance CD a => CD (Maybe a) where cd = maybe CDoc_Emp cd cdIsEmpty :: CDoc -> Bool cdIsEmpty (CDoc_Emp) = True cdIsEmpty (CDoc_Hor d1 d2) = cdIsEmpty d1 && cdIsEmpty d2 cdIsEmpty (CDoc_Ver d1 d2) = cdIsEmpty d1 && cdIsEmpty d2 cdIsEmpty (CDoc_Str s) = null s cdIsEmpty _ = False cdToMaybe :: CDoc -> Maybe CDoc cdToMaybe d = case d of CDoc_Emp -> Nothing _ -> Just d infixr 2 .-. infixr 3 .|. , .#. (.|.) :: (CD a, CD b) => a -> b -> CDoc (.|.) a b = cd a `CDoc_Hor` cd b (.-.) :: (CD a, CD b) => a -> b -> CDoc (.-.) a b = cd a `CDoc_Ver` cd b (.#.) :: (CD a, CD b) => a -> b -> CDoc (.#.) a b = cd a .|. " " .|. cd b cdListSep' :: (CD s, CD c, CD o, CD a) => (forall x . CD x => [x] -> CDoc) -> (forall x y . (CD x, CD y) => x -> y -> CDoc) -> o -> c -> s -> [a] -> CDoc cdListSep' list aside o c s pps = l pps where l [] = o `aside` c l [p] = o `aside` p `aside` c l (p:ps) = list ([o `aside` p] ++ map (s `aside`) (init ps) ++ [s `aside` last ps `aside` c]) cdListSep :: (CD s, CD c, CD o, CD a) => o -> c -> s -> [a] -> CDoc cdListSep = cdListSep' cdHor (.|.) cdListSepV :: (CD s, CD c, CD o, CD a) => o -> c -> s -> [a] -> CDoc cdListSepV = cdListSep' cdVer (.|.) cdDots :: CD a => [a] -> CDoc cdDots = cdListSep "" "" "." } ------------------------------------------------------------------------- -- Chunk doc wrapping ------------------------------------------------------------------------- { chWrap :: ChWrap -> CDoc -> CDoc chWrap w d = case w of ChWrapCode -> "\\begin{code}" .-. d .-. "\\end{code}" ChWrapHsBox -> "\\begin{hsbox}" .-. d .-. "\\end{hsbox}" ChWrapBoxCode mw -> "\\parbox{" .|. maybe "" id mw .|. "\\linewidth}{%" .-. chWrap ChWrapCode d .-. "}" ChWrapBeamerBlockCode title -> "\\begin{block}{%" .-. title .-. "}" .-. chWrap (ChWrapBoxCode Nothing) d .-. "\\end{block}" ChWrapVerbatim -> "\\begin{verbatim}" .-. d .-. "\\end{verbatim}" ChWrapVerbatimSmall -> "{\\small\n\\begin{verbatim}" .-. d .-. "\\end{verbatim}\n}" ChWrapTT -> "\\begin{TT}" .-. d .-. "\\end{TT}" ChWrapTTtiny -> "\\begin{TTtiny}" .-. d .-. "\\end{TTtiny}" ChWrapT2T chKind | isJust mbt2t -> "@@[" .|. t2t .-. d .-. "@@]" where mbt2t = Map.lookup chKind t2tChKinds t2t = fromJust mbt2t ChWrapComp w1 w2 -> chWrap w1 $ chWrap w2 d _ -> d chWrapT2T :: Opts -> ChKind -> ChWrap chWrapT2T opts chKind = if optGenText2Text opts then ChWrapT2T chKind else ChWrapNone } ------------------------------------------------------------------------- -- Utils ------------------------------------------------------------------------- { mkTexCmd1 :: CD a => String -> a -> CDoc mkTexCmd1 cmd a1 = "\\" .|. cmd .|. "{" .|. cd a1 .|. "}" mkTexCmd2 :: (CD a, CD b) => String -> a -> b -> CDoc mkTexCmd2 cmd a1 a2 = "\\" .|. cmd .|. "{" .|. cd a1 .|. "}{%" .-. cd a2 .-. "}" mkTexCmd3 :: (CD a, CD b, CD c) => String -> a -> b -> c -> CDoc mkTexCmd3 cmd a1 a2 a3 = "\\" .|. cmd .|. "{" .|. cd a1 .|. "}{%" .-. cd a2 .-. "}{%" .-. cd a3 .-. "}" mkTexCmdDef :: (CD a, CD b) => String -> a -> b -> CDoc mkTexCmdDef = mkTexCmd2 mkTexCmdUse :: CD a => String -> a -> CDoc mkTexCmdUse = mkTexCmd1 mkTexCmdUse' :: CD a => String -> a -> CDoc mkTexCmdUse' cmd nm = mkTexCmdUse cmd nm .|. "%" }