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 SourceSyntax.Annotation as Ann
12import SourceSyntax.Expression
13import qualified SourceSyntax.Pattern as P
14import qualified SourceSyntax.Type as ST
15import qualified SourceSyntax.Variable as V
16import Type.Type hiding (Descriptor(..))
18import qualified Type.Environment as Env
19import qualified Type.Constrain.Literal as Literal
20import qualified Type.Constrain.Pattern as Pattern
22constrain :: Env.Environment -> Expr -> Type -> ErrorT [PP.Doc] IO TypeConstraint
23constrain env (A region expr) tipe =
24 let list t = Env.get env Env.types "_List" <| t
27 t1 === t2 = A region (CEqual t1 t2)
28 x <? t = A region (CInstance x t)
29 clet schemes c = A region (CLet schemes c)
32 Literal lit -> liftIO $ Literal.constrain env region lit tipe
35 | name == saveEnvName -> return (A region CSaveEnv)
36 | otherwise -> return (name <? tipe)
39 existsNumber $ \n -> do
40 clo <- constrain env lo n
41 chi <- constrain env hi n
42 return $ and [clo, chi, list n === tipe]
46 cs <- mapM (\e -> constrain env e x) exprs
47 return . and $ list x === tipe : cs
52 c1 <- constrain env e1 t1
53 c2 <- constrain env e2 t2
54 return $ and [ c1, c2, op <? (t1 ==> t2 ==> tipe) ]
59 fragment <- try region $ Pattern.constrain env p t1
60 c2 <- constrain env e t2
61 let c = ex (vars fragment) (clet [monoscheme (typeEnv fragment)]
62 (typeConstraint fragment /\ c2 ))
63 return $ c /\ tipe === (t1 ==> t2)
67 c1 <- constrain env e1 (t ==> tipe)
68 c2 <- constrain env e2 t
71 MultiIf branches -> and <$> mapM constrain' branches
73 bool = Env.get env Env.types "Bool"
75 cb <- constrain env b bool
76 ce <- constrain env e tipe
81 ce <- constrain env exp t
83 fragment <- try region $ Pattern.constrain env p t
84 clet [toScheme fragment] <$> constrain env e tipe
85 and . (:) ce <$> mapM branch branches
88 do vars <- forM exprs $ \_ -> liftIO (var Flexible)
89 let pairs = zip exprs (map VarN vars)
90 (ctipe, cs) <- Monad.foldM step (tipe,true) (reverse pairs)
91 return $ ex vars (cs /\ name <? ctipe)
94 c' <- constrain env e x
95 return (x ==> t, c /\ c')
99 constrain env e (record (Map.singleton label [tipe]) t)
103 constrain env e (record (Map.singleton label [t]) tipe)
105 Insert e label value ->
108 cVal <- constrain env value tVal
109 cRec <- constrain env e tRec
110 let c = tipe === record (Map.singleton label [tVal]) tRec
111 return (and [cVal, cRec, c])
115 oldVars <- forM fields $ \_ -> liftIO (var Flexible)
116 let oldFields = ST.fieldMap (zip (map fst fields) (map VarN oldVars))
117 cOld <- ex oldVars <$> constrain env e (record oldFields t)
119 newVars <- forM fields $ \_ -> liftIO (var Flexible)
120 let newFields = ST.fieldMap (zip (map fst fields) (map VarN newVars))
121 let cNew = tipe === record newFields t
123 cs <- zipWithM (constrain env) (map snd fields) (map VarN newVars)
125 return $ cOld /\ ex newVars (and (cNew : cs))
128 do vars <- forM fields $ \_ -> liftIO (var Flexible)
129 cs <- zipWithM (constrain env) (map snd fields) (map VarN vars)
130 let fields' = ST.fieldMap (zip (map fst fields) (map VarN vars))
131 recordType = record fields' (TermN EmptyRecord1)
132 return . ex vars . and $ tipe === recordType : cs
135 do vars <- forM es $ \_ -> liftIO (var Flexible)
136 let tvars = map VarN vars
137 cs <- zipWithM (constrain env) es tvars
138 return . ex vars $ and ("Text.markdown" <? tipe : cs)
141 do c <- constrain env body tipe
142 (schemes, rqs, fqs, header, c2, c1) <-
143 Monad.foldM (constrainDef env)
144 ([], [], [], Map.empty, true, true)
145 (concatMap expandPattern defs)
146 return $ clet schemes
147 (clet [Scheme rqs fqs (clet [monoscheme header] c2) header ]
150 PortIn _ _ -> return true
152 PortOut _ _ signal ->
153 constrain env signal tipe
155constrainDef env info (Definition pattern expr maybeTipe) =
156 let qs = [] -- should come from the def, but I'm not sure what would live there...
157 (schemes, rigidQuantifiers, flexibleQuantifiers, headers, c2, c1) = info
159 do rigidVars <- forM qs (\_ -> liftIO $ var Rigid) -- Some mistake may be happening here.
160 -- Currently, qs is always [].
161 case (pattern, maybeTipe) of
162 (P.Var name, Just tipe) -> do
163 flexiVars <- forM qs (\_ -> liftIO $ var Flexible)
164 let inserts = zipWith (\arg typ -> Map.insert arg (VarN typ)) qs flexiVars
165 env' = env { Env.value = List.foldl' (\x f -> f x) (Env.value env) inserts }
166 (vars, typ) <- Env.instantiateType env tipe Map.empty
167 let scheme = Scheme { rigidQuantifiers = [],
168 flexibleQuantifiers = flexiVars ++ vars,
169 constraint = Ann.noneNoDocs CTrue,
170 header = Map.singleton name typ }
171 c <- constrain env' expr typ
172 return ( scheme : schemes
174 , flexibleQuantifiers
177 , fl rigidVars c /\ c1 )
179 (P.Var name, Nothing) -> do
180 v <- liftIO $ var Flexible
182 inserts = zipWith (\arg typ -> Map.insert arg (VarN typ)) qs rigidVars
183 env' = env { Env.value = List.foldl' (\x f -> f x) (Env.value env) inserts }
184 c <- constrain env' expr tipe
186 , rigidVars ++ rigidQuantifiers
187 , v : flexibleQuantifiers
188 , Map.insert name tipe headers
192 _ -> error (show pattern)
194expandPattern :: Def -> [Def]
195expandPattern def@(Definition pattern lexpr@(A r _) maybeType) =
198 _ -> Definition (P.Var x) lexpr maybeType : map toDef vars
200 vars = P.boundVarList pattern
201 x = "$" ++ concat vars
203 toDef y = Definition (P.Var y) (A r $ Case (mkVar x) [(pattern, mkVar y)]) Nothing
205try :: Region -> ErrorT (Region -> PP.Doc) IO a -> ErrorT [PP.Doc] IO a
206try region computation = do
207 result <- liftIO $ runErrorT computation
209 Left err -> throwError [err region]
210 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