@@ -47,11 +47,14 @@ import Control.Monad
4747import Control.Monad.Error (throwError, catchError)
4848import Control.Monad.State.Strict
4949
50+import Data.Function
5051import Data.Maybe
5152import qualified Data.List.Split as Spl
5253import Data.List
5354import Data.Monoid
5455import Data.Char
56+import Data.Ord
57+import qualified Data.Map as M
5558import qualified Data.HashSet as HS
5659import qualified Data.Text as T
5760import qualified Data.ByteString.UTF8 as UTF8
@@ -91,13 +94,15 @@ moduleHeader = try (do reserved "module"
9194{- | Parses an import statement
9295 Import ::= 'import' Identifier_t ';'?;
9396 -}
94−import_ :: IdrisParser String
95−import_ = do reserved "import"
97+import_ :: IdrisParser (String, Maybe String, FC)
98+import_ = do fc <- getFC
99+ reserved "import"
96100 id <- identifier
101+ newName <- optional (reserved "as" *> identifier)
97102 option ';' (lchar ';')
98− return (toPath id)
103+ return (toPath id, toPath <$> newName, fc)
99104 <?> "import statement"
100− where toPath f = foldl1' (</>) (Spl.splitOn "." f)
105+ where toPath = foldl1' (</>) . Spl.splitOn "."
101106
102107{- | Parses program source
103108 Prog ::= Decl* EOF;
@@ -934,7 +939,7 @@ parseTactic :: IState -> String -> Result PTactic
934939parseTactic st = runparser (fullTactic defaultSyntax) st "(input)"
935940
936941-- | Parse module header and imports
937−parseImports :: FilePath -> String -> Idris ([String], [String], Maybe Delta)
942+parseImports :: FilePath -> String -> Idris ([String], [(String, Maybe String, FC)], Maybe Delta)
938943parseImports fname input
939944 = do i <- getIState
940945 case parseString (runInnerParser (evalStateT imports i)) (Directed (UTF8.fromString fname) 0 0 0 0) input of
@@ -942,7 +947,7 @@ parseImports fname input
942947 Success (x, i) -> do -- Discard state updates (there should be
943948 -- none anyway)
944949 return x
945− where imports :: IdrisParser (([String], [String], Maybe Delta), IState)
950+ where imports :: IdrisParser (([String], [(String, Maybe String, FC)], Maybe Delta), IState)
946951 imports = do whiteSpace
947952 mname <- moduleHeader
948953 ps <- many import_
@@ -1053,13 +1058,24 @@ loadSource h lidr f
10531058 let def_total = default_total i
10541059 file_in <- runIO $ readFile f
10551060 file <- if lidr then tclift $ unlit f file_in else return file_in
1056− (mname, modules, pos) <- parseImports f file
1061+ (mname, imports, pos) <- parseImports f file
1062+
1063+ -- process and check module aliases
1064+ let modAliases = M.fromList
1065+ [(prep alias, prep realName) | (realName, Just alias, fc) <- imports]
1066+ prep = map T.pack . reverse . Spl.splitOn "/"
1067+ aliasNames = [(alias, fc) | (_, Just alias, fc) <- imports]
1068+ histogram = groupBy ((==) `on` fst) . sortBy (comparing fst) $ aliasNames
1069+ case map head . filter ((/= 1) . length) $ histogram of
1070+ [] -> logLvl 3 $ "Module aliases: " ++ show (M.toList modAliases)
1071+ (n,fc):_ -> throwError . At fc . Msg $ "import alias not unique: " ++ show n
1072+
10571073 i <- getIState
1058− putIState (i { default_access = Hidden })
1074+ putIState (i { default_access = Hidden, module_aliases = modAliases })
10591075 clearIBC -- start a new .ibc file
1060− mapM_ (addIBC . IBCImport) modules
1061− ds' <- parseProg (defaultSyntax {syn_namespace = reverse mname })
1062− f file pos
1076+ mapM_ (addIBC . IBCImport) [realName | (realName, alias, fc) <- imports]
1077+ let syntax = defaultSyntax{ syn_namespace = reverse mname }
1078+ ds' <- parseProg syntax f file pos
10631079 unless (null ds') $ do
10641080 let ds = namespaces mname ds'
10651081 logLvl 3 (show $ showDecls True ds)