nirum-0.3.0: src/Nirum/Targets.hs
{-# LANGUAGE QuasiQuotes, ScopedTypeVariables, TemplateHaskell #-}
module Nirum.Targets ( BuildError (CompileError, PackageError, TargetNameError)
, BuildResult
, Target ( CompileError
, CompileResult
, compilePackage
, parseTarget
, showCompileError
, targetName
, toByteString
)
, TargetName
, buildPackage
, targetNames
) where
import Data.Either (partitionEithers)
import Data.Maybe (fromMaybe)
import Data.Proxy (Proxy)
import Data.ByteString (ByteString)
import Data.Set (Set)
import qualified Data.Map.Strict as M
import Data.Text (Text)
import Nirum.Package (PackageError, scanPackage)
import Nirum.Package.Metadata ( Metadata (Metadata, target)
, Package (Package, metadata)
, Target ( CompileError
, CompileResult
, compilePackage
, parseTarget
, showCompileError
, targetName
, toByteString
)
, TargetName
)
import Nirum.Targets.List (targetProxyMapQ)
-- Imported targets below are automatically added to the list of targets.
-- These target names become options of `[targets.*]` sections of package.toml
-- and `-t`/`--target` of CLI as well.
--
-- CHECK: When a new target `Nirum.Targets.X` is added, write docs for it in
-- docs/target/x.md file too.
import Nirum.Targets.Docs ()
import Nirum.Targets.Python ()
data BuildError = TargetNameError TargetName
| CompileError (M.Map FilePath Text)
| PackageError PackageError
deriving (Eq, Show)
type BuildResult = M.Map FilePath ByteString
packageBuilders :: M.Map TargetName
(FilePath -> IO (Either BuildError BuildResult))
packageBuilders = M.fromList $(targetProxyMapQ [e|buildPackage'|])
targetNames :: Set TargetName
targetNames = M.keysSet packageBuilders
buildPackage :: TargetName -> FilePath -> IO (Either BuildError BuildResult)
buildPackage targetName' =
fromMaybe (\ _ -> return $ Left $ TargetNameError targetName') $
M.lookup targetName' packageBuilders
buildPackage' :: forall t. Target t
=> Proxy t
-> FilePath
-> IO (Either BuildError BuildResult)
buildPackage' _ packagePath = do
scanResult <- scanPackage packagePath
return $ case scanResult of
Left e -> Left $ PackageError e
Right (pkg :: Package t) ->
let Package { metadata = Metadata { target = target' } } = pkg
results = M.toList $ compilePackage pkg
eithers = [ case result of
Left e -> Left (f, showCompileError target' e)
Right r -> Right (f, toByteString target' r)
| (f, result) <- results
] :: [Either (FilePath, Text) (FilePath, ByteString)]
in
case partitionEithers eithers of
(errors@(_ : _), _) ->
Left $ CompileError $ M.fromList errors
([], outs) -> Right $ M.fromList outs