@@ -1,3 +1,4 @@
1+{-# OPTIONS_GHC -Wall #-}
1module Type.Constrain.Expression where
2module Type.Constrain.Expression where
3import Control.Applicative ((<$>))
4import Control.Applicative ((<$>))
@@ -5,9 +6,10 @@ import qualified Control.Monad as Monad
5import Control.Monad.Error
6import Control.Monad.Error
6import qualified Data.List as List
7import qualified Data.List as List
7import qualified Data.Map as Map
8import qualified Data.Map as Map
9+import Prelude hiding (and)
8import qualified Text.PrettyPrint as PP
10import qualified Text.PrettyPrint as PP
10−import AST.Literal as Lit
12+import qualified AST.Literal as Lit
11import AST.Annotation as Ann
13import AST.Annotation as Ann
12import AST.Expression.General
14import AST.Expression.General
13import qualified AST.Expression.Canonical as Canonical
15import qualified AST.Expression.Canonical as Canonical
@@ -15,7 +17,7 @@ import qualified AST.Pattern as P
15import qualified AST.Type as ST
17import qualified AST.Type as ST
16import qualified AST.Variable as V
18import qualified AST.Variable as V
17import Type.Type hiding (Descriptor(..))
19import Type.Type hiding (Descriptor(..))
18−import Type.Fragment
20+import qualified Type.Fragment as Fragment
19import qualified Type.Environment as Env
21import qualified Type.Environment as Env
20import qualified Type.Constrain.Literal as Literal
22import qualified Type.Constrain.Literal as Literal
21import qualified Type.Constrain.Pattern as Pattern
23import qualified Type.Constrain.Pattern as Pattern
@@ -26,7 +28,7 @@ constrain
26 -> Canonical.Expr
28 -> Canonical.Expr
28 -> ErrorT [PP.Doc] IO TypeConstraint
30 -> ErrorT [PP.Doc] IO TypeConstraint
29−constrain env (A region expr) tipe =
31+constrain env (A region expression) tipe =
30 let list t = Env.get env Env.types "List" <| t
32 let list t = Env.get env Env.types "List" <| t
31 and = A region . CAnd
33 and = A region . CAnd
32 true = A region CTrue
34 true = A region CTrue
@@ -34,8 +36,9 @@ constrain env (A region expr) tipe =
34 x <? t = A region (CInstance x t)
36 x <? t = A region (CInstance x t)
35 clet schemes c = A region (CLet schemes c)
37 clet schemes c = A region (CLet schemes c)
37− case expr of
39+ case expression of
38− Literal lit -> liftIO $ Literal.constrain env region lit tipe
41+ liftIO $ Literal.constrain env region lit tipe
40 GLShader _uid _src gltipe ->
43 GLShader _uid _src gltipe ->
41 exists $ \attr ->
44 exists $ \attr ->
@@ -51,7 +54,8 @@ constrain env (A region expr) tipe =
51 attribute = makeRec Lit.attribute attr
54 attribute = makeRec Lit.attribute attr
52 uniform = makeRec Lit.uniform unif
55 uniform = makeRec Lit.uniform unif
53 varying = makeRec Lit.varying (termN EmptyRecord1)
56 varying = makeRec Lit.varying (termN EmptyRecord1)
54− in return . A region $ CEqual tipe (shaderTipe attribute uniform varying)
58+ return . A region $ CEqual tipe (shaderTipe attribute uniform varying)
57 | name == saveEnvName -> return (A region CSaveEnv)
61 | name == saveEnvName -> return (A region CSaveEnv)
@@ -60,165 +64,135 @@ constrain env (A region expr) tipe =
60 name = V.toString var
64 name = V.toString var
62 Range lo hi ->
66 Range lo hi ->
63− existsNumber $ \n -> do
67+ existsNumber $ \n ->
64− clo <- constrain env lo n
68+ do clo <- constrain env lo n
65− chi <- constrain env hi n
69+ chi <- constrain env hi n
66− return $ and [clo, chi, list n === tipe]
70+ return $ and [clo, chi, list n === tipe]
68 ExplicitList exprs ->
72 ExplicitList exprs ->
69− exists $ \x -> do
73+ exists $ \x ->
70− cs <- mapM (\e -> constrain env e x) exprs
74+ do constraints <- mapM (\e -> constrain env e x) exprs
71− return . and $ list x === tipe : cs
75+ return . and $ list x === tipe : constraints
73 Binop op e1 e2 ->
77 Binop op e1 e2 ->
74 exists $ \t1 ->
78 exists $ \t1 ->
75− exists $ \t2 -> do
79+ exists $ \t2 ->
76− c1 <- constrain env e1 t1
80+ do c1 <- constrain env e1 t1
77− c2 <- constrain env e2 t2
81+ c2 <- constrain env e2 t2
78− return $ and [ c1, c2, V.toString op <? (t1 ==> t2 ==> tipe) ]
82+ return $ and [ c1, c2, V.toString op <? (t1 ==> t2 ==> tipe) ]
80 Lambda p e ->
84 Lambda p e ->
81 exists $ \t1 ->
85 exists $ \t1 ->
82− exists $ \t2 -> do
86+ exists $ \t2 ->
83− fragment <- try region $ Pattern.constrain env p t1
87+ do fragment <- try region $ Pattern.constrain env p t1
84− c2 <- constrain env e t2
88+ c2 <- constrain env e t2
89+ let c = ex (Fragment.vars fragment)
85− let c = ex (vars fragment) (clet [monoscheme (typeEnv fragment)]
90+ (clet [monoscheme (Fragment.typeEnv fragment)]
86− (typeConstraint fragment /\ c2 ))
91+ (Fragment.typeConstraint fragment /\ c2)
87− return $ c /\ tipe === (t1 ==> t2)
93+ return $ c /\ tipe === (t1 ==> t2)
89 App e1 e2 ->
95 App e1 e2 ->
90− exists $ \t -> do
96+ exists $ \t ->
91− c1 <- constrain env e1 (t ==> tipe)
97+ do c1 <- constrain env e1 (t ==> tipe)
92− c2 <- constrain env e2 t
98+ c2 <- constrain env e2 t
93− return $ c1 /\ c2
99+ return $ c1 /\ c2
95− MultiIf branches -> and <$> mapM constrain' branches
102+ and <$> mapM constrain' branches
97− bool = Env.get env Env.types "Bool"
104+ bool = Env.get env Env.types "Bool"
98− constrain' (b,e) = do
106+ constrain' (cond, expr) =
99− cb <- constrain env b bool
107+ do cb <- constrain env cond bool
100− ce <- constrain env e tipe
108+ ce <- constrain env expr tipe
101 return (cb /\ ce)
109 return (cb /\ ce)
103− Case exp branches ->
111+ Case expr branches ->
104− exists $ \t -> do
112+ exists $ \t ->
105− ce <- constrain env exp t
113+ do ce <- constrain env expr t
106− let branch (p,e) = do
114+ and . (:) ce <$> mapM (branch t) branches
116+ branch t (pattern, branchExpr) =
107− fragment <- try region $ Pattern.constrain env p t
117+ do fragment <- try region $ Pattern.constrain env pattern t
108− clet [toScheme fragment] <$> constrain env e tipe
118+ clet [Fragment.toScheme fragment] <$> constrain env branchExpr tipe
109− and . (:) ce <$> mapM branch branches
111 Data name exprs ->
120 Data name exprs ->
112− do vars <- forM exprs $ \_ -> liftIO (variable Flexible)
121+ do vars <- forM exprs $ \_ -> liftIO (variable Flexible)
113− let pairs = zip exprs (map varN vars)
122+ let pairs = zip exprs (map varN vars)
114− (ctipe, cs) <- Monad.foldM step (tipe,true) (reverse pairs)
123+ (ctipe, cs) <- Monad.foldM step (tipe,true) (reverse pairs)
115− return $ ex vars (cs /\ name <? ctipe)
124+ return $ ex vars (cs /\ name <? ctipe)
117− step (t,c) (e,x) = do
126+ step (t,c) (e,x) =
118− c' <- constrain env e x
127+ do c' <- constrain env e x
119− return (x ==> t, c /\ c')
128+ return (x ==> t, c /\ c')
121− Access e label ->
130+ Access expr label ->
122 exists $ \t ->
131 exists $ \t ->
123− constrain env e (record (Map.singleton label [tipe]) t)
132+ constrain env expr (record (Map.singleton label [tipe]) t)
125− Remove e label ->
134+ Remove expr label ->
126 exists $ \t ->
135 exists $ \t ->
127− constrain env e (record (Map.singleton label [t]) tipe)
136+ constrain env expr (record (Map.singleton label [t]) tipe)
129− Insert e label value ->
138+ Insert expr label value ->
130 exists $ \tVal ->
139 exists $ \tVal ->
131− exists $ \tRec -> do
140+ exists $ \tRec ->
132− cVal <- constrain env value tVal
141+ do cVal <- constrain env value tVal
133− cRec <- constrain env e tRec
142+ cRec <- constrain env expr tRec
134− let c = tipe === record (Map.singleton label [tVal]) tRec
143+ let c = tipe === record (Map.singleton label [tVal]) tRec
135− return (and [cVal, cRec, c])
144+ return (and [cVal, cRec, c])
137− Modify e fields ->
146+ Modify expr fields ->
138− exists $ \t -> do
147+ exists $ \t ->
139− oldVars <- forM fields $ \_ -> liftIO (variable Flexible)
148+ do oldVars <- forM fields $ \_ -> liftIO (variable Flexible)
140− let oldFields = ST.fieldMap (zip (map fst fields) (map varN oldVars))
149+ let oldFields = ST.fieldMap (zip (map fst fields) (map varN oldVars))
141− cOld <- ex oldVars <$> constrain env e (record oldFields t)
150+ cOld <- ex oldVars <$> constrain env expr (record oldFields t)
143− newVars <- forM fields $ \_ -> liftIO (variable Flexible)
152+ newVars <- forM fields $ \_ -> liftIO (variable Flexible)
144− let newFields = ST.fieldMap (zip (map fst fields) (map varN newVars))
153+ let newFields = ST.fieldMap (zip (map fst fields) (map varN newVars))
145− let cNew = tipe === record newFields t
154+ let cNew = tipe === record newFields t
147− cs <- zipWithM (constrain env) (map snd fields) (map varN newVars)
156+ cs <- zipWithM (constrain env) (map snd fields) (map varN newVars)
149− return $ cOld /\ ex newVars (and (cNew : cs))
158+ return $ cOld /\ ex newVars (and (cNew : cs))
151 Record fields ->
160 Record fields ->
152− do vars <- forM fields $ \_ -> liftIO (variable Flexible)
161+ do vars <- forM fields $ \_ -> liftIO (variable Flexible)
153− cs <- zipWithM (constrain env) (map snd fields) (map varN vars)
162+ cs <- zipWithM (constrain env) (map snd fields) (map varN vars)
154− let fields' = ST.fieldMap (zip (map fst fields) (map varN vars))
163+ let fields' = ST.fieldMap (zip (map fst fields) (map varN vars))
155− recordType = record fields' (termN EmptyRecord1)
164+ let recordType = record fields' (termN EmptyRecord1)
156− return . ex vars . and $ tipe === recordType : cs
165+ return . ex vars . and $ tipe === recordType : cs
158 Let defs body ->
167 Let defs body ->
159− do c <- constrain env body tipe
168+ do c <- constrain env body tipe
160− (schemes, rqs, fqs, header, c2, c1) <-
161− Monad.foldM (constrainDef env)
162− ([], [], [], Map.empty, true, true)
163− (concatMap expandPattern defs)
164− return $ clet schemes
165− (clet [Scheme rqs fqs (clet [monoscheme header] c2) header ]
168− Port _ _ ->
170+ (Info schemes rqs fqs headers c2 c1) <-
169− return true
171+ Monad.foldM
173+ (Info [] [] [] Map.empty true true)
174+ (concatMap expandPattern defs)
176+ let letScheme = [ Scheme rqs fqs (clet [monoscheme headers] c2) headers ]
172−constrainDef env info (Canonical.Definition pattern expr maybeTipe) =
178+ return $ clet schemes (clet letScheme (c1 /\ c))
173− let qs = [] -- should come from the def, but I'm not sure what would live there...
179+
174− (schemes, rigidQuantifiers, flexibleQuantifiers, headers, c2, c1) = info
180+ Port _ _ ->
176− do rigidVars <- forM qs (\_ -> liftIO $ variable Rigid) -- Some mistake may be happening here.
177− -- Currently, qs is always [].
178− case (pattern, maybeTipe) of
179− (P.Var name, Just tipe) -> do
180− flexiVars <- forM qs (\_ -> liftIO $ variable Flexible)
181− let inserts = zipWith (\arg typ -> Map.insert arg (varN typ)) qs flexiVars
182− env' = env { Env.value = List.foldl' (\x f -> f x) (Env.value env) inserts }
183− (vars, typ) <- Env.instantiateType env tipe Map.empty
184− let scheme = Scheme { rigidQuantifiers = [],
185− flexibleQuantifiers = flexiVars ++ vars,
186− constraint = Ann.noneNoDocs CTrue,
187− header = Map.singleton name typ }
188− c <- constrain env' expr typ
189− return ( scheme : schemes
191− , flexibleQuantifiers
194− , fl rigidVars c /\ c1 )
196− (P.Var name, Nothing) -> do
197− v <- liftIO $ variable Flexible
199− inserts = zipWith (\arg typ -> Map.insert arg (varN typ)) qs rigidVars
200− env' = env { Env.value = List.foldl' (\x f -> f x) (Env.value env) inserts }
201− c <- constrain env' expr tipe
202− return ( schemes
181+ return true
203− , rigidVars ++ rigidQuantifiers
204− , v : flexibleQuantifiers
205− , Map.insert name tipe headers
209− _ -> error ("problem in constrainDef with " ++ show pattern)
212expandPattern :: Canonical.Def -> [Canonical.Def]
184expandPattern :: Canonical.Def -> [Canonical.Def]
213expandPattern def@(Canonical.Definition pattern lexpr@(A r _) maybeType) =
185expandPattern def@(Canonical.Definition pattern lexpr@(A r _) maybeType) =
214 case pattern of
186 case pattern of
215− P.Var _ -> [def]
187+ P.Var _ ->
216− _ -> Canonical.Definition (P.Var x) lexpr maybeType : map toDef vars
190+ Canonical.Definition (P.Var x) lexpr maybeType : map toDef vars
218− vars = P.boundVarList pattern
192+ vars = P.boundVarList pattern
219− x = "$" ++ concat vars
193+ x = "$" ++ concat vars
220− mkVar = A r . localVar
194+ mkVar = A r . localVar
221− toDef y = Canonical.Definition (P.Var y) (A r $ Case (mkVar x) [(pattern, mkVar y)]) Nothing
195+ toDef y = Canonical.Definition (P.Var y) (A r $ Case (mkVar x) [(pattern, mkVar y)]) Nothing
224try :: Region -> ErrorT (Region -> PP.Doc) IO a -> ErrorT [PP.Doc] IO a
198try :: Region -> ErrorT (Region -> PP.Doc) IO a -> ErrorT [PP.Doc] IO a
@@ -227,3 +201,94 @@ try region computation =
227 case result of
201 case result of
228 Left err -> throwError [err region]
202 Left err -> throwError [err region]
229 Right value -> return value
203 Right value -> return value
206+-- CONSTRAIN DEFINITIONS
209+ { iSchemes :: [TypeScheme]
210+ , iRigid :: [Variable]
211+ , iFlex :: [Variable]
212+ , iHeaders :: Map.Map String Type
213+ , iC2 :: TypeConstraint
214+ , iC1 :: TypeConstraint
218+constrainDef :: Env.Environment -> Info -> Canonical.Def -> ErrorT [PP.Doc] IO Info
219+constrainDef env info (Canonical.Definition pattern expr maybeTipe) =
220+ let qs = [] -- should come from the def, but I'm not sure what would live there...
222+ case (pattern, maybeTipe) of
223+ (P.Var name, Just tipe) ->
224+ constrainAnnotatedDef env info qs name expr tipe
226+ (P.Var name, Nothing) ->
227+ constrainUnannotatedDef env info qs name expr
229+ _ -> error ("problem in constrainDef with " ++ show pattern)
232+constrainAnnotatedDef
239+ -> ErrorT [PP.Doc] IO Info
240+constrainAnnotatedDef env info qs name expr tipe =
241+ do -- Some mistake may be happening here. Currently, qs is always [].
242+ rigidVars <- forM qs (\_ -> liftIO $ variable Rigid)
244+ flexiVars <- forM qs (\_ -> liftIO $ variable Flexible)
246+ let inserts = zipWith (\arg typ -> Map.insert arg (varN typ)) qs flexiVars
248+ let env' = env { Env.value = List.foldl' (\x f -> f x) (Env.value env) inserts }
250+ (vars, typ) <- Env.instantiateType env tipe Map.empty
254+ { rigidQuantifiers = []
255+ , flexibleQuantifiers = flexiVars ++ vars
256+ , constraint = Ann.noneNoDocs CTrue
257+ , header = Map.singleton name typ
260+ c <- constrain env' expr typ
263+ { iSchemes = scheme : iSchemes info
264+ , iC1 = fl rigidVars c /\ iC1 info
268+constrainUnannotatedDef
274+ -> ErrorT [PP.Doc] IO Info
275+constrainUnannotatedDef env info qs name expr =
276+ do -- Some mistake may be happening here. Currently, qs is always [].
277+ rigidVars <- forM qs (\_ -> liftIO $ variable Rigid)
279+ v <- liftIO $ variable Flexible
283+ let inserts = zipWith (\arg typ -> Map.insert arg (varN typ)) qs rigidVars
285+ let env' = env { Env.value = List.foldl' (\x f -> f x) (Env.value env) inserts }
287+ c <- constrain env' expr tipe
290+ { iRigid = rigidVars ++ iRigid info
291+ , iFlex = v : iFlex info
292+ , iHeaders = Map.insert name tipe (iHeaders info)
293+ , iC2 = c /\ iC2 info