packages feed

HXQ-0.18.2: Main.hs

{--------------------------------------------------------------
-
- The main program of the XQuery interpreter
- Programmer: Leonidas Fegaras (fegaras@cse.uta.edu)
- Date: 10/08/2009
-
---------------------------------------------------------------}

{-# OPTIONS -cpp #-}

module Main where

import List(sort)
import System.Environment
import System.CPUTime
import Text.XML.HXQ.XQuery
import Text.XML.HXQ.Functions
import Text.XML.HXQ.XTree
import Text.XML.HXQ.Types
import Text.XML.HXQ.Interpreter(evalInput,xqueryE,xfileDB)
import qualified Control.OldException as C


type E = C.Exception


version = "0.18.2"


parseEnv :: [String] -> [(String,String)]
parseEnv [] = [("o","Temp.hs")]
parseEnv ("-help":xs) = ("help",""):(parseEnv xs)
parseEnv ("-c":file:xs) = ("c",file):(parseEnv xs)
parseEnv ("-o":file:xs) = ("o",file):(parseEnv xs)
parseEnv ("-db":file:xs) = ("db",file):(parseEnv xs)
parseEnv ("-v":xs) = ("v",""):(parseEnv xs)
parseEnv ("-tp":xs) = ("tp",""):(parseEnv xs)
parseEnv ("-t":xs) = ("t",""):(parseEnv xs)
parseEnv ("-p":query:file:xs) = ("p","doc('"++file++"')"++query):(parseEnv xs)
parseEnv (('-':x):_) = error ("Unrecognized option -"++x++". Use -help.")
parseEnv (file:xs) = ("r",file):(parseEnv xs)


noDBerror = error "Missing Database Connection; use the option -db in xquery"


main = do senv <- getArgs
          let env = parseEnv senv
              verbose = case lookup "v" env of Nothing -> False; _ -> True
              timing = case lookup "t" env of Nothing -> False; _ -> True
              typecheck = case lookup "tp" env of Nothing -> False; _ -> True
              putTime t = if timing then putStrLn $ "Evaluation time: "++show (div t (10^9))++" milliseconds" else return ()
          case lookup "help" env of
            Just _ -> do putStrLn ("HXQ: XQuery Interpreter version "++version)
                         putStrLn "The documentation is availabe at http://lambda.uta.edu/HXQ/"
                         putStrLn "Command line options and files:"
                         putStrLn "   xquery-file               evaluate the XQuery in xquery-file using the interpreter"
                         putStrLn "   -db database              use the relational database during querying"
                         putStrLn "   -c xquery-file            compile the XQuery in xquery-file into Haskell code"
                         putStrLn "   -o haskell-file           set the Haskell file for -c (default is Temp.hs)"
                         putStrLn "   -p XPath-query xml-file   interpret the XPath query against the xml-file"
                         putStrLn "   -v                        print verbose information (AST and optimized plan)"
                         putStrLn "   -t                        print timing information"
                         putStrLn "   -tp                       print typing information"
                         putStrLn "Without an xquery-file, it reads and evaluates the input using the HXQ interpreter."
                         putStrLn "   The input may be an XQuery or a 'declare variable' or a 'declare function'."
                         putStrLn "   To write an XQuery in multiple lines, wrap it in {}."
                         putStrLn $ "Functions (name/arity):  " ++ (unwords $ sort $ map (\(f,c,_,_,_) -> f++"/"++show c) systemFunctions)
                         putStrLn $ "Path Steps:  " ++ (unwords $ map fst pathFunctions)
                         putStrLn $ "Build-in Types:  xs:anyAtomicType " ++ (unwords $ map fst buildInTypes)
            _ -> case lookup "c" env of
                   Just file -> do query <- readFile file
                                   let qf = foldr (\c r -> if c=='\"' then '\\':c:r else c:r)
                                                  "" (foldr1 (\a r -> a++" "++r) (lines query))
                                       db = case lookup "db" env of Just filepath -> filepath; _ -> ""
                                       pr = "{-# LANGUAGE TemplateHaskell #-}\nmodule Main where\nimport Text.XML.HXQ.XQuery\n\nmain = do "
                                            ++ (if db=="" then "res <- " else "db <- connect \""++db++"\"\n          res <- ")
                                            ++ (if db=="" then "$(xq \"" else "$(xqdb \"")
                                            ++ qf ++ "\")"++(if db=="" then "" else " db")++"\n          putXSeq res\n"
                                       Just ofile = lookup "o" env
                                   writeFile ofile pr
                   _ -> case lookup "r" env of
                          Just file -> case lookup "db" env of
                                         Just filepath -> do db <- connect filepath
                                                             t1 <- getCPUTime
                                                             query <- readFile file
                                                             (result,_,_,_,_) <- xqueryE query [] [] initialNS [] db verbose typecheck
                                                             putXSeq result
                                                             t2 <- getCPUTime
                                                             putTime (t2-t1)
                                                             commit db
                                         _ -> do query <- readFile file
                                                 t1 <- getCPUTime
                                                 (result,_,_,_,_) <- xqueryE query [] [] initialNS [] noDBerror verbose typecheck
                                                 putXSeq result
                                                 t2 <- getCPUTime
                                                 putTime (t2-t1)
                          _ -> case lookup "p" env of
                                 Just query -> do t1 <- getCPUTime
                                                  (result,_,_,_,_) <- xqueryE query [] [] initialNS [] noDBerror verbose typecheck
                                                  putXSeq result
                                                  t2 <- getCPUTime
                                                  putTime (t2-t1)
                                 _ -> do putStrLn ("HXQ: XQuery Interpreter version "++version++". Use -help for help.")
                                         case lookup "db" env of
                                           Just filepath
                                               -> do db <- connect filepath
                                                     evalInput (\s es fs ns vs -> C.catch
                                                                    (do t1 <- getCPUTime
                                                                        (result,nes,nfs,nns,nvs) <- xqueryE s es fs ns vs db verbose typecheck
                                                                        putXSeq result
                                                                        t2 <- getCPUTime
                                                                        putTime (t2-t1)
                                                                        commit db
                                                                        return (nes,nfs,nns,nvs))
                                                                      (\e -> do putStrLn (show (e::E))
                                                                                return (es,fs,ns,vs))) [] [] initialNS [] "> " []
                                                     return ()
                                           _ -> do evalInput (\s es fs ns vs -> C.catch
                                                                      (do t1 <- getCPUTime
                                                                          (result,nes,nfs,nns,nvs) <- xqueryE s es fs ns vs noDBerror verbose typecheck
                                                                          putXSeq result
                                                                          t2 <- getCPUTime
                                                                          putTime (t2-t1)
                                                                          return (nes,nfs,nns,nvs))
                                                                      (\e -> do putStrLn (show (e::E))
                                                                                return (es,fs,ns,vs))) [] [] initialNS [] "> " []
                                                   return ()