@@ -0,0 +1,155 @@
1+{-# OPTIONS_GHC -Wall #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+module Type.Constrain.Module
9+import Control.Monad (replicateM)
10+import qualified Data.Map.Strict as Map
12+import qualified AST.Canonical as Can
13+import qualified AST.Module.Name as ModuleName
14+import qualified Elm.Name as N
15+import qualified Reporting.Annotation as A
16+import qualified Reporting.Region as R
17+import Type.Constraint
18+import qualified Type.Constrain.Expression as Expr
19+import qualified Type.Instantiate as Instantiate
20+import Type.Type (Type(..), Variable, (==>), mkFlexVar, never)
27+constrain :: Can.Module -> IO Constraint
28+constrain (Can.Module home _ _ decls _ _ _ effects) =
31+ constrainDecls CSaveTheEnvironment decls
34+ do header <- traverse portToHeader ports
35+ CLet [] [] header CTrue
36+ <$> constrainDecls CSaveTheEnvironment decls
38+ Can.Manager r0 r1 r2 manager ->
41+ do header <- mkCmd home cmdName
42+ fxCon <- constrainEffects r0 r1 r2 $ \msg result ->
43+ effectList home cmdName msg ==> result
44+ CLet [] [] header CTrue <$> constrainDecls fxCon decls
47+ do header <- mkSub home subName
48+ fxCon <- constrainEffects r0 r1 r2 $ \msg result ->
49+ effectList home subName msg ==> result
50+ CLet [] [] header CTrue <$> constrainDecls fxCon decls
52+ Can.Fx cmdName subName ->
53+ do header <- Map.union <$> mkCmd home cmdName <*> mkSub home subName
54+ fxCon <- constrainEffects r0 r1 r2 $ \msg result ->
55+ effectList home cmdName msg ==> effectList home subName msg ==> result
56+ CLet [] [] header CTrue <$> constrainDecls fxCon decls
60+-- CONSTRAIN DECLARATIONS
63+constrainDecls :: Constraint -> Can.Decls -> IO Constraint
64+constrainDecls finalConstraint decls =
66+ Can.Declare def otherDecls ->
67+ Expr.constrainDef Map.empty def
68+ =<< constrainDecls finalConstraint otherDecls
70+ Can.DeclareRec defs otherDecls ->
71+ Expr.constrainRecursiveDefs Map.empty defs
72+ =<< constrainDecls finalConstraint otherDecls
74+ Can.SaveTheEnvironment ->
75+ return finalConstraint
82+portToHeader :: Can.Port -> IO (A.Located Type)
85+ Can.Incoming freeVars tipe ->
86+ do vars <- traverse (\_ -> VarN <$> mkFlexVar) freeVars
87+ A.At zero <$> Instantiate.fromSrcType vars tipe
89+ Can.Outgoing freeVars tipe ->
90+ do vars <- traverse (\_ -> VarN <$> mkFlexVar) freeVars
91+ A.At zero <$> Instantiate.fromSrcType vars tipe
97+ R.Region (R.Position 0 0) (R.Position 0 0)
101+-- EFFECT MANAGER HELPERS
104+mkCmd :: ModuleName.Canonical -> N.Name -> IO (Map.Map N.Name (A.Located Type))
105+mkCmd home typeName =
106+ do msg <- VarN <$> mkFlexVar
107+ return $ Map.singleton "command" $ A.At zero $
108+ FunN (AppN home typeName [msg]) (AppN ModuleName.cmd N.cmd [msg])
111+mkSub :: ModuleName.Canonical -> N.Name -> IO (Map.Map N.Name (A.Located Type))
112+mkSub home typeName =
113+ do msg <- VarN <$> mkFlexVar
114+ return $ Map.singleton "subscription" $ A.At zero $
115+ FunN (AppN home typeName [msg]) (AppN ModuleName.sub N.sub [msg])
122+ -> (Variable -> Type -> Type)
124+constrainEffects r0 r1 r2 toFinalArgs =
127+ AppN ModuleName.platform N.task [ never, VarN t ]
129+ router msg selfMsg =
130+ AppN ModuleName.platform N.router [ VarN msg, VarN selfMsg ]
132+ equal region var tipe =
133+ CEqual region Effects (VarN var) (NoExpectation tipe)
135+ do vars@[s0,s1,s2,msg1,msg2,selfMsg1,selfMsg2] <- replicateM 7 mkFlexVar
137+ CLet [] vars Map.empty
139+ [ CLookup r0 "init" $ NoExpectation $
141+ , CLookup r1 "onEffects" $ NoExpectation $
142+ router msg1 selfMsg1 ==> toFinalArgs msg1 (VarN s1 ==> task s1)
143+ , CLookup r2 "onSelfMsg" $ NoExpectation $
144+ router msg2 selfMsg2 ==> VarN selfMsg2 ==> VarN s2 ==> task s2
145+ , equal r1 s0 (VarN s1)
146+ , equal r2 s0 (VarN s2)
147+ , equal r2 selfMsg1 (VarN selfMsg2)
153+effectList :: ModuleName.Canonical -> N.Name -> Variable -> Type
154+effectList home name msg =
155+ AppN ModuleName.list N.list [AppN home name [VarN msg]]