packages feed

tableaux-0.3: src/Main.hs

{-
  Tableaux theorem prover for first order logic

  Pedro Vasconcelos <pbv@dcc.fc.up.pt>, 2009--2010
-}
module Main where
import Text.Html
import Network.CGI
import FOL
import Tableaux
import Markup
import Examples
import Parser
import Zipper
import Util
import Control.Monad.State
import qualified Data.Map as Map

main :: IO ()
main = runCGI cgi_start

-- CGI entry point 
cgi_start = do opstart <- getInput "refute" -- parse a formula to refute
               case opstart of
                 Just txt -> cgi_refute (parseFormula txt)
                 Nothing -> -- fetch current tableau 
                            do script<-scriptName
                               cmds <- getInputWithDefault "cmd" ""
                               op1 <- getInput "tableau" 
                               op2 <- getInput "status" 
                               let optf = do t <- op1 
                                             s <- op2
                                             return (Form script 
                                                     (read $ unquote t) 
                                                     (read $ unquote s))
                               case optf of
                                 Just tf -> cgi_tableau tf cmds
                                 Nothing ->  do setHeader "Content-type" "text/html"
                                                output (renderHtml (greetings script))

cgi_refute (Left msg)
          = do setHeader "Content-type" "text/plain"
               output (show msg)
cgi_refute (Right f)
          = do script<-scriptName 
               cgi_tableau (Form script tableau initial_status) ""
    where tableau = newTableau (Not f)


cgi_tableau t cmds 
    = do setHeader "Content-type" "text/html"
         output (renderHtml (htmlpage << tableau_header t'))
    where t' =  foldl perform t cmds



perform :: Form -> Char -> Form
perform t 'u' = t { form_tableau = cursorUp (form_tableau t) }
perform t 'd' = t { form_tableau = cursorDown (form_tableau t) }
perform t 'l' = t { form_tableau = cursorLeft (form_tableau t) }
perform t 'r' = t { form_tableau = cursorRight (form_tableau t) }
perform t 'x' = let ft = form_tableau t
                    st = form_status t
                    (ft', st') = runState (expand ft) st
                in t { form_tableau=ft', form_status=st' }

perform t 's' = t { form_tableau=resolve (form_tableau t) }
perform t _   = t


getInputWithDefault :: MonadCGI m => String -> String -> m String
getInputWithDefault var def = do opt<-getInput var
                                 return (maybe def id opt)


tableau_header t
    = [h2 << "Instructions",
       form![action (form_script t), method "POST"] << ordList 
       [ primHtml "Use <EM>Expand</EM> to split a formula into sub components.",
         primHtml "Move the current focus node by clicking on sub-formulas.",
         primHtml "Use <EM>Resolve</EM> on an <EM>atomic</EM> formula to unify with another of inverted sign in the same branch (thus <EM>closing</EM> the branch).",
         toHtml "The proof is complete when all branches are closed, i.e. end in False.",
         ("To return to the start page, click " +++ submit "bt" "Restart")
       ],
       hr,
       p << math << t,
       hr,
       signature
      ]
             


-- startup page
-- allows typing in a formula or selecting an example
greetings script 
    = htmlpage << 
      [ h1 << "Welcome to the interactive tableaux prover",
        p << [ toHtml "This web page allows constructing proofs of ",
               toHtml "propositional and first-order logic sentences using ",
               toHtml "the method of semantic tableaux. To learn more about tableaux, check the ",
               anchor![href "http://en.wikipedia.org/wiki/Method_of_analytic_tableaux"] << "Wikipedia article."
             ],
      form![action script, method "POST"] << 
        [ p << "Please type in a formula to prove or choose an example from the list below.",
          p << [inputField "refute"![size "60"],  submit "bt" "Start"]
        , p << table << map make_example (zip [1..] examples)
        , hr
        , p << [ toHtml "This theorem prover is written in "
               , anchor![href "http://www.haskell.org"] << "Haskell;"
               , toHtml " the source code package is available in the "
               , anchor![href "http://hackage.haskell.org"] << "HackageDB site."
               ]
        , signature
        ]
      ]
    where
      -- n-th example            
      make_example (n,(txt,f))
          = tr << [td << input ![name "sel", thetype "radio", 
                                 value (show n), onclick cmd],
                   td << math << f,
                   td![align "right"] << primHtml txt,
                   hiddenField id (showFormula f)
                  ]
            
          where cmd = "copy('" ++ id ++ "')"
                id = "ex" ++ show n


signature =
    address << [toHtml "Pedro Vasconcelos <pbv@dcc.fc.up.pt>",
                br,
                toHtml "LIACC, University of Porto, PORTUGAL"]