Refactored, added comments
This commit is contained in:
parent
9652b4e13b
commit
6242b2f1eb
1 changed files with 27 additions and 17 deletions
|
@ -11,7 +11,7 @@ import Control.Monad (filterM)
|
||||||
import Control.Monad.Catch ( MonadThrow, )
|
import Control.Monad.Catch ( MonadThrow, )
|
||||||
import Control.Monad.Trans (lift, MonadIO (liftIO))
|
import Control.Monad.Trans (lift, MonadIO (liftIO))
|
||||||
import Control.Monad.Trans.Except ()
|
import Control.Monad.Trans.Except ()
|
||||||
import Control.Monad.Trans.Reader (asks)
|
import Control.Monad.Trans.Reader (asks, ReaderT)
|
||||||
|
|
||||||
import Data.Functor ((<&>))
|
import Data.Functor ((<&>))
|
||||||
|
|
||||||
|
@ -22,18 +22,20 @@ import qualified Data.List.NonEmpty as NonEmpty
|
||||||
|
|
||||||
import qualified System.Directory as IO
|
import qualified System.Directory as IO
|
||||||
|
|
||||||
import Text.Parsec (sepBy1, ParsecT, anyChar, many, char, choice, notFollowedBy, oneOf)
|
import Text.Parsec (sepBy1, ParsecT, anyChar, many, char, choice, notFollowedBy, oneOf, option)
|
||||||
import qualified Text.Parsec as Parsec
|
import qualified Text.Parsec as Parsec
|
||||||
|
|
||||||
import Path as Path ( Path, File, parseRelFile, Rel, parseRelDir, Dir, Abs, (</>), fromAbsFile, fromRelFile )
|
import Path as Path ( Path, File, parseRelFile, Rel, parseRelDir, Dir, Abs, (</>), fromAbsFile, fromRelFile )
|
||||||
|
|
||||||
import Ubc.Parse.Syntax (Transformer)
|
import Ubc.Parse.Syntax (Transformer)
|
||||||
|
import Ubc.Parse.Syntax.Config (Config)
|
||||||
import qualified Ubc.Parse.Syntax.Config as Config
|
import qualified Ubc.Parse.Syntax.Config as Config
|
||||||
import qualified Ubc.Parse.Syntax.File as File
|
import qualified Ubc.Parse.Syntax.File as File
|
||||||
import qualified Ubc.Parse.Syntax.Language as UbcLanguage
|
import qualified Ubc.Parse.Syntax.Language as UbcLanguage
|
||||||
|
|
||||||
data Import = Import
|
data Import = Import
|
||||||
{ file :: File.File
|
{ file :: File.File
|
||||||
|
, alias :: String
|
||||||
}
|
}
|
||||||
|
|
||||||
importPath :: Monad m => ParsecT String u m (NonEmpty String)
|
importPath :: Monad m => ParsecT String u m (NonEmpty String)
|
||||||
|
@ -50,19 +52,27 @@ parse :: ParsecT String u Transformer Import
|
||||||
parse = do
|
parse = do
|
||||||
UbcLanguage.reserved "import"
|
UbcLanguage.reserved "import"
|
||||||
fragments <- importPath
|
fragments <- importPath
|
||||||
|
importAs <- option (NonEmpty.last fragments) importAlias
|
||||||
|
|
||||||
case parseRelPath fragments of
|
-- concatenate directory and file parts, also utf-decoding
|
||||||
Left err -> fail $ "Failed to decode path:\n" <> show err
|
relFile <- case parseRelPath fragments of
|
||||||
Right relFile -> do
|
Left err -> fail $ "Failed to decode path:\n" <> show err
|
||||||
possiblePaths <- lift $ constructPaths relFile
|
Right relFile -> pure relFile
|
||||||
existingFiles <- liftIO $ filterInexistent possiblePaths
|
|
||||||
tryImport relFile possiblePaths existingFiles
|
|
||||||
|
|
||||||
tryImport :: Path Rel File -> [Path Abs File] -> [Path Abs File] -> ParsecT String u Transformer Import
|
-- appended to all search directories
|
||||||
tryImport targetFile searchedPaths = \case
|
possiblePaths <- lift $ constructPaths relFile
|
||||||
[] -> fail $ notFoundMessage targetFile searchedPaths
|
-- only existing files
|
||||||
[path] -> parseFile path
|
existingFiles <- liftIO $ filterInexistent possiblePaths
|
||||||
fs@_ -> fail $ multipleFoundMessage targetFile fs
|
|
||||||
|
-- fail if there are multiple files
|
||||||
|
case existingFiles of
|
||||||
|
[] -> fail $ notFoundMessage relFile possiblePaths
|
||||||
|
[path] -> parseFile path importAs
|
||||||
|
fs@_ -> fail $ multipleFoundMessage relFile fs
|
||||||
|
|
||||||
|
importAlias :: Monad m => ParsecT String u m String
|
||||||
|
importAlias = UbcLanguage.reserved "as"
|
||||||
|
*> UbcLanguage.identifier
|
||||||
|
|
||||||
multipleFoundMessage :: Path Rel File -> [Path Abs File] -> String
|
multipleFoundMessage :: Path Rel File -> [Path Abs File] -> String
|
||||||
multipleFoundMessage relFile foundFiles = "Could not identify imported file " <> Path.fromRelFile relFile <> "\n"
|
multipleFoundMessage relFile foundFiles = "Could not identify imported file " <> Path.fromRelFile relFile <> "\n"
|
||||||
|
@ -74,8 +84,8 @@ notFoundMessage relFile searchedLocations = "Could not locate import file path"
|
||||||
<> "Searched locations were:"
|
<> "Searched locations were:"
|
||||||
<> (unlines . List.map (('\t':) . Path.fromAbsFile) $ searchedLocations)
|
<> (unlines . List.map (('\t':) . Path.fromAbsFile) $ searchedLocations)
|
||||||
|
|
||||||
parseFile :: MonadIO m => Path Abs File -> ParsecT String u m Import
|
parseFile :: MonadIO m => Path Abs File -> String -> ParsecT String u m Import
|
||||||
parseFile path = do
|
parseFile path importAs = do
|
||||||
let stringPath = Path.fromAbsFile path
|
let stringPath = Path.fromAbsFile path
|
||||||
contents <- liftIO . readFile $ stringPath
|
contents <- liftIO . readFile $ stringPath
|
||||||
|
|
||||||
|
@ -98,7 +108,7 @@ parseFile path = do
|
||||||
Parsec.setInput oldInput
|
Parsec.setInput oldInput
|
||||||
Parsec.setPosition oldPosition
|
Parsec.setPosition oldPosition
|
||||||
|
|
||||||
pure $ Import importedFile
|
pure $ Import importedFile importAs
|
||||||
|
|
||||||
parseRelPath :: MonadThrow m => NonEmpty FilePath -> m (Path Rel File)
|
parseRelPath :: MonadThrow m => NonEmpty FilePath -> m (Path Rel File)
|
||||||
parseRelPath fragments = do
|
parseRelPath fragments = do
|
||||||
|
@ -112,7 +122,7 @@ constructRelative = foldr (</>)
|
||||||
filterInexistent :: [Path Abs File] -> IO [Path Abs File]
|
filterInexistent :: [Path Abs File] -> IO [Path Abs File]
|
||||||
filterInexistent paths = filterM (IO.doesFileExist . Path.fromAbsFile) paths
|
filterInexistent paths = filterM (IO.doesFileExist . Path.fromAbsFile) paths
|
||||||
|
|
||||||
constructPaths :: Path Rel File -> Transformer [Path Abs File]
|
constructPaths :: Monad m => Path Rel t -> ReaderT Config m [Path Abs t]
|
||||||
constructPaths suffix = do
|
constructPaths suffix = do
|
||||||
paths <- asks Config.includePaths
|
paths <- asks Config.includePaths
|
||||||
Set.toList
|
Set.toList
|
||||||
|
|
Loading…
Reference in a new issue