Subversion

ptable

[/] [ptableweb.wash] - Rev 11

Compare with Previous - Blame


module Main where

import PTable
import Synthesis
import Analysis
import Matchings
--import TypesMatching
--import Normalizing
import Prelude hiding (span, div, map)
import System.IO
import WASH.CGI.CGI hiding (head, standardQuery, map)
import Data.Map as Map hiding (empty, map)
import Data.List as List
import Data.Maybe
--import Codec.Serialize.SerTH
import Language.Haskell.Pretty
import Language.Pointfree.Pretty
import Language.Pointfree.Syntax
import Examples (freshTable, example)


standardQuery t b = ask $ cssPage t "../style.css" $ makeForm b
{-
serialize :: PTable -> IO ()
serialize ptable = do
  h <- openBinaryFile "db.serialized" WriteMode
  s <- handleEncoder h
  --putStrLn "Creating encoder ok"
  let foo = fromPTable ptable
  encodeWith s foo
  --putStrLn "Encoder ok"
  encodeWith s Flush
  --putStrLn "Encoder flush ok"
  hClose h

unserialize :: IO PTable
unserialize = do
  h <- openBinaryFile "db.serialized" ReadMode
  d <- handleDecoder h
  x <- decodeWith d
  hClose h
  return (toPTable x)
-}
--main = unserialize >>= run . indexCGI

main = run $ indexCGI $ either error snd example

--main = run (io (serialize (toPTable ([],([],([],[]))))) >> standardQuery "bla" empty)

errorPage _ s F0 = standardQuery "Error page" 
  <body>
    <h1><%= "Error: " ++ s %></h1>
  </body>

indexCGI ex = do 
  standardQuery "The \"Periodic Table\" of algorithms - select operating mode" (index ex)

index ex = 
  <div>
    <% submit F0 (redirect ex) <[ value="Consult the table"]> %>
    <% submit F0 (errorPage ex "this function is disabled") <[ value="Add your own function(s) (DISABLED)"]> %>
  </div>

