@@ -10,10 +10,12 @@ import qualified Data.Map as Map
10import qualified Data.Set as Set
10import qualified Data.Set as Set
12import qualified AST.Expression.Canonical as Can
12import qualified AST.Expression.Canonical as Can
13+import qualified AST.Expression.Source as Src
13import qualified AST.Expression.Valid as Valid
14import qualified AST.Expression.Valid as Valid
14import qualified AST.Module.Name as ModuleName
15import qualified AST.Module.Name as ModuleName
15import qualified AST.Type as Type
16import qualified AST.Type as Type
16import qualified Canonicalize.Environment as Env
17import qualified Canonicalize.Environment as Env
18+import qualified Canonicalize.Environment.Dups as Dups
17import qualified Canonicalize.Expression as Expr
19import qualified Canonicalize.Expression as Expr
18import qualified Canonicalize.Pattern as Pattern
20import qualified Canonicalize.Pattern as Pattern
19import qualified Canonicalize.Type as Type
21import qualified Canonicalize.Type as Type
@@ -47,15 +49,34 @@ canonicalize
47 -> Result Can.Module
49 -> Result Can.Module
48canonicalize pkg importDict interfaces module_ =
50canonicalize pkg importDict interfaces module_ =
49 do env <- Env.create pkg importDict interfaces module_
51 do env <- Env.create pkg importDict interfaces module_
50− let (Valid.Module name _ _ _ _ decls unions aliases binops _) = module_
52+ let (Valid.Module name _ _ exports _ decls unions aliases binops effects) = module_
51− Can.Module (ModuleName.Canonical pkg name)
53+ (cdecls, cunions, caliases) <-
52− <$> error "TODO docs"
54+ (,,)
53− <*> error "TODO imports"
54− <*> canonicalizeDecls env decls
55+ <$> canonicalizeDecls env decls
55− <*> (Map.fromList <$> traverse (canonicalizeUnion env) unions)
56+ <*> (Map.fromList <$> traverse (canonicalizeUnion env) unions)
56− <*> (Map.fromList <$> traverse (canonicalizeAlias env) aliases)
57+ <*> (Map.fromList <$> traverse (canonicalizeAlias env) aliases)
57− <*> return (Map.fromList (map canonicalizeBinop binops))
59+ let cbinops = Map.fromList (map canonicalizeBinop binops)
58− <*> error "TODO effects"
60+ ceffects <- canonicalizeEffects env cunions effects
61+ cexports <- canonicalizeExports decls cunions caliases cbinops ceffects exports
63+ let home = ModuleName.Canonical pkg name
64+ let docs = toDocs module_
65+ return $ Can.Module home docs cexports cdecls cunions caliases cbinops ceffects
72+toDocs :: Valid.Module -> A.Located (Maybe Can.Docs)
73+toDocs (Valid.Module _ (A.A region maybeOverview) comments _ _ _ _ _ _ _) =
74+ case maybeOverview of
79+ A.A region (Just (Can.Docs overview comments))
@@ -65,7 +86,17 @@ canonicalize pkg importDict interfaces module_ =
65canonicalizeAlias :: Env.Env -> Valid.Alias -> Result ( N.Name, Can.Alias )
86canonicalizeAlias :: Env.Env -> Valid.Alias -> Result ( N.Name, Can.Alias )
66canonicalizeAlias env (Valid.Alias (A.A _ name) args tipe) =
87canonicalizeAlias env (Valid.Alias (A.A _ name) args tipe) =
67 do ctipe <- Type.canonicalize env tipe
88 do ctipe <- Type.canonicalize env tipe
68− return (name, Can.Alias (map A.drop args) ctipe)
89+ return (name, Can.Alias (map A.drop args) ctipe (toRecordCtorInfo tipe))
92+toRecordCtorInfo :: Type.Raw -> Maybe [N.Name]
93+toRecordCtorInfo (A.A _ tipe) =
95+ Type.RRecord fields Nothing ->
96+ Just (map (A.drop . fst) fields)
@@ -178,3 +209,138 @@ detectBadCyclesHelp decl =
179 Function _ _ _ _ ->
210 Function _ _ _ _ ->
215+-- CANONICALIZE EFFECTS
218+canonicalizeEffects :: Env.Env -> Map.Map N.Name a -> Valid.Effects -> Result Can.Effects
219+canonicalizeEffects env unions effects =
222+ Result.ok Can.NoEffects
224+ Valid.Ports ports ->
225+ do pairs <- traverse (canonicalizePort env) ports
226+ return $ Can.Ports (Map.fromList pairs)
228+ Valid.Cmd cmdType ->
229+ Can.Cmd <$> verifyEffectType cmdType unions
231+ Valid.Sub subType ->
232+ Can.Sub <$> verifyEffectType subType unions
234+ Valid.Fx cmdType subType ->
236+ <$> verifyEffectType cmdType unions
237+ <*> verifyEffectType subType unions
240+canonicalizePort :: Env.Env -> Valid.Port -> Result (N.Name, Type.Canonical)
241+canonicalizePort env (Valid.Port (A.A _ name) tipe) =
242+ (,) name <$> Type.canonicalize env tipe
245+verifyEffectType :: A.Located N.Name -> Map.Map N.Name a -> Result N.Name
246+verifyEffectType (A.A region name) unions =
247+ if Map.member name unions then
250+ Result.throw region (Error.EffectNotFound name)
254+-- CANONICALIZE EXPORTS
258+ :: [A.Located Valid.Decl]
259+ -> Map.Map N.Name union
260+ -> Map.Map N.Name alias
261+ -> Map.Map N.Name binop
264+ -> Result Can.Exports
265+canonicalizeExports decls unions aliases binops effects exposing =
268+ Result.ok Can.ExportEverything
270+ Src.Explicit exposeds ->
271+ do let names = Map.fromList (map declToName decls)
272+ infos <- traverse (checkExposed names unions aliases binops effects) exposeds
273+ let toError name () () = Error.ExportDuplicate name
274+ Can.Export <$> Dups.detect toError infos
277+declToName :: A.Located Valid.Decl -> (N.Name, Can.Export)
278+declToName (A.A _ (Valid.Decl (A.A _ name) _ _ _)) =
279+ (name, Can.ExportValue)
283+ :: Map.Map N.Name decl
284+ -> Map.Map N.Name union
285+ -> Map.Map N.Name alias
286+ -> Map.Map N.Name binop
288+ -> A.Located Src.Exposed
289+ -> Result (N.Name, [Dups.Info () Can.Export])
290+checkExposed decls unions aliases binops effects (A.A region exposed) =
293+ if Map.member name decls then
294+ Result.ok (Dups.info name region () Can.ExportValue)
296+ case checkPorts effects name of
298+ Result.ok (Dups.info name region () Can.ExportPort)
301+ Result.throw region $ Error.ExportNotFound Error.BadVar name $
302+ ports ++ Map.keys decls
304+ Src.Operator name ->
305+ if Map.member name binops then
306+ Result.ok (Dups.info name region () Can.ExportBinop)
308+ Result.throw region $ Error.ExportNotFound Error.BadOp name $
311+ Src.Upper name Src.Public ->
312+ if Map.member name unions then
313+ Result.ok (Dups.info name region () Can.ExportUnionOpen)
314+ else if Map.member name aliases then
315+ Result.throw region $ Error.ExportOpenAlias name
317+ Result.throw region $ Error.ExportNotFound Error.BadType name $
318+ Map.keys unions ++ Map.keys aliases
320+ Src.Upper name Src.Private ->
321+ if Map.member name unions then
322+ Result.ok (Dups.info name region () Can.ExportUnionClosed)
323+ else if Map.member name aliases then
324+ Result.ok (Dups.info name region () Can.ExportAlias)
326+ Result.throw region $ Error.ExportNotFound Error.BadType name $
327+ Map.keys unions ++ Map.keys aliases
330+checkPorts :: Can.Effects -> N.Name -> Maybe [N.Name]
331+checkPorts effects name =
337+ if Map.member name ports then Nothing else Just (Map.keys ports)