git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Merge pull request #299 from garyb/master

Qualified imports

commit6f0b317dbe6e9e5a5b46663379f28bca3457302a authorPhil Freeman <paf31@cantab.net> dateMon 17 Mar 2014, 15:09 (13 years ago) parent9eff663b6ce447
22 files changed+70−58
examples/manual/ExportExplicit3.purs → examples/manual/failing/ExportExplicit.purs examples/manual/ExportExplicit4.purs → examples/manual/failing/ExportExplicit1.purs examples/manual/ExportExplicit5.purs → examples/manual/failing/ExportExplicit2.purs examples/manual/ExportExplicit6.purs → examples/manual/failing/ExportExplicit3.purs examples/manual/ImportExplicit2.purs → examples/manual/failing/ImportExplicit.purs examples/manual/ImportExplicit3.purs → examples/manual/failing/ImportExplicit2.purs examples/manual/ImportModule.purs → examples/manual/failing/ImportModule.purs examples/manual/ExportExplicit.purs → examples/manual/passing/ExportExplicit.purs examples/manual/ExportExplicit2.purs → examples/manual/passing/ExportExplicit2.purs examples/manual/Import.purs → examples/manual/passing/Import.purs examples/manual/ImportExplicit.purs → examples/manual/passing/ImportExplicit.purs examples/manual/passing/ImportQualified.purs+12 examples/manual/Module.purs → examples/manual/passing/Module.purs examples/manual/ModuleDeps.purs → examples/manual/passing/ModuleDeps.purs examples/manual/RedefinedFixity.purs → examples/manual/passing/RedefinedFixity.purs psci/Main.hs+1−1 src/Language/PureScript/Declarations.hs+3−2 src/Language/PureScript/ModuleDependencies.hs+1−1 src/Language/PureScript/Parser/Declarations.hs+14−3 src/Language/PureScript/Sugar/Names.hs+37−49 src/Language/PureScript/Sugar/Operators.hs+1−1 src/Language/PureScript/TypeChecker.hs+1−1
examples/manual/ExportExplicit3.purs → examples/manual/failing/ExportExplicit.pursrenamed

The content is the same.

examples/manual/ExportExplicit4.purs → examples/manual/failing/ExportExplicit1.pursrenamed

The content is the same.

examples/manual/ExportExplicit5.purs → examples/manual/failing/ExportExplicit2.pursrenamed

The content is the same.

examples/manual/ExportExplicit6.purs → examples/manual/failing/ExportExplicit3.pursrenamed

The content is the same.

examples/manual/ImportExplicit2.purs → examples/manual/failing/ImportExplicit.pursrenamed

The content is the same.

examples/manual/ImportExplicit3.purs → examples/manual/failing/ImportExplicit2.pursrenamed

The content is the same.

examples/manual/ImportModule.purs → examples/manual/failing/ImportModule.pursrenamed

The content is the same.

examples/manual/ExportExplicit.purs → examples/manual/passing/ExportExplicit.pursrenamed

The content is the same.

examples/manual/ExportExplicit2.purs → examples/manual/passing/ExportExplicit2.pursrenamed

The content is the same.

examples/manual/Import.purs → examples/manual/passing/Import.pursrenamed

The content is the same.

examples/manual/ImportExplicit.purs → examples/manual/passing/ImportExplicit.pursrenamed

The content is the same.

examples/manual/passing/ImportQualified.pursnew file+12
@@ -0,0 +1,12 @@
1+module M1 where
2+
3+ trace x = x
4+
5+module Main where
6+
7+ import Prelude
8+ import Control.Monad.Eff
9+ import M1
10+ import qualified Debug.Trace as T
11+
12+ main = T.trace (trace "Done")
examples/manual/Module.purs → examples/manual/passing/Module.pursrenamed

The content is the same.

examples/manual/ModuleDeps.purs → examples/manual/passing/ModuleDeps.pursrenamed

The content is the same.

examples/manual/RedefinedFixity.purs → examples/manual/passing/RedefinedFixity.pursrenamed

The content is the same.

