1{-# OPTIONS_GHC -Wall #-}
2module Transform.Canonicalize.Setup
5 , typeAliasErrorExplanation
8import Control.Arrow (first)
9import Control.Monad (foldM)
10import Control.Monad.Error (throwError)
11import qualified Data.Graph as Graph
12import qualified Data.List as List
13import qualified Data.Map as Map
15import qualified AST.Expression.Valid as Valid
17import AST.Module (Interface(iAdts, iTypes, iAliases))
18import qualified AST.Module as Module
19import qualified AST.Type as Type
20import qualified AST.Variable as Var
21import qualified AST.Declaration as D
22import AST.PrettyPrint (pretty, eightyCharLines)
23import qualified AST.Pattern as P
24import Text.PrettyPrint as P
26import Transform.Canonicalize.Environment as Env
27import qualified Transform.Canonicalize.Type as Canonicalize
28import qualified Transform.Interface as Interface
31environment :: Module.Interfaces -> Module.ValidModule -> Canonicalizer [Doc] Environment
32environment interfaces modul@(Module.Module _ _ _ imports decls) =
33 do () <- allImportsAvailable
38 foldM (addImports moduleName interfaces) (builtIns moduleName) imports
41 List.foldl' (addDecl moduleName) ([], nonLocalEnv) decls
43 addTypeAliases moduleName aliases env
46 allImportsAvailable :: Canonicalizer [Doc] ()
48 case filter (not . found) modules of
50 missings -> throwError [ P.text (missingModuleError missings) ]
56 Map.member m interfaces || Module.nameIsNative m
58 missingModuleError missings =
60 [ "The following imports were not found:\n "
61 , List.intercalate ", " (map Module.nameToString missings)
69 -> (Module.Name, Module.ImportMethod)
70 -> Canonicalizer [Doc] Environment
71addImports moduleName interfaces environ (name, method)
72 | Module.nameIsNative name =
76 let (Module.ImportMethod maybeAlias listing) = method
78 (Var.Listing exposedVars open) = listing
81 maybe (Module.nameToString name) id maybeAlias
84 updateEnviron (qualifier ++ ".") environ
87 then return (updateEnviron "" env)
88 else foldM (addValue name interface) env exposedVars
91 Interface.filterExports ((Map.!) interfaces name)
93 updateEnviron prefix env =
94 let dict' = dict . map (first (prefix++)) in
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
103 canonical :: String -> Var.Canonical
105 Var.Canonical (Var.Module name)
107 pair :: String -> (String, Var.Canonical)
111 alias (x,(tvars,tipe)) =
112 (x, (canonical x, tvars, tipe))
116 (map (pair . fst) . snd . snd)
117 (Map.toList (iAdts interface))
125 -> Canonicalizer [Doc] Environment
126addValue moduleName interface env value =
127 let name = Module.nameToString moduleName
128 insert' x = insert x (Var.Canonical (Var.Module moduleName) x)
129 msg x = "Import Error: Could not import value '" ++ name ++ "." ++ x ++
130 "'.\n It is not exported by module " ++ name ++ "."
131 notFound x = throwError [ P.text (msg x) ]
135 | Map.notMember x (iTypes interface) ->
139 return $ env { _values = insert' x (_values env) }
142 case Map.lookup x (iAliases interface) of
145 { _aliases = insert x v (_aliases env)
146 , _values = updatedValues
149 v = (Var.Canonical (Var.Module moduleName) x, tvars, t)
151 if Map.member x (iTypes interface)
152 then insert' x (_values env)
156 case Map.lookup x (iAdts interface) of
157 Nothing -> notFound x
159 return $ env { _adts = insert' x (_adts env) }
161 Var.Union x (Var.Listing xs open) ->
162 case Map.lookup x (iAdts interface) of
163 Nothing -> notFound x
164 Just (_tvars, ctors) ->
165 do ctors' <- filterNames (map fst ctors)
167 { _adts = insert' x (_adts env)
168 , _values = foldr insert' (_values env) ctors'
169 , _patterns = foldr insert' (_patterns env) ctors'
173 | open = return names
175 case filter (`notElem` names) xs of
180type Node = ((String, [String], Type.RawType), String, [String])
183node :: String -> [String] -> Type.RawType -> Node
184node name tvars alias =
185 ((name, tvars, alias), name, edges alias)
189 Type.Lambda t1 t2 -> edges t1 ++ edges t2
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
201 -> Canonicalizer [Doc] Environment
202addTypeAliases moduleName nodes environ =
203 foldM (addTypeAlias moduleName) environ (Graph.stronglyConnComp nodes)
209 -> Graph.SCC (String, [String], Type.RawType)
210 -> Canonicalizer [Doc] Environment
211addTypeAlias moduleName env scc =
212 case Graph.flattenSCC scc of
213 [(name, tvars, alias)] ->
214 do alias' <- Env.onError throw (Canonicalize.tipe env alias)
215 let value = (Var.Canonical (Var.Module moduleName) name, tvars, alias')
216 return $ env { _aliases = insert name value (_aliases env) }
219 let msg = "Problem with type alias '" ++ name ++ "':"
220 in P.vcat [ P.text msg, P.text err ]
225 [ P.text (eightyCharLines 0 mutuallyRecursiveMessage)
226 , indented (map typeAlias aliases)
227 , P.text (eightyCharLines 0 typeAliasErrorSegue)
228 , indented (map datatype aliases)
229 , P.text (eightyCharLines 0 typeAliasErrorExplanation)
235 :: (String, [String], Type.Type var)
236 -> D.Declaration' port def var
242 :: (String, [String], Type.Type var)
243 -> D.Declaration' port def var
245 D.Datatype n ts [(n,[t])]
248indented :: [D.ValidDecl] -> Doc
249indented decls = P.vcat (map prty decls) <> P.text "\n"
251 prty decl = P.text "\n " <> pretty decl
254mutuallyRecursiveMessage :: String
255mutuallyRecursiveMessage =
256 "The following type aliases are mutually recursive, forming an \
257 \infinite type. When you expand them, they just keep getting bigger:"
260typeAliasErrorSegue :: String
265typeAliasErrorExplanation :: String
266typeAliasErrorExplanation =
267 "It looks very similar, but the 'type' keyword creates a brand new type, \
268 \not just an alias for an existing one. This lets us avoid infinitely \
269 \expanding it during type inference."
272-- When canonicalizing, all _values should be Local, but all _adts and _patterns
273-- should be fully namespaced. With _adts, they may appear in types that can
277 -> ([Node], Environment)
279 -> ([Node], Environment)
280addDecl moduleName info@(nodes,env) decl =
281 let namespacedVar = Var.Canonical (Var.Module moduleName)
282 addLocal x e = insert x (Var.local x) e
283 addNamespaced x e = insert x (namespacedVar x) e
286 D.Definition (Valid.Definition pattern _ _) ->
289 foldr addLocal (_values env) (P.boundVarList pattern)
292 D.Datatype name _ ctors ->
295 addCtors addLocal (_values env)
297 addNamespaced name (_adts env)
299 addCtors addNamespaced (_patterns env)
302 addCtors how e = foldr how e (map fst ctors)
304 D.TypeAlias name tvars alias ->
305 (,) (node name tvars alias : nodes) $ env
309 addLocal name (_values env)
317 addLocal (D.wireName wire) (_values env)
320 D.Fixity _ _ _ -> info
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list