1module Type.Constrain.Expression where
3import Control.Applicative ((<$>))
4import qualified Control.Monad as Monad
5import Control.Monad.Error
6import qualified Data.List as List
7import qualified Data.Map as Map
8import qualified Text.PrettyPrint as PP
10import AST.Literal as Lit
11import AST.Annotation as Ann
12import AST.Expression.General
13import qualified AST.Expression.Canonical as Canonical
14import qualified AST.Pattern as P
15import qualified AST.Type as ST
16import qualified AST.Variable as V
17import Type.Type hiding (Descriptor(..))
19import qualified Type.Environment as Env
20import qualified Type.Constrain.Literal as Literal
21import qualified Type.Constrain.Pattern as Pattern
28 -> ErrorT [PP.Doc] IO TypeConstraint
29constrain env (A region expr) tipe =
30 let list t = Env.get env Env.types "List" <| t
33 t1 === t2 = A region (CEqual t1 t2)
34 x <? t = A region (CInstance x t)
35 clet schemes c = A region (CLet schemes c)
38 Literal lit -> liftIO $ Literal.constrain env region lit tipe
40 GLShader _uid _src gltipe ->
44 shaderTipe a u v = Env.get env Env.types "WebGL.Shader" <| a <| u <| v
45 glTipe = Env.get env Env.types . Lit.glTipeName
46 makeRec accessor baseRec =
47 let decls = accessor gltipe
48 in if Map.size decls == 0
50 else record (Map.map (\t -> [glTipe t]) decls) baseRec
51 attribute = makeRec Lit.attribute attr
52 uniform = makeRec Lit.uniform unif
53 varying = makeRec Lit.varying (termN EmptyRecord1)
54 in return . A region $ CEqual tipe (shaderTipe attribute uniform varying)
57 | name == saveEnvName -> return (A region CSaveEnv)
58 | otherwise -> return (name <? tipe)
63 existsNumber $ \n -> do
64 clo <- constrain env lo n
65 chi <- constrain env hi n
66 return $ and [clo, chi, list n === tipe]
70 cs <- mapM (\e -> constrain env e x) exprs
71 return . and $ list x === tipe : cs
76 c1 <- constrain env e1 t1
77 c2 <- constrain env e2 t2
78 return $ and [ c1, c2, V.toString op <? (t1 ==> t2 ==> tipe) ]
83 fragment <- try region $ Pattern.constrain env p t1
84 c2 <- constrain env e t2
85 let c = ex (vars fragment) (clet [monoscheme (typeEnv fragment)]
86 (typeConstraint fragment /\ c2 ))
87 return $ c /\ tipe === (t1 ==> t2)
91 c1 <- constrain env e1 (t ==> tipe)
92 c2 <- constrain env e2 t
95 MultiIf branches -> and <$> mapM constrain' branches
97 bool = Env.get env Env.types "Bool"
99 cb <- constrain env b bool
100 ce <- constrain env e tipe
105 ce <- constrain env exp t
106 let branch (p,e) = do
107 fragment <- try region $ Pattern.constrain env p t
108 clet [toScheme fragment] <$> constrain env e tipe
109 and . (:) ce <$> mapM branch branches
112 do vars <- forM exprs $ \_ -> liftIO (variable Flexible)
113 let pairs = zip exprs (map varN vars)
114 (ctipe, cs) <- Monad.foldM step (tipe,true) (reverse pairs)
115 return $ ex vars (cs /\ name <? ctipe)
117 step (t,c) (e,x) = do
118 c' <- constrain env e x
119 return (x ==> t, c /\ c')
123 constrain env e (record (Map.singleton label [tipe]) t)
127 constrain env e (record (Map.singleton label [t]) tipe)
129 Insert e label value ->
132 cVal <- constrain env value tVal
133 cRec <- constrain env e tRec
134 let c = tipe === record (Map.singleton label [tVal]) tRec
135 return (and [cVal, cRec, c])
139 oldVars <- forM fields $ \_ -> liftIO (variable Flexible)
140 let oldFields = ST.fieldMap (zip (map fst fields) (map varN oldVars))
141 cOld <- ex oldVars <$> constrain env e (record oldFields t)
143 newVars <- forM fields $ \_ -> liftIO (variable Flexible)
144 let newFields = ST.fieldMap (zip (map fst fields) (map varN newVars))
145 let cNew = tipe === record newFields t
147 cs <- zipWithM (constrain env) (map snd fields) (map varN newVars)
149 return $ cOld /\ ex newVars (and (cNew : cs))
152 do vars <- forM fields $ \_ -> liftIO (variable Flexible)
153 cs <- zipWithM (constrain env) (map snd fields) (map varN vars)
154 let fields' = ST.fieldMap (zip (map fst fields) (map varN vars))
155 recordType = record fields' (termN EmptyRecord1)
156 return . ex vars . and $ tipe === recordType : cs
159 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 ]
172 constrain env signal tipe
174 Loopback _ _ maybeExpr ->
179 constrain env expr tipe
182constrainDef env info (Canonical.Definition pattern expr maybeTipe) =
183 let qs = [] -- should come from the def, but I'm not sure what would live there...
184 (schemes, rigidQuantifiers, flexibleQuantifiers, headers, c2, c1) = info
186 do rigidVars <- forM qs (\_ -> liftIO $ variable Rigid) -- Some mistake may be happening here.
187 -- Currently, qs is always [].
188 case (pattern, maybeTipe) of
189 (P.Var name, Just tipe) -> do
190 flexiVars <- forM qs (\_ -> liftIO $ variable Flexible)
191 let inserts = zipWith (\arg typ -> Map.insert arg (varN typ)) qs flexiVars
192 env' = env { Env.value = List.foldl' (\x f -> f x) (Env.value env) inserts }
193 (vars, typ) <- Env.instantiateType env tipe Map.empty
194 let scheme = Scheme { rigidQuantifiers = [],
195 flexibleQuantifiers = flexiVars ++ vars,
196 constraint = Ann.noneNoDocs CTrue,
197 header = Map.singleton name typ }
198 c <- constrain env' expr typ
199 return ( scheme : schemes
201 , flexibleQuantifiers
204 , fl rigidVars c /\ c1 )
206 (P.Var name, Nothing) -> do
207 v <- liftIO $ variable Flexible
209 inserts = zipWith (\arg typ -> Map.insert arg (varN typ)) qs rigidVars
210 env' = env { Env.value = List.foldl' (\x f -> f x) (Env.value env) inserts }
211 c <- constrain env' expr tipe
213 , rigidVars ++ rigidQuantifiers
214 , v : flexibleQuantifiers
215 , Map.insert name tipe headers
219 _ -> error ("problem in constrainDef with " ++ show pattern)
222expandPattern :: Canonical.Def -> [Canonical.Def]
223expandPattern def@(Canonical.Definition pattern lexpr@(A r _) maybeType) =
226 _ -> Canonical.Definition (P.Var x) lexpr maybeType : map toDef vars
228 vars = P.boundVarList pattern
229 x = "$" ++ concat vars
230 mkVar = A r . localVar
231 toDef y = Canonical.Definition (P.Var y) (A r $ Case (mkVar x) [(pattern, mkVar y)]) Nothing
234try :: Region -> ErrorT (Region -> PP.Doc) IO a -> ErrorT [PP.Doc] IO a
235try region computation =
236 do result <- liftIO $ runErrorT computation
238 Left err -> throwError [err region]
239 Right value -> return value
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