on master help sign in
Merge branch 'exposing'
commit876c49e0190f09557beec9850cc8d02dc1f84188 authorEvan Czaplicki <info@elm-lang.org> dateSun 22 Feb 2015, 02:28 (12 years ago) parent94b3091a6708cc
7 files changed+207−177
src/AST/Module.hs+39−30 src/AST/Variable.hs+10 src/Elm/Compiler/Module.hs+1−1 src/Parse/Helpers.hs+1−1 src/Parse/Module.hs+19−14 src/Transform/AddDefaultImports.hs+12−62 src/Transform/Canonicalize/Setup.hs+125−69
src/AST/Module.hs+39−30
@@ -1,4 +1,14 @@
1−module AST.Module where
1+module AST.Module
2+ ( Interfaces
3+ , Types, Aliases, ADTs
4+ , AdtInfo, CanonicalAdt
5+ , SourceModule, ValidModule, CanonicalModule
6+ , Module(..), CanonicalBody(..)
7+ , HeaderAndImports(..)
8+ , Name, nameToString, nameIsNative
9+ , Interface(..), toInterface
10+ , ImportMethod(..)
11+ ) where
212
313import Data.Binary
414import qualified Data.List as List
@@ -65,10 +75,14 @@ data HeaderAndImports = HeaderAndImports
6575 , _imports :: [(Name, ImportMethod)]
6676 }
6777
78+
6879type Name = [String] -- must be non-empty
6980
81+
7082nameToString :: Name -> String
71−nameToString = List.intercalate "."
83+nameToString =
84+ List.intercalate "."
85+
7286
7387nameIsNative :: Name -> Bool
7488nameIsNative name =
@@ -121,27 +135,19 @@ instance Binary Interface where
121135
122136-- IMPORT METHOD
123137
124−data ImportMethod
125− = As !String
126− | Open !(Var.Listing Var.Value)
127−
128−open :: ImportMethod
129−open = Open (Var.openListing)
138+data ImportMethod = ImportMethod
139+ { alias :: Maybe String
140+ , exposedVars :: !(Var.Listing Var.Value)
141+ }
130142
131−importing :: [Var.Value] -> ImportMethod
132−importing xs = Open (Var.Listing xs False)
133143
134144instance Binary ImportMethod where
135− put method =
136− case method of
137− As alias -> putWord8 0 >> put alias
138− Open listing -> putWord8 1 >> put listing
145+ put (ImportMethod alias exposedVars) =
146+ do put alias
147+ put exposedVars
139148
140− get = do tag <- getWord8
141− case tag of
142− 0 -> As <$> get
143− 1 -> Open <$> get
144− _ -> error "Error reading valid ImportMethod type from serialized string"
149+ get =
150+ ImportMethod <$> get <*> get
145151
146152
147153-- PRETTY PRINTING
@@ -150,19 +156,22 @@ instance (Pretty exs, Pretty body) => Pretty (Module exs body) where
150156 pretty (Module names _ exs ims body) =
151157 P.vcat [modul, P.text "", prettyImports, P.text "", pretty body]
152158 where
153− modul = P.text "module" <+> name <+> pretty exs <+> P.text "where"
154− name = P.text (List.intercalate "." names)
159+ modul =
160+ P.text "module" <+> name <+> pretty exs <+> P.text "where"
161+
162+ name =
163+ P.text (nameToString names)
155164
156165 prettyImports =
157− P.vcat $ map prettyMethod ims
166+ P.vcat $ map prettyMethod ims
158167
159168
160169prettyMethod :: (Name, ImportMethod) -> Doc
161−prettyMethod import' =
162− case import' of
163− ([name], As alias)
164− | name == alias -> P.empty
165−
166− (_, As alias) -> P.text "as" <+> P.text alias
167−
168− (_, Open listing) -> pretty listing
170+prettyMethod (name, ImportMethod maybeAlias exposedVars) =
171+ let prettyAlias =
172+ case maybeAlias of
173+ Nothing -> P.empty
174+ Just alias ->
175+ P.text "as" <+> P.text alias
176+ in
177+ prettyAlias <+> P.text "exposing" <+> pretty exposedVars
src/AST/Variable.hs+10
@@ -137,6 +137,16 @@ openListing =
137137 Listing [] True
138138
139139
140+closedListing :: Listing a
141+closedListing =
142+ Listing [] False
143+
144+
145+listing :: [a] -> Listing a
146+listing xs =
147+ Listing xs False
148+
149+
140150-- | A value that can be imported or exported
141151data Value
142152 = Value !String
src/Elm/Compiler/Module.hs+1−1
@@ -34,7 +34,7 @@ newtype Name = Name [String]
3434
3535defaultImports :: [Name]
3636defaultImports =
37− map Name (Map.keys Defaults.defaultImports)
37+ map (Name . fst) Defaults.defaultImports
3838
3939
4040-- POKING AROUND INTERFACES
src/Parse/Helpers.hs+1−1
@@ -29,7 +29,7 @@ reserveds =
2929 , "let", "in"
3030 , "type"
3131 , "module", "where"
32− , "import", "as", "hiding", "open"
32+ , "import", "as", "hiding", "exposing"
3333 , "export", "foreign"
3434 , "deriving"
3535 , "input", "output"
src/Parse/Module.hs+19−14
@@ -1,7 +1,6 @@
11module Parse.Module (header, headerAndImports, getModuleName) where
22
33import Control.Applicative ((<$>), (<*>))
4−import Data.List (intercalate)
54import Text.Parsec hiding (newline, spaces)
65
76import Parse.Helpers
@@ -18,7 +17,7 @@ getModuleName source =
1817 getModuleName =
1918 do optional freshLine
2019 (names, _) <- header
21− return (intercalate "." names)
20+ return (Module.nameToString names)
2221
2322
2423headerAndImports :: IParser Module.HeaderAndImports
@@ -52,19 +51,25 @@ import' =
5251 do try (reserved "import")
5352 whitespace
5453 names <- dotSep1 capVar
55− (,) names <$> option (Module.As (intercalate "." names)) method
54+ (,) names <$> method (Module.nameToString names)
5655 where
57− method :: IParser Module.ImportMethod
58− method = as' <|> importing'
59−
60− as' :: IParser Module.ImportMethod
61− as' = do
62− try (whitespace >> reserved "as")
63− whitespace
64− Module.As <$> capVar <?> "alias for module"
65−
66− importing' :: IParser Module.ImportMethod
67− importing' = Module.Open <$> listing value
56+ method :: String -> IParser Module.ImportMethod
57+ method defaultAlias =
58+ Module.ImportMethod
59+ <$> option (Just defaultAlias) (Just <$> as')
60+ <*> option Var.closedListing exposing
61+
62+ as' :: IParser String
63+ as' =
64+ do try (whitespace >> reserved "as")
65+ whitespace
66+ capVar <?> "alias for module"
67+
68+ exposing :: IParser (Var.Listing Var.Value)
69+ exposing =
70+ do try (whitespace >> reserved "exposing")
71+ whitespace
72+ listing value
6873
6974
7075listing :: IParser a -> IParser (Var.Listing a)
src/Transform/AddDefaultImports.hs+12−62
@@ -1,47 +1,28 @@
1−{-# LANGUAGE FlexibleContexts #-}
21module Transform.AddDefaultImports (add, defaultImports) where
32
4−import Prelude hiding (maybe)
5−import qualified Data.Map as Map
6−
73import qualified AST.Module as Module
84import qualified AST.Variable as Var
95
106
11−type ImportDict =
12− Map.Map Module.Name ([String], Var.Listing Var.Value)
13−
14−
157-- DESCRIPTION OF DEFAULT IMPORTS
168
179(==>) :: a -> b -> (a,b)
1810(==>) = (,)
1911
2012
21−defaultImports :: ImportDict
13+defaultImports :: [(Module.Name, Module.ImportMethod)]
2214defaultImports =
23− Map.fromList
24− [ ["Basics"] ==> ([], Var.openListing)
25− , ["List"] ==> ([], Var.Listing [Var.Value "::"] False)
26− , ["Maybe"] ==> ([], Var.Listing [maybe] False)
27− , ["Result"] ==> ([], Var.Listing [result] False)
28− , ["Signal"] ==> ([], Var.Listing [signal] False)
15+ [ ["Basics"] ==> Module.ImportMethod Nothing Var.openListing
16+ , ["List"] ==> exposing [Var.Value "::"]
17+ , ["Maybe"] ==> exposing [Var.Union "Maybe" Var.openListing]
18+ , ["Result"] ==> exposing [Var.Union "Result" Var.openListing]
19+ , ["Signal"] ==> exposing [Var.Union "Signal" Var.closedListing]
2920 ]
3021
3122
32−maybe :: Var.Value
33−maybe =
34− Var.Union "Maybe" Var.openListing
35−
36−
37−result :: Var.Value
38−result =
39− Var.Union "Result" Var.openListing
40−
41−
42−signal :: Var.Value
43−signal =
44− Var.Union "Signal" (Var.Listing [] False)
23+exposing :: [Var.Value] -> Module.ImportMethod
24+exposing vars =
25+ Module.ImportMethod Nothing (Var.listing vars)
4526
4627
4728-- ADDING DEFAULT IMPORTS TO A MODULE
@@ -51,37 +32,6 @@ add needsDefaults (Module.Module moduleName path exports imports decls) =
5132 Module.Module moduleName path exports ammendedImports decls
5233 where
5334 ammendedImports =
54− importDictToList $
55− foldr addImport (if needsDefaults then defaultImports else Map.empty) imports
56−
57−
58−importDictToList :: ImportDict -> [(Module.Name, Module.ImportMethod)]
59−importDictToList dict =
60− concatMap toImports (Map.toList dict)
61− where
62− toImports (name, (qualifiers, listing@(Var.Listing explicits open))) =
63− map (\qualifier -> (name, Module.As qualifier)) qualifiers
64− ++
65− if open || not (null explicits)
66− then [(name, Module.Open listing)]
67− else []
68−
69−
70−addImport :: (Module.Name, Module.ImportMethod) -> ImportDict -> ImportDict
71−addImport (name, method) importDict =
72− Map.alter mergeMethods name importDict
73− where
74− mergeMethods :: Maybe ([String], Var.Listing Var.Value)
75− -> Maybe ([String], Var.Listing Var.Value)
76− mergeMethods entry =
77− let (qualifiers, listing) =
78− case entry of
79− Nothing -> ([], Var.Listing [] False)
80− Just v -> v
81− in
82− case method of
83− Module.As qualifier ->
84− Just (qualifier : qualifiers, listing)
85−
86− Module.Open newListing ->
87− Just (qualifiers, newListing)
35+ if needsDefaults
36+ then defaultImports ++ imports
37+ else imports
src/Transform/Canonicalize/Setup.hs+125−69
@@ -30,11 +30,18 @@ import qualified Transform.Interface as Interface
3030
3131environment :: Module.Interfaces -> Module.ValidModule -> Canonicalizer [Doc] Environment
3232environment interfaces modul@(Module.Module _ _ _ imports decls) =
33− do () <- allImportsAvailable
34− let moduleName = Module.names modul
35− nonLocalEnv <- foldM (addImports moduleName interfaces) (builtIns moduleName) imports
36− let (aliases, env) = List.foldl' (addDecl moduleName) ([], nonLocalEnv) decls
37− addTypeAliases moduleName aliases env
33+ do () <- allImportsAvailable
34+ let moduleName =
35+ Module.names modul
36+
37+ nonLocalEnv <-
38+ foldM (addImports moduleName interfaces) (builtIns moduleName) imports
39+
40+ let (aliases, env) =
41+ List.foldl' (addDecl moduleName) ([], nonLocalEnv) decls
42+
43+ addTypeAliases moduleName aliases env
44+
3845 where
3946 allImportsAvailable :: Canonicalizer [Doc] ()
4047 allImportsAvailable =
@@ -42,53 +49,80 @@ environment interfaces modul@(Module.Module _ _ _ imports decls) =
4249 [] -> return ()
4350 missings -> throwError [ P.text (missingModuleError missings) ]
4451 where
45− modules = map fst imports
52+ modules =
53+ map fst imports
4654
47− found m = Map.member m interfaces || Module.nameIsNative m
55+ found m =
56+ Map.member m interfaces || Module.nameIsNative m
4857
4958 missingModuleError missings =
50− concat [ "The following imports were not found:\n "
51− , List.intercalate ", " (map Module.nameToString missings)
52− ]
59+ concat
60+ [ "The following imports were not found:\n "
61+ , List.intercalate ", " (map Module.nameToString missings)
62+ ]
5363
5464
55−addImports :: Module.Name -> Module.Interfaces -> Environment -> (Module.Name, Module.ImportMethod)
56− -> Canonicalizer [Doc] Environment
65+addImports
66+ :: Module.Name
67+ -> Module.Interfaces
68+ -> Environment
69+ -> (Module.Name, Module.ImportMethod)
70+ -> Canonicalizer [Doc] Environment
5771addImports moduleName interfaces environ (name, method)
58− | Module.nameIsNative name = return environ
72+ | Module.nameIsNative name =
73+ return environ
74+
5975 | otherwise =
60− case method of
61− Module.As name' ->
62− return (updateEnviron (name' ++ "."))
76+ let (Module.ImportMethod maybeAlias listing) = method
6377
64− Module.Open (Var.Listing vs open)
65− | open -> return (updateEnviron "")
66− | otherwise -> foldM (addValue name interface) environ vs
67− where
68− interface = Interface.filterExports ((Map.!) interfaces name)
69−
70− updateEnviron prefix =
71− let dict' = dict . map (first (prefix++)) in
72− merge environ $
73− Env { _home = moduleName
74− , _values = dict' $ map pair (Map.keys (iTypes interface)) ++ ctors
75− , _adts = dict' $ map pair (Map.keys (iAdts interface))
76− , _aliases = dict' $ map alias (Map.toList (iAliases interface))
77− , _patterns = dict' $ ctors
78− }
78+ (Var.Listing exposedVars open) = listing
79+
80+ qualifier =
81+ maybe (Module.nameToString name) id maybeAlias
82+
83+ env =
84+ updateEnviron (qualifier ++ ".") environ
85+ in
86+ if open
87+ then return (updateEnviron "" env)
88+ else foldM (addValue name interface) env exposedVars
89+ where
90+ interface =
91+ Interface.filterExports ((Map.!) interfaces name)
92+
93+ updateEnviron prefix env =
94+ let dict' = dict . map (first (prefix++)) in
95+ merge env $
96+ Env { _home = moduleName
97+ , _values = dict' $ map pair (Map.keys (iTypes interface)) ++ ctors
98+ , _adts = dict' $ map pair (Map.keys (iAdts interface))
99+ , _aliases = dict' $ map alias (Map.toList (iAliases interface))
100+ , _patterns = dict' $ ctors
101+ }
79102
80− canonical :: String -> Var.Canonical
81− canonical = Var.Canonical (Var.Module name)
103+ canonical :: String -> Var.Canonical
104+ canonical =
105+ Var.Canonical (Var.Module name)
82106
83− pair :: String -> (String, Var.Canonical)
84− pair key = (key, canonical key)
107+ pair :: String -> (String, Var.Canonical)
108+ pair key =
109+ (key, canonical key)
85110
86− alias (x,(tvars,tipe)) = (x, (canonical x, tvars, tipe))
111+ alias (x,(tvars,tipe)) =
112+ (x, (canonical x, tvars, tipe))
87113
88− ctors = concatMap (map (pair . fst) . snd . snd) (Map.toList (iAdts interface))
114+ ctors =
115+ concatMap
116+ (map (pair . fst) . snd . snd)
117+ (Map.toList (iAdts interface))
89118
90−addValue :: Module.Name -> Module.Interface -> Environment -> Var.Value
91− -> Canonicalizer [Doc] Environment
119+
120+addValue
121+ :: Module.Name
122+ -> Module.Interface
123+ -> Environment
124+ -> Var.Value
125+ -> Canonicalizer [Doc] Environment
92126addValue moduleName interface env value =
93127 let name = Module.nameToString moduleName
94128 insert' x = insert x (Var.Canonical (Var.Module moduleName) x)
@@ -98,7 +132,9 @@ addValue moduleName interface env value =
98132 in
99133 case value of
100134 Var.Value x
101− | Map.notMember x (iTypes interface) -> notFound x
135+ | Map.notMember x (iTypes interface) ->
136+ notFound x
137+
102138 | otherwise ->
103139 return $ env { _values = insert' x (_values env) }
104140
@@ -126,11 +162,12 @@ addValue moduleName interface env value =
126162 case Map.lookup x (iAdts interface) of
127163 Nothing -> notFound x
128164 Just (_tvars, ctors) ->
129− do ctors' <- filterNames (map fst ctors)
130− return $ env { _adts = insert' x (_adts env)
131− , _values = foldr insert' (_values env) ctors'
132− , _patterns = foldr insert' (_patterns env) ctors'
133− }
165+ do ctors' <- filterNames (map fst ctors)
166+ return $ env
167+ { _adts = insert' x (_adts env)
168+ , _values = foldr insert' (_values env) ctors'
169+ , _patterns = foldr insert' (_patterns env) ctors'
170+ }
134171 where
135172 filterNames names
136173 | open = return names
@@ -139,19 +176,22 @@ addValue moduleName interface env value =
139176 [] -> return names
140177 c:_ -> notFound c
141178
179+
142180type Node = ((String, [String], Type.RawType), String, [String])
143181
182+
144183node :: String -> [String] -> Type.RawType -> Node
145−node name tvars alias = ((name, tvars, alias), name, edges alias)
146− where
147− edges tipe =
148− case tipe of
149− Type.Lambda t1 t2 -> edges t1 ++ edges t2
150− Type.Var _ -> []
151− Type.Type (Var.Raw x) -> [x]
152− Type.App t ts -> edges t ++ concatMap edges ts
153− Type.Record fs ext -> maybe [] edges ext ++ concatMap (edges . snd) fs
154− Type.Aliased _ t -> edges t
184+node name tvars alias =
185+ ((name, tvars, alias), name, edges alias)
186+ where
187+ edges tipe =
188+ case tipe of
189+ Type.Lambda t1 t2 -> edges t1 ++ edges t2
190+ Type.Var _ -> []
191+ Type.Type (Var.Raw x) -> [x]
192+ Type.App t ts -> edges t ++ concatMap edges ts
193+ Type.Record fs ext -> maybe [] edges ext ++ concatMap (edges . snd) fs
194+ Type.Aliased _ t -> edges t
155195
156196
157197addTypeAliases
@@ -232,7 +272,11 @@ typeAliasErrorExplanation =
232272-- When canonicalizing, all _values should be Local, but all _adts and _patterns
233273-- should be fully namespaced. With _adts, they may appear in types that can
234274-- escape the module.
235−addDecl :: Module.Name -> ([Node], Environment) -> D.ValidDecl -> ([Node], Environment)
275+addDecl
276+ :: Module.Name
277+ -> ([Node], Environment)
278+ -> D.ValidDecl
279+ -> ([Node], Environment)
236280addDecl moduleName info@(nodes,env) decl =
237281 let namespacedVar = Var.Canonical (Var.Module moduleName)
238282 addLocal x e = insert x (Var.local x) e
@@ -241,29 +285,41 @@ addDecl moduleName info@(nodes,env) decl =
241285 case decl of
242286 D.Definition (Valid.Definition pattern _ _) ->
243287 (,) nodes $ env
244− { _values = foldr addLocal (_values env) (P.boundVarList pattern) }
288+ { _values =
289+ foldr addLocal (_values env) (P.boundVarList pattern)
290+ }
245291
246292 D.Datatype name _ ctors ->
247293 (,) nodes $ env
248− { _values = addCtors addLocal (_values env)
249− , _adts = addNamespaced name (_adts env)
250− , _patterns = addCtors addNamespaced (_patterns env)
251− }
294+ { _values =
295+ addCtors addLocal (_values env)
296+ , _adts =
297+ addNamespaced name (_adts env)
298+ , _patterns =
299+ addCtors addNamespaced (_patterns env)
300+ }
252301 where
253302 addCtors how e = foldr how e (map fst ctors)
254303
255304 D.TypeAlias name tvars alias ->
256305 (,) (node name tvars alias : nodes) $ env
257− { _values = case alias of
258− Type.Record _ _ -> addLocal name (_values env)
259− _ -> _values env
260− }
306+ { _values =
307+ case alias of
308+ Type.Record _ _ ->
309+ addLocal name (_values env)
310+ _ ->
311+ _values env
312+ }
261313
262314 D.Port port ->
263− let portName = case port of
264− D.Out name _ _ -> name
265− D.In name _ -> name
315+ let portName =
316+ case port of
317+ D.Out name _ _ -> name
318+ D.In name _ -> name
266319 in
267− (,) nodes $ env { _values = addLocal portName (_values env) }
320+ (,) nodes $ env
321+ { _values =
322+ addLocal portName (_values env)
323+ }
268324
269325 D.Fixity _ _ _ -> info