redirect ex F0 = selectFunctCGI ex
{-
upload ex F0 = standardQuery "Add your own functions to the table"
  <body>
    <h2>Type your code below...</h2>
    <p>Note: the code you type must be an entire Haskell module</p>
    <% codeIF <- makeTextarea "" <[ rows="20" cols="80" ]> %>
    <br />
    <% submit codeIF (uploadCheckLCGI ex) <[ value="Add"]> %>
    <h2>... or upload from a file in your disk</h2>
    <% codeFile <- fileInputField empty %>
    <br />
    <% submit codeFile (uploadCheckRCGI ex) <[ value="Upload"]> %>
  </body>

-- Code from textbox
uploadCheckLCGI ex = standardQuery "Hylofactorization" . (uploadCheck ex . value)

uploadCheckRCGI ex iCode = io (f iCode) >>= (standardQuery "Hylofactorization" . (uploadCheck ex))
  where f s = readFile $ fileReferenceName $ value s

ppResult (a,(b,(c,d))) = do
  <p>Name <%= show a %></p>
  <p>Functor: <%= show b%></p>
  <p>Algebra:</p>
  <pre class="pf"><%= prettyPrint $ pf2hs c %></pre>
  <p>Coalgebra:</p>
  <pre class="pf"><%= prettyPrint $ pf2hs d %></pre>

uploadCheck ex codeStr = do 
  let result = str2hylos codeStr
  <h2>Input code:</h2>
  <pre class="pw"><%= codeStr %></pre>
  <h2>Derived hylofactorizations:</h2>
  case result of
    Nothing -> <p>Could not parse the input file!</p>
    Just result -> 
        <span>
          <p><% foldr (\a b -> a >> <hr /> >> b) empty $ fmap ppResult result %></p>
          <% submit F0 (addTableCGI ex result 0) <[ value="Add these functions to the table"]> %>
        </span>

addTableCGI ex functions n F0 = standardQuery ("Adding function " ++ (show $ succ n)) (addTable ex functions n)

addTable ex functions n = do
  let currFun = succ n
      totFun = length functions
      (funName,(functor,(a,c))) = functions !! n
  <#>
    <h2>Adding function <%= show currFun %> of <%= show totFun %></h2>
    <p>Name you supplied: <%= funName %></p>
    <p>Name as you want it in the table: <% funNameFromUser <- textInputField <[ value=<% funName %> ]> %></p>
    <p>A comment on this function: <% funCommFromUser <- textInputField empty %></p>
    <hr />
    <p>Derived functor: <%= show functor%></p>
    <p>Name for this functor: <% functNameFromUser <- textInputField empty %></p>
    <p>A comment on this functor: <% functCommFromUser <- textInputField <[ value=<% show functor %> ]> %></p>
    <hr />
    <p>Algebra:</p>
    <pre class="pf"><%= prettyPrint $ pf2hs a %></pre>
    <p>Name for this gene: <% aNameFromUser <- textInputField empty %></p>
    <p>A comment on this gene: <% aCommFromUser <- textInputField empty %></p>
    <hr />
    <p>Coalgebra:</p>
    <pre class="pf"><%= prettyPrint $ pf2hs c %></pre>
    <p>Name for this gene: <% cNameFromUser <- textInputField empty %></p>
    <p>A comment on this gene: <% cCommFromUser <- textInputField empty %></p>
    <% submit (F8 funNameFromUser funCommFromUser functNameFromUser functCommFromUser aNameFromUser aCommFromUser cNameFromUser cCommFromUser) (reallyAddCGI ex functions n) <[ value="Add"]> %>
  </#>

reallyAddCGI ex functions n x = standardQuery "Adding function" (reallyAdd ex functions n x)

-- TODO: Add error checking
reallyAdd ex functions n (F8 ifunNameFU ifunCommFU ifunctNameFU ifunctCommFU iaNameFU iaCommFU icNameFU icCommFU) = do
  let 
    (funNameFU:funCommFU:functNameFU:functCommFU:aNameFU:aCommFU:cNameFU:cCommFU:[]) = 
      fmap value [ifunNameFU, ifunCommFU, ifunctNameFU, ifunctCommFU, iaNameFU, iaCommFU, icNameFU, icCommFU]
    currFun = succ n
    totFun = length functions
    (funName,(functor,(a,c))) = functions !! n
    funMatch = [ f | f <- fmap funct (Map.elems (functors ex)), isJust (match (normalize f) (normalize functor)) ]
    functName = 
      case funMatch of
        [] -> functNameFU
        (h:_) -> 
          let aux = Map.assocs (functors ex)
              aux2 = List.filter (\(a,(Functor b c)) -> c == h) aux
          in if (length aux2 /= 1) then (error "4") else (fst $ head aux2)
    ex1 = 
      case funMatch of
        [] -> insertFunctor functName (Functor functCommFU functor) ex
        (h:_) -> ex
    ex2 = insertAlg aNameFU (Gene aCommFU functName "" a) ex1
    ex3 = insertCoAlg cNameFU (Gene cCommFU functName "" c) ex2
    ex4 = insertFunction funNameFU (Function funCommFU functName aNameFU cNameFU) ex3
  <#>
    <p>Function <%= funNameFU %> added to the table!</p>
    <% if (funMatch == [])
        then empty
        else <p>The derived functor for your function already existed in the table, so you can find your genes under the functor <%= functName %>!</p> %>
    <% submit F0 (pressToAddCGI ex4 functions (succ n)) <[ value="Continue adding"]> %>
  </#>
  
pressToAddCGI ex functions n F0
  | n < length functions = io (serialize ex) >> (standardQuery "Adding function" (addTable ex functions n))
  | otherwise = io (serialize ex) >> (standardQuery "Finished adding!" (index ex))
-}

selectFunctCGI ex = standardQuery "Select functor..." (selectFunct ex)

selectFunct ex =
  let dispFunct idF = show (functors ex ! idF)
  in
  <div>
    <% funct <- selectSingle dispFunct Nothing (keys $ functors ex) empty %>
    <% submit funct (tableFunctCGI ex) <[ value="Choose this functor"]> %>
  </div> >>
  <script type="text/javascript" src="../wz_tooltip.js"></script>

tableFunctCGI ex = standardQuery "Select genes..." . (tableFunct ex Nothing)

