@@ -1,344 +0,0 @@
1−
2−module Types.Constrain (constrain) where
3−
4−import Control.Arrow (second)
5−import Control.Monad (liftM,mapM,zipWithM,foldM)
6−import Control.Monad.State (evalState)
7−import Data.Char (isDigit)
8−import Data.List (foldl',sort,group,isPrefixOf,intercalate,isSuffixOf)
9−import qualified Data.Map as Map
10−import qualified Data.Set as Set
11−
12−import SourceSyntax.Everything
13−import Unique
14−
15−import Types.Types
16−import qualified Types.Substitutions as Subs
17−
18−import System.IO.Unsafe
19−
20−beta = VarT `liftM` guid
21−unionA = Map.unionWith (++)
22−unionsA = Map.unionsWith (++)
23−
24−getAliases :: [(String,ImportMethod)] -> [(String,Scheme)] -> [(String,Scheme)]
25−getAliases imports hints = concatMap aliasesFrom imports
26− where
27− -- Get the names of values that are now in scope after a particular
28− -- import statement.
29− aliasesFrom :: (String,ImportMethod) -> [(String,Scheme)]
30− aliasesFrom (name,method) =
31− let values = concatMap (getValue name) hints
32− prefixed name = map (\(n,t) -> (name ++ "." ++ n, t)) values
33− in case method of
34− As alias -> prefixed alias
35− Hiding vs -> prefixed name ++ filter (\(n,t) -> n `notElem` vs) values
36− Importing vs -> prefixed name ++ filter (\(n,t) -> n `elem` vs) values
37−
38− -- Take a module name and a type annotation. Return the unprefxed
39− -- type annotation: getValue "List" ("List.map",t) == [("map",t)]
40− getValue :: String -> (String,Scheme) -> [(String,Scheme)]
41− getValue inModule (name,tipe) =
42− case inModule `isPrefixOf` name of
43− True -> [ (drop (length inModule + 1) name, tipe) ]
44− False -> []
45−
46−findAmbiguous hints assumptions continue =
47− let potentialDups = map head . filter (\g -> length g > 1) . group . sort $
48− filter (elem '.') hints
49− dups = filter (\k -> Map.member k assumptions) potentialDups
50− in case dups of
51− n:_ -> return . Left $ "Error: Ambiguous occurrence of '" ++ n ++
52− "' could refer to " ++
53− intercalate ", " (filter (isSuffixOf n) hints)
54− _ -> continue
55−
56−mergeSchemes :: [Map.Map String Scheme]
57− -> Unique (TVarMap, Constraints, Map.Map String Scheme)
58−mergeSchemes schmss = do (ass,css,sss) <- unzip3 `liftM` mapM split kvs
59− return (Map.unions ass, concat css, Map.unions sss)
60− where
61− kvs = Map.toList $ Map.unionsWith (++) (map (Map.map (:[])) schmss)
62− split (k,vs) =
63− let ps = zipWith (\s v -> (s++k,v)) (map (flip replicate '_') [0..]) vs
64− eq t u = L (Just $ msg ++ k) NoSpan (VarT t :=: VarT u)
65− msg = "the definition of "
66− in do xs <- mapM (\_ -> guid) vs
67− return ( Map.fromList $ zip (map fst ps) (map (:[]) xs)
68− , case xs of
69− t:ts -> zipWith eq xs ts
70− [] -> []
71− , Map.fromList ps )
72−
73−--constrain :: Map.Map String Scheme
74−-- -> Module
75−-- -> Unique (Either String Constraints)
76−constrain typeHints (Module _ _ imports stmts) = do
77− (ass,css,schemess) <- unzip3 `liftM` mapM stmtGen stmts
78− aliasHints <- getAliases imports `liftM` typeHints
79− (as', cs', schemes) <- mergeSchemes schemess
80− let constraints = concat (cs':css)
81− as = unionsA (as':ass)
82− allHints = Map.union schemes (Map.fromList aliasHints)
83− insert as n = do v <- guid; return $ Map.insertWith' (\_ x -> x) n [v] as
84− assumptions <- foldM insert as (Map.keys schemes)
85− findAmbiguous (map fst aliasHints) assumptions $ do
86− let f k s vs = map (\v -> L (Just k) NoSpan $ v :<<: s) vs
87− cs = concat . Map.elems $ Map.intersectionWithKey f allHints assumptions
88− escapees = Map.keys $ Map.difference assumptions allHints
89− msg = "Warning! Type-checker could not find variables:\n" ++ intercalate ", " escapees
90− return $ case escapees of
91− [] -> Right (schemess, constraints ++ cs)
92− _ -> unsafePerformIO (putStrLn msg) `seq` Right (schemess, constraints ++ cs)
93− --_ -> Left ("Undefined variable(s): " ++ intercalate ", " escapees)
94−
95−type TVarMap = Map.Map String [X]
96−type Constraints = [Located Constraint]
97−
98−loc e span = L (Just $ show e) span
99−
100−gen :: LExpr t v -> Unique (TVarMap, Constraints, Type)
101−gen (L _ span expr) =
102− let loc' = L (Just $ show expr) span in
103− case expr of
104− Var x ->
105− do b <- guid
106− return (Map.singleton x [b], [], VarT b)
107−
108− App e1 e2 ->
109− do (a1,c1,t1) <- gen e1
110− (a2,c2,t2) <- gen e2
111− b <- beta
112− return ( unionA a1 a2
113− , c1 ++ c2 ++ [loc' $ t1 :=: (LambdaT t2 b)]
114− , b )
115−
116− Lambda x e ->
117− do (a,c,t) <- gen e
118− b <- beta
119− v <- guid
120− return ( Map.delete x a
121− , (++) c . map (\x -> loc' $ VarT x :=: b) $
122− Map.findWithDefault [v] x a
123− , LambdaT b t )
124−
125− Let defs e ->
126− do (as,cs,t) <- gen e
127− (ass, schemes) <- liftM unzip (mapM defScheme defs)
128− let assumptions = unionsA (as:ass)
129− getName d = case d of FnDef f _ _ -> f
130− OpDef op _ _ _ -> op
131− TypeAnnotation n _ -> n
132− names = map getName defs
133− genCs name s = do
134− v <- guid
135− let vs = Map.findWithDefault [v] name assumptions
136− return $ map (\x -> loc name span $ x :<<: s) vs
137− cs' <- zipWithM genCs names schemes
138− return ( foldr Map.delete assumptions names
139− , concat cs' ++ cs
140− , t )
141−
142− Case e cases ->
143− do (as,cs,t) <- gen e
144− (ass,css,ts) <- liftM unzip3 $ mapM (caseGen t) cases
145− b <- beta
146− return ( unionsA $ as:ass
147− , let cases' = map snd cases
148− locs = zipWith merge cases' (tail cases')
149− cs' = zipWith (\t loc -> loc (b :=: t)) ts locs
150− in concat $ cs' : cs : css
151− , b)
152−
153− ExplicitList es ->
154− do (ass,css,ts) <- unzip3 `liftM` mapM gen es
155− t <- beta
156− let cs = zipWith (\t' (L a b _) -> L a b (t :=: t')) ts es
157− return ( unionsA ass, cs ++ concat css, listOf t )
158−
159− Data name es ->
160− gen $ foldl' (\f x -> merge f x $ App f x) (loc' $ Var name) es
161−
162− Binop op e1 e2 ->
163− gen $ loc' (App (loc' $ App (loc' $ Var op) e1) e2)
164−
165− Access e label ->
166− do (as,cs,rtype) <- gen e
167− t <- beta
168− rtype' <- beta
169− let fs = Map.singleton label [t]
170− c = (loc' (RecordT fs rtype' :=: rtype))
171− return (as, c:cs, t)
172−
173− Remove e x ->
174− do (as,cs,rtype) <- gen e
175− t <- beta
176− rtype' <- beta
177− let c = (loc' (RecordT (Map.singleton x [t]) rtype' :=: rtype))
178− return (as, c:cs, rtype')
179−
180− Insert e x v ->
181− do (eas,ecs,etype) <- gen e
182− (vas,vcs,vtype) <- gen v
183− return ( unionA eas vas
184− , ecs ++ vcs
185− , RecordT (Map.singleton x [vtype]) etype )
186−
187− Modify record fields ->
188− do (ras,rcs,rtype) <- gen record
189− (ass,css,newTs) <- unzip3 `liftM` mapM gen (map snd fields)
190− oldTs <- mapM (\_ -> beta) fields
191− rtype' <- beta
192− let rT ts = RecordT (recordT (zip (map fst fields) ts)) rtype'
193− c = [ loc' (rtype :=: rT oldTs) ]
194− return ( unionsA (ras:ass), concat (c : rcs : css), rT newTs )
195−
196− Record fields ->
197− let insert label tipe = Map.insertWith (++) label [tipe]
198− getScheme (f,args,e) = do
199− (as, _, (label, Forall _ cs tipe)) <- defGenHelp f args e
200− return (as, cs, insert label tipe)
201− in do (ass, css, fs) <- unzip3 `liftM` mapM getScheme fields
202− return ( unionsA ass
203− , concat css
204− , RecordT (foldr ($) Map.empty fs) EmptyRecord )
205−
206− Range e1@(L w1 s1 _) e2@(L w2 s2 _) ->
207− do (a1,c1,t1) <- gen e1
208− (a2,c2,t2) <- gen e2
209− return ( unionsA [a1,a2]
210− , c1 ++ c2 ++ [ L w1 s1 (t1 :=: int), L w1 s2 (t2 :=: int) ]
211− , listOf int )
212−
213− MultiIf ps -> do (ass,css,t:ts) <- unzip3 `liftM` mapM genPair ps
214− let cs = map (loc' . (t :=:)) ts
215− return (unionsA ass, concat (cs:css), t)
216− where genPair (b@(L t s _),e) = do
217− (a1,c1,t1) <- gen b
218− (a2,c2,t2) <- gen e
219− return ( unionsA [a1,a2]
220− , c1 ++ c2 ++ [ L t s (t1 :=: bool) ]
221− , t2 )
222−
223− Markdown _ -> primitive element
224− Literal lit -> literalGen loc' lit
225−
226−literalGen :: (Constraint -> Located Constraint)
227− -> Literal
228− -> Unique (TVarMap, Constraints, Type)
229−literalGen loc lit =
230− case lit of
231− IntNum _ -> do t <- beta
232− return (Map.empty, [loc $ t :<: number], t)
233− FloatNum _ -> primitive float
234− Boolean _ -> primitive bool
235− Chr _ -> primitive char
236− Str _ -> primitive string
237−
238−
239−primitive :: Type -> Unique (TVarMap, Constraints, Type)
240−primitive t = return (Map.empty, [], t)
241−
242−caseGen :: Type
243− -> (Pattern, LExpr t v)
244− -> Unique (TVarMap, Constraints, Type)
245−caseGen tipe (p, ce@(L _ span e)) = do
246− (as ,cs ,t) <- gen ce
247− (as',cs',_) <- patternGen (loc p span) tipe as p
248− return ( as', cs ++ cs', t )
249−
250−patternGen :: (Constraint -> Located Constraint)
251− -> Type -- Type of e in `case e of ...`
252− -> TVarMap
253− -> Pattern
254− -> Unique (TVarMap, Constraints, Type)
255−patternGen loc tipe as pattern =
256− case pattern of
257− PAnything -> do b <- beta ; return ( as, [], b )
258−
259− PLiteral lit -> literalGen loc lit
260−
261− PVar v -> do
262− b <- beta
263− let cs = map (loc . (b :=:) . VarT) (Map.findWithDefault [] v as)
264− return ( Map.delete v as, loc (b :=: tipe) : cs, b )
265−
266− PAlias v p -> do
267− b <- beta
268− let cs = map (loc . (b :=:) . VarT) (Map.findWithDefault [] v as)
269− (as', cs', tipe') <- patternGen loc b as p
270− return (Map.delete v as',
271− cs' ++ [ loc (b :=: tipe), loc (b :=: tipe') ] ++ cs,
272− b)
273−
274− PData name ps -> do
275− constr <- guid
276− output <- beta
277− let step (as,cs,tipe) p = do b <- beta
278− (as',cs',t) <- patternGen loc b as p
279− return (as', cs ++ cs', t ==> tipe)
280− (as',cs, t) <- foldM step (as,[],tipe) (reverse ps)
281− return ( Map.insert name [constr] as'
282− , loc (VarT constr :=: t) : cs
283− , output )
284− PRecord fs ->
285− do pairs <- mapM (\f -> do b <- beta; return (f,b)) fs
286− b <- beta
287− let t = RecordT (Map.fromList $ map (second (:[])) pairs) b
288− mkCs (name,tipe) = map (loc . (tipe :=:) . VarT)
289− (Map.findWithDefault [] name as)
290− return ( foldr Map.delete as fs
291− , loc (t :=: tipe) : concatMap mkCs pairs
292− , t )
293−
294−
295−defScheme :: Def t v -> Unique (Map.Map String [X], Scheme)
296−defScheme def = do (as,cs,hint) <- defGen def
297− return ( as, snd hint )
298−
299−defGen def = case def of
300− FnDef f args e -> defGenHelp f args e
301− OpDef op a1 a2 e -> defGenHelp op [a1,a2] e
302− TypeAnnotation name tipe -> do
303− schm <- Subs.generalize [] =<< Subs.superize name tipe
304− return (Map.empty, [], (name, schm))
305−
306−defGenHelp name args e = do
307− argDict <- mapM (\a -> liftM ((,) a) guid) args
308− (as,cs,t) <- gen e
309− let as' = foldr Map.delete as args
310− tipe = foldr (==>) t $ map (VarT . snd) argDict
311− genCs (arg,x) = do
312− v <- guid
313− let as' = Map.findWithDefault [v] arg as
314− return $ map (\y -> loc arg NoSpan $ VarT x :=: VarT y) as'
315− cs' <- concat `liftM` mapM genCs argDict
316− scheme <- Subs.generalize (concat $ Map.elems as') $
317− Forall (map snd argDict) (cs' ++ cs) tipe
318− return ( as', [], (name, scheme) )
319−
320−
321−stmtGen :: Declaration t v
322− -> Unique (TVarMap, Constraints, Map.Map String Scheme)
323−stmtGen stmt =
324− case stmt of
325− Definition def -> do (as,cs,hint) <- defGen def
326− return ( as, cs, uncurry Map.singleton hint )
327−
328− Datatype name xs tcs ->
329− let toScheme ts = Forall xs [] (foldr (==>) (ADT name $ map VarT xs) ts)
330− in return (Map.empty, [], Map.fromList (map (second toScheme) tcs))
331−
332− ExportEvent js elm tipe ->
333− do x <- guid
334− return ( Map.singleton elm [x]
335− , [ loc elm NoSpan $ VarT x :=: tipe ]
336− , Map.empty )
337−
338− ImportEvent js e@(L txt span base) elm tipe ->
339− do (as,cs,t) <- gen e
340− return ( as
341− , L txt span (signalOf t :=: tipe) : cs
342− , Map.singleton elm (Forall [] [] tipe) )
343−
344− TypeAlias _ _ _ -> return (Map.empty, [], Map.empty)