module ExampleService(cgiMain,cgiMain',newPGFCache) where import System.Random(newStdGen) import System.FilePath((),makeRelative) import Data.Map(fromList) import Data.Char(isDigit) import Data.Maybe(fromJust) import qualified Codec.Binary.UTF8.String as UTF8 (decodeString) import PGF import GF.Compile.ToAPI import Network.CGI import Text.JSON import CGIUtils import Cache import qualified ExampleDemo as E newPGFCache = newCache readPGF cgiMain :: Cache PGF -> CGI CGIResult cgiMain = handleErrors . handleCGIErrors . cgiMain' "." "." cgiMain' root cwd cache = do command <- getInp "command" environ <- parseEnviron =<< getInp "state" case command of "possibilities" -> doPossibilities environ "provide_example" -> doProvideExample root cwd cache environ "abstract_example" -> doAbstractExample cwd cache environ "test_function" -> doTestFunction cwd cache environ _ -> throwCGIError 400 ("Unknown command: "++command) [] doPossibilities environ = do example_environ <- parseEnviron =<< getInp "example_state" outputJSONP (E.getNext environ example_environ) doProvideExample root cwd cache environ = do Just lang <- readInput "lang" fun <- getCId "fun" parsePGF <- readParsePGF cwd cache let adjpath path = rootmakeRelative "/" (makeRelative root cwdpath) pgf <- liftIO . readCache cache . adjpath =<< getInp "grammar" gen <- liftIO newStdGen let Just (e,s) = E.provideExample gen environ fun parsePGF pgf lang res = (showExpr [] e,s) liftIO $ logError $ "proveExample ... = "++show res outputJSONP res doAbstractExample cwd cache environ = do example <- getInp "input" Just params <- readInput "params" absstr <- getInp "abstract" Just abs <- return $ readExpr absstr liftIO $ logError $ "abstract = "++showExpr [] abs Just cat <- readInput "cat" let t = mkType [] cat [] parsePGF <- readParsePGF cwd cache let lang:_ = languages parsePGF ae <- liftIO $ abstractExample parsePGF environ lang t abs example outputJSONP (fmap (\(e,_)->(exprToAPI (instExpMeta params e),e)) ae) abstractExample parsePGF env lang cat abs example = E.searchGoodTree env abs (parse parsePGF lang cat example) doTestFunction cwd cache environ = do fun <- getCId "fun" parsePGF <- readParsePGF cwd cache let lang:_ = languages parsePGF Just txt <- return (E.testThis environ fun parsePGF lang) outputJSONP txt getCId :: String -> CGI CId getCId name = maybe err return =<< fmap readCId (getInp name) where err = throwCGIError 400 ("Bad "++name) [] {- getLimit :: CGI Int getLimit = maybe err return =<< readInput "limit" where err = throwCGIError 400 "Missing/bad limit" [] -} readParsePGF cwd cache = do parsepgf <- getInp "parser" liftIO $ readCache cache (cwdparsepgf) parseEnviron s = do state <- liftIO $ readIO s return $ environ state getInp name = maybe err (return . UTF8.decodeString) =<< getInput name where err = throwCGIError 400 ("Missing parameter: "++name) [] instance JSON CId where showJSON = showJSON . show readJSON = (readResult =<<) . readJSON instance JSON Expr where showJSON = showJSON . showExpr [] readJSON = (m2r . readExpr =<<) . readJSON m2r = maybe (Error "read failed") Ok readResult s = case reads s of (x,r):_ | lex r==[("","")] -> Ok x _ -> Error "read failed" -------------------------------------------------------------------------------- -- cat lincat fun lin fun cat cat environ :: ([(CId, CId)],[(CId, Expr)],[((CId, CId), [CId])]) -> E.Environ environ (lincats,lins0,funs) = E.initial (fromList lincats) concmap fs allfs where concmap = fromList lins allfs = map E.mkFuncWithArg funs fs = [E.mkFuncWithArg f | f@((fn,_),_)<-funs, fn `elem` cns] cns = map fst lins lins = filter (not . E.isMeta .snd) lins0 instExpMeta :: [CId] -> Expr -> Expr instExpMeta ps = fromJust . readExpr . instMeta ps . showExpr [] instMeta :: [CId] -> String -> String instMeta ps s = case break (=='?') s of (s1,'?':s2) -> case span isDigit s2 of (s21@(_:_),s22) -> s1++show (ps!!(read s21-1))++instMeta ps s22 ("",s22) -> s1++'?':instMeta ps s22 (_,_) -> s