1{-# LANGUAGE DataKinds #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE RecordWildCards #-}
4{-# LANGUAGE ScopedTypeVariables #-}
5{-# LANGUAGE TupleSections #-}
9import Control.Applicative
11import Control.Monad.Writer.Strict
13import qualified Data.Aeson as A
14import Data.Bool (bool)
15import qualified Data.ByteString.Lazy as B
16import qualified Data.ByteString.UTF8 as BU8
17import qualified Data.Map as M
18import Data.Text (Text)
19import Data.Version (showVersion)
21import qualified Language.PureScript as P
22import Language.PureScript.Errors.JSON
23import Language.PureScript.Make
25import Options.Applicative as Opts
27import qualified Paths_purescript as Paths
29import qualified System.Console.ANSI as ANSI
30import System.Exit (exitSuccess, exitFailure)
31import System.FilePath.Glob (glob)
32import System.IO (hSetEncoding, hPutStrLn, stdout, stderr, utf8)
33import System.IO.UTF8 (readUTF8FileT)
35data PSCMakeOptions = PSCMakeOptions
36 { pscmInput :: [FilePath]
37 , pscmOutputDir :: FilePath
38 , pscmOpts :: P.Options
39 , pscmUsePrefix :: Bool
40 , pscmJSONErrors :: Bool
43-- | Argumnets: verbose, use JSON, warnings, errors
44printWarningsAndErrors :: Bool -> Bool -> P.MultipleErrors -> Either P.MultipleErrors a -> IO ()
45printWarningsAndErrors verbose False warnings errors = do
46 cc <- bool Nothing (Just P.defaultCodeColor) <$> ANSI.hSupportsANSI stderr
47 let ppeOpts = P.defaultPPEOptions { P.ppeCodeColor = cc, P.ppeFull = verbose }
48 when (P.nonEmpty warnings) $
49 hPutStrLn stderr (P.prettyPrintMultipleWarnings ppeOpts warnings)
52 hPutStrLn stderr (P.prettyPrintMultipleErrors ppeOpts errs)
55printWarningsAndErrors verbose True warnings errors = do
56 hPutStrLn stderr . BU8.toString . B.toStrict . A.encode $
57 JSONResult (toJSONErrors verbose P.Warning warnings)
58 (either (toJSONErrors verbose P.Error) (const []) errors)
59 either (const exitFailure) (const (return ())) errors
61compile :: PSCMakeOptions -> IO ()
62compile PSCMakeOptions{..} = do
63 input <- globWarningOnMisses (unless pscmJSONErrors . warnFileTypeNotFound) pscmInput
64 when (null input && not pscmJSONErrors) $ do
65 hPutStrLn stderr "psc: No input files."
67 moduleFiles <- readInput input
68 (makeErrors, makeWarnings) <- runMake pscmOpts $ do
69 ms <- P.parseModulesFromFiles id moduleFiles
70 let filePathMap = M.fromList $ map (\(fp, P.Module _ _ mn _ _) -> (mn, Right fp)) ms
71 foreigns <- inferForeignModules filePathMap
72 let makeActions = buildMakeActions pscmOutputDir filePathMap foreigns pscmUsePrefix
73 P.make makeActions (map snd ms)
74 printWarningsAndErrors (P.optionsVerboseErrors pscmOpts) pscmJSONErrors makeWarnings makeErrors
77warnFileTypeNotFound :: String -> IO ()
78warnFileTypeNotFound = hPutStrLn stderr . ("psc: No files found using pattern: " ++)
80globWarningOnMisses :: (String -> IO ()) -> [FilePath] -> IO [FilePath]
81globWarningOnMisses warn = concatMapM globWithWarning
83 globWithWarning pattern' = do
84 paths <- glob pattern'
85 when (null paths) $ warn pattern'
87 concatMapM f = fmap concat . mapM f
89readInput :: [FilePath] -> IO [(FilePath, Text)]
90readInput inputFiles = forM inputFiles $ \inFile -> (inFile, ) <$> readUTF8FileT inFile
92inputFile :: Parser FilePath
93inputFile = strArgument $
95 <> help "The input .purs file(s)"
97outputDirectory :: Parser FilePath
98outputDirectory = strOption $
101 <> Opts.value "output"
103 <> help "The output directory"
108 <> help "Disable tail call optimizations"
110noMagicDo :: Parser Bool
113 <> help "Disable the optimization that overloads the do keyword to generate efficient code specifically for the Eff monad"
118 <> help "Skip the optimization phase"
120comments :: Parser Bool
124 <> help "Include comments in the generated code"
126verboseErrors :: Parser Bool
127verboseErrors = switch $
129 <> long "verbose-errors"
130 <> help "Display verbose error messages"
132noPrefix :: Parser Bool
136 <> help "Do not include comment header"
138jsonErrors :: Parser Bool
141 <> help "Print errors to stderr as JSON"
142sourceMaps :: Parser Bool
145 <> help "Generate source maps"
147dumpCoreFn :: Parser Bool
150 <> help "Dump the (functional) core representation of the compiled code at output/*/corefn.json"
153options :: Parser P.Options
154options = P.Options <$> noTco
159 <*> (not <$> comments)
163pscMakeOptions :: Parser PSCMakeOptions
164pscMakeOptions = PSCMakeOptions <$> many inputFile
167 <*> (not <$> noPrefix)
172 hSetEncoding stdout utf8
173 hSetEncoding stderr utf8
174 execParser opts >>= compile
176 opts = info (version <*> helper <*> pscMakeOptions) infoModList
177 infoModList = fullDesc <> headerInfo <> footerInfo
178 headerInfo = header "psc - Compiles PureScript to Javascript"
179 footerInfo = footer $ "psc " ++ showVersion Paths.version
181 version :: Parser (a -> a)
182 version = abortOption (InfoMsg (showVersion Paths.version)) $ long "version" <> help "Show the version number" <> hidden
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list