@@ -1,8 +1,6 @@
1module Transform.Canonicalize (module') where
1module Transform.Canonicalize (module') where
3import Control.Applicative ((<$>),(<*>))
3import Control.Applicative ((<$>),(<*>))
4−import Control.Monad.Error (runErrorT, throwError)
5−import Control.Monad.State (runState)
6import qualified Data.List as List
4import qualified Data.List as List
7import qualified Data.Map as Map
5import qualified Data.Map as Map
8import qualified Data.Set as Set
6import qualified Data.Set as Set
@@ -14,20 +12,20 @@ import qualified AST.Expression.Valid as Valid
14import qualified AST.Expression.Canonical as Canonical
12import qualified AST.Expression.Canonical as Canonical
16import AST.Module (CanonicalBody(..))
14import AST.Module (CanonicalBody(..))
17−import qualified AST.Module as Module
18−import qualified AST.Type as Type
19−import qualified AST.Variable as Var
20import qualified AST.Annotation as A
15import qualified AST.Annotation as A
21import qualified AST.Declaration as D
16import qualified AST.Declaration as D
22−import AST.PrettyPrint (pretty, commaSep)
17+import qualified AST.Module as Module
23import qualified AST.Pattern as P
18import qualified AST.Pattern as P
24−import Text.PrettyPrint as P
19+import qualified AST.Type as Type
20+import qualified AST.Variable as Var
26import qualified Transform.Canonicalize.Environment as Env
22import qualified Transform.Canonicalize.Environment as Env
23+import qualified Transform.Canonicalize.Error as Error
24+import qualified Transform.Canonicalize.Port as Port
25+import qualified Transform.Canonicalize.Result as Result
27import qualified Transform.Canonicalize.Setup as Setup
26import qualified Transform.Canonicalize.Setup as Setup
28import qualified Transform.Canonicalize.Type as Canonicalize
27import qualified Transform.Canonicalize.Type as Canonicalize
29import qualified Transform.Canonicalize.Variable as Canonicalize
28import qualified Transform.Canonicalize.Variable as Canonicalize
30−import qualified Transform.Canonicalize.Port as Port
31import qualified Transform.SortDefinitions as Transform
29import qualified Transform.SortDefinitions as Transform
32import qualified Transform.Declaration as Transform
30import qualified Transform.Declaration as Transform
@@ -35,111 +33,130 @@ import qualified Transform.Declaration as Transform
36 :: Module.Interfaces
34 :: Module.Interfaces
37 -> Module.ValidModule
35 -> Module.ValidModule
38− -> Either [Doc] Module.CanonicalModule
36+ -> ([Module.Name], Either [Error.Error] Module.CanonicalModule)
39−module' interfaces modul =
37+module' interfaces modul@(Module.Module _ _ _ imports _) =
40− filterImports <$> modul'
38+ let (Result.Result uses rawResults) =
42− (modul', usedModules) =
43− runState (runErrorT (moduleHelp interfaces modul)) Set.empty
39+ moduleHelp interfaces modul
45− filterImports m =
41+ unusedImports =
46− let used (name,_) = Set.member name usedModules
42+ filter (\name -> not (Set.member name uses)) (map fst imports)
46+ Result.Ok canonicalModule ->
47+ Right canonicalModule
48− m { Module.imports = filter used (Module.imports m) }
52+ (unusedImports, either)
52 :: Module.Interfaces
56 :: Module.Interfaces
53 -> Module.ValidModule
57 -> Module.ValidModule
54− -> Env.Canonicalizer [Doc] Module.CanonicalModule
58+ -> Result.Result Module.CanonicalModule
55moduleHelp interfaces modul@(Module.Module _ _ exports _ decls) =
59moduleHelp interfaces modul@(Module.Module _ _ exports _ decls) =
56− do env <- Setup.environment interfaces modul
60+ canonicalModule
57− canonicalDecls <- mapM (declaration env) decls
61+ <$> canonicalDeclsResult
58− exports' <- resolveExports locals exports
62+ <*> resolveExports locals exports
60− { Module.exports = exports'
61− , Module.body = body canonicalDecls
64+ canonicalModule canonicalDecls canonicalExports =
66+ { Module.exports = canonicalExports
67+ , Module.body = body canonicalDecls
64 locals :: [Var.Value]
70 locals :: [Var.Value]
65− locals = concatMap declToValue decls
72+ concatMap declToValue decls
74+ canonicalDeclsResult =
75+ Setup.environment interfaces modul
76+ `Result.andThen` \env -> T.traverse (declaration env) decls
67 body :: [D.CanonicalDecl] -> Module.CanonicalBody
78 body :: [D.CanonicalDecl] -> Module.CanonicalBody
68 body decls =
79 body decls =
69− Module.CanonicalBody
80+ Module.CanonicalBody
70− { program =
81+ { program =
71− let expr = Transform.toExpr (Module.names modul) decls
82+ let expr = Transform.toExpr (Module.names modul) decls
72− in Transform.sortDefs (dummyLet expr)
83+ in Transform.sortDefs (dummyLet expr)
73− , types = Map.empty
84+ , types = Map.empty
74− , datatypes =
85+ , datatypes =
75− Map.fromList [ (name,(vars,ctors)) | D.Datatype name vars ctors <- decls ]
86+ Map.fromList [ (name,(vars,ctors)) | D.Datatype name vars ctors <- decls ]
76− , fixities =
87+ , fixities =
77− [ (assoc,level,op) | D.Fixity assoc level op <- decls ]
88+ [ (assoc,level,op) | D.Fixity assoc level op <- decls ]
78− , aliases =
89+ , aliases =
79− Map.fromList [ (name,(tvs,alias)) | D.TypeAlias name tvs alias <- decls ]
90+ Map.fromList [ (name,(tvs,alias)) | D.TypeAlias name tvs alias <- decls ]
80− , ports =
91+ , ports =
81− [ E.portName impl | D.Port (D.CanonicalPort impl) <- decls ]
92+ [ E.portName impl | D.Port (D.CanonicalPort impl) <- decls ]
85resolveExports
96resolveExports
86 :: [Var.Value]
97 :: [Var.Value]
87 -> Var.Listing Var.Value
98 -> Var.Listing Var.Value
88− -> Env.Canonicalizer [Doc] [Var.Value]
99+ -> Result.Result [Var.Value]
89resolveExports fullList (Var.Listing partialList open) =
100resolveExports fullList (Var.Listing partialList open) =
91− then return fullList
102+ then Result.ok fullList
104+ (\xs ys zs -> xs ++ ys ++ zs)
93− valueExports <- getValueExports
105+ <$> getValueExports
94− aliasExports <- concat `fmap` mapM getAliasExport aliases
106+ <*> (concat <$> T.traverse getAliasExport aliases)
95− adtExports <- mapM getAdtExport adts
107+ <*> T.traverse getAdtExport adts
96− return $ valueExports ++ aliasExports ++ adtExports
108+ where
98− (allValues, allAliases, allAdts) = splitValues fullList
109+ (allValues, allAliases, allAdts) =
99−
110+ splitValues fullList
112+ (values, aliases, adts) =
100− (values, aliases, adts) = splitValues partialList
113+ splitValues partialList
102− getValueExports =
115+ getValueExports =
103− case Set.toList (Set.difference values' allValues') of
116+ case Set.toList (Set.difference values' allValues') of
104− [] -> return (map Var.Value values)
117+ [] -> Result.ok (map Var.Value values)
105− xs -> notFound xs
118+ xs -> manyNotFound xs allValues
107− allValues' = Set.fromList allValues
120+ allValues' = Set.fromList allValues
108− values' = Set.fromList values
121+ values' = Set.fromList values
110− getAliasExport alias
123+ getAliasExport alias
111− | alias `elem` allAliases =
124+ | alias `elem` allAliases =
112− let recordConstructor =
125+ let recordConstructor =
113− if alias `elem` allValues then [Var.Value alias] else []
126+ if alias `elem` allValues then [Var.Value alias] else []
115− return $ Var.Alias alias : recordConstructor
128+ Result.ok (Var.Alias alias : recordConstructor)
117− | otherwise =
130+ | otherwise =
118− case List.find (\(name, _ctors) -> name == alias) allAdts of
131+ case List.find (\(name, _ctors) -> name == alias) allAdts of
119− Nothing -> notFound [alias]
132+ Nothing -> manyNotFound [alias] allAliases
120− Just (name, _ctor) ->
133+ Just (name, _ctor) ->
121− return [Var.Union name (Var.Listing [] False)]
134+ Result.ok [Var.Union name (Var.Listing [] False)]
123− getAdtExport (name, Var.Listing ctors open) =
136+ getAdtExport (name, Var.Listing ctors open) =
124− case lookup name allAdts of
137+ case lookup name allAdts of
125− Nothing -> notFound [name]
138+ Nothing -> manyNotFound [name] (map fst allAdts)
126− Just (Var.Listing allCtors _)
139+ Just (Var.Listing allCtors _)
127− | open -> return $ Var.Union name (Var.Listing allCtors False)
141+ Result.ok (Var.Union name (Var.Listing allCtors False))
128− | otherwise ->
142+ | otherwise ->
129− case filter (`notElem` allCtors) ctors of
143+ case filter (`notElem` allCtors) ctors of
130− [] -> return $ Var.Union name (Var.Listing ctors False)
144+ [] -> Result.ok (Var.Union name (Var.Listing ctors False))
131− unfoundCtors -> notFound unfoundCtors
145+ unfoundCtors -> manyNotFound unfoundCtors allCtors
133− notFound xs =
147+ manyNotFound nameList possibilities =
134− throwError [ P.text "Export Error: trying to export non-existent values:" <+>
148+ Result.errors (map (notFound possibilities) nameList)
135− commaSep (map pretty xs)
149+
136− ]
150+ notFound possibilities name =
151+ Error.Export name (Error.nearbyNames id name possibilities)
139{-| Split a list of values into categories so we can work with them
154{-| Split a list of values into categories so we can work with them
140independently.
155independently.
142−splitValues :: [Var.Value] -> ([String], [String], [(String, Var.Listing String)])
159+ -> ([String], [String], [(String, Var.Listing String)])
143splitValues mixedValues =
160splitValues mixedValues =
144 case mixedValues of
161 case mixedValues of
145 [] -> ([], [], [])
162 [] -> ([], [], [])
@@ -156,7 +173,6 @@ splitValues mixedValues =
156 (values, aliases, (name, listing) : adts)
173 (values, aliases, (name, listing) : adts)
160declToValue :: D.ValidDecl -> [Var.Value]
176declToValue :: D.ValidDecl -> [Var.Value]
161declToValue decl =
177declToValue decl =
162 case decl of
178 case decl of
@@ -178,75 +194,73 @@ declToValue decl =
178declaration
194declaration
179 :: Env.Environment
195 :: Env.Environment
180 -> D.ValidDecl
196 -> D.ValidDecl
181− -> Env.Canonicalizer [Doc] D.CanonicalDecl
197+ -> Result.Result D.CanonicalDecl
182declaration env decl =
198declaration env decl =
183− let canonicalize kind context pattern env v =
199+ let canonicalize kind _context _pattern env v =
184− let ctx = P.text ("Error in " ++ context) <+> pretty pattern <> P.colon
185− throw err = P.vcat [ ctx, P.text err ]
187− Env.onError throw (kind env v)
200+ kind env v
189 case decl of
202 case decl of
190 D.Definition (Valid.Definition p e t) ->
203 D.Definition (Valid.Definition p e t) ->
205+ Canonical.Definition
191− do p' <- canonicalize pattern "definition" p env p
206+ <$> canonicalize pattern "definition" p env p
192− e' <- expression env e
207+ <*> expression env e
193− t' <- T.traverse (canonicalize Canonicalize.tipe "definition" p env) t
208+ <*> T.traverse (canonicalize Canonicalize.tipe "definition" p env) t
194− return $ D.Definition (Canonical.Definition p' e' t')
209+ )
196 D.Datatype name tvars ctors ->
211 D.Datatype name tvars ctors ->
197− D.Datatype name tvars <$> mapM canonicalize' ctors
212+ D.Datatype name tvars <$> T.traverse canonicalize' ctors
199 canonicalize' (ctor,args) =
214 canonicalize' (ctor,args) =
200− (,) ctor <$> mapM (canonicalize Canonicalize.tipe "datatype" name env) args
215+ (,) ctor <$> T.traverse (canonicalize Canonicalize.tipe "datatype" name env) args
202 D.TypeAlias name tvars expanded ->
217 D.TypeAlias name tvars expanded ->
218+ D.TypeAlias name tvars
203− do expanded' <- canonicalize Canonicalize.tipe "type alias" name env expanded
219+ <$> canonicalize Canonicalize.tipe "type alias" name env expanded
204− return (D.TypeAlias name tvars expanded')
206 D.Port validPort ->
221 D.Port validPort ->
207− do Env.uses ["Native","Port"]
222+ Result.addModule ["Native","Port"] $
208− Env.uses ["Native","Json"]
223+ Result.addModule ["Native","Json"] $
209 case validPort of
224 case validPort of
210 D.In name tipe ->
225 D.In name tipe ->
211− do tipe' <- canonicalize Canonicalize.tipe "port" name env tipe
226+ canonicalize Canonicalize.tipe "port" name env tipe
227+ `Result.andThen` \canonicalType ->
212− port' <- Port.check name Nothing tipe'
228+ D.Port <$> Port.check name Nothing canonicalType
213− return (D.Port port')
216 D.Out name expr tipe ->
230 D.Out name expr tipe ->
231+ let exprTypeResult =
217− do expr' <- expression env expr
233+ <$> expression env expr
218− tipe' <- canonicalize Canonicalize.tipe "port" name env tipe
234+ <*> canonicalize Canonicalize.tipe "port" name env tipe
237+ `Result.andThen` \(expr', tipe') ->
219− port' <- Port.check name (Just expr') tipe'
238+ D.Port <$> Port.check name (Just expr') tipe'
220− return (D.Port port')
222 D.Fixity assoc prec op ->
240 D.Fixity assoc prec op ->
223− return $ D.Fixity assoc prec op
241+ Result.ok (D.Fixity assoc prec op)
226expression
244expression
227 :: Env.Environment
245 :: Env.Environment
228 -> Valid.Expr
246 -> Valid.Expr
229− -> Env.Canonicalizer [Doc] Canonical.Expr
247+ -> Result.Result Canonical.Expr
230expression env (A.A ann validExpr) =
248expression env (A.A ann validExpr) =
231 let go = expression env
249 let go = expression env
232− tipe' environ = format . Canonicalize.tipe environ
250+ tipe' environ =
233− throw err =
251+ format . Canonicalize.tipe environ
235− [ P.text "Error" <+> pretty ann <> P.colon
238− format = Env.onError throw
252+ format = id
240 A.A ann <$>
254 A.A ann <$>
241 case validExpr of
255 case validExpr of
242 Literal lit ->
256 Literal lit ->
243− return (Literal lit)
257+ Result.ok (Literal lit)
245 Range lowExpr highExpr ->
259 Range lowExpr highExpr ->
246 Range <$> go lowExpr <*> go highExpr
260 Range <$> go lowExpr <*> go highExpr
248 Access record field ->
262 Access record field ->
249− Access <$> go record <*> return field
263+ Access <$> go record <*> Result.ok field
251 Remove record field ->
265 Remove record field ->
252 flip Remove field <$> go record
266 flip Remove field <$> go record
@@ -257,15 +271,17 @@ expression env (A.A ann validExpr) =
257 Modify record fields ->
271 Modify record fields ->
259 <$> go record
273 <$> go record
260− <*> mapM (\(field,expr) -> (,) field <$> go expr) fields
274+ <*> T.traverse (\(field,expr) -> (,) field <$> go expr) fields
262 Record fields ->
276 Record fields ->
264− <$> mapM (\(field,expr) -> (,) field <$> go expr) fields
278+ <$> T.traverse (\(field,expr) -> (,) field <$> go expr) fields
266 Binop (Var.Raw op) leftExpr rightExpr ->
280 Binop (Var.Raw op) leftExpr rightExpr ->
267− do op' <- format (Canonicalize.variable env op)
282+ <$> format (Canonicalize.variable env op)
268− Binop op' <$> go leftExpr <*> go rightExpr
284+ <*> go rightExpr
270 Lambda arg body ->
286 Lambda arg body ->
271 let env' = Env.addPattern arg env
287 let env' = Env.addPattern arg env
@@ -276,13 +292,13 @@ expression env (A.A ann validExpr) =
276 App <$> go func <*> go arg
292 App <$> go func <*> go arg
278 MultiIf branches ->
294 MultiIf branches ->
279− MultiIf <$> mapM go' branches
295+ MultiIf <$> T.traverse go' branches
281 go' (condition, branch) =
297 go' (condition, branch) =
282 (,) <$> go condition <*> go branch
298 (,) <$> go condition <*> go branch
284 Let defs body ->
300 Let defs body ->
285− Let <$> mapM rename' defs <*> expression env' body
301+ Let <$> T.traverse rename' defs <*> expression env' body
288 foldr Env.addPattern env $ map (\(Valid.Definition p _ _) -> p) defs
304 foldr Env.addPattern env $ map (\(Valid.Definition p _ _) -> p) defs
@@ -297,13 +313,13 @@ expression env (A.A ann validExpr) =
297 Var <$> format (Canonicalize.variable env x)
313 Var <$> format (Canonicalize.variable env x)
299 Data name exprs ->
315 Data name exprs ->
300− Data name <$> mapM go exprs
316+ Data name <$> T.traverse go exprs
302 ExplicitList exprs ->
318 ExplicitList exprs ->
303− ExplicitList <$> mapM go exprs
319+ ExplicitList <$> T.traverse go exprs
305 Case expr cases ->
321 Case expr cases ->
306− Case <$> go expr <*> mapM branch cases
322+ Case <$> go expr <*> T.traverse branch cases
308 branch (p,b) =
324 branch (p,b) =
309 (,) <$> format (pattern env p)
325 (,) <$> format (pattern env p)
@@ -330,20 +346,31 @@ expression env (A.A ann validExpr) =
330 E.Task name <$> go expr <*> portType tipe
346 E.Task name <$> go expr <*> portType tipe
332 GLShader uid src tipe ->
348 GLShader uid src tipe ->
333− return (GLShader uid src tipe)
349+ Result.ok (GLShader uid src tipe)
337 :: Env.Environment
353 :: Env.Environment
338 -> P.RawPattern
354 -> P.RawPattern
339− -> Env.Canonicalizer String P.CanonicalPattern
355+ -> Result.Result P.CanonicalPattern
340pattern env ptrn =
356pattern env ptrn =
341 case ptrn of
357 case ptrn of
342− P.Var x -> return $ P.Var x
358+ P.Var x ->
343− P.Literal lit -> return $ P.Literal lit
361+ P.Literal lit ->
362+ Result.ok (P.Literal lit)
344− P.Record fs -> return $ P.Record fs
364+ P.Record fs ->
365+ Result.ok (P.Record fs)
345− P.Anything -> return P.Anything
367+ P.Anything ->
368+ Result.ok P.Anything
346− P.Alias x p -> P.Alias x <$> pattern env p
371+ P.Alias x <$> pattern env p
347 P.Data (Var.Raw name) ps ->
373 P.Data (Var.Raw name) ps ->
348− P.Data <$> Canonicalize.pvar env name
375+ <$> Canonicalize.pvar env name
349− <*> mapM (pattern env) ps
376+ <*> T.traverse (pattern env) ps