1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Type.Constrain.Module
9import qualified Data.Map.Strict as Map
11import qualified AST.Canonical as Can
12import qualified AST.Module.Name as ModuleName
13import qualified Elm.Name as N
14import qualified Reporting.Annotation as A
15import qualified Reporting.Error.Type as E
16import qualified Reporting.Region as R
17import qualified Type.Constrain.Expression as Expr
18import qualified Type.Instantiate as Instantiate
19import Type.Type (Type(..), Constraint(..), (==>), mkFlexVar, never)
26constrain :: Can.Module -> IO Constraint
27constrain (Can.Module home _ _ decls _ _ _ effects) =
30 constrainDecls decls CSaveTheEnvironment
33 Map.foldrWithKey letPort (constrainDecls decls CSaveTheEnvironment) ports
35 Can.Manager r0 r1 r2 manager ->
38 letCmd home cmdName =<<
39 constrainDecls decls =<< constrainEffects home r0 r1 r2 manager
42 letSub home subName =<<
43 constrainDecls decls =<< constrainEffects home r0 r1 r2 manager
45 Can.Fx cmdName subName ->
46 letCmd home cmdName =<<
47 letSub home subName =<<
48 constrainDecls decls =<< constrainEffects home r0 r1 r2 manager
52-- CONSTRAIN DECLARATIONS
55constrainDecls :: Can.Decls -> Constraint -> IO Constraint
56constrainDecls decls finalConstraint =
58 Can.Declare def otherDecls ->
59 Expr.constrainDef Map.empty def =<< constrainDecls otherDecls finalConstraint
61 Can.DeclareRec defs otherDecls ->
62 Expr.constrainRecursiveDefs Map.empty defs =<< constrainDecls otherDecls finalConstraint
64 Can.SaveTheEnvironment ->
65 return finalConstraint
72letPort :: N.Name -> Can.Port -> IO Constraint -> IO Constraint
73letPort name port_ makeConstraint =
75 Can.Incoming freeVars _ srcType ->
76 do vars <- traverse (\_ -> mkFlexVar) freeVars
77 tipe <- Instantiate.fromSrcType (Map.map VarN vars) srcType
78 let header = Map.singleton name (A.At zero tipe)
79 CLet (Map.elems vars) [] header CTrue <$> makeConstraint
81 Can.Outgoing freeVars _ srcType ->
82 do vars <- traverse (\_ -> mkFlexVar) freeVars
83 tipe <- Instantiate.fromSrcType (Map.map VarN vars) srcType
84 let header = Map.singleton name (A.At zero tipe)
85 CLet (Map.elems vars) [] header CTrue <$> makeConstraint
91 R.Region (R.Position 0 0) (R.Position 0 0)
95-- EFFECT MANAGER HELPERS
98letCmd :: ModuleName.Canonical -> N.Name -> Constraint -> IO Constraint
99letCmd home tipe constraint =
100 do msgVar <- mkFlexVar
101 let msg = VarN msgVar
102 let cmdType = FunN (AppN home tipe [msg]) (AppN ModuleName.cmd N.cmd [msg])
103 let header = Map.singleton "command" (A.At zero cmdType)
104 return $ CLet [msgVar] [] header CTrue constraint
107letSub :: ModuleName.Canonical -> N.Name -> Constraint -> IO Constraint
108letSub home tipe constraint =
109 do msgVar <- mkFlexVar
110 let msg = VarN msgVar
111 let subType = FunN (AppN home tipe [msg]) (AppN ModuleName.sub N.sub [msg])
112 let header = Map.singleton "subscription" (A.At zero subType)
113 return $ CLet [msgVar] [] header CTrue constraint
116constrainEffects :: ModuleName.Canonical -> R.Region -> R.Region -> R.Region -> Can.Manager -> IO Constraint
117constrainEffects home r0 r1 r2 manager =
134 let onSelfMsg = router msg2 self2 ==> self2 ==> state2 ==> task state2
137 Can.Cmd cmd -> router msg1 self1 ==> effectList home cmd msg1 ==> state1 ==> task state1
138 Can.Sub sub -> router msg1 self1 ==> effectList home sub msg1 ==> state1 ==> task state1
139 Can.Fx cmd sub -> router msg1 self1 ==> effectList home cmd msg1 ==> effectList home sub msg1 ==> state1 ==> task state1
143 [ CLocal r0 "init" (E.NoExpectation (task state0))
144 , CLocal r1 "onEffects" (E.NoExpectation onEffects)
145 , CLocal r2 "onSelfMsg" (E.NoExpectation onSelfMsg)
146 , CEqual r1 E.Effects state0 (E.NoExpectation state1)
147 , CEqual r2 E.Effects state0 (E.NoExpectation state2)
148 , CEqual r2 E.Effects self1 (E.NoExpectation self2)
151 CLet [] [s0,s1,s2,m1,m2,sm1,sm2] Map.empty effectCons <$>
154 checkMap "cmdMap" home cmd CSaveTheEnvironment
157 checkMap "subMap" home sub CSaveTheEnvironment
160 checkMap "cmdMap" home cmd =<<
161 checkMap "subMap" home sub CSaveTheEnvironment
164effectList :: ModuleName.Canonical -> N.Name -> Type -> Type
165effectList home name msg =
166 AppN ModuleName.list N.list [AppN home name [msg]]
171 AppN ModuleName.platform N.task [ never, answer ]
174router :: Type -> Type -> Type
176 AppN ModuleName.platform N.router [ msg, self ]
179checkMap :: N.Name -> ModuleName.Canonical -> N.Name -> Constraint -> IO Constraint
180checkMap name home tipe constraint =
183 let mapType = toMapType home tipe (VarN a) (VarN b)
184 let mapCon = CLocal zero name (E.NoExpectation mapType)
185 return $ CLet [a,b] [] Map.empty mapCon constraint
188toMapType :: ModuleName.Canonical -> N.Name -> Type -> Type -> Type
189toMapType home tipe a b =
190 (a ==> b) ==> AppN home tipe [a] ==> AppN home tipe [b]
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