2{-# LANGUAGE FlexibleInstances #-}
3module Type.Constrain.Pattern where
5import Control.Arrow (second)
6import Control.Applicative ((<$>))
7import qualified Control.Monad as Monad
8import Control.Monad.Error
9import qualified Data.Map as Map
10import qualified Text.PrettyPrint as PP
12import qualified SourceSyntax.Annotation as A
13import qualified SourceSyntax.Pattern as P
14import SourceSyntax.PrettyPrint (pretty)
17import Type.Environment as Env
18import qualified Type.Constrain.Literal as Literal
21constrain :: Environment -> P.Pattern -> Type -> ErrorT (A.Region -> PP.Doc) IO Fragment
22constrain env pattern tipe =
23 let region = A.None (pretty pattern)
24 t1 === t2 = A.A region (CEqual t1 t2)
25 x <? t = A.A region (CInstance x t)
28 P.Anything -> return emptyFragment
31 c <- liftIO $ Literal.constrain env region lit tipe
32 return $ emptyFragment { typeConstraint = c }
35 v <- liftIO $ var Flexible
37 typeEnv = Map.singleton name (VarN v),
39 typeConstraint = VarN v === tipe
43 fragment <- constrain env p tipe
45 typeEnv = Map.insert name tipe (typeEnv fragment),
46 typeConstraint = name <? tipe /\ typeConstraint fragment
49 P.Data name patterns -> do
50 (kind, cvars, args, result) <- liftIO $ freshDataScheme env name
51 let msg = concat [ "Constructor '", name, "' expects ", show kind
52 , " argument", if kind == 1 then "" else "s"
53 , " but was given ", show (length patterns), "." ]
54 err span = PP.vcat [ PP.text $ "Type error " ++ show span
56 case length patterns == kind of
57 False -> throwError err
59 fragment <- Monad.liftM joinFragments (Monad.zipWithM (constrain env) patterns args)
61 typeConstraint = typeConstraint fragment /\ tipe === result,
62 vars = cvars ++ vars fragment
66 pairs <- liftIO $ mapM (\name -> (,) name <$> var Flexible) fields
67 let tenv = Map.fromList (map (second VarN) pairs)
68 c <- exists $ \t -> return (tipe === record (Map.map (:[]) tenv) t)
75instance Error (A.Region -> PP.Doc) where
78 PP.vcat [ PP.text $ "Type error " ++ show span
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