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 R.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 R.zero tipe)
85 CLet (Map.elems vars) [] header CTrue <$> makeConstraint
89-- EFFECT MANAGER HELPERS
92letCmd :: ModuleName.Canonical -> N.Name -> Constraint -> IO Constraint
93letCmd home tipe constraint =
94 do msgVar <- mkFlexVar
96 let cmdType = FunN (AppN home tipe [msg]) (AppN ModuleName.cmd N.cmd [msg])
97 let header = Map.singleton "command" (A.At R.zero cmdType)
98 return $ CLet [msgVar] [] header CTrue constraint
101letSub :: ModuleName.Canonical -> N.Name -> Constraint -> IO Constraint
102letSub home tipe constraint =
103 do msgVar <- mkFlexVar
104 let msg = VarN msgVar
105 let subType = FunN (AppN home tipe [msg]) (AppN ModuleName.sub N.sub [msg])
106 let header = Map.singleton "subscription" (A.At R.zero subType)
107 return $ CLet [msgVar] [] header CTrue constraint
110constrainEffects :: ModuleName.Canonical -> R.Region -> R.Region -> R.Region -> Can.Manager -> IO Constraint
111constrainEffects home r0 r1 r2 manager =
128 let onSelfMsg = router msg2 self2 ==> self2 ==> state2 ==> task state2
131 Can.Cmd cmd -> router msg1 self1 ==> effectList home cmd msg1 ==> state1 ==> task state1
132 Can.Sub sub -> router msg1 self1 ==> effectList home sub msg1 ==> state1 ==> task state1
133 Can.Fx cmd sub -> router msg1 self1 ==> effectList home cmd msg1 ==> effectList home sub msg1 ==> state1 ==> task state1
137 [ CLocal r0 "init" (E.NoExpectation (task state0))
138 , CLocal r1 "onEffects" (E.NoExpectation onEffects)
139 , CLocal r2 "onSelfMsg" (E.NoExpectation onSelfMsg)
140 , CEqual r1 E.Effects state0 (E.NoExpectation state1)
141 , CEqual r2 E.Effects state0 (E.NoExpectation state2)
142 , CEqual r2 E.Effects self1 (E.NoExpectation self2)
145 CLet [] [s0,s1,s2,m1,m2,sm1,sm2] Map.empty effectCons <$>
148 checkMap "cmdMap" home cmd CSaveTheEnvironment
151 checkMap "subMap" home sub CSaveTheEnvironment
154 checkMap "cmdMap" home cmd =<<
155 checkMap "subMap" home sub CSaveTheEnvironment
158effectList :: ModuleName.Canonical -> N.Name -> Type -> Type
159effectList home name msg =
160 AppN ModuleName.list N.list [AppN home name [msg]]
165 AppN ModuleName.platform N.task [ never, answer ]
168router :: Type -> Type -> Type
170 AppN ModuleName.platform N.router [ msg, self ]
173checkMap :: N.Name -> ModuleName.Canonical -> N.Name -> Constraint -> IO Constraint
174checkMap name home tipe constraint =
177 let mapType = toMapType home tipe (VarN a) (VarN b)
178 let mapCon = CLocal R.zero name (E.NoExpectation mapType)
179 return $ CLet [a,b] [] Map.empty mapCon constraint
182toMapType :: ModuleName.Canonical -> N.Name -> Type -> Type -> Type
183toMapType home tipe a b =
184 (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