@@ -1,11 +1,12 @@
11
2−module Constrain where
2+module Constrain (constrain, Context (..)) where
33
44import Ast
55import Types
66import Data.List (foldl')
77import qualified Data.Set as Set
88import qualified Data.Map as Map
9+import Control.Arrow (second)
910import Control.Monad (liftM,mapM,zipWithM)
1011import Control.Monad.State (evalState)
1112import Guid
@@ -14,39 +15,42 @@ beta = VarT `liftM` guid
1415unionA = Map.unionWith (++)
1516unionsA = Map.unionsWith (++)
1617
17−data Context a b = Context a b deriving (Eq,Show)
18+data Context a b = Context a b deriving (Eq, Show)
1819ctx e = Context e
1920
2021instance (Ord a, Eq c) => Ord (Context c a) where
2122 compare (Context _ x) (Context _ y) = compare x y
2223
23−constrain hints expr = do
24− (as,cs,t) <- inference expr
25− let cMap = Map.intersectionWithKey combine (Map.fromList hints) as
26− where combine k s vs = map (\v -> ctx (Var k) $ VarT v :<<: s) vs
27− return (Set.toList cs ++ (concatMap snd $ Map.toList cMap))
24+constrain hints (Module _ _ _ stmts) = do
25+ (ass,css,schemess) <- unzip3 `liftM` mapM stmtGen stmts
26+ let allHints = Map.fromList $ hints ++ concat schemess
27+ let combine k s vs = map (\v -> ctx (Var k) $ VarT v :<<: s) vs
28+ let cMap = Map.intersectionWithKey combine allHints (unionsA ass)
29+ return (Set.toList (Set.unions css) ++ (concatMap snd $ Map.toList cMap))
2830
29−inference :: Expr -> GuidCounter (Map.Map String [X], Set.Set (Context Expr Constraint), Type)
30−inference (Var x) =
31+gen :: Expr -> GuidCounter (Map.Map String [X], Set.Set (Context Expr Constraint), Type)
32+
33+gen (Var x) =
3134 do b <- guid
3235 return (Map.singleton x [b], Set.empty, VarT b)
33−inference e@(App e1 e2) =
34− do (a1,c1,t1) <- inference e1
35− (a2,c2,t2) <- inference e2
36+
37+gen e@(App e1 e2) =
38+ do (a1,c1,t1) <- gen e1
39+ (a2,c2,t2) <- gen e2
3640 b <- beta
3741 return ( unionA a1 a2
3842 , Set.unions [c1,c2,Set.singleton . ctx e $ t1 :=: (LambdaT t2 b)]
3943 , b )
40−inference (Lambda x e) =
41− do (a,c,t) <- inference e
44+gen (Lambda x e) =
45+ do (a,c,t) <- gen e
4246 b <- beta
4347 v <- guid
4448 return ( Map.delete x a
4549 , Set.union c . Set.fromList . map (\x -> ctx e $ VarT x :=: b) $
4650 Map.findWithDefault [v] x a
4751 , LambdaT b t )
48−inference (Let defs e) =
49− do (as,cs,t) <- inference e
52+gen (Let defs e) =
53+ do (as,cs,t) <- gen e
5054 (ass, schemes) <- liftM unzip (mapM defScheme defs)
5155 let assumptions = unionsA (as:ass)
5256 let names = map (\(Definition x _ _) -> x) defs
@@ -58,28 +62,28 @@ inference (Let defs e) =
5862 , Set.union (Set.fromList . concat $ cs') cs
5963 , t )
6064
61−inference ce@(Case e cases) =
62− do (as,cs,t) <- inference e
63− (ass,css,ts) <- liftM unzip3 $ mapM (caseInference t) cases
65+gen ce@(Case e cases) =
66+ do (as,cs,t) <- gen e
67+ (ass,css,ts) <- liftM unzip3 $ mapM (caseGen t) cases
6468 return ( unionsA $ as:ass
6569 , let combine t1 t2 = ctx ce (t1 :=: t2) in
6670 Set.unions $ Set.fromList (zipWith combine ts $ tail ts) : cs : css
6771 , head ts)
6872
69−inference e@(If e1 e2 e3) =
70− do (a1,c1,t1) <- inference e1
71− (a2,c2,t2) <- inference e2
72− (a3,c3,t3) <- inference e3
73+gen e@(If e1 e2 e3) =
74+ do (a1,c1,t1) <- gen e1
75+ (a2,c2,t2) <- gen e2
76+ (a3,c3,t3) <- gen e3
7377 return ( unionsA [a1,a2,a3]
7478 , Set.unions [c1,c2,c3, Set.fromList [ ctx e1 (t1 :=: bool), ctx e (t2 :=: t3) ] ]
7579 , t2 )
7680
77−inference (Data name es) = inference $ foldl' App (Var name) es
78−inference (Binop op e1 e2) = inference (Var op `App` e1 `App` e2)
79−inference (Access (Var x) y) = inference . Var $ x ++ "." ++ y
80−inference (Range e1 e2) = inference (Var "elmRange" `App` e1 `App` e2)
81+gen (Data name es) = gen $ foldl' App (Var name) es
82+gen (Binop op e1 e2) = gen (Var op `App` e1 `App` e2)
83+gen (Access (Var x) y) = gen . Var $ x ++ "." ++ y
84+gen (Range e1 e2) = gen (Var "elmRange" `App` e1 `App` e2)
8185
82−inference other =
86+gen other =
8387 case other of
8488 IntNum _ -> do t <- beta
8589 return (Map.empty, Set.singleton (ctx other $ t :<: number), t)
@@ -91,8 +95,8 @@ inference other =
9195
9296primitive t = return (Map.empty, Set.empty, t)
9397
94−caseInference tipe (p,e) = do
95− (as,cs,t) <- inference e
98+caseGen tipe (p,e) = do
99+ (as,cs,t) <- gen e
96100 return ( foldr Map.delete as (namesIn p)
97101 , cs
98102 , t)
@@ -103,7 +107,7 @@ namesIn (PData name ps) = concatMap namesIn ps
103107
104108defScheme (Definition name args e) =
105109 do argDict <- mapM (\a -> liftM ((,) a) guid) args
106− (as,cs,t) <- inference e
110+ (as,cs,t) <- gen e
107111 let genCs (arg,x) = do
108112 v <- guid
109113 return . map (\y -> VarT x :=: VarT y) $ Map.findWithDefault [v] arg as
@@ -112,3 +116,52 @@ defScheme (Definition name args e) =
112116 let tipe = foldr (==>) t $ map (VarT . snd) argDict
113117 return ( foldr Map.delete as args
114118 , Forall (map snd argDict) (cs' ++ cs'') tipe)
119+
120+stmtGen (Def name args e) = do
121+ argDict <- mapM (\a -> liftM ((,) a) guid) args
122+ (as,cs,t) <- gen e
123+ let genCs (arg,x) = do
124+ v <- guid
125+ return . map (\y -> VarT x :=: VarT y) $ Map.findWithDefault [v] arg as
126+ cs' <- concat `liftM` mapM genCs argDict
127+ let cs'' = map (\(Context _ c) -> c) (Set.toList cs)
128+ let tipe = foldr (==>) t $ map (VarT . snd) argDict
129+ return ( foldr Map.delete as args
130+ , Set.empty
131+ , [ (name, Forall (map snd argDict) (cs' ++ cs'') tipe) ] )
132+
133+stmtGen (Datatype name xs tcs) = do schemes <- mapM gen' tcs'
134+ return (Map.empty, Set.empty, schemes)
135+ where names = map (+ (length xs)) [1..5]
136+ tcs' = map (second . map $ rnm names) tcs
137+ supers t = zipWith (:<:) (map VarT names)
138+ [ number, time, appendable t, comparable, transformable ]
139+ gen' (n,ts) = do
140+ t <- beta
141+ return . (,) n . Forall (xs ++ names) (supers t) $
142+ foldr (==>) (ADT name $ map VarT xs) ts
143+ rnm [a,b,c,d,e] (ADT n []) | n == "Number" = VarT a
144+ | n == "Time" = VarT b
145+ | n == "Appendable" = VarT c
146+ | n == "Comparable" = VarT d
147+ | n == "Transformable" = VarT e
148+ rnm _ t = t
149+
150+stmtGen (ExportEvent js elm tipe) = do
151+ x <- guid
152+ return ( Map.singleton elm [x]
153+ , Set.singleton . ctx (Var elm) $ VarT x :=: tipe
154+ , [] )
155+
156+stmtGen (ImportEvent js base elm tipe) = do
157+ (as,cs,t) <- gen base
158+ return ( as
159+ , Set.insert (ctx (Var elm) (t :=: tipe)) cs
160+ , [ (elm, Forall [] [] tipe) ] )
161+
162+ffiHints (ims,exs) =
163+ map (\(_,_,n,t) -> n -: t) ims ++ map (\(_,n,t) -> n -: t) exs
164+
165+checkFFI dict ims exs = list $ ims' ++ exs'
166+ where ims' = map (\(_,b,n,_)-> Binop "==" (Var n) (App (Var "constant") b)) ims
167+ exs' = map (\(_,n,_) -> Binop "==" (Var n) (Var $ dict n)) exs