@@ -1,8 +1,6 @@
11module Transform.Canonicalize (module') where
22
33import Control.Applicative ((<$>),(<*>))
4−import Control.Monad.Error (runErrorT, throwError)
5−import Control.Monad.State (runState)
64import qualified Data.List as List
75import qualified Data.Map as Map
86import qualified Data.Set as Set
@@ -14,20 +12,20 @@ import qualified AST.Expression.Valid as Valid
1412import qualified AST.Expression.Canonical as Canonical
1513
1614import AST.Module (CanonicalBody(..))
17−import qualified AST.Module as Module
18−import qualified AST.Type as Type
19−import qualified AST.Variable as Var
2015import qualified AST.Annotation as A
2116import qualified AST.Declaration as D
22−import AST.PrettyPrint (pretty, commaSep)
17+import qualified AST.Module as Module
2318import 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
2521
2622import 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
2726import qualified Transform.Canonicalize.Setup as Setup
2827import qualified Transform.Canonicalize.Type as Canonicalize
2928import qualified Transform.Canonicalize.Variable as Canonicalize
30−import qualified Transform.Canonicalize.Port as Port
3129import qualified Transform.SortDefinitions as Transform
3230import qualified Transform.Declaration as Transform
3331
@@ -35,111 +33,130 @@ import qualified Transform.Declaration as Transform
3533module'
3634 :: Module.Interfaces
3735 -> Module.ValidModule
38− -> Either [Doc] Module.CanonicalModule
39−module' interfaces modul =
40− filterImports <$> modul'
41− where
42− (modul', usedModules) =
43− runState (runErrorT (moduleHelp interfaces modul)) Set.empty
36+ -> ([Module.Name], Either [Error.Error] Module.CanonicalModule)
37+module' interfaces modul@(Module.Module _ _ _ imports _) =
38+ let (Result.Result uses rawResults) =
39+ moduleHelp interfaces modul
4440
45− filterImports m =
46− let used (name,_) = Set.member name usedModules
47− in
48− m { Module.imports = filter used (Module.imports m) }
41+ unusedImports =
42+ filter (\name -> not (Set.member name uses)) (map fst imports)
43+
44+ either =
45+ case rawResults of
46+ Result.Ok canonicalModule ->
47+ Right canonicalModule
48+
49+ Result.Err msgs ->
50+ Left msgs
51+ in
52+ (unusedImports, either)
4953
5054
5155moduleHelp
5256 :: Module.Interfaces
5357 -> Module.ValidModule
54− -> Env.Canonicalizer [Doc] Module.CanonicalModule
58+ -> Result.Result Module.CanonicalModule
5559moduleHelp interfaces modul@(Module.Module _ _ exports _ decls) =
56− do env <- Setup.environment interfaces modul
57− canonicalDecls <- mapM (declaration env) decls
58− exports' <- resolveExports locals exports
59− return $ modul
60− { Module.exports = exports'
61− , Module.body = body canonicalDecls
62− }
60+ canonicalModule
61+ <$> canonicalDeclsResult
62+ <*> resolveExports locals exports
6363 where
64+ canonicalModule canonicalDecls canonicalExports =
65+ modul
66+ { Module.exports = canonicalExports
67+ , Module.body = body canonicalDecls
68+ }
69+
6470 locals :: [Var.Value]
65− locals = concatMap declToValue decls
71+ locals =
72+ concatMap declToValue decls
73+
74+ canonicalDeclsResult =
75+ Setup.environment interfaces modul
76+ `Result.andThen` \env -> T.traverse (declaration env) decls
6677
6778 body :: [D.CanonicalDecl] -> Module.CanonicalBody
6879 body decls =
69− Module.CanonicalBody
70− { program =
71− let expr = Transform.toExpr (Module.names modul) decls
72− in Transform.sortDefs (dummyLet expr)
73− , types = Map.empty
74− , datatypes =
75− Map.fromList [ (name,(vars,ctors)) | D.Datatype name vars ctors <- decls ]
76− , fixities =
77− [ (assoc,level,op) | D.Fixity assoc level op <- decls ]
78− , aliases =
79− Map.fromList [ (name,(tvs,alias)) | D.TypeAlias name tvs alias <- decls ]
80− , ports =
81− [ E.portName impl | D.Port (D.CanonicalPort impl) <- decls ]
82− }
80+ Module.CanonicalBody
81+ { program =
82+ let expr = Transform.toExpr (Module.names modul) decls
83+ in Transform.sortDefs (dummyLet expr)
84+ , types = Map.empty
85+ , datatypes =
86+ Map.fromList [ (name,(vars,ctors)) | D.Datatype name vars ctors <- decls ]
87+ , fixities =
88+ [ (assoc,level,op) | D.Fixity assoc level op <- decls ]
89+ , aliases =
90+ Map.fromList [ (name,(tvs,alias)) | D.TypeAlias name tvs alias <- decls ]
91+ , ports =
92+ [ E.portName impl | D.Port (D.CanonicalPort impl) <- decls ]
93+ }
8394
8495
8596resolveExports
8697 :: [Var.Value]
8798 -> Var.Listing Var.Value
88− -> Env.Canonicalizer [Doc] [Var.Value]
99+ -> Result.Result [Var.Value]
89100resolveExports fullList (Var.Listing partialList open) =
90− if open
91− then return fullList
92− else do
93− valueExports <- getValueExports
94− aliasExports <- concat `fmap` mapM getAliasExport aliases
95− adtExports <- mapM getAdtExport adts
96− return $ valueExports ++ aliasExports ++ adtExports
97− where
98− (allValues, allAliases, allAdts) = splitValues fullList
99−
100− (values, aliases, adts) = splitValues partialList
101−
102− getValueExports =
103− case Set.toList (Set.difference values' allValues') of
104− [] -> return (map Var.Value values)
105− xs -> notFound xs
106− where
107− allValues' = Set.fromList allValues
108− values' = Set.fromList values
109−
110− getAliasExport alias
111− | alias `elem` allAliases =
112− let recordConstructor =
113− if alias `elem` allValues then [Var.Value alias] else []
114− in
115− return $ Var.Alias alias : recordConstructor
116−
117− | otherwise =
118− case List.find (\(name, _ctors) -> name == alias) allAdts of
119− Nothing -> notFound [alias]
120− Just (name, _ctor) ->
121− return [Var.Union name (Var.Listing [] False)]
122−
123− getAdtExport (name, Var.Listing ctors open) =
124− case lookup name allAdts of
125− Nothing -> notFound [name]
126− Just (Var.Listing allCtors _)
127− | open -> return $ Var.Union name (Var.Listing allCtors False)
128− | otherwise ->
129− case filter (`notElem` allCtors) ctors of
130− [] -> return $ Var.Union name (Var.Listing ctors False)
131− unfoundCtors -> notFound unfoundCtors
132−
133− notFound xs =
134− throwError [ P.text "Export Error: trying to export non-existent values:" <+>
135− commaSep (map pretty xs)
136− ]
101+ if open
102+ then Result.ok fullList
103+ else
104+ (\xs ys zs -> xs ++ ys ++ zs)
105+ <$> getValueExports
106+ <*> (concat <$> T.traverse getAliasExport aliases)
107+ <*> T.traverse getAdtExport adts
108+ where
109+ (allValues, allAliases, allAdts) =
110+ splitValues fullList
111+
112+ (values, aliases, adts) =
113+ splitValues partialList
114+
115+ getValueExports =
116+ case Set.toList (Set.difference values' allValues') of
117+ [] -> Result.ok (map Var.Value values)
118+ xs -> manyNotFound xs allValues
119+ where
120+ allValues' = Set.fromList allValues
121+ values' = Set.fromList values
122+
123+ getAliasExport alias
124+ | alias `elem` allAliases =
125+ let recordConstructor =
126+ if alias `elem` allValues then [Var.Value alias] else []
127+ in
128+ Result.ok (Var.Alias alias : recordConstructor)
129+
130+ | otherwise =
131+ case List.find (\(name, _ctors) -> name == alias) allAdts of
132+ Nothing -> manyNotFound [alias] allAliases
133+ Just (name, _ctor) ->
134+ Result.ok [Var.Union name (Var.Listing [] False)]
135+
136+ getAdtExport (name, Var.Listing ctors open) =
137+ case lookup name allAdts of
138+ Nothing -> manyNotFound [name] (map fst allAdts)
139+ Just (Var.Listing allCtors _)
140+ | open ->
141+ Result.ok (Var.Union name (Var.Listing allCtors False))
142+ | otherwise ->
143+ case filter (`notElem` allCtors) ctors of
144+ [] -> Result.ok (Var.Union name (Var.Listing ctors False))
145+ unfoundCtors -> manyNotFound unfoundCtors allCtors
146+
147+ manyNotFound nameList possibilities =
148+ Result.errors (map (notFound possibilities) nameList)
149+
150+ notFound possibilities name =
151+ Error.Export name (Error.nearbyNames id name possibilities)
137152
138153
139154{-| Split a list of values into categories so we can work with them
140155independently.
141156-}
142−splitValues :: [Var.Value] -> ([String], [String], [(String, Var.Listing String)])
157+splitValues
158+ :: [Var.Value]
159+ -> ([String], [String], [(String, Var.Listing String)])
143160splitValues mixedValues =
144161 case mixedValues of
145162 [] -> ([], [], [])
@@ -156,7 +173,6 @@ splitValues mixedValues =
156173 (values, aliases, (name, listing) : adts)
157174
158175
159−
160176declToValue :: D.ValidDecl -> [Var.Value]
161177declToValue decl =
162178 case decl of
@@ -178,75 +194,73 @@ declToValue decl =
178194declaration
179195 :: Env.Environment
180196 -> D.ValidDecl
181− -> Env.Canonicalizer [Doc] D.CanonicalDecl
197+ -> Result.Result D.CanonicalDecl
182198declaration env decl =
183− 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 ]
186− in
187− Env.onError throw (kind env v)
199+ let canonicalize kind _context _pattern env v =
200+ kind env v
188201 in
189202 case decl of
190203 D.Definition (Valid.Definition p e t) ->
191− do p' <- canonicalize pattern "definition" p env p
192− e' <- expression env e
193− t' <- T.traverse (canonicalize Canonicalize.tipe "definition" p env) t
194− return $ D.Definition (Canonical.Definition p' e' t')
204+ D.Definition <$> (
205+ Canonical.Definition
206+ <$> canonicalize pattern "definition" p env p
207+ <*> expression env e
208+ <*> T.traverse (canonicalize Canonicalize.tipe "definition" p env) t
209+ )
195210
196211 D.Datatype name tvars ctors ->
197− D.Datatype name tvars <$> mapM canonicalize' ctors
212+ D.Datatype name tvars <$> T.traverse canonicalize' ctors
198213 where
199214 canonicalize' (ctor,args) =
200− (,) ctor <$> mapM (canonicalize Canonicalize.tipe "datatype" name env) args
215+ (,) ctor <$> T.traverse (canonicalize Canonicalize.tipe "datatype" name env) args
201216
202217 D.TypeAlias name tvars expanded ->
203− do expanded' <- canonicalize Canonicalize.tipe "type alias" name env expanded
204− return (D.TypeAlias name tvars expanded')
218+ D.TypeAlias name tvars
219+ <$> canonicalize Canonicalize.tipe "type alias" name env expanded
205220
206221 D.Port validPort ->
207− do Env.uses ["Native","Port"]
208− Env.uses ["Native","Json"]
222+ Result.addModule ["Native","Port"] $
223+ Result.addModule ["Native","Json"] $
209224 case validPort of
210225 D.In name tipe ->
211− do tipe' <- canonicalize Canonicalize.tipe "port" name env tipe
212− port' <- Port.check name Nothing tipe'
213− return (D.Port port')
214−
226+ canonicalize Canonicalize.tipe "port" name env tipe
227+ `Result.andThen` \canonicalType ->
228+ D.Port <$> Port.check name Nothing canonicalType
215229
216230 D.Out name expr tipe ->
217− do expr' <- expression env expr
218− tipe' <- canonicalize Canonicalize.tipe "port" name env tipe
219− port' <- Port.check name (Just expr') tipe'
220− return (D.Port port')
231+ let exprTypeResult =
232+ (,)
233+ <$> expression env expr
234+ <*> canonicalize Canonicalize.tipe "port" name env tipe
235+ in
236+ exprTypeResult
237+ `Result.andThen` \(expr', tipe') ->
238+ D.Port <$> Port.check name (Just expr') tipe'
221239
222240 D.Fixity assoc prec op ->
223− return $ D.Fixity assoc prec op
241+ Result.ok (D.Fixity assoc prec op)
224242
225243
226244expression
227245 :: Env.Environment
228246 -> Valid.Expr
229− -> Env.Canonicalizer [Doc] Canonical.Expr
247+ -> Result.Result Canonical.Expr
230248expression env (A.A ann validExpr) =
231249 let go = expression env
232− tipe' environ = format . Canonicalize.tipe environ
233− throw err =
234− P.vcat
235− [ P.text "Error" <+> pretty ann <> P.colon
236− , P.text err
237− ]
238− format = Env.onError throw
250+ tipe' environ =
251+ format . Canonicalize.tipe environ
252+ format = id
239253 in
240254 A.A ann <$>
241255 case validExpr of
242256 Literal lit ->
243− return (Literal lit)
257+ Result.ok (Literal lit)
244258
245259 Range lowExpr highExpr ->
246260 Range <$> go lowExpr <*> go highExpr
247261
248262 Access record field ->
249− Access <$> go record <*> return field
263+ Access <$> go record <*> Result.ok field
250264
251265 Remove record field ->
252266 flip Remove field <$> go record
@@ -257,15 +271,17 @@ expression env (A.A ann validExpr) =
257271 Modify record fields ->
258272 Modify
259273 <$> go record
260− <*> mapM (\(field,expr) -> (,) field <$> go expr) fields
274+ <*> T.traverse (\(field,expr) -> (,) field <$> go expr) fields
261275
262276 Record fields ->
263277 Record
264− <$> mapM (\(field,expr) -> (,) field <$> go expr) fields
278+ <$> T.traverse (\(field,expr) -> (,) field <$> go expr) fields
265279
266280 Binop (Var.Raw op) leftExpr rightExpr ->
267− do op' <- format (Canonicalize.variable env op)
268− Binop op' <$> go leftExpr <*> go rightExpr
281+ Binop
282+ <$> format (Canonicalize.variable env op)
283+ <*> go leftExpr
284+ <*> go rightExpr
269285
270286 Lambda arg body ->
271287 let env' = Env.addPattern arg env
@@ -276,13 +292,13 @@ expression env (A.A ann validExpr) =
276292 App <$> go func <*> go arg
277293
278294 MultiIf branches ->
279− MultiIf <$> mapM go' branches
295+ MultiIf <$> T.traverse go' branches
280296 where
281297 go' (condition, branch) =
282298 (,) <$> go condition <*> go branch
283299
284300 Let defs body ->
285− Let <$> mapM rename' defs <*> expression env' body
301+ Let <$> T.traverse rename' defs <*> expression env' body
286302 where
287303 env' =
288304 foldr Env.addPattern env $ map (\(Valid.Definition p _ _) -> p) defs
@@ -297,13 +313,13 @@ expression env (A.A ann validExpr) =
297313 Var <$> format (Canonicalize.variable env x)
298314
299315 Data name exprs ->
300− Data name <$> mapM go exprs
316+ Data name <$> T.traverse go exprs
301317
302318 ExplicitList exprs ->
303− ExplicitList <$> mapM go exprs
319+ ExplicitList <$> T.traverse go exprs
304320
305321 Case expr cases ->
306− Case <$> go expr <*> mapM branch cases
322+ Case <$> go expr <*> T.traverse branch cases
307323 where
308324 branch (p,b) =
309325 (,) <$> format (pattern env p)
@@ -330,20 +346,31 @@ expression env (A.A ann validExpr) =
330346 E.Task name <$> go expr <*> portType tipe
331347
332348 GLShader uid src tipe ->
333− return (GLShader uid src tipe)
349+ Result.ok (GLShader uid src tipe)
334350
335351
336352pattern
337353 :: Env.Environment
338354 -> P.RawPattern
339− -> Env.Canonicalizer String P.CanonicalPattern
355+ -> Result.Result P.CanonicalPattern
340356pattern env ptrn =
341357 case ptrn of
342− P.Var x -> return $ P.Var x
343− P.Literal lit -> return $ P.Literal lit
344− P.Record fs -> return $ P.Record fs
345− P.Anything -> return P.Anything
346− P.Alias x p -> P.Alias x <$> pattern env p
358+ P.Var x ->
359+ Result.ok (P.Var x)
360+
361+ P.Literal lit ->
362+ Result.ok (P.Literal lit)
363+
364+ P.Record fs ->
365+ Result.ok (P.Record fs)
366+
367+ P.Anything ->
368+ Result.ok P.Anything
369+
370+ P.Alias x p ->
371+ P.Alias x <$> pattern env p
372+
347373 P.Data (Var.Raw name) ps ->
348− P.Data <$> Canonicalize.pvar env name
349− <*> mapM (pattern env) ps
374+ P.Data
375+ <$> Canonicalize.pvar env name
376+ <*> T.traverse (pattern env) ps