module BNFC.Backend.Haskell.HsOpts where

import BNFC.Utils
import BNFC.Options
import System.FilePath (pathSeparator, (<.>))
import Data.List (intercalate)
import Data.Maybe (catMaybes)

type Options = SharedOptions

absFile, absFileM,
 alexFile, alexFileHs, alexFileM,
 composOpFile, composOpFileM,
 happyFile, happyFileHs, happyFileM,
 errFile, errFileM,
 templateFile, templateFileM,
 printerFile, printerFileM,
 layoutFile, layoutFileM,
 tFile, tFileExe :: Options -> String
absFile :: Options -> [Char]
absFile       = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
withLang [Char]
"Abs" [Char]
"hs"
absFileM :: Options -> [Char]
absFileM      = (Options -> [Char] -> [Char]) -> [Char] -> Options -> [Char]
mkMod  Options -> [Char] -> [Char]
withLang [Char]
"Abs"
alexFile :: Options -> [Char]
alexFile      = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
withLang [Char]
"Lex" [Char]
"x"
alexFileHs :: Options -> [Char]
alexFileHs    = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
withLang [Char]
"Lex" [Char]
"hs"
alexFileM :: Options -> [Char]
alexFileM     = (Options -> [Char] -> [Char]) -> [Char] -> Options -> [Char]
mkMod  Options -> [Char] -> [Char]
withLang [Char]
"Lex"
happyFile :: Options -> [Char]
happyFile     = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
withLang [Char]
"Par" [Char]
"y"
happyFileHs :: Options -> [Char]
happyFileHs   = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
withLang [Char]
"Par" [Char]
"hs"
happyFileM :: Options -> [Char]
happyFileM    = (Options -> [Char] -> [Char]) -> [Char] -> Options -> [Char]
mkMod  Options -> [Char] -> [Char]
withLang [Char]
"Par"
txtFile :: Options -> [Char]
txtFile       = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
withLang [Char]
"Doc" [Char]
"txt"
templateFile :: Options -> [Char]
templateFile  = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
withLang [Char]
"Skel" [Char]
"hs"
templateFileM :: Options -> [Char]
templateFileM = (Options -> [Char] -> [Char]) -> [Char] -> Options -> [Char]
mkMod  Options -> [Char] -> [Char]
withLang [Char]
"Skel"
printerFile :: Options -> [Char]
printerFile   = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
withLang [Char]
"Print" [Char]
"hs"
printerFileM :: Options -> [Char]
printerFileM  = (Options -> [Char] -> [Char]) -> [Char] -> Options -> [Char]
mkMod  Options -> [Char] -> [Char]
withLang [Char]
"Print"
tFile :: Options -> [Char]
tFile         = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
withLang [Char]
"Test" [Char]
"hs"
tFileExe :: Options -> [Char]
tFileExe      = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
withLang [Char]
"Test" [Char]
""
errFile :: Options -> [Char]
errFile       = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
noLang   [Char]
"ErrM" [Char]
"hs"
errFileM :: Options -> [Char]
errFileM      = (Options -> [Char] -> [Char]) -> [Char] -> Options -> [Char]
mkMod  Options -> [Char] -> [Char]
noLang   [Char]
"ErrM"
layoutFileM :: Options -> [Char]
layoutFileM   = (Options -> [Char] -> [Char]) -> [Char] -> Options -> [Char]
mkMod  Options -> [Char] -> [Char]
withLang [Char]
"Layout"
layoutFile :: Options -> [Char]
layoutFile    = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
withLang [Char]
"Layout" [Char]
"hs"
xmlFile :: Options -> [Char]
xmlFile       = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
withLang [Char]
"XML" [Char]
"hs"
xmlFileM :: Options -> [Char]
xmlFileM      = (Options -> [Char] -> [Char]) -> [Char] -> Options -> [Char]
mkMod  Options -> [Char] -> [Char]
withLang [Char]
"XML"
composOpFile :: Options -> [Char]
composOpFile  = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
noLang   [Char]
"ComposOp" [Char]
"hs"
composOpFileM :: Options -> [Char]
composOpFileM = (Options -> [Char] -> [Char]) -> [Char] -> Options -> [Char]
mkMod  Options -> [Char] -> [Char]
noLang   [Char]
"ComposOp"

