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
34 -> Canonicalizer [Doc] Environment
35environment interfaces modul@(Module.Module _ _ _ imports decls) =
36 do () <- allImportsAvailable
41 foldM (addImports moduleName interfaces) (builtIns moduleName) imports
44 List.foldl' (addDecl moduleName) ([], nonLocalEnv) decls
46 addTypeAliases moduleName aliases env
49 allImportsAvailable :: Canonicalizer [Doc] ()
51 case filter (not . found) modules of
53 missings -> throwError [ P.text (missingModuleError missings) ]
59 Map.member m interfaces || Module.nameIsNative m
61 missingModuleError missings =
63 [ "The following imports were not found:\n "
64 , List.intercalate ", " (map Module.nameToString missings)
72 -> (Module.Name, Module.ImportMethod)
73 -> Canonicalizer [Doc] Environment
74addImports moduleName interfaces environ (name, method)
75 | Module.nameIsNative name =
79 let (Module.ImportMethod maybeAlias listing) = method
81 (Var.Listing exposedVars open) = listing
84 maybe (Module.nameToString name) id maybeAlias
87 updateEnviron (qualifier ++ ".") environ
90 then return (updateEnviron "" env)
91 else foldM (addValue name interface) env exposedVars
94 Interface.filterExports ((Map.!) interfaces name)
96 updateEnviron prefix env =
97 let dict' = dict . map (first (prefix++)) in
99 Env { _home = moduleName
100 , _values = dict' $ map pair (Map.keys (iTypes interface)) ++ ctors
101 , _adts = dict' $ map pair (Map.keys (iAdts interface))
102 , _aliases = dict' $ map alias (Map.toList (iAliases interface))
103 , _patterns = dict' $ ctors
106 canonical :: String -> Var.Canonical
108 Var.Canonical (Var.Module name)
110 pair :: String -> (String, Var.Canonical)
114 alias (x,(tvars,tipe)) =
115 (x, (canonical x, tvars, tipe))
119 (map (pair . fst) . snd . snd)
120 (Map.toList (iAdts interface))
128 -> Canonicalizer [Doc] Environment
129addValue moduleName interface env value =
130 let name = Module.nameToString moduleName
131 insert' x = insert x (Var.Canonical (Var.Module moduleName) x)
132 msg x = "Import Error: Could not import value '" ++ name ++ "." ++ x ++
133 "'.\n It is not exported by module " ++ name ++ "."
134 notFound x = throwError [ P.text (msg x) ]
138 | Map.notMember x (iTypes interface) ->
142 return $ env { _values = insert' x (_values env) }
145 case Map.lookup x (iAliases interface) of
148 { _aliases = insert x v (_aliases env)
149 , _values = updatedValues
152 v = (Var.Canonical (Var.Module moduleName) x, tvars, t)
154 if Map.member x (iTypes interface)
155 then insert' x (_values env)
159 case Map.lookup x (iAdts interface) of
160 Nothing -> notFound x
162 return $ env { _adts = insert' x (_adts env) }
164 Var.Union x (Var.Listing xs open) ->
165 case Map.lookup x (iAdts interface) of
166 Nothing -> notFound x
167 Just (_tvars, ctors) ->
168 do ctors' <- filterNames (map fst ctors)
170 { _adts = insert' x (_adts env)
171 , _values = foldr insert' (_values env) ctors'
172 , _patterns = foldr insert' (_patterns env) ctors'
176 | open = return names
178 case filter (`notElem` names) xs of
183type Node = ((String, [String], Type.RawType), String, [String])
186node :: String -> [String] -> Type.RawType -> Node
187node name tvars alias =
188 ((name, tvars, alias), name, edges alias)
198 Type.Type (Var.Raw x) ->
202 edges t ++ concatMap edges ts
204 Type.Record fs ext ->
205 maybe [] edges ext ++ concatMap (edges . snd) fs
207 Type.Aliased _ args t ->
208 edges t ++ concatMap (edges . snd) args
215 -> Canonicalizer [Doc] Environment
216addTypeAliases moduleName nodes environ =
217 foldM (addTypeAlias moduleName) environ (Graph.stronglyConnComp nodes)
223 -> Graph.SCC (String, [String], Type.RawType)
224 -> Canonicalizer [Doc] Environment
225addTypeAlias moduleName env scc =
226 case Graph.flattenSCC scc of
227 [(name, tvars, alias)] ->
228 do alias' <- Env.onError throw (Canonicalize.tipe env alias)
229 let value = (Var.Canonical (Var.Module moduleName) name, tvars, alias')
230 return $ env { _aliases = insert name value (_aliases env) }
233 let msg = "Problem with type alias '" ++ name ++ "':"
234 in P.vcat [ P.text msg, P.text err ]
239 [ P.text (eightyCharLines 0 mutuallyRecursiveMessage)
240 , indented (map typeAlias aliases)
241 , P.text (eightyCharLines 0 typeAliasErrorSegue)
242 , indented (map datatype aliases)
243 , P.text (eightyCharLines 0 typeAliasErrorExplanation)
249 :: (String, [String], Type.Type var)
250 -> D.Declaration' wire def var
256 :: (String, [String], Type.Type var)
257 -> D.Declaration' wire def var
259 D.Datatype n ts [(n,[t])]
262indented :: [D.ValidDecl] -> Doc
264 P.vcat (map prty decls) <> P.text "\n"
266 prty decl = P.text "\n " <> pretty decl
269mutuallyRecursiveMessage :: String
270mutuallyRecursiveMessage =
271 "The following type aliases are mutually recursive, forming an \
272 \infinite type. When you expand them, they just keep getting bigger:"
275typeAliasErrorSegue :: String
280typeAliasErrorExplanation :: String
281typeAliasErrorExplanation =
282 "It looks very similar, but the 'type' keyword creates a brand new type, \
283 \not just an alias for an existing one. This lets us avoid infinitely \
284 \expanding it during type inference."
287-- When canonicalizing, all _values should be Local, but all _adts and _patterns
288-- should be fully namespaced. With _adts, they may appear in types that can
292 -> ([Node], Environment)
294 -> ([Node], Environment)
295addDecl moduleName info@(nodes,env) decl =
296 let namespacedVar = Var.Canonical (Var.Module moduleName)
297 addLocal x e = insert x (Var.local x) e
298 addNamespaced x e = insert x (namespacedVar x) e
301 D.Definition (Valid.Definition pattern _ _) ->
304 foldr addLocal (_values env) (P.boundVarList pattern)
307 D.Datatype name _ ctors ->
310 addCtors addLocal (_values env)
312 addNamespaced name (_adts env)
314 addCtors addNamespaced (_patterns env)
317 addCtors how e = foldr how e (map fst ctors)
319 D.TypeAlias name tvars alias ->
320 (,) (node name tvars alias : nodes) $ env
324 addLocal name (_values env)
332 addLocal (D.wireName wire) (_values env)
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