diff options
| author | krasimir <krasimir@chalmers.se> | 2009-12-13 18:50:29 +0000 |
|---|---|---|
| committer | krasimir <krasimir@chalmers.se> | 2009-12-13 18:50:29 +0000 |
| commit | f85232947e74ee7ef8c7b0ad2338212e7e68f1be (patch) | |
| tree | 667b886a5e3a4b026a63d4e3597f32497d824761 /src/GF/Infra | |
| parent | d88a865faff59c98fc91556ff8700b10ee5f2df8 (diff) | |
reorganize the directories under src, and rescue the JavaScript interpreter from deprecated
Diffstat (limited to 'src/GF/Infra')
| -rw-r--r-- | src/GF/Infra/CheckM.hs | 77 | ||||
| -rw-r--r-- | src/GF/Infra/CompactPrint.hs | 22 | ||||
| -rw-r--r-- | src/GF/Infra/Dependencies.hs | 61 | ||||
| -rw-r--r-- | src/GF/Infra/GetOpt.hs | 381 | ||||
| -rw-r--r-- | src/GF/Infra/Ident.hs | 152 | ||||
| -rw-r--r-- | src/GF/Infra/Modules.hs | 349 | ||||
| -rw-r--r-- | src/GF/Infra/Option.hs | 609 | ||||
| -rw-r--r-- | src/GF/Infra/UseIO.hs | 186 |
8 files changed, 0 insertions, 1837 deletions
diff --git a/src/GF/Infra/CheckM.hs b/src/GF/Infra/CheckM.hs deleted file mode 100644 index 8a1b42cdf..000000000 --- a/src/GF/Infra/CheckM.hs +++ /dev/null @@ -1,77 +0,0 @@ ----------------------------------------------------------------------- --- | --- Module : CheckM --- Maintainer : (Maintainer) --- Stability : (stable) --- Portability : (portable) --- --- > CVS $Date: 2005/04/21 16:22:33 $ --- > CVS $Author: bringert $ --- > CVS $Revision: 1.5 $ --- --- (Description of the module) ------------------------------------------------------------------------------ - -module GF.Infra.CheckM - (Check, Message, runCheck, - checkError, checkCond, checkWarn, - checkErr, checkIn, checkMap - ) where - -import GF.Data.Operations -import GF.Infra.Ident -import GF.Grammar.Grammar -import GF.Grammar.Printer - -import qualified Data.Map as Map -import Text.PrettyPrint - -type Message = Doc -data CheckResult a - = Fail [Message] - | Success a [Message] -newtype Check a = Check {unCheck :: Context -> [Message] -> CheckResult a} - -instance Monad Check where - return x = Check (\ctxt msgs -> Success x msgs) - f >>= g = Check (\ctxt msgs -> case unCheck f ctxt msgs of - Success x msgs -> unCheck (g x) ctxt msgs - Fail msgs -> Fail msgs) - -instance ErrorMonad Check where - raise s = checkError (text s) - handle f h = Check (\ctxt msgs -> case unCheck f ctxt msgs of - Success x msgs -> Success x msgs - Fail (msg:msgs) -> unCheck (h (render msg)) ctxt msgs) - -checkError :: Message -> Check a -checkError msg = Check (\ctxt msgs -> Fail (msg : msgs)) - -checkCond :: Message -> Bool -> Check () -checkCond s b = if b then return () else checkError s - --- | warnings should be reversed in the end -checkWarn :: Message -> Check () -checkWarn msg = Check (\ctxt msgs -> Success () ((text "Warning:" <+> msg) : msgs)) - -runCheck :: Check a -> Err (a,String) -runCheck c = - case unCheck c [] [] of - Fail msgs -> Bad ( render (vcat (reverse msgs))) - Success v msgs -> Ok (v, render (vcat (reverse msgs))) - -checkMap :: (Ord a) => (a -> b -> Check b) -> Map.Map a b -> Check (Map.Map a b) -checkMap f map = do xs <- mapM (\(k,v) -> do v <- f k v - return (k,v)) (Map.toList map) - return (Map.fromAscList xs) - -checkErr :: Err a -> Check a -checkErr (Ok x) = return x -checkErr (Bad err) = checkError (text err) - -checkIn :: Doc -> Check a -> Check a -checkIn msg c = Check $ \ctxt msgs -> - case unCheck c ctxt [] of - Fail msgs' -> Fail ((msg $$ nest 3 (vcat (reverse msgs'))) : msgs) - Success v msgs' | null msgs' -> Success v msgs - | otherwise -> Success v ((msg $$ nest 3 (vcat (reverse msgs'))) : msgs) diff --git a/src/GF/Infra/CompactPrint.hs b/src/GF/Infra/CompactPrint.hs deleted file mode 100644 index 486c9e183..000000000 --- a/src/GF/Infra/CompactPrint.hs +++ /dev/null @@ -1,22 +0,0 @@ -module GF.Infra.CompactPrint where -import Data.Char - -compactPrint = compactPrintCustom keywordGF (const False) - -compactPrintGFCC = compactPrintCustom (const False) keywordGFCC - -compactPrintCustom pre post = dps . concat . map (spaceIf pre post) . words - -dps = dropWhile isSpace - -spaceIf pre post w = case w of - _ | pre w -> "\n" ++ w - _ | post w -> w ++ "\n" - c:_ | isAlpha c || isDigit c -> " " ++ w - '_':_ -> " " ++ w - _ -> w - -keywordGF w = elem w ["cat","fun","lin","lincat","lindef","oper","param"] -keywordGFCC w = - last w == ';' || - elem w ["flags","fun","cat","lin","oper","lincat","lindef","printname","param"] diff --git a/src/GF/Infra/Dependencies.hs b/src/GF/Infra/Dependencies.hs deleted file mode 100644 index af2088711..000000000 --- a/src/GF/Infra/Dependencies.hs +++ /dev/null @@ -1,61 +0,0 @@ -module GF.Infra.Dependencies ( - depGraph - ) where - -import GF.Grammar.Grammar -import GF.Infra.Modules -import GF.Infra.Ident - -depGraph :: SourceGrammar -> String -depGraph = prDepGraph . grammar2moddeps - -prDepGraph :: [(Ident,ModDeps)] -> String -prDepGraph deps = unlines $ [ - "digraph {" - ] ++ - map mkNode deps ++ - concatMap mkArrows deps ++ [ - "}" - ] - where - mkNode (i,dep) = unwords [showIdent i, "[",nodeAttr (modtype dep),"]"] - nodeAttr ty = case ty of - MTAbstract -> "style = \"solid\", shape = \"box\"" - MTConcrete _ -> "style = \"solid\", shape = \"ellipse\"" - _ -> "style = \"dashed\", shape = \"ellipse\"" - mkArrows (i,dep) = - [unwords [showIdent i,"->",showIdent j,"[",arrowAttr "of","]"] | j <- ofs dep] ++ - [unwords [showIdent i,"->",showIdent j,"[",arrowAttr "ex","]"] | j <- extendeds dep] ++ - [unwords [showIdent i,"->",showIdent j,"[",arrowAttr "op","]"] | j <- openeds dep] ++ - [unwords [showIdent i,"->",showIdent j,"[",arrowAttr "ed","]"] | j <- extrads dep] - arrowAttr s = case s of - "of" -> "style = \"solid\", arrowhead = \"empty\"" - "ex" -> "style = \"solid\"" - "op" -> "style = \"dashed\"" - "ed" -> "style = \"dotted\"" - -data ModDeps = ModDeps { - modtype :: ModuleType Ident, - ofs :: [Ident], - extendeds :: [Ident], - openeds :: [Ident], - extrads :: [Ident], - functors :: [Ident], - interfaces :: [Ident], - instances :: [Ident] - } - -noModDeps = ModDeps MTAbstract [] [] [] [] [] [] [] - -grammar2moddeps :: SourceGrammar -> [(Ident,ModDeps)] -grammar2moddeps gr = [(i,depMod m) | (i,m) <- modules gr] where - depMod m = noModDeps{ - modtype = mtype m, - ofs = case mtype m of - MTConcrete i -> [i] - MTInstance i -> [i] - _ -> [], - extendeds = map fst (extend m), - openeds = map openedModule (opens m), - extrads = mexdeps m - } diff --git a/src/GF/Infra/GetOpt.hs b/src/GF/Infra/GetOpt.hs deleted file mode 100644 index ede561c90..000000000 --- a/src/GF/Infra/GetOpt.hs +++ /dev/null @@ -1,381 +0,0 @@ --- This is a version of System.Console.GetOpt which has been hacked to --- support long options with a single dash. Since we don't want the annoying --- clash with short options that start with the same character as a long --- one, we don't allow short options to be given together (e.g. -zxf), --- nor do we allow options to be given as any unique prefix. - ------------------------------------------------------------------------------ --- | --- Module : System.Console.GetOpt --- Copyright : (c) Sven Panne 2002-2005 --- License : BSD-style (see the file libraries/base/LICENSE) --- --- Maintainer : libraries@haskell.org --- Stability : experimental --- Portability : portable --- --- This library provides facilities for parsing the command-line options --- in a standalone program. It is essentially a Haskell port of the GNU --- @getopt@ library. --- ------------------------------------------------------------------------------ - -{- -Sven Panne <Sven.Panne@informatik.uni-muenchen.de> Oct. 1996 (small -changes Dec. 1997) - -Two rather obscure features are missing: The Bash 2.0 non-option hack -(if you don't already know it, you probably don't want to hear about -it...) and the recognition of long options with a single dash -(e.g. '-help' is recognised as '--help', as long as there is no short -option 'h'). - -Other differences between GNU's getopt and this implementation: - -* To enforce a coherent description of options and arguments, there - are explanation fields in the option/argument descriptor. - -* Error messages are now more informative, but no longer POSIX - compliant... :-( - -And a final Haskell advertisement: The GNU C implementation uses well -over 1100 lines, we need only 195 here, including a 46 line example! -:-) --} - ---module System.Console.GetOpt ( -module GF.Infra.GetOpt ( - -- * GetOpt - getOpt, getOpt', - usageInfo, - ArgOrder(..), - OptDescr(..), - ArgDescr(..), - - -- * Examples - - -- |To hopefully illuminate the role of the different data structures, - -- here are the command-line options for a (very simple) compiler, - -- done in two different ways. - -- The difference arises because the type of 'getOpt' is - -- parameterized by the type of values derived from flags. - - -- ** Interpreting flags as concrete values - -- $example1 - - -- ** Interpreting flags as transformations of an options record - -- $example2 -) where - -import Prelude -- necessary to get dependencies right - -import Data.List ( isPrefixOf, find ) - --- |What to do with options following non-options -data ArgOrder a - = RequireOrder -- ^ no option processing after first non-option - | Permute -- ^ freely intersperse options and non-options - | ReturnInOrder (String -> a) -- ^ wrap non-options into options - -{-| -Each 'OptDescr' describes a single option. - -The arguments to 'Option' are: - -* list of short option characters - -* list of long option strings (without \"--\") - -* argument descriptor - -* explanation of option for user --} -data OptDescr a = -- description of a single options: - Option [Char] -- list of short option characters - [String] -- list of long option strings (without "--") - (ArgDescr a) -- argument descriptor - String -- explanation of option for user - --- |Describes whether an option takes an argument or not, and if so --- how the argument is injected into a value of type @a@. -data ArgDescr a - = NoArg a -- ^ no argument expected - | ReqArg (String -> a) String -- ^ option requires argument - | OptArg (Maybe String -> a) String -- ^ optional argument - -data OptKind a -- kind of cmd line arg (internal use only): - = Opt a -- an option - | UnreqOpt String -- an un-recognized option - | NonOpt String -- a non-option - | EndOfOpts -- end-of-options marker (i.e. "--") - | OptErr String -- something went wrong... - --- | Return a string describing the usage of a command, derived from --- the header (first argument) and the options described by the --- second argument. -usageInfo :: String -- header - -> [OptDescr a] -- option descriptors - -> String -- nicely formatted decription of options -usageInfo header optDescr = unlines (header:table) - where (ss,ls,ds) = (unzip3 . concatMap fmtOpt) optDescr - table = zipWith3 paste (sameLen ss) (sameLen ls) ds - paste x y z = " " ++ x ++ " " ++ y ++ " " ++ z - sameLen xs = flushLeft ((maximum . map length) xs) xs - flushLeft n xs = [ take n (x ++ repeat ' ') | x <- xs ] - -fmtOpt :: OptDescr a -> [(String,String,String)] -fmtOpt (Option sos los ad descr) = - case lines descr of - [] -> [(sosFmt,losFmt,"")] - (d:ds) -> (sosFmt,losFmt,d) : [ ("","",d') | d' <- ds ] - where sepBy _ [] = "" - sepBy _ [x] = x - sepBy ch (x:xs) = x ++ ch:' ':sepBy ch xs - sosFmt = sepBy ',' (map (fmtShort ad) sos) - losFmt = sepBy ',' (map (fmtLong ad) los) - -fmtShort :: ArgDescr a -> Char -> String -fmtShort (NoArg _ ) so = "-" ++ [so] -fmtShort (ReqArg _ ad) so = "-" ++ [so] ++ " " ++ ad -fmtShort (OptArg _ ad) so = "-" ++ [so] ++ "[" ++ ad ++ "]" - -fmtLong :: ArgDescr a -> String -> String -fmtLong (NoArg _ ) lo = "--" ++ lo -fmtLong (ReqArg _ ad) lo = "--" ++ lo ++ "=" ++ ad -fmtLong (OptArg _ ad) lo = "--" ++ lo ++ "[=" ++ ad ++ "]" - -{-| -Process the command-line, and return the list of values that matched -(and those that didn\'t). The arguments are: - -* The order requirements (see 'ArgOrder') - -* The option descriptions (see 'OptDescr') - -* The actual command line arguments (presumably got from - 'System.Environment.getArgs'). - -'getOpt' returns a triple consisting of the option arguments, a list -of non-options, and a list of error messages. --} -getOpt :: ArgOrder a -- non-option handling - -> [OptDescr a] -- option descriptors - -> [String] -- the command-line arguments - -> ([a],[String],[String]) -- (options,non-options,error messages) -getOpt ordering optDescr args = (os,xs,es ++ map errUnrec us) - where (os,xs,us,es) = getOpt' ordering optDescr args - -{-| -This is almost the same as 'getOpt', but returns a quadruple -consisting of the option arguments, a list of non-options, a list of -unrecognized options, and a list of error messages. --} -getOpt' :: ArgOrder a -- non-option handling - -> [OptDescr a] -- option descriptors - -> [String] -- the command-line arguments - -> ([a],[String], [String] ,[String]) -- (options,non-options,unrecognized,error messages) -getOpt' _ _ [] = ([],[],[],[]) -getOpt' ordering optDescr (arg:args) = procNextOpt opt ordering - where procNextOpt (Opt o) _ = (o:os,xs,us,es) - procNextOpt (UnreqOpt u) _ = (os,xs,u:us,es) - procNextOpt (NonOpt x) RequireOrder = ([],x:rest,[],[]) - procNextOpt (NonOpt x) Permute = (os,x:xs,us,es) - procNextOpt (NonOpt x) (ReturnInOrder f) = (f x :os, xs,us,es) - procNextOpt EndOfOpts RequireOrder = ([],rest,[],[]) - procNextOpt EndOfOpts Permute = ([],rest,[],[]) - procNextOpt EndOfOpts (ReturnInOrder f) = (map f rest,[],[],[]) - procNextOpt (OptErr e) _ = (os,xs,us,e:es) - - (opt,rest) = getNext arg args optDescr - (os,xs,us,es) = getOpt' ordering optDescr rest - --- take a look at the next cmd line arg and decide what to do with it -getNext :: String -> [String] -> [OptDescr a] -> (OptKind a,[String]) -getNext ('-':'-':[]) rest _ = (EndOfOpts,rest) -getNext ('-':'-':xs) rest optDescr = longOpt xs rest optDescr -getNext ('-' :xs) rest optDescr = longOpt xs rest optDescr -getNext a rest _ = (NonOpt a,rest) - --- handle long option -longOpt :: String -> [String] -> [OptDescr a] -> (OptKind a,[String]) -longOpt ls rs optDescr = long ads arg rs - where (opt,arg) = break (=='=') ls - options = [ o | o@(Option ss xs _ _) <- optDescr - , opt `elem` map (:[]) ss || opt `elem` xs ] - ads = [ ad | Option _ _ ad _ <- options ] - optStr = ("--"++opt) - - long (_:_:_) _ rest = (errAmbig options optStr,rest) - long [NoArg a ] [] rest = (Opt a,rest) - long [NoArg _ ] ('=':_) rest = (errNoArg optStr,rest) - long [ReqArg _ d] [] [] = (errReq d optStr,[]) - long [ReqArg f _] [] (r:rest) = (Opt (f r),rest) - long [ReqArg f _] ('=':xs) rest = (Opt (f xs),rest) - long [OptArg f _] [] rest = (Opt (f Nothing),rest) - long [OptArg f _] ('=':xs) rest = (Opt (f (Just xs)),rest) - long _ _ rest = (UnreqOpt ("--"++ls),rest) - - --- miscellaneous error formatting - -errAmbig :: [OptDescr a] -> String -> OptKind a -errAmbig ods optStr = OptErr (usageInfo header ods) - where header = "option `" ++ optStr ++ "' is ambiguous; could be one of:" - -errReq :: String -> String -> OptKind a -errReq d optStr = OptErr ("option `" ++ optStr ++ "' requires an argument " ++ d ++ "\n") - -errUnrec :: String -> String -errUnrec optStr = "unrecognized option `" ++ optStr ++ "'\n" - -errNoArg :: String -> OptKind a -errNoArg optStr = OptErr ("option `" ++ optStr ++ "' doesn't allow an argument\n") - -{- ------------------------------------------------------------------------------------------ --- and here a small and hopefully enlightening example: - -data Flag = Verbose | Version | Name String | Output String | Arg String deriving Show - -options :: [OptDescr Flag] -options = - [Option ['v'] ["verbose"] (NoArg Verbose) "verbosely list files", - Option ['V','?'] ["version","release"] (NoArg Version) "show version info", - Option ['o'] ["output"] (OptArg out "FILE") "use FILE for dump", - Option ['n'] ["name"] (ReqArg Name "USER") "only dump USER's files"] - -out :: Maybe String -> Flag -out Nothing = Output "stdout" -out (Just o) = Output o - -test :: ArgOrder Flag -> [String] -> String -test order cmdline = case getOpt order options cmdline of - (o,n,[] ) -> "options=" ++ show o ++ " args=" ++ show n ++ "\n" - (_,_,errs) -> concat errs ++ usageInfo header options - where header = "Usage: foobar [OPTION...] files..." - --- example runs: --- putStr (test RequireOrder ["foo","-v"]) --- ==> options=[] args=["foo", "-v"] --- putStr (test Permute ["foo","-v"]) --- ==> options=[Verbose] args=["foo"] --- putStr (test (ReturnInOrder Arg) ["foo","-v"]) --- ==> options=[Arg "foo", Verbose] args=[] --- putStr (test Permute ["foo","--","-v"]) --- ==> options=[] args=["foo", "-v"] --- putStr (test Permute ["-?o","--name","bar","--na=baz"]) --- ==> options=[Version, Output "stdout", Name "bar", Name "baz"] args=[] --- putStr (test Permute ["--ver","foo"]) --- ==> option `--ver' is ambiguous; could be one of: --- -v --verbose verbosely list files --- -V, -? --version, --release show version info --- Usage: foobar [OPTION...] files... --- -v --verbose verbosely list files --- -V, -? --version, --release show version info --- -o[FILE] --output[=FILE] use FILE for dump --- -n USER --name=USER only dump USER's files ------------------------------------------------------------------------------------------ --} - -{- $example1 - -A simple choice for the type associated with flags is to define a type -@Flag@ as an algebraic type representing the possible flags and their -arguments: - -> module Opts1 where -> -> import System.Console.GetOpt -> import Data.Maybe ( fromMaybe ) -> -> data Flag -> = Verbose | Version -> | Input String | Output String | LibDir String -> deriving Show -> -> options :: [OptDescr Flag] -> options = -> [ Option ['v'] ["verbose"] (NoArg Verbose) "chatty output on stderr" -> , Option ['V','?'] ["version"] (NoArg Version) "show version number" -> , Option ['o'] ["output"] (OptArg outp "FILE") "output FILE" -> , Option ['c'] [] (OptArg inp "FILE") "input FILE" -> , Option ['L'] ["libdir"] (ReqArg LibDir "DIR") "library directory" -> ] -> -> inp,outp :: Maybe String -> Flag -> outp = Output . fromMaybe "stdout" -> inp = Input . fromMaybe "stdin" -> -> compilerOpts :: [String] -> IO ([Flag], [String]) -> compilerOpts argv = -> case getOpt Permute options argv of -> (o,n,[] ) -> return (o,n) -> (_,_,errs) -> ioError (userError (concat errs ++ usageInfo header options)) -> where header = "Usage: ic [OPTION...] files..." - -Then the rest of the program will use the constructed list of flags -to determine it\'s behaviour. - --} - -{- $example2 - -A different approach is to group the option values in a record of type -@Options@, and have each flag yield a function of type -@Options -> Options@ transforming this record. - -> module Opts2 where -> -> import System.Console.GetOpt -> import Data.Maybe ( fromMaybe ) -> -> data Options = Options -> { optVerbose :: Bool -> , optShowVersion :: Bool -> , optOutput :: Maybe FilePath -> , optInput :: Maybe FilePath -> , optLibDirs :: [FilePath] -> } deriving Show -> -> defaultOptions = Options -> { optVerbose = False -> , optShowVersion = False -> , optOutput = Nothing -> , optInput = Nothing -> , optLibDirs = [] -> } -> -> options :: [OptDescr (Options -> Options)] -> options = -> [ Option ['v'] ["verbose"] -> (NoArg (\ opts -> opts { optVerbose = True })) -> "chatty output on stderr" -> , Option ['V','?'] ["version"] -> (NoArg (\ opts -> opts { optShowVersion = True })) -> "show version number" -> , Option ['o'] ["output"] -> (OptArg ((\ f opts -> opts { optOutput = Just f }) . fromMaybe "output") -> "FILE") -> "output FILE" -> , Option ['c'] [] -> (OptArg ((\ f opts -> opts { optInput = Just f }) . fromMaybe "input") -> "FILE") -> "input FILE" -> , Option ['L'] ["libdir"] -> (ReqArg (\ d opts -> opts { optLibDirs = optLibDirs opts ++ [d] }) "DIR") -> "library directory" -> ] -> -> compilerOpts :: [String] -> IO (Options, [String]) -> compilerOpts argv = -> case getOpt Permute options argv of -> (o,n,[] ) -> return (foldl (flip id) defaultOptions o, n) -> (_,_,errs) -> ioError (userError (concat errs ++ usageInfo header options)) -> where header = "Usage: ic [OPTION...] files..." - -Similarly, each flag could yield a monadic function transforming a record, -of type @Options -> IO Options@ (or any other monad), allowing option -processing to perform actions of the chosen monad, e.g. printing help or -version messages, checking that file arguments exist, etc. - --} diff --git a/src/GF/Infra/Ident.hs b/src/GF/Infra/Ident.hs deleted file mode 100644 index efe6f9261..000000000 --- a/src/GF/Infra/Ident.hs +++ /dev/null @@ -1,152 +0,0 @@ ----------------------------------------------------------------------- --- | --- Module : Ident --- Maintainer : AR --- Stability : (stable) --- Portability : (portable) --- --- > CVS $Date: 2005/11/15 11:43:33 $ --- > CVS $Author: aarne $ --- > CVS $Revision: 1.8 $ --- --- (Description of the module) ------------------------------------------------------------------------------ - -module GF.Infra.Ident (-- * Identifiers - Ident(..), ident2bs, showIdent, - identC, identV, identA, identAV, identW, - argIdent, varStr, varX, isWildIdent, varIndex, - -- * refreshing identifiers - IdState, initIdStateN, initIdState, - lookVar, refVar, refVarPlus - ) where - -import GF.Data.Operations -import qualified Data.ByteString.Char8 as BS --- import Monad - - --- | the constructors labelled /INTERNAL/ are --- internal representation never returned by the parser -data Ident = - IC {-# UNPACK #-} !BS.ByteString -- ^ raw identifier after parsing, resolved in Rename - | IW -- ^ wildcard --- --- below this constructor: internal representation never returned by the parser - | IV {-# UNPACK #-} !BS.ByteString {-# UNPACK #-} !Int -- ^ /INTERNAL/ variable - | IA {-# UNPACK #-} !BS.ByteString {-# UNPACK #-} !Int -- ^ /INTERNAL/ argument of cat at position - | IAV {-# UNPACK #-} !BS.ByteString {-# UNPACK #-} !Int {-# UNPACK #-} !Int -- ^ /INTERNAL/ argument of cat with bindings at position --- - - deriving (Eq, Ord, Show, Read) - -ident2bs :: Ident -> BS.ByteString -ident2bs i = case i of - IC s -> s - IV s n -> BS.append s (BS.pack ('_':show n)) - IA s j -> BS.append s (BS.pack ('_':show j)) - IAV s b j -> BS.append s (BS.pack ('_':show b ++ '_':show j)) - IW -> BS.pack "_" - -showIdent :: Ident -> String -showIdent i = BS.unpack $! ident2bs i - -identC :: BS.ByteString -> Ident -identV :: BS.ByteString -> Int -> Ident -identA :: BS.ByteString -> Int -> Ident -identAV:: BS.ByteString -> Int -> Int -> Ident -identW :: Ident -(identC, identV, identA, identAV, identW) = - (IC, IV, IA, IAV, IW) - --- normal identifier --- ident s = IC s - --- | to mark argument variables -argIdent :: Int -> Ident -> Int -> Ident -argIdent 0 (IC c) i = identA c i -argIdent b (IC c) i = identAV c b i - --- | used in lin defaults -varStr :: Ident -varStr = identA (BS.pack "str") 0 - --- | refreshing variables -varX :: Int -> Ident -varX = identV (BS.pack "x") - -isWildIdent :: Ident -> Bool -isWildIdent x = case x of - IW -> True - IC s | s == BS.pack "_" -> True - _ -> False - -varIndex :: Ident -> Int -varIndex (IV _ n) = n -varIndex _ = -1 --- other than IV should not count - --- refreshing identifiers - -type IdState = ([(Ident,Ident)],Int) - -initIdStateN :: Int -> IdState -initIdStateN i = ([],i) - -initIdState :: IdState -initIdState = initIdStateN 0 - -lookVar :: Ident -> STM IdState Ident -lookVar a@(IA _ _) = return a -lookVar x = do - (sys,_) <- readSTM - stm (\s -> maybe (Bad ("cannot find" +++ show x +++ prParenth (show sys))) - return $ - lookup x sys >>= (\y -> return (y,s))) - -refVar :: Ident -> STM IdState Ident -----refVar IW = return IW --- no update of wildcard -refVar x = do - (_,m) <- readSTM - let x' = IV (ident2bs x) m - updateSTM (\(sys,mx) -> ((x, x'):sys, mx + 1)) - return x' - -refVarPlus :: Ident -> STM IdState Ident -----refVarPlus IW = refVar (identC "h") -refVarPlus x = refVar x - - -{- ------------------------------- --- to test - -refreshExp :: Exp -> Err Exp -refreshExp e = err Bad (return . fst) (appSTM (refresh e) initState) - -refresh :: Exp -> STM State Exp -refresh e = case e of - Atom x -> lookVar x >>= return . Atom - App f a -> liftM2 App (refresh f) (refresh a) - Abs x b -> liftM2 Abs (refVar x) (refresh b) - Fun xs a b -> do - a' <- refresh a - xs' <- mapM refVar xs - b' <- refresh b - return $ Fun xs' a' b' - -data Exp = - Atom Ident - | App Exp Exp - | Abs Ident Exp - | Fun [Ident] Exp Exp - deriving Show - -exp1 = Abs (IC "y") (Atom (IC "y")) -exp2 = Abs (IC "y") (App (Atom (IC "y")) (Atom (IC "y"))) -exp3 = Abs (IC "y") (Abs (IC "z") (App (Atom (IC "y")) (Atom (IC "z")))) -exp4 = Abs (IC "y") (Abs (IC "y") (App (Atom (IC "y")) (Atom (IC "z")))) -exp5 = Abs (IC "y") (Abs (IC "y") (App (Atom (IC "y")) (Atom (IC "y")))) -exp6 = Abs (IC "y") (Fun [IC "x", IC "y"] (Atom (IC "y")) (Atom (IC "y"))) -exp7 = Abs (IL "8") (Atom (IC "y")) - --} diff --git a/src/GF/Infra/Modules.hs b/src/GF/Infra/Modules.hs deleted file mode 100644 index 0710b8f40..000000000 --- a/src/GF/Infra/Modules.hs +++ /dev/null @@ -1,349 +0,0 @@ ----------------------------------------------------------------------- --- | --- Module : Modules --- Maintainer : AR --- Stability : (stable) --- Portability : (portable) --- --- > CVS $Date: 2005/11/09 15:14:30 $ --- > CVS $Author: aarne $ --- > CVS $Revision: 1.26 $ --- --- Datastructures and functions for modules, common to GF and GFC. --- --- AR 29\/4\/2003 --- --- The same structure will be used in both source code and canonical. --- The parameters tell what kind of data is involved. --- Invariant: modules are stored in dependency order ------------------------------------------------------------------------------ - -module GF.Infra.Modules ( - MGrammar(..), ModInfo(..), ModuleType(..), - MInclude (..), - extends, isInherited,inheritAll, - updateMGrammar, updateModule, replaceJudgements, addFlag, - addOpenQualif, flagsModule, allFlags, mapModules, - OpenSpec(..), - ModuleStatus(..), - openedModule, depPathModule, allDepsModule, partOfGrammar, - allExtends, allExtendSpecs, allExtendsPlus, allExtensions, - searchPathModule, addModule, - emptyMGrammar, emptyModInfo, - IdentM(..), - abstractOfConcrete, abstractModOfConcrete, - lookupModule, lookupModuleType, lookupInfo, - lookupPosition, ppPosition, - isModAbs, isModRes, isModCnc, - sameMType, isCompilableModule, isCompleteModule, - allAbstracts, greatestAbstract, allResources, - greatestResource, allConcretes, allConcreteModules - ) where - -import GF.Infra.Ident -import GF.Infra.Option -import GF.Data.Operations - -import Data.List -import Text.PrettyPrint - --- AR 29/4/2003 - --- The same structure will be used in both source code and canonical. --- The parameters tell what kind of data is involved. --- Invariant: modules are stored in dependency order - -newtype MGrammar i a = MGrammar {modules :: [(i,ModInfo i a)]} - deriving Show - -data ModInfo i a = ModInfo { - mtype :: ModuleType i , - mstatus :: ModuleStatus , - flags :: Options, - extend :: [(i,MInclude i)], - mwith :: Maybe (i,MInclude i,[(i,i)]), - opens :: [OpenSpec i] , - mexdeps :: [i] , - jments :: BinTree i a , - positions :: BinTree i (String,(Int,Int)) -- file, first line, last line - } - deriving Show - --- | encoding the type of the module -data ModuleType i = - MTAbstract - | MTResource - | MTConcrete i - -- ^ up to this, also used in GFC. Below, source only. - | MTInterface - | MTInstance i - deriving (Eq,Ord,Show) - -data MInclude i = MIAll | MIOnly [i] | MIExcept [i] - deriving (Eq,Ord,Show) - -extends :: ModInfo i a -> [i] -extends = map fst . extend - -isInherited :: Eq i => MInclude i -> i -> Bool -isInherited c i = case c of - MIAll -> True - MIOnly is -> elem i is - MIExcept is -> notElem i is - -inheritAll :: i -> (i,MInclude i) -inheritAll i = (i,MIAll) - --- destructive update - --- | dep order preserved since old cannot depend on new -updateMGrammar :: Ord i => MGrammar i a -> MGrammar i a -> MGrammar i a -updateMGrammar old new = MGrammar $ - [(i,m) | (i,m) <- os, notElem i (map fst ns)] ++ ns - where - os = modules old - ns = modules new - -updateModule :: Ord i => ModInfo i t -> i -> t -> ModInfo i t -updateModule (ModInfo mt ms fs me mw ops med js ps) i t = ModInfo mt ms fs me mw ops med (updateTree (i,t) js) ps - -replaceJudgements :: ModInfo i t -> BinTree i t -> ModInfo i t -replaceJudgements (ModInfo mt ms fs me mw ops med _ ps) js = ModInfo mt ms fs me mw ops med js ps - -addOpenQualif :: i -> i -> ModInfo i t -> ModInfo i t -addOpenQualif i j (ModInfo mt ms fs me mw ops med js ps) = ModInfo mt ms fs me mw (OQualif i j : ops) med js ps - -addFlag :: Options -> ModInfo i t -> ModInfo i t -addFlag f mo = mo {flags = flags mo `addOptions` f} - -flagsModule :: (i,ModInfo i a) -> Options -flagsModule (_,mi) = flags mi - -allFlags :: MGrammar i a -> Options -allFlags gr = concatOptions [flags m | (_,m) <- modules gr] - -mapModules :: (ModInfo i a -> ModInfo i a) -> MGrammar i a -> MGrammar i a -mapModules f (MGrammar ms) = MGrammar (map (onSnd f) ms) - -data OpenSpec i = - OSimple i - | OQualif i i - deriving (Eq,Ord,Show) - -data ModuleStatus = - MSComplete - | MSIncomplete - deriving (Eq,Ord,Show) - -openedModule :: OpenSpec i -> i -openedModule o = case o of - OSimple m -> m - OQualif _ m -> m - --- | initial dependency list -depPathModule :: Ord i => ModInfo i a -> [OpenSpec i] -depPathModule m = fors m ++ exts m ++ opens m - where - fors m = - case mtype m of - MTConcrete i -> [OSimple i] - MTInstance i -> [OSimple i] - _ -> [] - exts m = map OSimple (extends m) - --- | all dependencies -allDepsModule :: Ord i => MGrammar i a -> ModInfo i a -> [OpenSpec i] -allDepsModule gr m = iterFix add os0 where - os0 = depPathModule m - add os = [m | o <- os, Just n <- [lookup (openedModule o) mods], - m <- depPathModule n] - mods = modules gr - --- | select just those modules that a given one depends on, including itself -partOfGrammar :: Ord i => MGrammar i a -> (i,ModInfo i a) -> MGrammar i a -partOfGrammar gr (i,m) = MGrammar [mo | mo@(j,_) <- mods, elem j modsFor] - where - mods = modules gr - modsFor = (i:) $ map openedModule $ allDepsModule gr m - --- | all modules that a module extends, directly or indirectly, without restricts -allExtends :: (Show i,Ord i) => MGrammar i a -> i -> [i] -allExtends gr i = - case lookupModule gr i of - Ok m -> case extends m of - [] -> [i] - is -> i : concatMap (allExtends gr) is - _ -> [] - --- | all modules that a module extends, directly or indirectly, with restricts -allExtendSpecs :: (Show i,Ord i) => MGrammar i a -> i -> [(i,MInclude i)] -allExtendSpecs gr i = - case lookupModule gr i of - Ok m -> case extend m of - [] -> [(i,MIAll)] - is -> (i,MIAll) : concatMap (allExtendSpecs gr . fst) is - _ -> [] - --- | this plus that an instance extends its interface -allExtendsPlus :: (Show i,Ord i) => MGrammar i a -> i -> [i] -allExtendsPlus gr i = - case lookupModule gr i of - Ok m -> i : concatMap (allExtendsPlus gr) (exts m) - _ -> [] - where - exts m = extends m ++ [j | MTInstance j <- [mtype m]] - --- | conversely: all modules that extend a given module, incl. instances of interface -allExtensions :: (Show i,Ord i) => MGrammar i a -> i -> [i] -allExtensions gr i = - case lookupModule gr i of - Ok m -> let es = exts i in es ++ concatMap (allExtensions gr) es - _ -> [] - where - exts i = [j | (j,m) <- mods, elem i (extends m) - || elem (MTInstance i) [mtype m]] - mods = modules gr - --- | initial search path: the nonqualified dependencies -searchPathModule :: Ord i => ModInfo i a -> [i] -searchPathModule m = [i | OSimple i <- depPathModule m] - --- | a new module can safely be added to the end, since nothing old can depend on it -addModule :: Ord i => - MGrammar i a -> i -> ModInfo i a -> MGrammar i a -addModule gr name mi = MGrammar $ (modules gr ++ [(name,mi)]) - -emptyMGrammar :: MGrammar i a -emptyMGrammar = MGrammar [] - -emptyModInfo :: ModInfo i a -emptyModInfo = ModInfo MTResource MSComplete noOptions [] Nothing [] [] emptyBinTree emptyBinTree - --- | we store the module type with the identifier -data IdentM i = IdentM { - identM :: i , - typeM :: ModuleType i - } - deriving (Eq,Ord,Show) - -abstractOfConcrete :: (Show i, Eq i) => MGrammar i a -> i -> Err i -abstractOfConcrete gr c = do - n <- lookupModule gr c - case mtype n of - MTConcrete a -> return a - _ -> Bad $ "expected concrete" +++ show c - -abstractModOfConcrete :: (Show i, Eq i) => - MGrammar i a -> i -> Err (ModInfo i a) -abstractModOfConcrete gr c = do - a <- abstractOfConcrete gr c - lookupModule gr a - - --- the canonical file name - ---- canonFileName s = prt s ++ ".gfc" - -lookupModule :: (Show i,Eq i) => MGrammar i a -> i -> Err (ModInfo i a) -lookupModule gr m = case lookup m (modules gr) of - Just i -> return i - _ -> Bad $ "unknown module" +++ show m - +++ "among" +++ unwords (map (show . fst) (modules gr)) ---- debug - -lookupModuleType :: (Show i,Eq i) => MGrammar i a -> i -> Err (ModuleType i) -lookupModuleType gr m = do - mi <- lookupModule gr m - return $ mtype mi - -lookupInfo :: (Show i, Ord i) => ModInfo i a -> i -> Err a -lookupInfo mo i = lookupTree show i (jments mo) - -lookupPosition :: (Show i, Ord i) => ModInfo i a -> i -> Err (String,(Int,Int)) -lookupPosition mo i = lookupTree show i (positions mo) - -ppPosition :: (Show i, Ord i) => ModInfo i a -> i -> Doc -ppPosition mo i = case lookupPosition mo i of - Ok (f,(b,e)) | b == e -> text "in" <+> text f <> text ", line" <+> int b - | otherwise -> text "in" <+> text f <> text ", lines" <+> int b <> text "-" <> int e - _ -> empty - -isModAbs :: ModInfo i a -> Bool -isModAbs m = case mtype m of - MTAbstract -> True ----- MTUnion t -> isModAbs t - _ -> False - -isModRes :: ModInfo i a -> Bool -isModRes m = case mtype m of - MTResource -> True - MTInterface -> True --- - MTInstance _ -> True - _ -> False - -isModCnc :: ModInfo i a -> Bool -isModCnc m = case mtype m of - MTConcrete _ -> True - _ -> False - -sameMType :: Eq i => ModuleType i -> ModuleType i -> Bool -sameMType m n = case (n,m) of - (MTConcrete _, MTConcrete _) -> True - - (MTInstance _, MTInstance _) -> True - (MTInstance _, MTResource) -> True - (MTInstance _, MTConcrete _) -> True - - (MTInterface, MTInstance _) -> True - (MTInterface, MTResource) -> True -- for reuse - (MTInterface, MTAbstract) -> True -- for reuse - (MTInterface, MTConcrete _) -> True -- for reuse - - (MTResource, MTInstance _) -> True - (MTResource, MTConcrete _) -> True -- for reuse - - _ -> m == n - --- | don't generate code for interfaces and for incomplete modules -isCompilableModule :: ModInfo i a -> Bool -isCompilableModule m = - case mtype m of - MTInterface -> False - _ -> mstatus m == MSComplete - --- | interface and "incomplete M" are not complete -isCompleteModule :: (Eq i) => ModInfo i a -> Bool -isCompleteModule m = mstatus m == MSComplete && mtype m /= MTInterface - - --- | all abstract modules sorted from least to most dependent -allAbstracts :: (Ord i, Show i) => MGrammar i a -> [i] -allAbstracts gr = - case topoTest [(i,extends m) | (i,m) <- modules gr, mtype m == MTAbstract] of - Left is -> is - Right cycles -> error $ "Cyclic abstract modules: " ++ show cycles - --- | the last abstract in dependency order (head of list) -greatestAbstract :: (Ord i, Show i) => MGrammar i a -> Maybe i -greatestAbstract gr = case allAbstracts gr of - [] -> Nothing - as -> return $ last as - --- | all resource modules -allResources :: MGrammar i a -> [i] -allResources gr = [i | (i,m) <- modules gr, isModRes m || isModCnc m] - --- | the greatest resource in dependency order -greatestResource :: MGrammar i a -> Maybe i -greatestResource gr = case allResources gr of - [] -> Nothing - a -> return $ head a ---- why not last as in Abstract? works though AR 24/5/2008 - --- | all concretes for a given abstract -allConcretes :: Eq i => MGrammar i a -> i -> [i] -allConcretes gr a = - [i | (i, m) <- modules gr, mtype m == MTConcrete a, isCompleteModule m] - --- | all concrete modules for any abstract -allConcreteModules :: Eq i => MGrammar i a -> [i] -allConcreteModules gr = - [i | (i, m) <- modules gr, MTConcrete _ <- [mtype m], isCompleteModule m] diff --git a/src/GF/Infra/Option.hs b/src/GF/Infra/Option.hs deleted file mode 100644 index dc15d1929..000000000 --- a/src/GF/Infra/Option.hs +++ /dev/null @@ -1,609 +0,0 @@ -module GF.Infra.Option - ( - -- * Option types - Options, - Flags(..), - Mode(..), Phase(..), Verbosity(..), Encoding(..), OutputFormat(..), - SISRFormat(..), Optimization(..), CFGTransform(..), HaskellOption(..), - Dump(..), Printer(..), Recomp(..), BuildParser(..), - -- * Option parsing - parseOptions, parseModuleOptions, fixRelativeLibPaths, - -- * Option pretty-printing - optionsGFO, - optionsPGF, - -- * Option manipulation - addOptions, concatOptions, noOptions, - modifyFlags, - helpMessage, - -- * Checking specific options - flag, cfgTransform, haskellOption, readOutputFormat, - isLexicalCat, encodings, - -- * Setting specific options - setOptimization, setCFGTransform, - -- * Convenience methods for checking options - verbAtLeast, dump - ) where - -import Control.Monad -import Data.Char (toLower) -import Data.List -import Data.Maybe -import GF.Infra.GetOpt ---import System.Console.GetOpt -import System.FilePath - -import GF.Data.ErrM - -import Data.Set (Set) -import qualified Data.Set as Set - - - - -usageHeader :: String -usageHeader = unlines - ["Usage: gfc [OPTIONS] [FILE [...]]", - "", - "How each FILE is handled depends on the file name suffix:", - "", - ".gf Normal or old GF source, will be compiled.", - ".gfo Compiled GF source, will be loaded as is.", - ".gfe Example-based GF source, will be converted to .gf and compiled.", - ".ebnf Extended BNF format, will be converted to .gf and compiled.", - ".cf Context-free (BNF) format, will be converted to .gf and compiled.", - "", - "If multiple FILES are given, they must be normal GF source, .gfo or .gfe files.", - "For the other input formats, only one file can be given.", - "", - "Command-line options:"] - - -helpMessage :: String -helpMessage = usageInfo usageHeader optDescr - - --- FIXME: do we really want multi-line errors? -errors :: [String] -> Err a -errors = fail . unlines - --- Types - -data Mode = ModeVersion | ModeHelp | ModeInteractive | ModeRun | ModeCompiler - deriving (Show,Eq,Ord) - -data Verbosity = Quiet | Normal | Verbose | Debug - deriving (Show,Eq,Ord,Enum,Bounded) - -data Phase = Preproc | Convert | Compile | Link - deriving (Show,Eq,Ord) - -data Encoding = UTF_8 | ISO_8859_1 | CP_1250 | CP_1251 | CP_1252 - deriving (Eq,Ord) - -data OutputFormat = FmtPGFPretty - | FmtPMCFGPretty - | FmtJavaScript - | FmtHaskell - | FmtProlog - | FmtProlog_Abs - | FmtBNF - | FmtEBNF - | FmtRegular - | FmtNoLR - | FmtSRGS_XML - | FmtSRGS_XML_NonRec - | FmtSRGS_ABNF - | FmtSRGS_ABNF_NonRec - | FmtJSGF - | FmtGSL - | FmtVoiceXML - | FmtSLF - | FmtRegExp - | FmtFA - deriving (Eq,Ord) - -data SISRFormat = - -- | SISR Working draft 1 April 2003 - -- <http://www.w3.org/TR/2003/WD-semantic-interpretation-20030401/> - SISR_WD20030401 - | SISR_1_0 - deriving (Show,Eq,Ord) - -data Optimization = OptStem | OptCSE | OptExpand | OptParametrize - deriving (Show,Eq,Ord) - -data CFGTransform = CFGNoLR - | CFGRegular - | CFGTopDownFilter - | CFGBottomUpFilter - | CFGStartCatOnly - | CFGMergeIdentical - | CFGRemoveCycles - deriving (Show,Eq,Ord) - -data HaskellOption = HaskellNoPrefix | HaskellGADT | HaskellLexical - deriving (Show,Eq,Ord) - -data Warning = WarnMissingLincat - deriving (Show,Eq,Ord) - -data Dump = DumpSource | DumpRebuild | DumpExtend | DumpRename | DumpTypeCheck | DumpRefresh | DumpOptimize | DumpCanon - deriving (Show,Eq,Ord) - --- | Pretty-printing options -data Printer = PrinterStrip -- ^ Remove name qualifiers. - deriving (Show,Eq,Ord) - -data Recomp = AlwaysRecomp | RecompIfNewer | NeverRecomp - deriving (Show,Eq,Ord) - -data BuildParser = BuildParser | DontBuildParser | BuildParserOnDemand - deriving (Show,Eq,Ord) - -data Flags = Flags { - optMode :: Mode, - optStopAfterPhase :: Phase, - optVerbosity :: Verbosity, - optProf :: Bool, - optShowCPUTime :: Bool, - optEmitGFO :: Bool, - optOutputFormats :: [OutputFormat], - optSISR :: Maybe SISRFormat, - optHaskellOptions :: Set HaskellOption, - optLexicalCats :: Set String, - optGFODir :: Maybe FilePath, - optOutputFile :: Maybe FilePath, - optOutputDir :: Maybe FilePath, - optGFLibPath :: Maybe FilePath, - optRecomp :: Recomp, - optPrinter :: [Printer], - optProb :: Bool, - optRetainResource :: Bool, - optName :: Maybe String, - optAbsName :: Maybe String, - optCncName :: Maybe String, - optResName :: Maybe String, - optPreprocessors :: [String], - optEncoding :: Encoding, - optOptimizations :: Set Optimization, - optCFGTransforms :: Set CFGTransform, - optLibraryPath :: [FilePath], - optStartCat :: Maybe String, - optSpeechLanguage :: Maybe String, - optLexer :: Maybe String, - optUnlexer :: Maybe String, - optErasing :: Bool, - optBuildParser :: BuildParser, - optWarnings :: [Warning], - optDump :: [Dump] - } - deriving (Show) - -newtype Options = Options (Flags -> Flags) - -instance Show Options where - show (Options o) = show (o defaultFlags) - --- Option parsing - -parseOptions :: [String] -- ^ list of string arguments - -> Err (Options, [FilePath]) -parseOptions args - | not (null errs) = errors errs - | otherwise = do opts <- liftM concatOptions $ sequence optss - return (opts, files) - where - (optss, files, errs) = getOpt RequireOrder optDescr args - -parseModuleOptions :: [String] -- ^ list of string arguments - -> Err Options -parseModuleOptions args = do - (opts,nonopts) <- parseOptions args - if null nonopts - then return opts - else errors $ map ("Non-option among module options: " ++) nonopts - -fixRelativeLibPaths curr_dir lib_dir (Options o) = Options (fixPathFlags . o) - where - fixPathFlags f@(Flags{optLibraryPath=path}) = f{optLibraryPath=concatMap (\dir -> [curr_dir </> dir, lib_dir </> dir]) path} - --- Showing options - --- | Pretty-print the options that are preserved in .gfo files. -optionsGFO :: Options -> [(String,String)] -optionsGFO opts = optionsPGF opts - ++ [("coding", show (flag optEncoding opts))] - --- | Pretty-print the options that are preserved in .pgf files. -optionsPGF :: Options -> [(String,String)] -optionsPGF opts = - maybe [] (\x -> [("language",x)]) (flag optSpeechLanguage opts) - ++ maybe [] (\x -> [("startcat",x)]) (flag optStartCat opts) - ++ (if flag optErasing opts then [("erasing","on")] else []) - ++ (if flag optBuildParser opts == BuildParserOnDemand then [("parser","ondemand")] else []) - --- Option manipulation - -flag :: (Flags -> a) -> Options -> a -flag f (Options o) = f (o defaultFlags) - -addOptions :: Options -> Options -> Options -addOptions (Options o1) (Options o2) = Options (o2 . o1) - -noOptions :: Options -noOptions = Options id - -concatOptions :: [Options] -> Options -concatOptions = foldr addOptions noOptions - -modifyFlags :: (Flags -> Flags) -> Options -modifyFlags = Options - --- Default options - -defaultFlags :: Flags -defaultFlags = Flags { - optMode = ModeInteractive, - optStopAfterPhase = Compile, - optVerbosity = Normal, - optProf = False, - optShowCPUTime = False, - optEmitGFO = True, - optOutputFormats = [], - optSISR = Nothing, - optHaskellOptions = Set.empty, - optLexicalCats = Set.empty, - optGFODir = Nothing, - optOutputFile = Nothing, - optOutputDir = Nothing, - optGFLibPath = Nothing, - optRecomp = RecompIfNewer, - optPrinter = [], - optProb = False, - optRetainResource = False, - - optName = Nothing, - optAbsName = Nothing, - optCncName = Nothing, - optResName = Nothing, - optPreprocessors = [], - optEncoding = ISO_8859_1, - optOptimizations = Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize], - optCFGTransforms = Set.fromList [CFGRemoveCycles, CFGBottomUpFilter, - CFGTopDownFilter, CFGMergeIdentical], - optLibraryPath = [], - optStartCat = Nothing, - optSpeechLanguage = Nothing, - optLexer = Nothing, - optUnlexer = Nothing, - optErasing = True, - optBuildParser = BuildParser, - optWarnings = [], - optDump = [] - } - --- Option descriptions - -optDescr :: [OptDescr (Err Options)] -optDescr = - [ - Option ['?','h'] ["help"] (NoArg (mode ModeHelp)) "Show help message.", - Option ['V'] ["version"] (NoArg (mode ModeVersion)) "Display GF version number.", - Option ['v'] ["verbose"] (OptArg verbosity "N") "Set verbosity (default 1). -v alone is the same as -v 2.", - Option ['q','s'] ["quiet"] (NoArg (verbosity (Just "0"))) "Quiet, same as -v 0.", - Option [] ["batch"] (NoArg (mode ModeCompiler)) "Run in batch compiler mode.", - Option [] ["interactive"] (NoArg (mode ModeInteractive)) "Run in interactive mode (default).", - Option [] ["run"] (NoArg (mode ModeRun)) "Run in interactive mode, showing output only (no other messages).", - Option ['E'] [] (NoArg (phase Preproc)) "Stop after preprocessing (with --preproc).", - Option ['C'] [] (NoArg (phase Convert)) "Stop after conversion to .gf.", - Option ['c'] [] (NoArg (phase Compile)) "Stop after compiling to .gfo (default) .", - Option [] ["make"] (NoArg (liftM2 addOptions (mode ModeCompiler) (phase Link))) "Build .pgf file and other output files and exit.", - Option [] ["prof"] (NoArg (prof True)) "Dump profiling information when compiling to PMCFG", - Option [] ["cpu"] (NoArg (cpu True)) "Show compilation CPU time statistics.", - Option [] ["no-cpu"] (NoArg (cpu False)) "Don't show compilation CPU time statistics (default).", - Option [] ["emit-gfo"] (NoArg (emitGFO True)) "Create .gfo files (default).", - Option [] ["no-emit-gfo"] (NoArg (emitGFO False)) "Do not create .gfo files.", - Option [] ["gfo-dir"] (ReqArg gfoDir "DIR") "Directory to put .gfo files in (default = '.').", - Option ['f'] ["output-format"] (ReqArg outFmt "FMT") - (unlines ["Output format. FMT can be one of:", - "Multiple concrete: pgf (default), gar, js, prolog, ...", - "Single concrete only: cf, bnf, lbnf, gsl, srgs_xml, srgs_abnf, ...", - "Abstract only: haskell, prolog_abs, ..."]), - Option [] ["sisr"] (ReqArg sisrFmt "FMT") - (unlines ["Include SISR tags in generated speech recognition grammars.", - "FMT can be one of: old, 1.0"]), - Option [] ["haskell"] (ReqArg hsOption "OPTION") - ("Turn on an optional feature when generating Haskell data types. OPTION = " - ++ concat (intersperse " | " (map fst haskellOptionNames))), - Option [] ["lexical"] (ReqArg lexicalCat "CAT[,CAT[...]]") - "Treat CAT as a lexical category.", - Option ['o'] ["output-file"] (ReqArg outFile "FILE") - "Save output in FILE (default is out.X, where X depends on output format.", - Option ['D'] ["output-dir"] (ReqArg outDir "DIR") - "Save output files (other than .gfo files) in DIR.", - Option [] ["gf-lib-path"] (ReqArg gfLibPath "DIR") - "Overides the value of GF_LIB_PATH.", - Option [] ["src","force-recomp"] (NoArg (recomp AlwaysRecomp)) - "Always recompile from source.", - Option [] ["gfo","recomp-if-newer"] (NoArg (recomp RecompIfNewer)) - "(default) Recompile from source if the source is newer than the .gfo file.", - Option [] ["gfo","no-recomp"] (NoArg (recomp NeverRecomp)) - "Never recompile from source, if there is already .gfo file.", - Option [] ["strip"] (NoArg (printer PrinterStrip)) - "Remove name qualifiers when pretty-printing.", - Option [] ["retain"] (NoArg (set $ \o -> o { optRetainResource = True })) "Retain opers.", - Option [] ["prob"] (NoArg (prob True)) "Read probabilities from '--# prob' pragmas.", - Option ['n'] ["name"] (ReqArg name "NAME") - (unlines ["Use NAME as the name of the output. This is used in the output file names, ", - "with suffixes depending on the formats, and, when relevant, ", - "internally in the output."]), - Option [] ["abs"] (ReqArg absName "NAME") - ("Use NAME as the name of the abstract syntax module generated from " - ++ "a grammar in GF 1 format."), - Option [] ["cnc"] (ReqArg cncName "NAME") - ("Use NAME as the name of the concrete syntax module generated from " - ++ "a grammar in GF 1 format."), - Option [] ["res"] (ReqArg resName "NAME") - ("Use NAME as the name of the resource module generated from " - ++ "a grammar in GF 1 format."), - Option ['i'] [] (ReqArg addLibDir "DIR") "Add DIR to the library search path.", - Option [] ["path"] (ReqArg setLibPath "DIR:DIR:...") "Set the library search path.", - Option [] ["preproc"] (ReqArg preproc "CMD") - (unlines ["Use CMD to preprocess input files.", - "Multiple preprocessors can be used by giving this option multiple times."]), - Option [] ["coding"] (ReqArg coding "ENCODING") - ("Character encoding of the source grammar, ENCODING = " - ++ concat (intersperse " | " (map fst encodings)) ++ "."), - Option [] ["erasing"] (onOff erasing False) "Generate erasing grammar (default off).", - Option [] ["parser"] (ReqArg buildParser "VALUE") "Build parser (default on). VALUE = on | off | ondemand", - Option [] ["startcat"] (ReqArg startcat "CAT") "Grammar start category.", - Option [] ["language"] (ReqArg language "LANG") "Set the speech language flag to LANG in the generated grammar.", - Option [] ["lexer"] (ReqArg lexer "LEXER") "Use lexer LEXER.", - Option [] ["unlexer"] (ReqArg unlexer "UNLEXER") "Use unlexer UNLEXER.", - Option [] ["optimize"] (ReqArg optimize "OPT") - "Select an optimization package. OPT = all | values | parametrize | none", - Option [] ["stem"] (onOff (toggleOptimize OptStem) True) "Perform stem-suffix analysis (default on).", - Option [] ["cse"] (onOff (toggleOptimize OptCSE) True) "Perform common sub-expression elimination (default on).", - Option [] ["cfg"] (ReqArg cfgTransform "TRANS") "Enable or disable specific CFG transformations. TRANS = merge, no-merge, bottomup, no-bottomup, ...", - dumpOption "source" DumpSource, - dumpOption "rebuild" DumpRebuild, - dumpOption "extend" DumpExtend, - dumpOption "rename" DumpRename, - dumpOption "tc" DumpTypeCheck, - dumpOption "refresh" DumpRefresh, - dumpOption "opt" DumpOptimize, - dumpOption "canon" DumpCanon - - ] - where phase x = set $ \o -> o { optStopAfterPhase = x } - mode x = set $ \o -> o { optMode = x } - verbosity mv = case mv of - Nothing -> set $ \o -> o { optVerbosity = Verbose } - Just v -> case readMaybe v >>= toEnumBounded of - Just i -> set $ \o -> o { optVerbosity = i } - Nothing -> fail $ "Bad verbosity: " ++ show v - prof x = set $ \o -> o { optProf = x } - cpu x = set $ \o -> o { optShowCPUTime = x } - emitGFO x = set $ \o -> o { optEmitGFO = x } - gfoDir x = set $ \o -> o { optGFODir = Just x } - outFmt x = readOutputFormat x >>= \f -> - set $ \o -> o { optOutputFormats = optOutputFormats o ++ [f] } - sisrFmt x = case x of - "old" -> set $ \o -> o { optSISR = Just SISR_WD20030401 } - "1.0" -> set $ \o -> o { optSISR = Just SISR_1_0 } - _ -> fail $ "Unknown SISR format: " ++ show x - hsOption x = case lookup x haskellOptionNames of - Just p -> set $ \o -> o { optHaskellOptions = Set.insert p (optHaskellOptions o) } - Nothing -> fail $ "Unknown Haskell option: " ++ x - ++ " Known: " ++ show (map fst haskellOptionNames) - lexicalCat x = set $ \o -> o { optLexicalCats = foldr Set.insert (optLexicalCats o) (splitBy (==',') x) } - outFile x = set $ \o -> o { optOutputFile = Just x } - outDir x = set $ \o -> o { optOutputDir = Just x } - gfLibPath x = set $ \o -> o { optGFLibPath = Just x } - recomp x = set $ \o -> o { optRecomp = x } - printer x = set $ \o -> o { optPrinter = x : optPrinter o } - prob x = set $ \o -> o { optProb = x } - - name x = set $ \o -> o { optName = Just x } - absName x = set $ \o -> o { optAbsName = Just x } - cncName x = set $ \o -> o { optCncName = Just x } - resName x = set $ \o -> o { optResName = Just x } - addLibDir x = set $ \o -> o { optLibraryPath = x:optLibraryPath o } - setLibPath x = set $ \o -> o { optLibraryPath = splitInModuleSearchPath x } - preproc x = set $ \o -> o { optPreprocessors = optPreprocessors o ++ [x] } - coding x = case lookup x encodings of - Just c -> set $ \o -> o { optEncoding = c } - Nothing -> fail $ "Unknown character encoding: " ++ x - erasing x = set $ \o -> o { optErasing = x } - buildParser x = do v <- case x of - "on" -> return BuildParser - "off" -> return DontBuildParser - "ondemand" -> return BuildParserOnDemand - set $ \o -> o { optBuildParser = v } - startcat x = set $ \o -> o { optStartCat = Just x } - language x = set $ \o -> o { optSpeechLanguage = Just x } - lexer x = set $ \o -> o { optLexer = Just x } - unlexer x = set $ \o -> o { optUnlexer = Just x } - - optimize x = case lookup x optimizationPackages of - Just p -> set $ \o -> o { optOptimizations = p } - Nothing -> fail $ "Unknown optimization package: " ++ x - - toggleOptimize x b = set $ setOptimization' x b - - cfgTransform x = let (x', b) = case x of - 'n':'o':'-':rest -> (rest, False) - _ -> (x, True) - in case lookup x' cfgTransformNames of - Just t -> set $ setCFGTransform' t b - Nothing -> fail $ "Unknown CFG transformation: " ++ x' - ++ " Known: " ++ show (map fst cfgTransformNames) - - dumpOption s d = Option [] ["dump-"++s] (NoArg (set $ \o -> o { optDump = d:optDump o})) ("Dump output of the " ++ s ++ " phase.") - - set = return . Options - -outputFormats :: [(String,OutputFormat)] -outputFormats = - [("pgf_pretty", FmtPGFPretty), - ("pmcfg_pretty", FmtPMCFGPretty), - ("js", FmtJavaScript), - ("haskell", FmtHaskell), - ("prolog", FmtProlog), - ("prolog_abs", FmtProlog_Abs), - ("bnf", FmtBNF), - ("ebnf", FmtEBNF), - ("regular", FmtRegular), - ("nolr", FmtNoLR), - ("srgs_xml", FmtSRGS_XML), - ("srgs_xml_nonrec", FmtSRGS_XML_NonRec), - ("srgs_abnf", FmtSRGS_ABNF), - ("srgs_abnf_nonrec", FmtSRGS_ABNF_NonRec), - ("jsgf", FmtJSGF), - ("gsl", FmtGSL), - ("vxml", FmtVoiceXML), - ("slf", FmtSLF), - ("regexp", FmtRegExp), - ("fa", FmtFA)] - -instance Show OutputFormat where - show = lookupShow outputFormats - -instance Read OutputFormat where - readsPrec = lookupReadsPrec outputFormats - -optimizationPackages :: [(String, Set Optimization)] -optimizationPackages = - [("all", Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize]), - ("values", Set.fromList [OptStem,OptCSE,OptExpand]), - ("noexpand", Set.fromList [OptStem,OptCSE]), - - -- deprecated - ("all_subs", Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize]), - ("parametrize", Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize]), - ("none", Set.fromList [OptStem,OptCSE,OptExpand]) - ] - -cfgTransformNames :: [(String, CFGTransform)] -cfgTransformNames = - [("nolr", CFGNoLR), - ("regular", CFGRegular), - ("topdown", CFGTopDownFilter), - ("bottomup", CFGBottomUpFilter), - ("startcatonly", CFGStartCatOnly), - ("merge", CFGMergeIdentical), - ("removecycles", CFGRemoveCycles)] - -haskellOptionNames :: [(String, HaskellOption)] -haskellOptionNames = - [("noprefix", HaskellNoPrefix), - ("gadt", HaskellGADT), - ("lexical", HaskellLexical)] - -encodings :: [(String,Encoding)] -encodings = - [("utf8", UTF_8), - ("cp1250", CP_1250), - ("cp1251", CP_1251), - ("cp1252", CP_1252), - ("latin1", ISO_8859_1) - ] - -instance Show Encoding where - show = lookupShow encodings - -lookupShow :: Eq a => [(String,a)] -> a -> String -lookupShow xs z = fromMaybe "lookupShow" $ lookup z [(y,x) | (x,y) <- xs] - -lookupReadsPrec :: [(String,a)] -> Int -> ReadS a -lookupReadsPrec xs _ s = [(z,rest) | (x,rest) <- lex s, (y,z) <- xs, y == x] - -onOff :: Monad m => (Bool -> m a) -> Bool -> ArgDescr (m a) -onOff f def = OptArg g "[on,off]" - where g ma = maybe (return def) readOnOff ma >>= f - readOnOff x = case map toLower x of - "on" -> return True - "off" -> return False - _ -> fail $ "Expected [on,off], got: " ++ show x - -readOutputFormat :: Monad m => String -> m OutputFormat -readOutputFormat s = - maybe (fail $ "Unknown output format: " ++ show s) return $ lookup s outputFormats - --- FIXME: this is a copy of the function in GF.Devel.UseIO. -splitInModuleSearchPath :: String -> [FilePath] -splitInModuleSearchPath s = case break isPathSep s of - (f,_:cs) -> f : splitInModuleSearchPath cs - (f,_) -> [f] - where - isPathSep :: Char -> Bool - isPathSep c = c == ':' || c == ';' - --- --- * Convenience functions for checking options --- - -verbAtLeast :: Options -> Verbosity -> Bool -verbAtLeast opts v = flag optVerbosity opts >= v - -dump :: Options -> Dump -> Bool -dump opts d = flag ((d `elem`) . optDump) opts - -cfgTransform :: Options -> CFGTransform -> Bool -cfgTransform opts t = Set.member t (flag optCFGTransforms opts) - -haskellOption :: Options -> HaskellOption -> Bool -haskellOption opts o = Set.member o (flag optHaskellOptions opts) - -isLexicalCat :: Options -> String -> Bool -isLexicalCat opts c = Set.member c (flag optLexicalCats opts) - --- --- * Convenience functions for setting options --- - -setOptimization :: Optimization -> Bool -> Options -setOptimization o b = modifyFlags (setOptimization' o b) - -setOptimization' :: Optimization -> Bool -> Flags -> Flags -setOptimization' o b f = f { optOptimizations = toggle o b (optOptimizations f)} - -setCFGTransform :: CFGTransform -> Bool -> Options -setCFGTransform t b = modifyFlags (setCFGTransform' t b) - -setCFGTransform' :: CFGTransform -> Bool -> Flags -> Flags -setCFGTransform' t b f = f { optCFGTransforms = toggle t b (optCFGTransforms f) } - -toggle :: Ord a => a -> Bool -> Set a -> Set a -toggle o True = Set.insert o -toggle o False = Set.delete o - --- --- * General utilities --- - -readMaybe :: Read a => String -> Maybe a -readMaybe s = case reads s of - [(x,"")] -> Just x - _ -> Nothing - -toEnumBounded :: (Bounded a, Enum a, Ord a) => Int -> Maybe a -toEnumBounded i = let mi = minBound - ma = maxBound `asTypeOf` mi - in if i >= fromEnum mi && i <= fromEnum ma - then Just (toEnum i `asTypeOf` mi) - else Nothing - -splitBy :: (a -> Bool) -> [a] -> [[a]] -splitBy _ [] = [] -splitBy p s = case break p s of - (l, _ : t@(_ : _)) -> l : splitBy p t - (l, _) -> [l] - -instance Functor OptDescr where - fmap f (Option cs ss d s) = Option cs ss (fmap f d) s - -instance Functor ArgDescr where - fmap f (NoArg x) = NoArg (f x) - fmap f (ReqArg g s) = ReqArg (f . g) s - fmap f (OptArg g s) = OptArg (f . g) s diff --git a/src/GF/Infra/UseIO.hs b/src/GF/Infra/UseIO.hs deleted file mode 100644 index bb1a75b6e..000000000 --- a/src/GF/Infra/UseIO.hs +++ /dev/null @@ -1,186 +0,0 @@ -{-# OPTIONS -cpp #-} ----------------------------------------------------------------------- --- | --- Module : UseIO --- Maintainer : AR --- Stability : (stable) --- Portability : (portable) --- --- > CVS $Date: 2005/08/08 09:01:25 $ --- > CVS $Author: peb $ --- > CVS $Revision: 1.17 $ --- --- (Description of the module) ------------------------------------------------------------------------------ - -module GF.Infra.UseIO where - -import GF.Data.Operations -import GF.Infra.Option -import Paths_gf(getDataDir) - -import System.Directory -import System.FilePath -import System.IO -import System.IO.Error -import System.Environment -import System.Exit -import System.CPUTime -import Text.Printf -import Control.Monad -import Control.Exception(evaluate) -import qualified Data.ByteString.Char8 as BS -import Data.List(nub) - -putShow' :: Show a => (c -> a) -> c -> IO () -putShow' f = putStrLn . show . length . show . f - -putIfVerb :: Options -> String -> IO () -putIfVerb opts msg = - when (verbAtLeast opts Verbose) $ putStrLn msg - -putIfVerbW :: Options -> String -> IO () -putIfVerbW opts msg = - when (verbAtLeast opts Verbose) $ putStr (' ' : msg) - -errOptIO :: Options -> a -> Err a -> IO a -errOptIO os e m = case m of - Ok x -> return x - Bad k -> do - putIfVerb os k - return e - -type FileName = String -type InitPath = String -type FullPath = String - -gfLibraryPath = "GF_LIB_PATH" -gfGrammarPathVar = "GF_GRAMMAR_PATH" - -getLibraryDirectory :: Options -> IO FilePath -getLibraryDirectory opts = - case flag optGFLibPath opts of - Just path -> return path - Nothing -> catch - (getEnv gfLibraryPath) - (\ex -> getDataDir >>= \path -> return (path </> "lib")) - -getGrammarPath :: FilePath -> IO [FilePath] -getGrammarPath lib_dir = do - catch (fmap splitSearchPath $ getEnv gfGrammarPathVar) (\_ -> return [lib_dir </> "prelude"]) -- e.g. GF_GRAMMAR_PATH - --- | extends the search path with the --- 'gfLibraryPath' and 'gfGrammarPathVar' --- environment variables. Returns only existing paths. -extendPathEnv :: Options -> IO [FilePath] -extendPathEnv opts = do - opt_path <- return $ flag optLibraryPath opts -- e.g. paths given as options - lib_dir <- getLibraryDirectory opts -- e.g. GF_LIB_PATH - grm_path <- getGrammarPath lib_dir -- e.g. GF_GRAMMAR_PATH - let paths = opt_path ++ [lib_dir] ++ grm_path - ps <- liftM concat $ mapM allSubdirs paths - mapM canonicalizePath ps - where - allSubdirs :: FilePath -> IO [FilePath] - allSubdirs [] = return [[]] - allSubdirs p = case last p of - '*' -> do let path = init p - fs <- getSubdirs path - return [path </> f | f <- fs] - _ -> do exists <- doesDirectoryExist p - if exists - then return [p] - else return [] - -getSubdirs :: FilePath -> IO [FilePath] -getSubdirs dir = do - fs <- catch (getDirectoryContents dir) (const $ return []) - foldM (\fs f -> do let fpath = dir </> f - p <- getPermissions fpath - if searchable p && not (take 1 f==".") - then return (fpath:fs) - else return fs ) [] fs - -justModuleName :: FilePath -> String -justModuleName = dropExtension . takeFileName - -splitInModuleSearchPath :: String -> [FilePath] -splitInModuleSearchPath s = case break isPathSep s of - (f,_:cs) -> f : splitInModuleSearchPath cs - (f,_) -> [f] - where - isPathSep :: Char -> Bool - isPathSep c = c == ':' || c == ';' - --- - -putStrFlush :: String -> IO () -putStrFlush s = putStr s >> hFlush stdout - -putStrLnFlush :: String -> IO () -putStrLnFlush s = putStrLn s >> hFlush stdout - --- * IO monad with error; adapted from state monad - -newtype IOE a = IOE (IO (Err a)) - -appIOE :: IOE a -> IO (Err a) -appIOE (IOE iea) = iea - -ioe :: IO (Err a) -> IOE a -ioe = IOE - -ioeIO :: IO a -> IOE a -ioeIO io = ioe (io >>= return . return) - -ioeErr :: Err a -> IOE a -ioeErr = ioe . return - -instance Monad IOE where - return a = ioe (return (return a)) - IOE c >>= f = IOE $ do - x <- c -- Err a - appIOE $ err ioeBad f x -- f :: a -> IOE a - -ioeBad :: String -> IOE a -ioeBad = ioe . return . Bad - -useIOE :: a -> IOE a -> IO a -useIOE a ioe = appIOE ioe >>= err (\s -> putStrLn s >> return a) return - -foldIOE :: (a -> b -> IOE a) -> a -> [b] -> IOE (a, Maybe String) -foldIOE f s xs = case xs of - [] -> return (s,Nothing) - x:xx -> do - ev <- ioeIO $ appIOE (f s x) - case ev of - Ok v -> foldIOE f v xx - Bad m -> return $ (s, Just m) - -dieIOE :: IOE a -> IO a -dieIOE x = appIOE x >>= err die return - -die :: String -> IO a -die s = do hPutStrLn stderr s - exitFailure - -putStrLnE :: String -> IOE () -putStrLnE = ioeIO . putStrLnFlush - -putStrE :: String -> IOE () -putStrE = ioeIO . putStrFlush - -putPointE :: Verbosity -> Options -> String -> IOE a -> IOE a -putPointE v opts msg act = do - when (verbAtLeast opts v) $ ioeIO $ putStrFlush msg - - t1 <- ioeIO $ getCPUTime - a <- act >>= ioeIO . evaluate - t2 <- ioeIO $ getCPUTime - - if flag optShowCPUTime opts - then do let msec = (t2 - t1) `div` 1000000000 - putStrLnE (printf " %5d msec" msec) - else when (verbAtLeast opts v) $ putStrLnE "" - - return a |
