@@ -0,0 +1,155 @@
1+module Type.Constrain.Expression where
2+
3+import Control.Arrow (second)
4+import Control.Applicative ((<$>))
5+import qualified Data.List as List
6+import qualified Data.Map as Map
7+import qualified Control.Monad as Monad
8+import Data.Map ((!))
9+
10+import SourceSyntax.Location as Loc
11+import SourceSyntax.Pattern (Pattern(PVar))
12+import SourceSyntax.Expression
13+import Type.Type hiding (Descriptor(..))
14+import Type.Constrain.Fragment
15+import Type.Constrain.Environment as Env
16+import qualified Type.Constrain.Literal as Literal
17+import qualified Type.Constrain.Pattern as Pattern
18+
19+
20+constrain :: Environment -> LExpr a b -> Type -> IO TypeConstraint
21+constrain env (L _ _ expr) tipe =
22+ let list t = TermN (App1 (Env.get env builtin "[]") t) in
23+ case expr of
24+ Literal lit -> return $ Literal.constrain env lit tipe
25+
26+ Var name -> return $ name <? tipe
27+
28+ Range lo hi ->
29+ exists $ \x -> do
30+ clo <- constrain env lo x
31+ chi <- constrain env hi x
32+ return $ CAnd [clo, chi, list x === tipe]
33+
34+ ExplicitList exprs ->
35+ exists $ \x -> do
36+ cs <- mapM (\e -> constrain env e x) exprs
37+ return $ CAnd (list x === tipe : cs)
38+
39+ Binop op e1 e2 ->
40+ exists $ \t1 ->
41+ exists $ \t2 -> do
42+ c1 <- constrain env e1 t1
43+ c2 <- constrain env e2 t2
44+ return $ CAnd [ c1, c2, (Env.get env value op) === (t1 ==> t2 ==> tipe) ]
45+
46+ Lambda p e ->
47+ exists $ \t1 ->
48+ exists $ \t2 -> do
49+ fragment <- Pattern.constrain env p t1
50+ c2 <- constrain env e t2
51+ let c = ex (vars fragment) (CLet [Scheme [] [] CTrue (typeEnv fragment)]
52+ (typeConstraint fragment /\ c2 ))
53+ return $ c /\ tipe === (t1 ==> t2)
54+
55+ App e1 e2 ->
56+ exists $ \t -> do
57+ c1 <- constrain env e1 (t ==> tipe)
58+ c2 <- constrain env e2 t
59+ return $ c1 /\ c2
60+
61+ MultiIf branches -> CAnd <$> mapM constrain' branches
62+ where
63+ bool = Env.get env builtin "Bool"
64+ constrain' (b,e) = do
65+ cb <- constrain env b bool
66+ ce <- constrain env e tipe
67+ return (cb /\ ce)
68+
69+ Let defs body -> error "not defined yet"
70+
71+ Case e branches ->
72+ exists $ \t -> do
73+ ce <- constrain env e t
74+ let branch (p,e) = do
75+ fragment <- Pattern.constrain env p t
76+ c <- constrain env e tipe
77+ return $ ex (vars fragment)
78+ (CLet [Scheme [] [] CTrue (typeEnv fragment)]
79+ (typeConstraint fragment /\ c))
80+ CAnd . (:) ce <$> mapM branch branches
81+
82+ Data name exprs ->
83+ do pairs <- mapM pair exprs
84+ (ctipe, cs) <- Monad.foldM step (tipe,CTrue) (reverse pairs)
85+ return (cs /\ name <? ctipe)
86+ where
87+ pair e = do v <- flexibleVar -- needs an ex
88+ return (e, VarN v)
89+
90+ step (t,c) (e,x) = do
91+ c' <- constrain env e x
92+ return (x ==> t, c /\ c')
93+
94+ Access e label ->
95+ exists $ \t ->
96+ constrain env e (record (Map.singleton label [tipe]) t)
97+
98+ Remove e label ->
99+ exists $ \t ->
100+ constrain env e (record (Map.singleton label [t]) tipe)
101+
102+ Insert e label value ->
103+ exists $ \tVal ->
104+ exists $ \tRec -> do
105+ cVal <- constrain env value tVal
106+ cRec <- constrain env e tRec
107+ let c = tipe === record (Map.singleton label [tVal]) tRec
108+ return (CAnd [cVal, cRec, c])
109+
110+ Modify e fields ->
111+ exists $ \t -> do
112+ dummyFields <- Map.fromList <$> mapM dummyField fields
113+ cOld <- constrain env e (record dummyFields t)
114+ (fieldTypes, constraints) <- unzip <$> mapM field fields
115+ let cNew = tipe === record (Map.fromList fieldTypes) t
116+ return (CAnd (cOld : cNew : constraints))
117+ where
118+ dummyField (label, _) = do
119+ v <- flexibleVar -- needs an ex
120+ return (label, [VarN v])
121+
122+ field (label, value) = do
123+ v <- flexibleVar -- needs an ex
124+ c <- ex [v] <$> constrain env value (VarN v)
125+ return ((label, [VarN v]), c)
126+
127+ Record fields ->
128+ do (pairs, cs) <- unzip <$> mapM field fields
129+ let fieldTypes = Map.fromList (map (second (\t -> [VarN t])) pairs)
130+ recordType = record fieldTypes (TermN EmptyRecord1)
131+ return $ ex (map snd pairs) (CAnd (tipe === recordType : cs))
132+ where
133+ field (name, args, body) = do
134+ let value = List.foldl' (\e arg -> Loc.none (Lambda (PVar arg) e)) body args
135+ v <- flexibleVar -- needs an ex
136+ c <- constrain env value (VarN v)
137+ return ((name, v), c)
138+
139+
140+ Markdown _ ->
141+ return $ tipe === Env.get env builtin "Element"
142+
143+
144+--collapseDefs :: [Def t v] -> [(String, [String], LExpr t v, Maybe Type)]
145+collapseDefs = go Map.empty Map.empty
146+ where
147+ go defs typs [] = Map.union (Map.intersectionWith (\f t -> f (Just t)) defs typs)
148+ (Map.map ($ Nothing) (Map.difference defs typs))
149+ go defs typs (d:ds) =
150+ case d of
151+ Def name args body ->
152+ go (Map.insert name ((,,) args body) defs) typs ds
153+ TypeAnnotation name typ ->
154+ go defs (Map.insert name typ typs) ds
155+