@@ -1,126 +1,208 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2−module Type.Constrain.Pattern (Info(..), joinInfos, infoToScheme, constrain) where
2+module Type.Constrain.Pattern
4−import Control.Arrow (second)
9+import Control.Monad (foldM)
5−import qualified Control.Monad as Monad
6import qualified Data.Map.Strict as Map
10import qualified Data.Map.Strict as Map
7−import qualified Data.List as List
8−import Data.Text (Text)
10−import qualified AST.Pattern as P
12+import qualified AST.Expression.Canonical as Can
11−import qualified AST.Variable as Var
13+import qualified AST.Module.Name as ModuleName
14+import qualified Data.Bag as Bag
15+import qualified Elm.Name as N
12import qualified Reporting.Annotation as A
16import qualified Reporting.Annotation as A
13import qualified Reporting.Error.Type as Error
17import qualified Reporting.Error.Type as Error
18+import qualified Reporting.Region as R
14import Type.Constraint
19import Type.Constraint
15import qualified Type.Constrain.Literal as Literal
20import qualified Type.Constrain.Literal as Literal
16−import qualified Type.Environment as Env
21+import qualified Type.Instantiate as Instantiate
17import Type.Type
22import Type.Type
21−-- PATTERN INFO
26+-- CONSTRAIN PATTERN
32+constrain :: Env -> Can.Pattern -> Type -> IO (Map.Map N.Name (A.Located Type), [Variable], Constraint)
33+constrain env pattern tipe =
34+ do (Info headers vars cons) <-
35+ addConstraints env Error.PatternUnknown pattern tipe $
36+ Info Map.empty Bag.empty []
38+ return ( headers, Bag.toList vars, CAnd (reverse cons) )
24data Info =
45data Info =
26− { _headers :: Map.Map Text (A.Located Type)
47+ { _headers :: Map.Map N.Name (A.Located Type)
27− , _vars :: [Variable]
48+ , _vars :: Bag.Bag Variable
28− , _cons :: Constraint
49+ , _cons :: [Constraint]
32−emptyInfo :: Info
53+addConstraints :: Env -> Error.PatternContext -> Can.Pattern -> Type -> Info -> IO Info
33−emptyInfo =
54+addConstraints env context (A.A region pattern) tipe info =
34− Info Map.empty [] CTrue
55+ case pattern of
60+ do let (Info headers vars revCons) = info
61+ litCon <- Literal.constrain region lit tipe
62+ return $ Info headers vars (litCon:revCons)
37−joinInfo :: Info -> Info -> Info
64+ Can.PVar name ->
38−joinInfo (Info headers1 vars1 cons1) (Info headers2 vars2 cons2) =
65+ do let (Info headers vars revCons) = info
39− Info
66+ let newHeaders = Map.insert name (A.A region tipe) headers
40− { _headers = Map.union headers1 headers2
67+ return $ Info newHeaders vars revCons
41− , _vars = vars1 ++ vars2
42− , _cons = cons1 /\ cons2
69+ Can.PAlias realPattern name ->
70+ do let (Info headers vars revCons) = info
71+ addConstraints env context realPattern tipe $
72+ Info (Map.insert name (A.A region tipe) headers) vars revCons
46−joinInfos :: [Info] -> Info
74+ Can.PUnit ->
47−joinInfos infos =
75+ do let (Info headers vars revCons) = info
48− List.foldl' (flip joinInfo) emptyInfo infos
76+ let unitCon = CEqual (Error.Pattern context Error.PUnit) region UnitN tipe
77+ return $ Info headers vars (unitCon:revCons)
79+ Can.PTuple a b maybeC ->
80+ addTupleConstraint env context region a b maybeC tipe info
51−infoToScheme :: Info -> Scheme
82+ Can.PCtor home typeName vs ctorName args ->
52−infoToScheme (Info headers vars cons) =
83+ do (Instantiate.Ctor tvars targs ttype) <- Instantiate.pattern home typeName vs args
53− Scheme [] vars cons headers
85+ (Info headers vars revCons) <-
86+ foldM (addCtorConstraint env ctorName) info targs
91+ , _vars = Bag.append vars (Bag.fromList id tvars)
93+ CEqual (Error.Pattern context (Error.PCtor ctorName)) region ttype tipe
57−-- CONSTRAIN PATTERN
97+ Can.PList patterns ->
98+ do entryVar <- mkFlexVar
99+ let entryVarN = VarN entryVar
100+ let listType = AppN ModuleName.list N.list [entryVarN]
102+ (Info headers vars revCons) <-
104+ (addListConstraint env entryVarN)
106+ (zip patterns [ 1 .. length patterns ])
108+ let listCon = CEqual (Error.Pattern context Error.PList) region listType tipe
109+ return $ Info headers (Bag.insert entryVar vars) (listCon:revCons)
111+ Can.PCons headPattern tailPattern ->
112+ do headVar <- mkFlexVar
113+ tailVar <- mkFlexVar
114+ let headVarN = VarN headVar
115+ let tailVarN = VarN tailVar
116+ let tailType = AppN ModuleName.list N.list [tailVarN]
118+ (Info headers vars revCons) <-
119+ addConstraints env Error.PatternTail tailPattern tailType =<<
120+ addConstraints env Error.PatternUnknown headPattern headVarN info
124+ { _headers = headers
125+ , _vars = Bag.insert headVar (Bag.insert tailVar vars)
127+ CEqual (Error.Pattern context Error.PList) region tailType tipe
128+ : CEqual Error.PatternCons region headVarN tailVarN
132+ Can.PRecord fields ->
133+ do extVar <- mkFlexVar
60−constrain :: Env.Env -> P.Canonical -> Type -> IO Info
135+ fieldVars <- traverse (\field -> (,) field <$> mkFlexVar) fields
61−constrain env (A.A region pattern) tipe =
136+ let fieldVarN = Map.fromList (map (fmap VarN) fieldVars)
63− equal patternError leftType rightType =
138+ let (Info headers vars revCons) = info
64− CEqual (Error.Pattern patternError) region leftType rightType
74− do c <- Literal.constrain region lit tipe
75− return $ emptyInfo { _cons = c }
139+ return $
78− do variable <- mkFlexVar
79− return $ Info
140+ Info
80− { _headers = Map.singleton name (rvar variable)
141+ { _headers = Map.union headers (Map.map (A.A region) fieldVarN)
81− , _vars = [variable]
142+ , _vars = Bag.insert extVar (Bag.append vars (Bag.fromList snd fieldVars))
82− , _cons = equal (Error.PVar name) (VarN variable) tipe
86− do variable <- mkFlexVar
87− info <- constrain env ptrn tipe
89− { _headers = Map.insert name (rvar variable) (_headers info)
90− , _vars = variable : _vars info
91 , _cons =
143 , _cons =
92− equal (Error.PAlias name) (VarN variable) tipe
144+ CEqual
93− /\ _cons info
145+ (Error.Pattern context Error.PRecord)
147+ (RecordN fieldVarN (VarN extVar))
96− P.Ctor name patterns ->
152+
97− do (_kind, cvars, args, result) <-
153+
98− Env.freshDataScheme env (Var.toText name)
154+-- CONSTRAIN TUPLE
100− fragList <- Monad.zipWithM (constrain env) patterns args
156+
101− let info = joinInfos fragList
157+addTupleConstraint
102− return $ info
158+ :: Env
103− { _vars = cvars ++ _vars info
159+ -> Error.PatternContext
104− , _cons =
160+ -> R.Region
105− equal (Error.PCtor name) result tipe
161+ -> Can.Pattern
106− /\ _cons info
162+ -> Can.Pattern
107− }
163+ -> Maybe Can.Pattern
109− P.Record fields ->
165+ -> Info
110− do pairs <-
166+ -> IO Info
111− mapM (\name -> (,) name <$> mkFlexVar) fields
167+addTupleConstraint env context region a b maybeC tipe (Info headers vars revCons) =
112−
168+ do let equal = CEqual (Error.Pattern context Error.PTuple) region
113− let tenv =
169+ let addCon = addConstraints env Error.PatternUnknown
114− Map.fromList (map (second rvar) pairs)
170+
115−
171+ aVar <- mkFlexVar
116− let unannotatedTenv =
172+ bVar <- mkFlexVar
117− Map.map A.drop tenv
173+ let aVarN = VarN aVar
118−
174+ let bVarN = VarN bVar
119− con <- exists $ \t ->
175+
120− return (equal Error.PRecord tipe (RecordN unannotatedTenv t))
176+ case maybeC of
122− return $ Info
178+ do let tupleCon = equal (TupleN aVarN bVarN Nothing) tipe
123− { _headers = tenv
179+ let newVars = Bag.insert aVar (Bag.insert bVar vars)
124− , _vars = map snd pairs
180+ addCon b bVarN =<<
125− , _cons = con
181+ addCon a aVarN (Info headers newVars (tupleCon:revCons))
184+ do cVar <- mkFlexVar
185+ let cVarN = VarN cVar
186+ let tupleCon = equal (TupleN aVarN bVarN (Just cVarN)) tipe
187+ let newVars = Bag.insert aVar (Bag.insert bVar (Bag.insert cVar vars))
190+ addCon a aVarN (Info headers newVars (tupleCon:revCons))
194+-- CONSTRAIN CONSTRUCTORS
197+addCtorConstraint :: Env -> N.Name -> Info -> (Int, Type, Can.Pattern) -> IO Info
198+addCtorConstraint env name info (index, argType, argPattern) =
199+ addConstraints env (Error.PatternArg name index) argPattern argType info
206+addListConstraint :: Env -> Type -> Info -> (Can.Pattern, Int) -> IO Info
207+addListConstraint env tipe info (pattern, index) =
208+ addConstraints env (Error.PatternList index) pattern tipe info