psci/Main.hs+1−1
@@ -204,7 +204,7 @@ createTemporaryModule :: Bool -> PSCiState -> P.Value -> P.Module
204204createTemporaryModule exec PSCiState{psciImportedModuleNames = imports, psciLetBindings = lets} value =
205205 let
206206 moduleName = P.ModuleName [P.ProperName "Main"]
207− importDecl m = P.ImportDeclaration m Nothing
207+ importDecl m = P.ImportDeclaration m Nothing Nothing
208208 traceModule = P.ModuleName [P.ProperName "Debug", P.ProperName "Trace"]
209209 trace = P.Var (P.Qualified (Just traceModule) (P.Ident "print"))
210210 itValue = foldl (\x f -> f x) value lets
src/Language/PureScript/Declarations.hs+3−2
@@ -117,9 +117,10 @@ data Declaration
117117 --
118118 | FixityDeclaration Fixity String
119119 -- |
120− -- A module import (module name, optional set of identifiers to import)
120+ -- A module import (module name, optional set of identifiers to import, optional "qualified as"
121+ -- name)
121122 --
122− | ImportDeclaration ModuleName (Maybe [DeclarationRef])
123+ | ImportDeclaration ModuleName (Maybe [DeclarationRef]) (Maybe ModuleName)
123124 -- |
124125 -- A type class declaration (name, argument, member declarations)
125126 --
src/Language/PureScript/ModuleDependencies.hs+1−1
@@ -47,7 +47,7 @@ usedModules = nub . everything (++) (mkQ [] qualifiedIdents `extQ` qualifiedProp
4747 qualifiedProperNames (Qualified (Just mn) _) = [mn]
4848 qualifiedProperNames _ = []
4949 imports :: Declaration -> [ModuleName]
50− imports (ImportDeclaration mn _) = [mn]
50+ imports (ImportDeclaration mn _ _) = [mn]
5151 imports _ = []
5252
5353getModuleName :: Module -> ModuleName
src/Language/PureScript/Parser/Declarations.hs+14−3
@@ -99,9 +99,20 @@ parseImportDeclaration :: P.Parsec String ParseState Declaration
9999parseImportDeclaration = do
100100 reserved "import"
101101 indented
102− moduleName' <- moduleName
103− idents <- P.optionMaybe $ parens $ commaSep parseDeclarationRef
104− return $ ImportDeclaration moduleName' idents
102+ qualImport <|> stdImport
103+ where
104+ stdImport = do
105+ moduleName' <- moduleName
106+ idents <- P.optionMaybe $ parens $ commaSep parseDeclarationRef
107+ return $ ImportDeclaration moduleName' idents Nothing
108+ qualImport = do
109+ reserved "qualified"
110+ indented
111+ moduleName' <- moduleName
112+ idents <- P.optionMaybe $ parens $ commaSep parseDeclarationRef
113+ reserved "as"
114+ asQ <- moduleName
115+ return $ ImportDeclaration moduleName' idents (Just asQ)
105116
106117parseDeclarationRef :: P.Parsec String ParseState DeclarationRef
107118parseDeclarationRef = ValueRef <$> parseIdent
src/Language/PureScript/Sugar/Names.hs+37−49
@@ -16,7 +16,7 @@ module Language.PureScript.Sugar.Names (
1616 desugarImports
1717) where
1818
19−import Data.Maybe (fromMaybe)
19+import Data.Maybe (fromMaybe, isJust)
2020import Data.Generics (extM, mkM, everywhereM)
2121import Data.Generics.Extras (mkS, extS, everywhereWithContextM')
2222
@@ -61,19 +61,19 @@ data ImportEnvironment = ImportEnvironment
6161 -- |
6262 -- Local names for types within a module mapped to to their qualified names
6363 --
64− { importedTypes :: M.Map ProperName (Qualified ProperName)
64+ { importedTypes :: M.Map (Qualified ProperName) (Qualified ProperName)
6565 -- |
6666 -- Local names for data constructors within a module mapped to to their qualified names
6767 --
68− , importedDataConstructors :: M.Map ProperName (Qualified ProperName)
68+ , importedDataConstructors :: M.Map (Qualified ProperName) (Qualified ProperName)
6969 -- |
7070 -- Local names for classes within a module mapped to to their qualified names
7171 --
72− , importedTypeClasses :: M.Map ProperName (Qualified ProperName)
72+ , importedTypeClasses :: M.Map (Qualified ProperName) (Qualified ProperName)
7373 -- |
7474 -- Local names for values within a module mapped to to their qualified names
7575 --
76− , importedValues :: M.Map Ident (Qualified Ident)
76+ , importedValues :: M.Map (Qualified Ident) (Qualified Ident)
7777 } deriving (Show)
7878
7979-- |
@@ -207,38 +207,26 @@ renameInModule imports exports (Module mn decls exps) =
207207 updateType t = return t
208208 updateConstraints = mapM (\(name, ts) -> (,) <$> updateClassName name <*> pure ts)
209209
210− updateTypeName (Qualified Nothing name) = update "type" importedTypes name
211− updateTypeName (Qualified (Just mn') name) = do
212− modExports <- getExports mn'
213− case name `lookup` exportedTypes modExports of
214− Nothing -> throwError $ "Unknown type '" ++ show (Qualified (Just mn') name) ++ "'"
215− _ -> return $ Qualified (Just mn') name
216−
217− updateDataConstructorName (Qualified Nothing name) = update "data constructor" importedDataConstructors name
218− updateDataConstructorName (Qualified (Just mn') name) = do
219− modExports <- getExports mn'
220− let allDcons = join $ snd `map` exportedTypes modExports
221− if name `elem` allDcons
222− then return $ Qualified (Just mn') name
223− else throwError $ "Unknown data constructor '" ++ show (Qualified (Just mn') name) ++ "'"
224−
225− updateClassName (Qualified Nothing name) = update "type class" importedTypeClasses name
226− updateClassName (Qualified (Just mn') name) = check "type class" exportedTypeClasses mn' name
227−
228− updateValueName (Qualified Nothing name) = update "value" importedValues name
229− updateValueName (Qualified (Just mn') name) = check "value" exportedValues mn' name
230−
231− -- Replace an unqualified name with a qualified
232− update :: (Ord a, Show a) => String -> (ImportEnvironment -> M.Map a (Qualified a)) -> a -> Either String (Qualified a)
233− update t get name = maybe (throwError $ "Unknown " ++ t ++ " '" ++ show name ++ "'") return $ M.lookup name (get imports)
234−
235− -- Check that a qualified name is valid
236− check :: (Show a, Eq a) => String -> (Exports -> [a]) -> ModuleName -> a -> Either String (Qualified a)
237− check t get mn' name = do
238− modExports <- getExports mn'
239− if name `elem` get modExports
240− then return $ Qualified (Just mn') name
241− else throwError $ "Unknown " ++ t ++ " '" ++ show (Qualified (Just mn') name) ++ "'"
210+ updateTypeName = update "type" importedTypes (\mes -> isJust . (`lookup` (exportedTypes mes)))
211+ updateClassName = update "type class" importedTypeClasses (flip elem . exportedTypeClasses)
212+ updateValueName = update "value" importedValues (flip elem . exportedValues)
213+ updateDataConstructorName = update "data constructor" importedDataConstructors (\mes -> flip elem (join $ snd `map` exportedTypes mes))
214+
215+ -- Update names so unqualified references become qualified, and locally qualified references
216+ -- are replaced with their canoncial qualified names (e.g. M.Map -> Data.Map.Map)
217+ update :: (Ord a, Show a) => String
218+ -> (ImportEnvironment -> M.Map (Qualified a) (Qualified a))
219+ -> (Exports -> a -> Bool)
220+ -> (Qualified a)
221+ -> Either String (Qualified a)
222+ update t getI checkE qname@(Qualified mn' name) = case (M.lookup qname (getI imports), mn') of
223+ (Just qname', _) -> return qname'
224+ (Nothing, Just mn'') -> do
225+ modExports <- getExports mn''
226+ if checkE modExports name
227+ then return qname
228+ else throwError $ "Unknown " ++ t ++ " '" ++ show (qname) ++ "'"
229+ _ -> throwError $ "Unknown " ++ t ++ " '" ++ show name ++ "'"
242230
243231 -- Gets the exports for a module, or an error message if the module doesn't exist
244232 getExports :: ModuleName -> Either String Exports
@@ -334,10 +322,10 @@ type ExplicitImports = [DeclarationRef]
334322-- Finds the imports within a module, mapping the imported module name to an optional set of
335323-- explicitly imported declarations.
336324--
337−findImports :: [Declaration] -> M.Map ModuleName (Maybe ExplicitImports)
325+findImports :: [Declaration] -> M.Map ModuleName (Maybe ExplicitImports, Maybe ModuleName)
338326findImports = foldl findImports' M.empty
339327 where
340− findImports' result (ImportDeclaration mn expl) = M.insert mn expl result
328+ findImports' result (ImportDeclaration mn expl qual) = M.insert mn (expl, qual) result
341329 findImports' result _ = result
342330
343331-- |
@@ -348,17 +336,17 @@ resolveImports env (Module currentModule decls _) =
348336 foldM resolveImport' (ImportEnvironment M.empty M.empty M.empty M.empty) (M.toList scope)
349337 where
350338 -- A Map from module name to imports from that module, where Nothing indicates everything is to be imported
351− scope :: M.Map ModuleName (Maybe ExplicitImports)
352− scope = M.insert currentModule Nothing (findImports decls)
353− resolveImport' imp (mn, i) = do
354− m <- maybe (throwError $ "Cannot import unknown module '" ++ show mn ++ "'") return $ mn `M.lookup` env
355− resolveImport currentModule mn m imp i
339+ scope :: M.Map ModuleName (Maybe ExplicitImports, Maybe ModuleName)
340+ scope = M.insert currentModule (Nothing, Nothing) (findImports decls)
341+ resolveImport' imp (mn, (explImports, impQual)) = do
342+ modExports <- maybe (throwError $ "Cannot import unknown module '" ++ show mn ++ "'") return $ mn `M.lookup` env
343+ resolveImport currentModule mn modExports imp impQual explImports
356344
357345-- |
358346-- Extends the local environment for a module by resolving an import of another module.
359347--
360−resolveImport :: ModuleName -> ModuleName -> Exports -> ImportEnvironment -> Maybe ExplicitImports -> Either String ImportEnvironment
361−resolveImport currentModule importModule exps imps = maybe importAll (foldM importExplicit imps)
348+resolveImport :: ModuleName -> ModuleName -> Exports -> ImportEnvironment -> Maybe ModuleName -> Maybe ExplicitImports-> Either String ImportEnvironment
349+resolveImport currentModule importModule exps imps impQual = maybe importAll (foldM importExplicit imps)
362350 where
363351
364352 -- Import everything from a module
@@ -392,9 +380,9 @@ resolveImport currentModule importModule exps imps = maybe importAll (foldM impo
392380 allExportedDataConstructors name = fromMaybe [] $ name `lookup` exportedTypes exps
393381
394382 -- Add something to the ImportEnvironment if it does not already exist there
395− updateImports :: (Ord a, Show a) => M.Map a (Qualified a) -> a -> Either String (M.Map a (Qualified a))
396− updateImports m name = case M.lookup name m of
397− Nothing -> return $ M.insert name (Qualified (Just importModule) name) m
383+ updateImports :: (Ord a, Show a) => M.Map (Qualified a) (Qualified a) -> a -> Either String (M.Map (Qualified a) (Qualified a))
384+ updateImports m name = case M.lookup (Qualified impQual name) m of
385+ Nothing -> return $ M.insert (Qualified impQual name) (Qualified (Just importModule) name) m
398386 Just (Qualified Nothing _) -> error "Invalid state in updateImports"
399387 Just x@(Qualified (Just mn) _) -> throwError $
400388 if mn == currentModule || importModule == currentModule
src/Language/PureScript/Sugar/Operators.hs+1−1
@@ -124,7 +124,7 @@ collectFixities m moduleName (FixityDeclaration fixity name : rest) = do
124124 let qual = Qualified (Just moduleName) (Op name)
125125 when (qual `M.member` m) (Left $ "redefined fixity for " ++ show name)
126126 collectFixities (M.insert qual fixity m) moduleName rest
127−collectFixities m moduleName (ImportDeclaration importedModule _ : rest) = do
127+collectFixities m moduleName (ImportDeclaration importedModule _ _ : rest) = do
128128 let fs = [ (i, fixity) | (Qualified mn i, fixity) <- M.toList m, mn == Just importedModule ]
129129 let m' = M.fromList (map (first (Qualified (Just moduleName))) fs)
130130 collectFixities (m' `M.union` m) moduleName rest
src/Language/PureScript/TypeChecker.hs+1−1
@@ -173,7 +173,7 @@ typeCheckAll mainModuleName moduleName (d@(FixityDeclaration _ name) : rest) = d
173173 env <- getEnv
174174 guardWith ("Fixity declaration with no binding: " ++ name) $ M.member (moduleName, Op name) $ names env
175175 return $ d : ds
176−typeCheckAll mainModuleName currentModule (d@(ImportDeclaration moduleName _) : rest) = do
176+typeCheckAll mainModuleName currentModule (d@(ImportDeclaration moduleName _ _) : rest) = do
177177 env <- getEnv
178178 let instances = filter (\tcd -> let Qualified (Just mn) _ = tcdName tcd in moduleName == mn) (typeClassDictionaries env)
179179 forM_ instances $ \tcd -> do