Be more explicit about strict functions
[darcs-mirror-polyfix.git] / polyfix-cgi.hs
1 module Main where
2
3 import ParseType (parseType')
4 import SimpleFT  (freeTheorem)
5 import Expr (specialize)
6 import ExFindExtended (getComplete')
7 import Language.Haskell.FreeTheorems.Parser.Haskell98 as FTP
8 import Language.Haskell.FreeTheorems
9         ( runChecks
10         , check
11         , filterSignatures
12         , prettyTheorem
13         , asTheorem
14         , interpret
15         , unfoldLifts
16         , prettyUnfoldedLift
17         , LanguageSubset(BasicSubset)
18         )
19
20 import Network.CGI
21 import Data.ByteString.Lazy.UTF8 (fromString)
22 import Text.XHtml
23 import Control.Monad
24 import System.Random (randomRIO)
25 import Data.Maybe
26 import Text.PrettyPrint.HughesPJ (render)
27
28 main = runCGI (handleErrors cgiMain)
29
30 cgiMain = do
31         setHeader "Content-type" "text/xml; charset=UTF-8"
32         
33         mTypeStr <- getInput "type"
34
35         
36         let content = case mTypeStr of 
37                 Nothing      -> askTypeForm
38                 Just typeStr -> case parseType' typeStr of
39                         Left err  -> typeError typeStr err
40                         Right typ -> generateResult typeStr typ
41         
42         outputFPS $ fromString $ showHtml $
43                header (
44                 thetitle << "PolyFix" +++
45                 style ! [ thetype "text/css" ] << cdata cssStyle
46                ) +++
47                body ( form ! [method "POST", action "#"] << (
48                 thediv ! [theclass "top"] << (
49                         thespan ! [theclass "title"] << "PolyFix" +++
50                         thespan ! [theclass "subtitle"] << "Counter Examples for Free Theorems"
51                 ) +++
52                 content +++
53                 maindiv ( p << ("© 2008 Daniel Seidel und Joachim Breitner <" +++
54                               hotlink "mailto:mail@joachim-breitner.de" << "mail@joachim-breitner.de" +++
55                               ">")
56                         )       
57                 ))
58
59 maindiv = thediv ! [theclass "main"]
60
61 cdata s = primHtml ("<![CDATA[\n"++ s ++ "\n]]>")
62
63 cssStyle = unlines 
64         [ "body { padding:0px; margin: 0px; }"
65         , "div.top { margin:0px; padding:10px; margin-bottom:20px;"
66         , "              background-color:#efefef;"
67         , "              border-bottom:1px solid black; }"
68         , "span.title { font-size:xx-large; font-weight:bold; }"
69         , "span.subtitle { padding-left:30px; font-size:large; }"
70         , "div.main { border:1px dotted black;"
71         , "                   padding:10px; margin:10px; }"
72         , "div.submain { padding:10px; margin:11px; }"
73         , "p.subtitle { font-size:large; font-weight:bold; }"
74         , "input.type { font-family:monospace; }"
75         , "input[type=\"submit\"] { font-family:monospace; background-color:#efefef; }"
76         , "span.mono { font-family:monospace; }"
77         , "pre { margin:10px; margin-left:20px; padding:10px;"
78         , "          border:1px solid black; }"
79         , "textarea { margin:10px; margin-left:20px; padding:10px;  }"
80         , "p { text-align:justify; }"
81         ]
82
83 askDiv v e =  maindiv << (
84         p << ( "Please enter a function type, prepended with a list of type variables, " +++
85                "whose relations should be allowed to be nonstrict, and a single dot.") +++            p << ( input ! [name "type", value v] +++ " " +++
86                submit "submit" "Generate Free Theorem and counter example" ) +++
87         e
88         )
89
90
91 askTypeForm = askDiv "a. (a -> b) -> b" noHtml
92
93 typeError typeStr err = askDiv typeStr (
94         p << ("There was a problem parsing your type: " +++
95               pre << err )
96         )
97
98 generateResult typeStr typ = askDiv typeStr noHtml +++
99         maindiv << (
100         h3 << "The Free Theorem" +++
101         (case ft_full of
102                 Left err -> p << "The full Free Theorem deriver failed:" +++
103                             pre << err
104                 Right s  -> p << "For your type, the following Free Theorem holds:" +++
105                             pre << s
106         ) +++
107         p << "Specializing relations to functions, canceling irrelvant terms and eta-reduction, this theorem can be written as:" +++
108         pre << show ft_simple +++
109         p << "Further specializing all types to (), all strict functions to id and all non-strict functions to const (), this theorem can be written as:" +++
110         pre << show (specialize ft_simple)
111         ) +++
112         maindiv << (
113         h3 << "The counter-example" +++
114         case counter_example of 
115                 Left err -> p << "No term could be derived: " +++ pre << err
116                 Right (res,used) ->
117                         p << ("By disregarding the strictness conditions for the chosen "+++
118                               "relations, the following term is a counter example:" +++
119                               pre << ("f = " ++ res) ) +++
120                         p << ("Wheres the abstraced variables are chosen as follows:" +++
121                               pre << used)
122         )
123   where ft_full = let properType = "f :: " ++ case span (/='.') typeStr of
124                                        (s,"")  -> s
125                                        (_,_:s) -> s
126                       (ds,es) = runChecks (parse properType >>= check)
127                       [s]     = filterSignatures ds
128                   in if null es
129                      then case interpret [] BasicSubset s of
130                         Nothing -> Left "interpret returned nothing"
131                         Just i  -> Right $ render (prettyTheorem [] (asTheorem i)) ++
132                               case unfoldLifts [] i of
133                                 [] -> ""
134                                 ls -> "\n\nWhereas the occuring lifts are defined as:\n\n "++
135                                       unlines (map (render . prettyUnfoldedLift []) ls)
136                      else Left (unlines (map render es))
137                     
138         ft_simple = freeTheorem typ
139         counter_example = getComplete' typ
140