1module Transform.Canonicalize (module') where
3import Control.Applicative ((<$>),(<*>))
4import Control.Monad.Error (runErrorT, throwError)
5import Control.Monad.State (runState)
6import qualified Data.List as List
7import qualified Data.Map as Map
8import qualified Data.Set as Set
9import qualified Data.Traversable as T
11import AST.Expression.General (Expr'(..), dummyLet)
12import qualified AST.Expression.Valid as Valid
13import qualified AST.Expression.Canonical as Canonical
15import AST.Module (CanonicalBody(..))
16import qualified AST.Module as Module
17import qualified AST.Type as Type
18import qualified AST.Variable as Var
19import qualified AST.Annotation as A
20import qualified AST.Declaration as D
21import AST.PrettyPrint (pretty, commaSep)
22import qualified AST.Pattern as P
23import Text.PrettyPrint as P
25import qualified Transform.Canonicalize.Environment as Env
26import qualified Transform.Canonicalize.Setup as Setup
27import qualified Transform.Canonicalize.Type as Canonicalize
28import qualified Transform.Canonicalize.Variable as Canonicalize
29import qualified Transform.SortDefinitions as Transform
30import qualified Transform.Declaration as Transform
36 -> Either [Doc] Module.CanonicalModule
37module' interfaces modul =
38 filterImports <$> modul'
40 (modul', usedModules) =
41 runState (runErrorT (moduleHelp interfaces modul)) Set.empty
44 let used (name,_) = Set.member name usedModules
46 m { Module.imports = filter used (Module.imports m) }
52 -> Env.Canonicalizer [Doc] Module.CanonicalModule
53moduleHelp interfaces modul@(Module.Module _ _ exports _ decls) =
54 do env <- Setup.environment interfaces modul
55 canonicalDecls <- mapM (declaration env) decls
56 exports' <- resolveExports locals exports
58 { Module.exports = exports'
59 , Module.body = body canonicalDecls
63 locals = concatMap declToValue decls
65 body :: [D.CanonicalDecl] -> Module.CanonicalBody
69 let expr = Transform.toExpr (Module.names modul) decls
70 in Transform.sortDefs (dummyLet expr)
73 Map.fromList [ (name,(vars,ctors)) | D.Datatype name vars ctors <- decls ]
75 [ (assoc,level,op) | D.Fixity assoc level op <- decls ]
77 Map.fromList [ (name,(tvs,alias)) | D.TypeAlias name tvs alias <- decls ]
79 [ D.wireName wire | D.Wire wire <- decls ]
85 -> Var.Listing Var.Value
86 -> Env.Canonicalizer [Doc] [Var.Value]
87resolveExports fullList (Var.Listing partialList open) =
91 valueExports <- getValueExports
92 aliasExports <- concat `fmap` mapM getAliasExport aliases
93 adtExports <- mapM getAdtExport adts
94 return $ valueExports ++ aliasExports ++ adtExports
96 (allValues, allAliases, allAdts) = splitValues fullList
98 (values, aliases, adts) = splitValues partialList
101 case Set.toList (Set.difference values' allValues') of
102 [] -> return (map Var.Value values)
105 allValues' = Set.fromList allValues
106 values' = Set.fromList values
109 | alias `elem` allAliases =
110 let recordConstructor =
111 if alias `elem` allValues then [Var.Value alias] else []
113 return $ Var.Alias alias : recordConstructor
116 case List.find (\(name, _ctors) -> name == alias) allAdts of
117 Nothing -> notFound [alias]
118 Just (name, _ctor) ->
119 return [Var.Union name (Var.Listing [] False)]
121 getAdtExport (name, Var.Listing ctors open) =
122 case lookup name allAdts of
123 Nothing -> notFound [name]
124 Just (Var.Listing allCtors _)
125 | open -> return $ Var.Union name (Var.Listing allCtors False)
127 case filter (`notElem` allCtors) ctors of
128 [] -> return $ Var.Union name (Var.Listing ctors False)
129 unfoundCtors -> notFound unfoundCtors
132 throwError [ P.text "Export Error: trying to export non-existent values:" <+>
133 commaSep (map pretty xs)
137{-| Split a list of values into categories so we can work with them
140splitValues :: [Var.Value] -> ([String], [String], [(String, Var.Listing String)])
141splitValues mixedValues =
145 let (values, aliases, adts) = splitValues xs in
148 (name : values, aliases, adts)
151 (values, name : aliases, adts)
153 Var.Union name listing ->
154 (values, aliases, (name, listing) : adts)
158declToValue :: D.ValidDecl -> [Var.Value]
161 D.Definition (Valid.Definition pattern _ _) ->
162 map Var.Value (P.boundVarList pattern)
164 D.Datatype name _tvs ctors ->
165 [ Var.Union name (Var.Listing (map fst ctors) False) ]
167 D.TypeAlias name _ tipe ->
170 [ Var.Alias name, Var.Value name ]
171 _ -> [ Var.Alias name ]
179 -> Env.Canonicalizer [Doc] D.CanonicalDecl
180declaration env decl =
181 let canonicalize kind context pattern env v =
182 let ctx = P.text ("Error in " ++ context) <+> pretty pattern <> P.colon
183 throw err = P.vcat [ ctx, P.text err ]
185 Env.onError throw (kind env v)
188 D.Definition (Valid.Definition p e t) ->
189 do p' <- canonicalize pattern "definition" p env p
190 e' <- expression env e
191 t' <- T.traverse (canonicalize Canonicalize.tipe "definition" p env) t
192 return $ D.Definition (Canonical.Definition p' e' t')
194 D.Datatype name tvars ctors ->
195 D.Datatype name tvars <$> mapM canonicalize' ctors
197 canonicalize' (ctor,args) =
198 (,) ctor <$> mapM (canonicalize Canonicalize.tipe "datatype" name env) args
200 D.TypeAlias name tvars expanded ->
201 do expanded' <- canonicalize Canonicalize.tipe "type alias" name env expanded
202 return (D.TypeAlias name tvars expanded')
205 do Env.uses ["Native","Ports"]
206 Env.uses ["Native","Json"]
210 do t' <- canonicalize Canonicalize.tipe "input" name env t
211 return (D.Input name t')
214 do e' <- expression env e
215 t' <- canonicalize Canonicalize.tipe "output" name env t
216 return (D.Output name e' t')
218 D.Loopback name maybeExpr t ->
219 do maybeExpr' <- T.traverse (expression env) maybeExpr
220 t' <- canonicalize Canonicalize.tipe "input" name env t
221 return (D.Loopback name maybeExpr' t')
223 D.Fixity assoc prec op ->
224 return $ D.Fixity assoc prec op
230 -> Env.Canonicalizer [Doc] Canonical.Expr
231expression env (A.A ann expr) =
232 let go = expression env
233 tipe' environ = format . Canonicalize.tipe environ
236 [ P.text "Error" <+> pretty ann <> P.colon
239 format = Env.onError throw
247 Range <$> go e1 <*> go e2
250 Access <$> go e <*> return x
253 flip Remove x <$> go e
256 flip Insert x <$> go e <*> go v
259 Modify <$> go e <*> mapM (\(k,v) -> (,) k <$> go v) fs
262 Record <$> mapM (\(k,v) -> (,) k <$> go v) fs
264 Binop (Var.Raw op) e1 e2 ->
265 do op' <- format (Canonicalize.variable env op)
266 Binop op' <$> go e1 <*> go e2
269 let env' = Env.addPattern p env
271 Lambda <$> format (pattern env' p) <*> expression env' e
274 App <$> go e1 <*> go e2
277 MultiIf <$> mapM go' ps
279 go' (b,e) = (,) <$> go b <*> go e
282 Let <$> mapM rename' defs <*> expression env' e
284 env' = foldr Env.addPattern env $ map (\(Valid.Definition p _ _) -> p) defs
285 rename' (Valid.Definition p body mtipe) =
287 <$> format (pattern env' p)
288 <*> expression env' body
289 <*> T.traverse (tipe' env') mtipe
292 Var <$> format (Canonicalize.variable env x)
295 Data name <$> mapM go es
298 ExplicitList <$> mapM go es
301 Case <$> go e <*> mapM branch cases
304 (,) <$> format (pattern env p)
305 <*> expression (Env.addPattern p env) b
308 Input name <$> tipe' env tipe
310 Output name st signal ->
311 Output name <$> tipe' env st <*> go signal
313 Loopback name st maybeExpr ->
314 Loopback name <$> tipe' env st <*> T.traverse go maybeExpr
316 GLShader uid src tipe ->
317 return (GLShader uid src tipe)
323 -> Env.Canonicalizer String P.CanonicalPattern
326 P.Var x -> return $ P.Var x
327 P.Literal lit -> return $ P.Literal lit
328 P.Record fs -> return $ P.Record fs
329 P.Anything -> return P.Anything
330 P.Alias x p -> P.Alias x <$> pattern env p
331 P.Data (Var.Raw name) ps ->
332 P.Data <$> Canonicalize.pvar env name
333 <*> mapM (pattern env) ps
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