1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Canonicalize.Effects
9import qualified Data.Foldable as F
10import qualified Data.Map as Map
11import qualified Data.Set as Set
12import Data.Text (Text)
14import qualified AST.Canonical as Can
15import qualified AST.Valid as Valid
16import qualified AST.Module.Name as ModuleName
17import qualified AST.Utils.Type as Type
18import qualified Canonicalize.Environment as Env
19import qualified Canonicalize.Type as Type
20import qualified Elm.Name as N
21import qualified Reporting.Annotation as A
22import qualified Reporting.Error.Canonicalize as Error
23import qualified Reporting.Region as R
24import qualified Reporting.Result as Result
32 Result.Result i w Error.Error a
41 -> [A.Located Valid.Decl]
42 -> Map.Map N.Name union
44 -> Result i w Can.Effects
45canonicalize env decls unions effects =
48 Result.ok Can.NoEffects
51 do pairs <- traverse (canonicalizePort env) ports
52 return $ Can.Ports (Map.fromList pairs)
54 Valid.Manager region manager ->
55 let dict = Map.fromList (map toNameRegion decls) in
57 <$> verifyManager region dict "init"
58 <*> verifyManager region dict "onEffects"
59 <*> verifyManager region dict "onSelfMsg"
63 Can.Cmd <$> verifyEffectType cmdType unions
66 Can.Sub <$> verifyEffectType subType unions
68 Valid.Fx cmdType subType ->
70 <$> verifyEffectType cmdType unions
71 <*> verifyEffectType subType unions
78canonicalizePort :: Env.Env -> Valid.Port -> Result i w (N.Name, Can.Port)
79canonicalizePort env (Valid.Port (A.At region portName) tipe) =
80 do (Can.Forall freeVars ctipe) <- Type.toAnnotation env tipe
81 case Type.deepDealias ctipe of
82 Can.TLambda outgoingType (Can.TType home name [Can.TVar _])
83 | home == ModuleName.cmd && name == "Cmd" ->
84 case checkPayload outgoingType of
85 Left (badType, err) ->
86 Result.throw (Error.PortPayloadInvalid region portName badType err)
89 Result.ok (portName, Can.Outgoing freeVars ctipe)
91 Can.TLambda (Can.TLambda incomingType (Can.TVar msg1)) (Can.TType home name [Can.TVar msg2])
92 | home == ModuleName.sub && name == "Sub" && msg1 == msg2 ->
93 case checkPayload incomingType of
94 Left (badType, err) ->
95 Result.throw (Error.PortPayloadInvalid region portName badType err)
98 Result.ok (portName, Can.Incoming freeVars ctipe)
101 Result.throw (Error.PortTypeInvalid region portName ctipe)
108verifyEffectType :: A.Located N.Name -> Map.Map N.Name a -> Result i w N.Name
109verifyEffectType (A.At region name) unions =
110 if Map.member name unions then
113 Result.throw (Error.EffectNotFound region name)
116toNameRegion :: A.Located Valid.Decl -> (N.Name, R.Region)
117toNameRegion (A.At _ (Valid.Decl (A.At region name) _ _ _)) =
121verifyManager :: R.Region -> Map.Map N.Name R.Region -> N.Name -> Result i w R.Region
122verifyManager tagRegion decls name =
123 case Map.lookup name decls of
128 Result.throw (Error.EffectFunctionNotFound tagRegion name)
132-- CHECK PAYLOAD TYPES
135checkPayload :: Can.Type -> Either (Can.Type, Error.InvalidPayload) ()
138 Can.TAlias _ _ args aliasedType ->
139 checkPayload (Type.dealias args aliasedType)
141 Can.TType home name args ->
144 | isPrim home name -> Right ()
145 | isJson home name -> Right ()
148 | isList home name -> checkPayload arg
149 | isMaybe home name -> checkPayload arg
150 | isArray home name -> checkPayload arg
153 Left (tipe, Error.UnsupportedType name)
158 Can.TTuple a b maybeC ->
169 Left (tipe, Error.TypeVariable name)
172 Left (tipe, Error.Function)
174 Can.TRecord _ (Just _) ->
175 Left (tipe, Error.ExtendedRecord)
177 Can.TRecord fields Nothing ->
178 F.traverse_ checkPayload fields
181isPrim :: ModuleName.Canonical -> N.Name -> Bool
183 home == ModuleName.basics && Set.member name primitives
186primitives :: Set.Set Text
188 Set.fromList [ N.int, N.float, N.string, N.bool ]
191isJson :: ModuleName.Canonical -> N.Name -> Bool
193 home == ModuleName.jsonEncode && name == N.value
196isList :: ModuleName.Canonical -> N.Name -> Bool
198 home == ModuleName.list && name == N.list
201isMaybe :: ModuleName.Canonical -> N.Name -> Bool
203 home == ModuleName.maybe && name == N.maybe
206isArray :: ModuleName.Canonical -> N.Name -> Bool
208 home == ModuleName.array && name == N.array
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