summaryrefslogtreecommitdiff
path: root/src/LambdaCube/Compiler/InferMonad.hs
diff options
context:
space:
mode:
authorPéter Diviánszky <divipp@gmail.com>2016-05-04 17:11:42 +0200
committerPéter Diviánszky <divipp@gmail.com>2016-05-04 17:11:42 +0200
commitb6133b895cd6d18909184f974b2d2c5157b20839 (patch)
treee3581ede03f169c38ff5dcdf9ef43fd003e68d34 /src/LambdaCube/Compiler/InferMonad.hs
parentd09859323b7213d6b3c3baf485d8389100faf469 (diff)
split Infer.hs
Diffstat (limited to 'src/LambdaCube/Compiler/InferMonad.hs')
-rw-r--r--src/LambdaCube/Compiler/InferMonad.hs223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/LambdaCube/Compiler/InferMonad.hs b/src/LambdaCube/Compiler/InferMonad.hs
new file mode 100644
index 00000000..6efaee3a
--- /dev/null
+++ b/src/LambdaCube/Compiler/InferMonad.hs
@@ -0,0 +1,223 @@
1{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE LambdaCase #-}
3{-# LANGUAGE ViewPatterns #-}
4{-# LANGUAGE PatternSynonyms #-}
5{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE FlexibleInstances #-}
7{-# LANGUAGE NoMonomorphismRestriction #-}
8{-# LANGUAGE ScopedTypeVariables #-}
9{-# LANGUAGE RecursiveDo #-}
10{-# LANGUAGE RankNTypes #-}
11{-# LANGUAGE MultiParamTypeClasses #-}
12{-# LANGUAGE GeneralizedNewtypeDeriving #-}
13{-# LANGUAGE DeriveFunctor #-}
14{-# OPTIONS_GHC -fno-warn-unused-binds #-} -- TODO: remove
15module LambdaCube.Compiler.InferMonad where
16
17import Data.Monoid
18import Data.List
19import qualified Data.Set as Set
20import qualified Data.Map as Map
21
22import Control.Monad.Except
23import Control.Monad.Reader
24import Control.Monad.Writer
25import Control.Arrow hiding ((<+>))
26import Control.DeepSeq
27
28import LambdaCube.Compiler.DeBruijn
29import LambdaCube.Compiler.Pretty hiding (braces, parens)
30import LambdaCube.Compiler.DesugaredSource hiding (getList)
31import LambdaCube.Compiler.Parser (ParseWarning) -- TODO: remove
32import LambdaCube.Compiler.Core
33
34-------------------------------------------------------------------------------- error messages
35
36data ErrorMsg
37 = ErrorMsg Doc
38 | ECantFind SName SI
39 | ETypeError Doc SI
40 | ERedefined SName SI SI
41
42instance NFData ErrorMsg where rnf = rnf . ppShow
43{-
44 rnf = \case
45 ErrorMsg m -> rnf m
46 ECantFind a b -> rnf (a, b)
47 ETypeError a b -> rnf (a, b)
48 ERedefined a b c -> rnf (a, b, c)
49-}
50errorRange_ = \case
51 ErrorMsg s -> []
52 ECantFind s si -> [si]
53 ETypeError msg si -> [si]
54 ERedefined s si si' -> [si, si']
55
56instance PShow ErrorMsg where
57 pShow = \case
58 ErrorMsg s -> s
59 ECantFind s si -> "can't find:" <+> text s <+> "in" <+> pShow si
60 ETypeError msg si -> "type error:" <+> msg <$$> "in" <+> pShow si
61 ERedefined s si si' -> "already defined" <+> text s <+> "at" <+> pShow si <$$> "and at" <+> pShow si'
62
63
64-------------------------------------------------------------------------------- infos
65
66data Info
67 = Info Range Doc
68 | IType SIName Exp
69 | ITrace String String
70 | IError ErrorMsg
71 | ParseWarning ParseWarning
72
73instance NFData Info where rnf = rnf . ppShow
74{-
75 where
76 rnf = \case
77 Info r s -> rnf (r, s)
78 IType a b -> rnf (a, b)
79 ITrace i s -> rnf (i, s)
80 IError x -> rnf x
81 ParseWarning w -> rnf w
82-}
83instance PShow Info where
84 pShow = \case
85 Info r s -> nest 4 $ shortForm (pShow r) <$$> s
86 IType a b -> shAnn (pShow a) (pShow b)
87 ITrace i s -> text i <> ": " <+> text s
88 IError e -> "!" <> pShow e
89 ParseWarning w -> pShow w
90
91errorRange is = [r | IError e <- is, RangeSI r <- errorRange_ e ]
92
93type Infos = [Info]
94
95throwError' e = tell [IError e] >> throwError e
96
97mkInfoItem (RangeSI r) i = [Info r i]
98mkInfoItem _ _ = mempty
99
100listAllInfos m = h "trace" (listTraceInfos m)
101 ++ h "tooltips" [ nest 4 $ shortForm $ pShow r <$$> hsep (intersperse "|" is) | (r, is) <- listTypeInfos m ]
102 ++ h "warnings" [ pShow w | ParseWarning w <- m ]
103 where
104 h x [] = []
105 h x xs = ("------------" <+> x) : xs
106
107listTraceInfos m = [DResetFreshNames $ pShow i | i <- m, case i of Info{} -> False; ParseWarning{} -> False; _ -> True]
108listTypeInfos m = Map.toList $ Map.unionsWith (<>) [Map.singleton r [DResetFreshNames i] | Info r i <- m]
109
110tellType si t = tell $ mkInfoItem (sourceInfo si) $ DTypeNamespace True $ mkDoc False t
111
112-------------------------------------------------------------------------------- global env
113
114type GlobalEnv = Map.Map SName (Exp, Type, SI)
115
116initEnv :: GlobalEnv
117initEnv = Map.fromList
118 [ (,) "'Type" (TType, TType, debugSI "source-of-Type")
119 ]
120
121-- inference monad
122type IM m = ExceptT ErrorMsg (ReaderT (Extensions, GlobalEnv) (WriterT Infos m))
123
124expAndType s (e, t, si) = (ET e t)
125
126-- todo: do only if NoTypeNamespace extension is not on
127lookupName s@(Ticked s') m = expAndType s <$> (Map.lookup s m `mplus` Map.lookup s' m)
128lookupName s m = expAndType s <$> Map.lookup s m
129
130getDef te si s = do
131 nv <- asks snd
132 maybe (throwError' $ ECantFind s si) return (lookupName s nv)
133
134addToEnv :: Monad m => SIName -> ExpType -> IM m GlobalEnv
135addToEnv sn@(SIName si s) (ET x t) = do
136-- maybe (pure ()) throwError_ $ ambiguityCheck s t -- TODO
137-- b <- asks $ (TraceTypeCheck `elem`) . fst
138 tell [IType sn t]
139 v <- asks $ Map.lookup s . snd
140 case v of
141 Nothing -> return $ Map.singleton s (closedExp x, closedExp t, si)
142 Just (_, _, si') -> throwError' $ ERedefined s si si'
143
144
145removeHiddenUnit (Pi Hidden (hnf -> Unit) (down 0 -> Just t)) = removeHiddenUnit t
146removeHiddenUnit (Pi h a b) = Pi h a $ removeHiddenUnit b
147removeHiddenUnit t = t
148
149addParams ps t = foldr (uncurry Pi) t ps
150
151addLams ps t = foldr (const Lam) t ps
152
153lamify t x = addLams (fst $ getParams t) $ x $ downTo 0 $ arity t
154
155arity :: Exp -> Int
156arity = length . fst . getParams
157
158downTo n m = map Var [n+m-1, n+m-2..n]
159
160withEnv e = local $ second (<> e)
161
162mkELet n x xt = {-(if null vs then id else trace_ $ "mkELet " ++ show (length vs) ++ " " ++ show n)-} term
163 where
164 vs = [Var i | i <- Set.toList $ free x <> free xt]
165 fn = FunName (mkFName n) (ExpDef x) xt
166
167 term = pmLabel fn vs [] $ getFix x 0
168
169 getFix (Lam z) i = Lam $ getFix z (i+1)
170 getFix (TFun FprimFix _ [t, Lam f]) i = subst 0 (foldl app_ term (downTo 0 i)) f
171 getFix x _ = x
172
173lamPi h t (ET x y) = ET (Lam x) (Pi h t y)
174
175-- Ambiguous: (Int ~ F a) => Int
176-- Not ambiguous: (Show a, a ~ F b) => b
177ambiguityCheck :: String -> Exp -> Maybe String
178ambiguityCheck s ty = case ambigVars ty of
179 [] -> Nothing
180 err -> Just $ s ++ " has ambiguous type:\n" ++ ppShow ty ++ "\nproblematic vars:\n" ++ ppShow err
181
182ambigVars :: Exp -> [(Int, Exp)]
183ambigVars ty = [(n, c) | (n, c) <- hid, not $ any (`Set.member` defined) $ Set.insert n $ free c]
184 where
185 (defined, hid, _i) = compDefined False ty
186
187floatLetMeta :: Exp -> Bool
188floatLetMeta ty = (i-1) `Set.member` defined
189 where
190 (defined, hid, i) = compDefined True ty
191
192compDefined b ty = (defined, hid, i)
193 where
194 defined = dependentVars hid $ Set.map (if b then (+i) else id) $ free ty
195
196 i = length hid_
197 hid = zipWith (\k t -> (k, up (k+1) t)) (reverse [0..i-1]) hid_
198 (hid_, ty') = hiddenVars ty
199
200hiddenVars (Pi Hidden a b) = first (a:) $ hiddenVars b
201hiddenVars t = ([], t)
202
203-- compute dependent type vars in constraints
204-- Example: dependentVars [(a, b) ~ F b c, d ~ F e] [c] == [a,b,c]
205dependentVars :: [(Int, Exp)] -> Set.Set Int -> Set.Set Int
206dependentVars ie = cycle mempty
207 where
208 freeVars = free
209
210 cycle acc s
211 | Set.null s = acc
212 | otherwise = cycle (acc <> s) (grow s Set.\\ acc)
213
214 grow = flip foldMap ie $ \case
215 (n, t) -> (Set.singleton n <-> freeVars t) <> case t of
216 (hnf -> CW (hnf -> CstrT _{-todo-} ty f)) -> freeVars ty <-> freeVars f
217 (hnf -> CSplit a b c) -> freeVars a <-> (freeVars b <> freeVars c)
218 _ -> mempty
219 where
220 a --> b = \s -> if Set.null $ a `Set.intersection` s then mempty else b
221 a <-> b = (a --> b) <> (b --> a)
222
223