marxup-1.0.2: MarXup/DerivationTrees.hs
{-# LANGUAGE DisambiguateRecordFields, NamedFieldPuns, RecordWildCards, PostfixOperators, LiberalTypeSynonyms, TypeOperators, OverloadedStrings #-}
module MarXup.DerivationTrees (
-- * Basics
module Data.Monoid,
module Data.LabeledTree,
-- * Derivation' building
-- axiom, rule, etc, aborted,
emptyDrv, haltDrv, haltDrv', abortDrv, delayPre,
dummy, rule, Derivation, Premise, Rule(..),
-- * Links
Alignment(..), LineStyle(..),defaultLink,Link(..),
-- * Figure building
Figure(..),
-- * Engine
derivationTree
) where
-- import DerivationTrees.Basics
import Data.List
import Data.Traversable hiding (mapM)
import Control.Monad.Writer
import Control.Monad.State
import Control.Applicative
import System.IO.Unsafe
import Data.LabeledTree
-- import Control.Applicative.State
import Data.Monoid hiding ((<>))
import MarXup.Tex hiding (label)
import MarXup.MetaPost
------------------
--- Basics
data LineStyle = None | Simple | Double | Dotted | Dashed | Waved | TeXDotted
deriving (Enum,Show)
data Link = Link {label :: Tex (), linkStyle :: LineStyle, align :: Alignment, steps :: Int} -- ^ Regular link
| Detached {label :: Tex ()} -- ^ Detach the derivation as another figure
| Delayed {align :: Alignment} -- ^ automatic delaying
-- deriving Show
defaultLink :: Link
defaultLink = Link mempty Dotted CenterA 0
data Alignment = LeftA | CenterA | RightA
instance Show Alignment where
show LeftA = "l"
show CenterA = "c"
show RightA = "r"
-------------------
data Rule tag = Rule {tag :: tag, ruleStyle :: LineStyle, delimiter :: Tex (), ruleLabel :: Tex (), conclusion :: Tex ()}
-- deriving Show
{-
instance Monoid t => Applicative (Writer t) where
pure = return
(<*>) = ap
-}
type Premise = Link ::> Derivation' ()
type Derivation' tag = Tree Link (Rule tag)
type Derivation = Derivation' ()
data Figure tag = Figure {figureTag :: Label, contents :: Derivation' tag}
------------------------------------------------------------
-- Phase 1: Detach
type Detach x = x -> WriterT [Figure ()] Tex x
detachP :: Detach Premise
detachP (Detached{..} ::> d) = do
d'@(Node r ps) <- detachD d
figureTag <- lift $ newLabel
tell [Figure {contents = Node r {delimiter = label} ps,..}]
return $ (defaultLink ::> haltDrv label d)
detachP (l ::> d) = (l ::>) <$> detachD d
detachD :: Detach Derivation
detachD (Node n ps) = Node n <$> for ps detachP
detachF :: Figure () -> WriterT [Figure ()] Tex ()
detachF Figure{..} = do
contents <- detachD contents
tell [Figure{..}]
detachTop :: [Figure ()] -> Tex [Figure ()]
detachTop fs = do
figs <- runWriterT $ for fs detachF
return $ snd $ figs
--------------------------------------------------
-- Phase 2: Delay
insertAt n x xs = take n xs ++ x : drop n xs
rm idx [] = []
rm 0 (x:xs) = xs
rm n (x:xs) = x : rm (n-1) xs
depth (Detached{} ::> _) = 2
depth (Link{steps} ::> Node _ ps) = 1 + steps + maximum (0 : map depth ps)
isDelayed :: Premise -> Bool
isDelayed (Delayed{} ::> _) = True
isDelayed _ = False
delayPre a s (Link {..} ::> j) = Link {steps = s, align = a, ..} ::> j
delayD :: Derivation -> Derivation
delayD (Node r ps0) = Node r (map delayP ps)
where ps = fmap (fmap delayD) ps0
ps' = filter (not . isDelayed) ps
delayP (Delayed{..} ::> d) = Link{..} ::> d
where steps = 1 + maximum (0 : map depth ps')
label = mempty
linkStyle = Dotted
delayP p = p
delayF :: Figure () -> Figure ()
delayF (Figure{..}) = Figure{contents = delayD contents,..}
delayTop = map delayF
---------------------------------------------------------
-- Phase 3: Tag
type Tag x = x () -> Tex (x Int)
tagify :: Tag Rule
tagify (Rule {..}) = do
tag <- newLabel
return $ Rule {..}
tagifyFig :: Tag Figure
tagifyFig (Figure {..}) = Figure figureTag <$> traverse tagify contents
tagifyTop :: [Figure ()] -> Tex [Figure Int]
tagifyTop = mapM tagifyFig
----------------------------------------------------------
-- Phase 4: Texify
mpQuote :: Tex () -> Tex ()
mpQuote t = Tex "\"" >> t >> Tex "\""
mkTuple :: [Tex ()] -> Tex ()
mkTuple l = Tex " (" >> sequence_ (intersperse "," l) >> Tex ") "
link (Link {..} ::> Node (Rule{tag}) _)
| steps == 0 = sho tag
| otherwise = Tex "MVD " >> sho tag >> Tex " " >>
mkTuple [sho steps,sho "",mpQuote label,sho align,sho (fromEnum linkStyle)]
type Stringize x = x Int -> Tex ()
stringize :: Derivation' Label -> Tex ()
stringize (Node Rule {tag = t, ..} premises) = do
traverse (traverse stringize) premises
Tex "jgm " >> reference t >> Tex " " >> mpQuote conclusion >> Tex ";\n"
Tex "Nfr " >> reference t >> mkTuple (map link premises) >> Tex " " >>
mkTuple [mpQuote ruleLabel,mpQuote delimiter,mpQuote (Tex ""),sho (fromEnum ruleStyle)] >> Tex ";\n"
stringizeFig :: Figure Label -> Tex ()
stringizeFig (Figure {..}) = metapostFigure figureTag $ do
stringize contents
texLn "draw drv_tree;"
------------------------------------------
-- Pipeline
derivationTree :: [String] -> Derivation -> Tex Label
derivationTree opts j = do
f <- newLabel
a <- delayTop <$> detachTop [Figure f j]
bz <- tagifyTop a
Metapost $ mapM stringizeFig bz
cmd' "includegraphics" opts (MPFigure f)
return f
-----------------------
rule ruleLabel conclusion = Rule {tag = (), delimiter = mempty, ruleStyle = Simple, ..}
dummy :: Rule ()
dummy = (rule mempty mempty) {ruleStyle = None}
emptyDrv = Node dummy []
abortDrv (Node Rule {..} _) = Node Rule {ruleStyle = Waved, ..} []
-- | Used when the rest of the derivation is known.
haltDrv' :: Tex () -> Derivation -> Derivation
haltDrv' tex (Node r _) = Node r {ruleStyle = None}
[defaultLink {linkStyle = TeXDotted, steps = 1, label = tex} ::> emptyDrv]
-- | More compact variant
haltDrv :: Tex () -> Derivation -> Derivation
haltDrv t (Node r _) = Node r [defaultLink ::> Node dummy {conclusion = cmd "vdots" nil >> cmd "hspace" (Tex "2pt") >> t} []]
{-------------------------
brace :: TeX -> TeX
brace (TeX x) = TeX $ '{' : x ++ ['}']
paren (TeX x) = TeX $ '(' : x ++ [')']
brack (TeX x) = TeX $ "[" ++ x ++ "]"
tex :: String -> [TeX] -> TeX
tex macro args = TeX ('\\' : macro) <> mconcat (map brace args)
text x = tex "text" [TeX x]
f ! x = brace f <> TeX "_" <> brace x
-}