2Module : Idris.Elab.Data
3Description : Code to elaborate data structures.
6Maintainer : The Idris Community.
8{-# LANGUAGE CPP, PatternGuards #-}
9module Idris.Elab.Data(elabData) where
13import Idris.Core.Evaluate
15import Idris.Core.Typecheck
16import Idris.Delaborate
17import Idris.Docstrings
18import Idris.Elab.Rewrite
20import Idris.Elab.Utils
21import Idris.Elab.Value
23import Idris.Output (iWarn, sendHighlighting)
27#if (MIN_VERSION_base(4,11,0))
28import Prelude hiding (id, (.), (<>))
30import Prelude hiding (id, (.))
33import Control.Category
35import Control.Monad.State.Strict as State
36import Data.Char (isLetter, toLower)
38import qualified Data.Map as Map
40import qualified Data.Set as S
41import qualified Data.Text as T
43warnLC :: FC -> Name -> Idris ()
45 = iWarn fc $ annName n <+> text "has a name which may be implicitly bound."
46 <> line <> text "This is likely to lead to problems!"
48elabData :: ElabInfo -> SyntaxInfo -> Docstring (Either Err PTerm)-> [(Name, Docstring (Either Err PTerm))] -> FC -> DataOpts -> PData -> Idris ()
49elabData info syn doc argDocs fc opts (PLaterdecl n nfc t_in)
50 = do logElab 1 (show (fc, doc))
52 when (implicitable (nsroot n)) $ warnLC fc n
53 (cty, _, t, inacc) <- buildType info syn fc [] n t_in
56 updateContext (addTyDecl n (TCon 0 0) cty) -- temporary, to check cons
57 sendHighlighting $ S.fromList [(FC' nfc, AnnName n Nothing Nothing Nothing)]
59elabData info syn doc argDocs fc opts (PDatadecl n nfc t_in dcons)
60 = do let codata = Codata `elem` opts
62 undef <- isUndefined fc n
63 when (implicitable (nsroot n)) $ warnLC fc n
64 (cty, ckind, t, inacc) <- buildType info syn fc [] n t_in
65 -- if n is defined already, make sure it is just a type declaration
66 -- with the same type we've just elaborated, and no constructors
69 checkDefinedAs fc n cty i
70 -- temporary, to check cons
71 when undef $ updateContext (addTyDecl n (TCon 0 0) cty)
72 let cnameinfo = cinfo info (map cname dcons)
73 unique <- case getRetTy (normalise (tt_ctxt i) [] cty) of
74 UType UniqueType -> return True
75 UType _ -> return False
76 TType _ -> return False
77 rt -> tclift $ tfail (At fc (Elaborating "type constructor " n Nothing (Msg "Not a valid type constructor")))
78 cons <- mapM (elabCon cnameinfo syn n codata (getRetTy cty) ckind) dcons
82 let params = findParams n (normalise ctxt [] cty) (map snd cons)
84 logElab 2 $ "Parameters : " ++ show params
85 addParamConstraints fc params cty cons
88 -- TI contains information about mutually declared types - this will
89 -- be updated when the mutual block is complete
90 putIState (i { idris_datatypes =
91 addDef n (TI (map fst cons) codata opts params [n]
92 (any linearArg (map snd cons)))
93 (idris_datatypes i) })
96 checkDocs fc argDocs t
97 doc' <- elabDocTerms info doc
98 argDocs' <- mapM (\(n, d) -> do d' <- elabDocTerms info d
99 return (n, d')) argDocs
100 addDocStr n doc' argDocs'
102 let metainf = DataMI params
103 addIBC (IBCMetaInformation n metainf)
104 -- TMP HACK! Make this a data option
105 updateContext (addDatatype (Data n ttag cty unique cons))
106 updateContext (setMetaInformation n metainf)
108 mapM_ totcheck (zip (repeat fc) (map fst cons))
109-- mapM_ (checkPositive n) cons
111 -- if there's exactly one constructor,
112 -- mark both the type and the constructor as detaggable
114 [(cn,ct)] -> setDetaggable cn >> setDetaggable n
115 >> addIBC (IBCOpt cn) >> addIBC (IBCOpt n)
118 -- create a rewriting lemma
119 when (n /= sUN "=") $
120 elabRewriteLemma info n cty
121 -- Emit highlighting info
122 sendHighlighting $ S.fromList $ [(FC' nfc, AnnName n Nothing Nothing Nothing)] ++
123 map (\(_, _, n, nfc, _, _, _) ->
124 (FC' nfc, AnnName n Nothing Nothing Nothing))
127 checkDefinedAs fc n t i
128 = let defined = tclift $ tfail (At fc (AlreadyDefined n))
130 case lookupDef n ctxt of
133 case converts ctxt [] t ty of
134 OK () -> case lookupCtxtExact n (idris_datatypes i) of
141 cname (_, _, n, _, _, _, _) = n
143 -- Abuse of ElabInfo.
144 -- TODO Contemplate whether the ElabInfo type needs modification.
145 cinfo :: ElabInfo -> [Name] -> ElabInfo
147 = let newps = params info
148 dsParams = map (\n -> (n, [])) ds
149 newb = addAlist dsParams (inblock info) in
150 info { params = newps,
152 liftname = id -- Is this appropriate?
155elabCon :: ElabInfo -> SyntaxInfo -> Name -> Bool ->
156 Type -> -- for unique kind checking
157 Type -> -- data type's kind
158 (Docstring (Either Err PTerm), [(Name, Docstring (Either Err PTerm))], Name, FC, PTerm, FC, [Name]) ->
160elabCon info syn tn codata expkind dkind (doc, argDocs, n, nfc, t_in, fc, forcenames)
161 = do checkUndefined fc n
162 when (implicitable (nsroot n)) $ warnLC fc n
163 logElab 2 $ show fc ++ ":Constructor " ++ show n ++ " : " ++ show t_in
164 (cty, ckind, t, inacc) <- buildType info syn fc [Constructor] n (if codata then mkLazy t_in else t_in)
166 let cty' = normalise ctxt [] cty
167 checkUniqueKind ckind expkind
169 -- Check that the constructor type is, in fact, a part of the family being defined
171 -- Need to calculate forceability from the non-normalised type,
172 -- because we might not be able to export the definitions which
173 -- we're normalising which changes the forceability status!
174 let force = if tn == sUN "Delayed"
175 then [] -- TMP HACK! Totality checker needs this info
176 else forceArgs ctxt tn cty
178 logElab 5 $ show fc ++ ":Constructor " ++ show n ++ " elaborated : " ++ show t
179 logElab 5 $ "Inaccessible args: " ++ show inacc
180 logElab 5 $ "Forceable args: " ++ show force
181 logElab 2 $ "---> " ++ show n ++ " : " ++ show cty
183 -- Add to the context (this is temporary, so that later constructors
184 -- can be indexed by it)
185 updateContext (addTyDecl n (DCon 0 0 False) cty)
188 checkDocs fc argDocs t
189 doc' <- elabDocTerms info doc
190 argDocs' <- mapM (\(n, d) -> do d' <- elabDocTerms info d
191 return (n, d')) argDocs
192 addDocStr n doc' argDocs'
194 fputState (opt_inaccessible . ist_optimisation n) inacc
195 fputState (opt_forceable . ist_optimisation n) force
199 tyIs con (Bind n b sc) = tyIs con (substV (P Bound n Erased) sc)
200 tyIs con t | (P Bound n' _, _) <- unApply t
202 tclift $ tfail (At fc (Elaborating "constructor " con Nothing
203 (Msg ("Type level variable " ++ show n' ++ " is not " ++ show tn))))
205 tyIs con t | (P _ n' _, _) <- unApply t
206 = if n' /= tn then tclift $ tfail (At fc (Elaborating "constructor " con Nothing (Msg (show n' ++ " is not " ++ show tn))))
208 tyIs con t = tclift $ tfail (At fc (Elaborating "constructor " con Nothing (Msg (show t ++ " is not " ++ show tn))))
210 mkLazy (PPi pl n nfc ty sc)
211 = let ty' = if getTyName ty
212 then PApp fc (PRef fc [] (sUN "Delayed"))
213 [pexp (PRef fc [] (sUN "Infinite")),
216 PPi pl n nfc ty' (mkLazy sc)
219 getTyName (PApp _ (PRef _ _ n) _) = n == nsroot tn
220 getTyName (PRef _ _ n) = n == nsroot tn
223 -- if the constructor is a UniqueType, the datatype must be too
224 -- (AnyType is fine, since that is checked for uniqueness too)
225 -- if hte contructor is AnyType, the datatype must be at least AnyType
226 checkUniqueKind (UType NullType) (UType NullType) = return ()
227 checkUniqueKind (UType NullType) _
228 = tclift $ tfail (At fc (UniqueKindError NullType n))
229 checkUniqueKind (UType UniqueType) (UType UniqueType) = return ()
230 checkUniqueKind (UType UniqueType) (UType AllTypes) = return ()
231 checkUniqueKind (UType UniqueType) _
232 = tclift $ tfail (At fc (UniqueKindError UniqueType n))
233 checkUniqueKind (UType AllTypes) (UType AllTypes) = return ()
234 checkUniqueKind (UType AllTypes) (UType UniqueType) = return ()
235 checkUniqueKind (UType AllTypes) _
236 = tclift $ tfail (At fc (UniqueKindError AllTypes n))
237 checkUniqueKind _ _ = return ()
239forceArgs :: Context -> Name -> Type -> [Int]
240forceArgs ctxt tn ty = forceFrom 0 ty
242 -- for each argument, substitute in MN pos "FF"
243 -- then when we look at the return type, if we see MN pos name
244 -- constructor guarded, then 'pos' is a forceable position
245 forceFrom :: Int -> Type -> [Int]
246 forceFrom i (Bind n (Pi _ _ _ _) sc)
247 = forceFrom (i + 1) (substV (P Ref (sMN i "FF") Erased) sc)
249 -- Go under the top level type application
250 -- We risk affecting erasure of more complex indices, so we'll only
251 -- mark something forced if *everything* which appears in an index
253 -- (FIXME: Actually the real risk is if we erase something a programmer
254 -- definitely wants, which is particularly the case with 'views'.
255 -- So perhaps we need a way of marking that in the source?)
256 | (P _ ty _, args) <- unApply sc,
257 ty == tn -- Must be the right top level type!
258 = if null (concatMap (findNonForcePos True) args)
259 then nub (concatMap findForcePos args)
263 findForcePos (P _ (MN i ff) _)
264 | ff == txt "FF" = [i]
265 -- Only look under constructors in applications
266 findForcePos ap@(App _ f a)
267 | (P _ con _, args) <- unApply ap,
269 = nub $ concatMap findForcePos args
272 findNonForcePos fok (P _ (MN i ff) _)
273 | ff == txt "FF" = if fok then [] else [i]
274 -- Look under non-constructors in applications for things which can't
276 findNonForcePos fok ap@(App _ f a)
277 | (P _ con _, args) <- unApply ap
278 = nub $ concatMap (findNonForcePos (fok && isConName con ctxt)) args
279 findNonForcePos _ _ = []
281addParamConstraints :: FC -> [Int] -> Type -> [(Name, Type)] -> Idris ()
282addParamConstraints fc ps cty cons
283 = case getRetTy cty of
284 TType cvar -> mapM_ (addConConstraint ps cvar)
285 (map getParamNames cons)
288 getParamNames (n, ty) = (ty, getPs ty)
290 getPs (Bind n (Pi _ _ _ _) sc)
291 = getPs (substV (P Ref n Erased) sc)
292 getPs t | (f, args) <- unApply t
295 paramArgs i (P _ n _ : args) | i `elem` ps = n : paramArgs (i + 1) args
296 paramArgs i (_ : args) = paramArgs (i + 1) args
299 addConConstraint ps cvar (ty, pnames) = constraintTy ty
301 constraintTy (Bind n (Pi _ _ ty _) sc)
302 = case getRetTy ty of
303 TType avar -> do tit <- typeInType
306 let tv = next_tvar ctxt
307 let con = if n `elem` pnames
310 addConstraints fc (tv, [con])
311 addIBC (IBCConstraint fc con)
313 constraintTy t = return ()
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