@@ -47,11 +47,13 @@ import Control.Monad
47import Control.Monad.Error (throwError, catchError)
47import Control.Monad.Error (throwError, catchError)
48import Control.Monad.State.Strict
48import Control.Monad.State.Strict
50import Data.Maybe
51import Data.Maybe
51import qualified Data.List.Split as Spl
52import qualified Data.List.Split as Spl
52import Data.List
53import Data.List
53import Data.Monoid
54import Data.Monoid
54import Data.Char
55import Data.Char
55import qualified Data.Map as M
57import qualified Data.Map as M
56import qualified Data.HashSet as HS
58import qualified Data.HashSet as HS
57import qualified Data.Text as T
59import qualified Data.Text as T
@@ -92,12 +94,13 @@ moduleHeader = try (do reserved "module"
92{- | Parses an import statement
94{- | Parses an import statement
93 Import ::= 'import' Identifier_t ';'?;
95 Import ::= 'import' Identifier_t ';'?;
95−import_ :: IdrisParser (String, Maybe String)
97+import_ :: IdrisParser (String, Maybe String, FC)
98+import_ = do fc <- getFC
96−import_ = do reserved "import"
99+ reserved "import"
97 id <- identifier
100 id <- identifier
98 newName <- optional (reserved "as" *> identifier)
101 newName <- optional (reserved "as" *> identifier)
99 option ';' (lchar ';')
102 option ';' (lchar ';')
100− return (toPath id, toPath <$> newName)
103+ return (toPath id, toPath <$> newName, fc)
101 <?> "import statement"
104 <?> "import statement"
102 where toPath = foldl1' (</>) . Spl.splitOn "."
105 where toPath = foldl1' (</>) . Spl.splitOn "."
@@ -936,7 +939,7 @@ parseTactic :: IState -> String -> Result PTactic
936parseTactic st = runparser (fullTactic defaultSyntax) st "(input)"
939parseTactic st = runparser (fullTactic defaultSyntax) st "(input)"
938-- | Parse module header and imports
941-- | Parse module header and imports
939−parseImports :: FilePath -> String -> Idris ([String], [(String, Maybe String)], Maybe Delta)
942+parseImports :: FilePath -> String -> Idris ([String], [(String, Maybe String, FC)], Maybe Delta)
940parseImports fname input
943parseImports fname input
941 = do i <- getIState
944 = do i <- getIState
942 case parseString (runInnerParser (evalStateT imports i)) (Directed (UTF8.fromString fname) 0 0 0 0) input of
945 case parseString (runInnerParser (evalStateT imports i)) (Directed (UTF8.fromString fname) 0 0 0 0) input of
@@ -944,7 +947,7 @@ parseImports fname input
944 Success (x, i) -> do -- Discard state updates (there should be
947 Success (x, i) -> do -- Discard state updates (there should be
945 -- none anyway)
948 -- none anyway)
947− where imports :: IdrisParser (([String], [(String, Maybe String)], Maybe Delta), IState)
950+ where imports :: IdrisParser (([String], [(String, Maybe String, FC)], Maybe Delta), IState)
948 imports = do whiteSpace
951 imports = do whiteSpace
949 mname <- moduleHeader
952 mname <- moduleHeader
950 ps <- many import_
953 ps <- many import_
@@ -1056,15 +1059,21 @@ loadSource h lidr f
1056 file_in <- runIO $ readFile f
1059 file_in <- runIO $ readFile f
1057 file <- if lidr then tclift $ unlit f file_in else return file_in
1060 file <- if lidr then tclift $ unlit f file_in else return file_in
1058 (mname, imports, pos) <- parseImports f file
1061 (mname, imports, pos) <- parseImports f file
1059− let modules = map fst imports
1062+
1063+ -- process and check module aliases
1060− modAliases = M.fromList
1064+ let modAliases = M.fromList
1061− [(prep alias, prep realName) | (realName, Just alias) <- imports]
1065+ [(prep alias, prep realName) | (realName, Just alias, fc) <- imports]
1062 prep = map T.pack . reverse . Spl.splitOn "/"
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
1063− logLvl 3 $ "Module aliases: " ++ show (M.toList modAliases)
1070+ [] -> logLvl 3 $ "Module aliases: " ++ show (M.toList modAliases)
1071+ (n,fc):_ -> throwError . At fc . Msg $ "import alias not unique: " ++ show n
1064 i <- getIState
1073 i <- getIState
1065 putIState (i { default_access = Hidden, module_aliases = modAliases })
1074 putIState (i { default_access = Hidden, module_aliases = modAliases })
1066 clearIBC -- start a new .ibc file
1075 clearIBC -- start a new .ibc file
1067− mapM_ (addIBC . IBCImport) modules
1076+ mapM_ (addIBC . IBCImport) [realName | (realName, alias, fc) <- imports]
1068 let syntax = defaultSyntax{ syn_namespace = reverse mname }
1077 let syntax = defaultSyntax{ syn_namespace = reverse mname }
1069 ds' <- parseProg syntax f file pos
1078 ds' <- parseProg syntax f file pos
1070 unless (null ds') $ do
1079 unless (null ds') $ do