2module Type.Constrain.Expression where
4import Control.Applicative ((<$>))
5import qualified Control.Monad as Monad
6import Control.Monad.Error
7import qualified Data.List as List
8import qualified Data.Map as Map
9import qualified Text.PrettyPrint as PP
11import AST.Literal as Lit
12import AST.Annotation as Ann
13import AST.Expression.General
14import qualified AST.Expression.Canonical as Canonical
15import qualified AST.Pattern as P
16import qualified AST.Type as ST
17import qualified AST.Variable as V
18import Type.Type hiding (Descriptor(..))
20import qualified Type.Environment as Env
21import qualified Type.Constrain.Literal as Literal
22import qualified Type.Constrain.Pattern as Pattern
24constrain :: Env.Environment -> Canonical.Expr -> Type
25 -> ErrorT [PP.Doc] IO TypeConstraint
26constrain env (A region expr) tipe =
27 let list t = Env.get env Env.types "_List" <| t
30 t1 === t2 = A region (CEqual t1 t2)
31 x <? t = A region (CInstance x t)
32 clet schemes c = A region (CLet schemes c)
35 Literal lit -> liftIO $ Literal.constrain env region lit tipe
37 GLShader _uid _src gltipe ->
41 shaderTipe a u v = Env.get env Env.types "Graphics.WebGL.Shader" <| a <| u <| v
42 glTipe = Env.get env Env.types . Lit.glTipeName
43 makeRec accessor baseRec =
44 let decls = accessor gltipe
45 in if Map.size decls == 0
47 else record (Map.map (\t -> [glTipe t]) decls) baseRec
48 attribute = makeRec Lit.attribute attr
49 uniform = makeRec Lit.uniform unif
50 varying = makeRec Lit.varying (termN EmptyRecord1)
51 in return . A region $ CEqual tipe (shaderTipe attribute uniform varying)
54 | name == saveEnvName -> return (A region CSaveEnv)
55 | otherwise -> return (name <? tipe)
60 existsNumber $ \n -> do
61 clo <- constrain env lo n
62 chi <- constrain env hi n
63 return $ and [clo, chi, list n === tipe]
67 cs <- mapM (\e -> constrain env e x) exprs
68 return . and $ list x === tipe : cs
73 c1 <- constrain env e1 t1
74 c2 <- constrain env e2 t2
75 return $ and [ c1, c2, V.toString op <? (t1 ==> t2 ==> tipe) ]
80 fragment <- try region $ Pattern.constrain env p t1
81 c2 <- constrain env e t2
82 let c = ex (vars fragment) (clet [monoscheme (typeEnv fragment)]
83 (typeConstraint fragment /\ c2 ))
84 return $ c /\ tipe === (t1 ==> t2)
88 c1 <- constrain env e1 (t ==> tipe)
89 c2 <- constrain env e2 t
92 MultiIf branches -> and <$> mapM constrain' branches
94 bool = Env.get env Env.types "Bool"
96 cb <- constrain env b bool
97 ce <- constrain env e tipe
102 ce <- constrain env exp t
103 let branch (p,e) = do
104 fragment <- try region $ Pattern.constrain env p t
105 clet [toScheme fragment] <$> constrain env e tipe
106 and . (:) ce <$> mapM branch branches
109 do vars <- forM exprs $ \_ -> liftIO (variable Flexible)
110 let pairs = zip exprs (map varN vars)
111 (ctipe, cs) <- Monad.foldM step (tipe,true) (reverse pairs)
112 return $ ex vars (cs /\ name <? ctipe)
114 step (t,c) (e,x) = do
115 c' <- constrain env e x
116 return (x ==> t, c /\ c')
120 constrain env e (record (Map.singleton label [tipe]) t)
124 constrain env e (record (Map.singleton label [t]) tipe)
126 Insert e label value ->
129 cVal <- constrain env value tVal
130 cRec <- constrain env e tRec
131 let c = tipe === record (Map.singleton label [tVal]) tRec
132 return (and [cVal, cRec, c])
136 oldVars <- forM fields $ \_ -> liftIO (variable Flexible)
137 let oldFields = ST.fieldMap (zip (map fst fields) (map varN oldVars))
138 cOld <- ex oldVars <$> constrain env e (record oldFields t)
140 newVars <- forM fields $ \_ -> liftIO (variable Flexible)
141 let newFields = ST.fieldMap (zip (map fst fields) (map varN newVars))
142 let cNew = tipe === record newFields t
144 cs <- zipWithM (constrain env) (map snd fields) (map varN newVars)
146 return $ cOld /\ ex newVars (and (cNew : cs))
149 do vars <- forM fields $ \_ -> liftIO (variable Flexible)
150 cs <- zipWithM (constrain env) (map snd fields) (map varN vars)
151 let fields' = ST.fieldMap (zip (map fst fields) (map varN vars))
152 recordType = record fields' (termN EmptyRecord1)
153 return . ex vars . and $ tipe === recordType : cs
156 do vars <- forM es $ \_ -> liftIO (variable Flexible)
157 let tvars = map varN vars
158 cs <- zipWithM (constrain env) es tvars
159 return . ex vars $ and ("Text.markdown" <? tipe : cs)
162 do c <- constrain env body tipe
163 (schemes, rqs, fqs, header, c2, c1) <-
164 Monad.foldM (constrainDef env)
165 ([], [], [], Map.empty, true, true)
166 (concatMap expandPattern defs)
167 return $ clet schemes
168 (clet [Scheme rqs fqs (clet [monoscheme header] c2) header ]
171 PortIn _ _ -> return true
173 PortOut _ _ signal ->
174 constrain env signal tipe
176constrainDef env info (Canonical.Definition pattern expr maybeTipe) =
177 let qs = [] -- should come from the def, but I'm not sure what would live there...
178 (schemes, rigidQuantifiers, flexibleQuantifiers, headers, c2, c1) = info
180 do rigidVars <- forM qs (\_ -> liftIO $ variable Rigid) -- Some mistake may be happening here.
181 -- Currently, qs is always [].
182 case (pattern, maybeTipe) of
183 (P.Var name, Just tipe) -> do
184 flexiVars <- forM qs (\_ -> liftIO $ variable Flexible)
185 let inserts = zipWith (\arg typ -> Map.insert arg (varN typ)) qs flexiVars
186 env' = env { Env.value = List.foldl' (\x f -> f x) (Env.value env) inserts }
187 (vars, typ) <- Env.instantiateType env tipe Map.empty
188 let scheme = Scheme { rigidQuantifiers = [],
189 flexibleQuantifiers = flexiVars ++ vars,
190 constraint = Ann.noneNoDocs CTrue,
191 header = Map.singleton name typ }
192 c <- constrain env' expr typ
193 return ( scheme : schemes
195 , flexibleQuantifiers
198 , fl rigidVars c /\ c1 )
200 (P.Var name, Nothing) -> do
201 v <- liftIO $ variable Flexible
203 inserts = zipWith (\arg typ -> Map.insert arg (varN typ)) qs rigidVars
204 env' = env { Env.value = List.foldl' (\x f -> f x) (Env.value env) inserts }
205 c <- constrain env' expr tipe
207 , rigidVars ++ rigidQuantifiers
208 , v : flexibleQuantifiers
209 , Map.insert name tipe headers
213 _ -> error ("problem in constrainDef with " ++ show pattern)
215expandPattern :: Canonical.Def -> [Canonical.Def]
216expandPattern def@(Canonical.Definition pattern lexpr@(A r _) maybeType) =
219 _ -> Canonical.Definition (P.Var x) lexpr maybeType : map toDef vars
221 vars = P.boundVarList pattern
222 x = "$" ++ concat vars
223 mkVar = A r . localVar
224 toDef y = Canonical.Definition (P.Var y) (A r $ Case (mkVar x) [(pattern, mkVar y)]) Nothing
226try :: Region -> ErrorT (Region -> PP.Doc) IO a -> ErrorT [PP.Doc] IO a
227try region computation = do
228 result <- liftIO $ runErrorT computation
230 Left err -> throwError [err region]
231 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