ideas-0.7: src/Documentation/ServicePage.hs
{-# OPTIONS -XRankNTypes #-}
-----------------------------------------------------------------------------
-- Copyright 2010, Open Universiteit Nederland. This file is distributed
-- under the terms of the GNU General Public License. For more information,
-- see the file "LICENSE.txt", which is included in the distribution.
-----------------------------------------------------------------------------
-- |
-- Maintainer : bastiaan.heeren@ou.nl
-- Stability : provisional
-- Portability : portable (depends on ghc)
--
-----------------------------------------------------------------------------
module Documentation.ServicePage (makeServicePage) where
import Documentation.DefaultPage
import Service.ExercisePackage
import Service.TypedExample
import Service.Types
import Service.DomainReasoner
import Service.State
import Text.HTML
import qualified Text.XML as XML
import Text.XML (XML)
import Control.Monad
import Common.Exercise
import Common.Utils (Some(..))
makeServicePage :: String -> Service -> DomainReasoner ()
makeServicePage dir s = do
xs <- examplesFor (showId s)
generatePageAt 1 dir (servicePageFile s) (servicePage xs s)
servicePage :: [Example] -> Service -> HTMLBuilder
servicePage xs s = do
h1 (showId s)
para $ do
bold $ text "Signature:"
space
case serviceFunction s of
_ ::: t -> ttText (show t)
para $ do
bold $ text "Description: "
br
text $ description s
when (serviceDeprecated s) $
para $ bold $ text "Warning: this service is deprecated!"
unless (null xs) $ do
h2 $ "XML examples (" ++ show (length xs) ++ ")"
forM_ (zip [1::Int ..] xs) $
\(i, (msg, (xmlRequest, xmlReply, xmlTest))) -> do
h2 $ show i ++ ". " ++ msg
bold $ text "Request:"
highlightXML True xmlRequest
bold $ text "Reply:"
highlightXML True xmlReply
unless xmlTest $
XML.element "font" $ do
"color" XML..=. "red"
bold $ text "Error: invalid request/reply pair"
-----------------------------------------------------------------------
-- Examples
type Example = (String, (XML, XML, Bool))
examplesFor :: String -> DomainReasoner [Example]
examplesFor s = tryAll [ f t | (t, f) <- list, s == t ]
where
list =
[ ("derivation", makeExample "logic.dnf" (noCfg +++ logic1))
, ("derivation", makeExample "math.lineq" (noCfg +++ lineq1))
, ("allfirsts", makeExample "logic.dnf" logic2)
, ("allfirsts", makeExample "math.lineq" lineq2)
, ("onefirst", makeExample "logic.dnf" logic2)
, ("onefirst", makeExample "math.lineq" lineq2)
, ("rulesinfo", makeExample "math.lineq" noArgs)
, ("rulelist", makeExample "math.lineq" exArgs)
, ("strategyinfo", makeExample "math.lineq" exArgs)
, ("examples", makeExample "math.lineq" exArgs)
]
logic1, logic2 :: Args
logic1 pkg = newState pkg "~(p /\\ ~q)"
logic2 pkg = newState pkg "~~p /\\ T"
lineq1, lineq2 :: Args
lineq1 pkg = newState pkg "5*(x+1) == 11"
lineq2 pkg = newState pkg "5*(x+1) == (x-1)/2"
(f +++ g) pkg = f pkg ++ g pkg
noCfg _ = [Nothing ::: maybeTp StrategyCfg]
noArgs _ = []
exArgs pkg = [pkg ::: ExercisePkg]
tryAll :: [DomainReasoner a] -> DomainReasoner [a]
tryAll xs =
let f m = liftM return m `catchError` const (return [])
in liftM concat (mapM f xs)
newState :: Monad m => ExercisePackage a -> String -> m (TypedValue a)
newState pkg s = do
let ex = exercise pkg
case parser ex s of
Left msg -> fail ("newState: " ++ msg)
Right a -> return (emptyState pkg a ::: stateTp)
type Args = forall a . ExercisePackage a -> [TypedValue a]
makeExample :: String -> Args -> String -> DomainReasoner Example
makeExample pkgName f srvName = do
let a = newId pkgName
Some pkg <- findPackage a
srv <- findService srvName
tr <- typedExample pkg srv (f pkg)
return (showId pkg, tr)