-- Files created by the Agda backend

agdaASTFile
  , agdaASTFileM
  , agdaParserFile
  , agdaParserFileM
  , agdaLibFile
  , agdaLibFileM
  , agdaMainFile
  , agdaMainFileM
 :: Options -> String
agdaASTFile :: Options -> [Char]
agdaASTFile     = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
withLang [Char]
"AST" [Char]
"agda"
agdaASTFileM :: Options -> [Char]
agdaASTFileM    = (Options -> [Char] -> [Char]) -> [Char] -> Options -> [Char]
mkMod  Options -> [Char] -> [Char]
withLang [Char]
"AST"
agdaParserFile :: Options -> [Char]
agdaParserFile  = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
withLang [Char]
"Parser" [Char]
"agda"
agdaParserFileM :: Options -> [Char]
agdaParserFileM = (Options -> [Char] -> [Char]) -> [Char] -> Options -> [Char]
mkMod  Options -> [Char] -> [Char]
withLang [Char]
"Parser"
agdaLibFile :: Options -> [Char]
agdaLibFile     = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
noLang   [Char]
"IOLib" [Char]
"agda"
agdaLibFileM :: Options -> [Char]
agdaLibFileM    = (Options -> [Char] -> [Char]) -> [Char] -> Options -> [Char]
mkMod  Options -> [Char] -> [Char]
noLang   [Char]
"IOLib"
agdaMainFile :: Options -> [Char]
agdaMainFile    = (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
noLang   [Char]
"Main" [Char]
"agda"
agdaMainFileM :: Options -> [Char]
agdaMainFileM   = (Options -> [Char] -> [Char]) -> [Char] -> Options -> [Char]
mkMod  Options -> [Char] -> [Char]
noLang   [Char]
"Main"


noLang :: Options -> String -> String
noLang :: Options -> [Char] -> [Char]
noLang Options
_ [Char]
name = [Char]
name

withLang :: Options -> String -> String
withLang :: Options -> [Char] -> [Char]
withLang Options
opts [Char]
name = [Char]
name [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [[Char]] -> NameStyle -> [Char] -> [Char]
mkName [] NameStyle
CamelCase (Options -> [Char]
lang Options
opts)

pkgToDir :: String -> FilePath
pkgToDir :: [Char] -> [Char]
pkgToDir [Char]
s = Char -> Char -> [Char] -> [Char]
forall a. Eq a => a -> a -> [a] -> [a]
replace Char
'.' Char
pathSeparator [Char]
s


-- |
-- >>> mkMod withLang "Abstract" defaultOptions { lang = "abc" }
-- "AbstractAbc"
-- >>> mkMod noLang "Abstract" defaultOptions { lang = "abc" }
-- "Abstract"
-- >>> mkMod withLang "Abstract" defaultOptions { lang = "abc", inPackage = Just "A.B.C" }
-- "A.B.C.AbstractAbc"
-- >>> mkMod withLang "Abstract" defaultOptions { lang = "abc", inDir = True }
-- "Abc.Abstract"
-- >>> mkMod withLang "Abstract" defaultOptions { lang = "abc", inDir = True, inPackage = Just "A.B.C" }
-- "A.B.C.Abc.Abstract"
mkMod :: (Options -> String -> String) -> String -> Options -> String
mkMod :: (Options -> [Char] -> [Char]) -> [Char] -> Options -> [Char]
mkMod Options -> [Char] -> [Char]
addLang [Char]
name Options
opts = Options -> [Char]
mkNamespace Options
opts [Char] -> [Char] -> [Char]
<.> [Char]
mod
  where
    [] <.> :: [Char] -> [Char] -> [Char]
<.> [Char]
s = [Char]
s
    [Char]
s1 <.> [Char]
s2 = [Char]
s1 [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"." [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
s2
    mod :: [Char]
mod | Options -> Bool
inDir Options
opts = [Char]
name
        | Bool
otherwise  = Options -> [Char] -> [Char]
addLang Options
opts [Char]
name
-- |
-- >>> mkFile withLang "Abstract" "hs" defaultOptions { lang = "abc" }
-- "AbstractAbc.hs"
-- >>> mkFile noLang "Abstract" "hs" defaultOptions { lang = "abc" }
-- "Abstract.hs"
-- >>> mkFile withLang "Abstract" "" defaultOptions { lang = "abc" }
-- "AbstractAbc"
-- >>> mkFile noLang "Abstract" "" defaultOptions { lang = "abc" }
-- "Abstract"
-- >>> mkFile withLang "Abstract" "hs" defaultOptions { lang = "abc", inDir = True }
-- "Abc/Abstract.hs"
-- >>> mkFile withLang "Abstract" "hs" defaultOptions { lang = "abc", inDir = True, inPackage = Just "A.B.C" }
-- "A/B/C/Abc/Abstract.hs"
mkFile :: (Options -> String -> String) -> String -> String -> Options -> FilePath
mkFile :: (Options -> [Char] -> [Char])
-> [Char] -> [Char] -> Options -> [Char]
mkFile Options -> [Char] -> [Char]
addLang [Char]
name [Char]
ext Options
opts = [Char] -> [Char]
pkgToDir ((Options -> [Char] -> [Char]) -> [Char] -> Options -> [Char]
mkMod Options -> [Char] -> [Char]
addLang [Char]
name Options
opts) [Char] -> [Char] -> [Char]
<.> [Char]
ext


-- | Determine the modules' namespace
--
-- >>> mkNamespace defaultOptions
-- ""
-- >>> mkNamespace defaultOptions { lang = "Bla", inDir = True }
-- "Bla"
-- >>> mkNamespace defaultOptions { inPackage = Just "My.Cool.Package" }
-- "My.Cool.Package"
-- >>> mkNamespace defaultOptions { lang = "bla_bla", inDir = True }
-- "BlaBla"
-- >>> mkNamespace defaultOptions { lang = "bla", inDir = True, inPackage = Just "P"}
-- "P.Bla"
mkNamespace :: Options -> FilePath
mkNamespace :: Options -> [Char]
mkNamespace Options
opts = [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"." ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ [Maybe [Char]] -> [[Char]]
forall a. [Maybe a] -> [a]
catMaybes [Options -> Maybe [Char]
inPackage Options
opts, Maybe [Char]
dir]
  where
    dir :: Maybe [Char]
dir | Options -> Bool
inDir Options
opts = [Char] -> Maybe [Char]
forall a. a -> Maybe a
Just ([[Char]] -> NameStyle -> [Char] -> [Char]
mkName [] NameStyle
CamelCase (Options -> [Char]
lang Options
opts))
        | Bool
otherwise  = Maybe [Char]
forall a. Maybe a
Nothing

-- | Determine the directory corresponding to the modules' namespace
--
-- >>> codeDir defaultOptions
-- ""
-- >>> codeDir defaultOptions { lang = "Bla", inDir = True }
-- "Bla"
-- >>> codeDir defaultOptions { inPackage = Just "My.Cool.Package" }
-- "My/Cool/Package"
-- >>> codeDir defaultOptions { lang = "bla_bla", inDir = True }
-- "BlaBla"
-- >>> codeDir defaultOptions { lang = "bla", inDir = True, inPackage = Just "P"}
-- "P/Bla"
codeDir :: Options -> FilePath
codeDir :: Options -> [Char]
codeDir = [Char] -> [Char]
pkgToDir ([Char] -> [Char]) -> (Options -> [Char]) -> Options -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Options -> [Char]
mkNamespace