tableFunct ex mac iFunct = 
  let idFunct = value iFunct
      algs = Map.filter ((== idFunct) . gfunctor) (algebras ex)
      coalgs = Map.filter ((== idFunct) . gfunctor) (coalgebras ex)
      f2comment f x = (\s -> "return escape('" ++ s ++ "')") $ if (aux f x == "") then "No user comment for this gene..." else (aux f x)
        where aux f x = either error gcomment (f x ex)
     
      colH a = <span onmouseover=<% f2comment getAlg a %> ><%= a %></span>
      header = foldr (>>) empty [<th scope="col"><% colH a %></th> | a <- keys algs]
      oldSelection o a c = maybe empty (\(a', c') -> if (a == a' && c == c') then o else empty) mac
      oldSelectionColor = \_ _ -> <[]> -- oldSelection <[ bgcolor="red"]> -- use for background color of the last selected function
      oldSelectionCheck = oldSelection <[ checked="checked"]>
      genCell a c rg = do
        let 
                str "" = "return escape('There\\'s no user comment for this function...')"
                str c  = "return escape('" ++ c ++ "')"
                mIdF = lookupByGenes a c ex
                radio = radioButton rg (a, c) (oldSelectionCheck a c)
              case mIdF of
                Left e -> <span onmouseover=<% str "Unnamed function" %> ><% radio %></span>
                Right idF -> either (const radio) (\f -> <span onmouseover=<% str (fcomment f) %> > <% radio >> text (show f) %> </span>) (getFunction idF ex)
      contents c rg = foldr (>>) empty [ <td <% oldSelectionColor a c %> ><% genCell a c rg %></td> | a <- keys algs]
      rowH c = <span onmouseover=<% f2comment getCoAlg c %> ><%= c %></span>
      rows rg = foldr (>>) empty [ <tr><th scope="row"><% rowH c %></th><% contents c rg %></tr> | c <- keys coalgs]
      functComment idF = if (aux == "") then "no user comment for this functor" else aux
        where aux = either error fccomment (getFunctor idF ex)
  in
  <#>
    <div>
    <p>Table for the functor <%= idFunct %> (User comment: <%= functComment idFunct %>)</p>
    <!-- Outer table for the string headers -->
    <table border="1">
      <tr><td/><td align="center">Algebras</td></tr>
      <tr><td valign="center">Coalgebras</td><td>
        <!-- Inner table with the actual data -->
        <table border="2">
        <% rg <- radioGroup %>
          <tr>
            <!-- Header row naming the algebras -->
            <td/><% header %>
          </tr>
          <!-- Rows, first with the name of the coalgebra and then the functions' names --> 
          <% rows rg %>
        </table>
      </td></tr>
    </table>
    <% submit rg (synthCGI iFunct ex) <[ value="Show/synthesize this function"]> %>
    </div>
    <h2>... or select another functor:</h2>
    <% selectFunct ex %>
    <h2>... or add your own functions</h2>
    <% submit F0 (errorPage ex "this function is disabled") <[ value="Add your own function(s) (DISABLED)"]> %>
  </#>

synthCGI iFunct ex = standardQuery "The function in this place is..." . (synth iFunct ex)

synth iFunct ex iGenes = 
  let (a, c) = value iGenes
      idF = combine a c "newF" "" ex
      wrapCode s = <pre class="pf"><%= prettyPrint s %></pre>
      wrapCode2 idF s = 
        let f = either error id (getFunction idF ex)
        in
          <#>
            <p>User comment: <%= if (fcomment f == "") then "No user comment for this function" else (fcomment f) %></p>
            <p>Code:</p>
            <pre class="pf"><%= prettyPrint s %></pre>
          </#>
  in 
  case idF of
    -- There was already a function, show it
    Left idF  -> either error (wrapCode2 idF) (expandPWById idF ex)
    -- Incompatible genes
    Right (Left e) -> <p>Incompatible genes!</p>
    -- New function generated
    Right (Right newFunct) -> either error wrapCode (expandPW newFunct ex)
  >>
  <#>
    <% submit F0 (generateCGI idF ex a c iFunct) <[ value="Get this function in a module"]> %>
    <h2>... select another function:</h2>
    <% tableFunct ex (Just (a,c)) iFunct %>
  </#>

generateCGI a b c d e F0 = standardQuery "Complete Haskell module" (generate a b c d e)

generate idF ex a c iFunct = do
  let 
    addOn = "module Output where\n\nimport Pointless.Functors\nimport Pointless.Combinators\nimport Pointless.Combinators.Uncurried\nimport Pointless.RecursionPatterns\n\nf = "
    code = 
      case idF of
        Left e	  -> "a" -- maybe (error "5") (prettyPrint . pf2hs) (mkhylo a c ex)
        Right idF -> "b" -- either error (prettyPrint . pf2hs) (expandPFById idF ex)	    
  <#>
    <pre class="pf"><%= addOn ++ code %></pre>
    <% tableFunct ex Nothing iFunct %>
  </#>

Theme by Vikram Singh | Powered by WebSVN v1.61