on 6e66041 help sign in
Idris-dev/src/Idris/AbsSyntax.hs
2615 lines 111 kB history raw
1{-|
2Module : Idris.AbsSyntax
3Description : Provides Idris' core data definitions and utility code.
4Copyright :
5License : BSD3
6Maintainer : The Idris Community.
7-}
9{-# LANGUAGE DeriveFunctor, FlexibleContexts, PatternGuards #-}
10-- FIXME: {-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
11{-# OPTIONS_GHC -fwarn-unused-imports #-}
13module Idris.AbsSyntax(
14 module Idris.AbsSyntax
15 , module Idris.AbsSyntaxTree
16 ) where
18import Idris.AbsSyntaxTree
19import Idris.Colours
20import Idris.Core.Evaluate
21import Idris.Core.TT
22import Idris.Docstrings
23import Idris.IdeMode hiding (Opt(..))
24import Idris.Options
25import IRTS.CodegenCommon
27import System.Directory (canonicalizePath, doesFileExist)
28import System.IO
30import Control.Applicative
31import Control.Monad.State
32import Prelude hiding (Applicative, Foldable, Traversable, (<$>))
34import Data.Either
35import Data.List hiding (insert, union)
36import qualified Data.Map as M
37import Data.Maybe
38import qualified Data.Set as S
39import qualified Data.Text as T
40import System.IO.Error (tryIOError)
42import Data.Generics.Uniplate.Data (descend, descendM)
44import Util.DynamicLinker
45import Util.Pretty
46import Util.System
48getContext :: Idris Context
49getContext = do i <- getIState; return (tt_ctxt i)
51forCodegen :: Codegen -> [(Codegen, a)] -> [a]
52forCodegen tgt xs = [x | (tgt', x) <- xs, eqLang tgt tgt']
53 where
54 eqLang (Via _ x) (Via _ y) = x == y
55 eqLang Bytecode Bytecode = True
56 eqLang _ _ = False
58getObjectFiles :: Codegen -> Idris [FilePath]
59getObjectFiles tgt = do i <- getIState; return (forCodegen tgt $ idris_objs i)
61addObjectFile :: Codegen -> FilePath -> Idris ()
62addObjectFile tgt f = do i <- getIState; putIState $ i { idris_objs = nub $ (tgt, f) : idris_objs i }
64getLibs :: Codegen -> Idris [String]
65getLibs tgt = do i <- getIState; return (forCodegen tgt $ idris_libs i)
67addLib :: Codegen -> String -> Idris ()
68addLib tgt f = do i <- getIState; putIState $ i { idris_libs = nub $ (tgt, f) : idris_libs i }
70getFlags :: Codegen -> Idris [String]
71getFlags tgt = do i <- getIState; return (forCodegen tgt $ idris_cgflags i)
73addFlag :: Codegen -> String -> Idris ()
74addFlag tgt f = do i <- getIState; putIState $ i { idris_cgflags = nub $ (tgt, f) : idris_cgflags i }
76addDyLib :: [String] -> Idris (Either DynamicLib String)
77addDyLib libs = do i <- getIState
78 let ls = idris_dynamic_libs i
79 let importdirs = opt_importdirs (idris_options i)
80 case mapMaybe (findDyLib ls) libs of
81 x:_ -> return (Left x)
82 [] -> do
83 handle <- lift . lift .
84 mapM (\l -> catchIO (tryLoadLib importdirs l)
85 (\_ -> return Nothing)) $ libs
86 case msum handle of
87 Nothing -> return (Right $ "Could not load dynamic alternatives \"" ++
88 intercalate "," libs ++ "\"")
89 Just x -> do putIState $ i { idris_dynamic_libs = x:ls }
90 return (Left x)
91 where findDyLib :: [DynamicLib] -> String -> Maybe DynamicLib
92 findDyLib [] _ = Nothing
93 findDyLib (lib:libs') l | l == lib_name lib = Just lib
94 | otherwise = findDyLib libs' l
96getAutoImports :: Idris [FilePath]
97getAutoImports = do i <- getIState
98 return (opt_autoImport (idris_options i))
100addAutoImport :: FilePath -> Idris ()
101addAutoImport fp = do i <- getIState
102 let opts = idris_options i
103 put (i { idris_options = opts { opt_autoImport =
104 fp : opt_autoImport opts } } )
106addDefinedName :: Name -> Idris ()
107addDefinedName n = do ist <- getIState
108 putIState $ ist { idris_inmodule = S.insert n (idris_inmodule ist) }
110getDefinedNames :: Idris [Name]
111getDefinedNames = do ist <- getIState
112 return (S.toList (idris_inmodule ist))
114addTT :: Term -> Idris (Maybe Term)
115addTT t = do ist <- getIState
116 case M.lookup t (idris_ttstats ist) of
117 Nothing -> do let tt' = M.insert t (1, t) (idris_ttstats ist)
118 putIState $ ist { idris_ttstats = tt' }
119 return Nothing
120 Just (i, t') -> do let tt' = M.insert t' (i + 1, t') (idris_ttstats ist)
121 putIState $ ist { idris_ttstats = tt' }
122 return (Just t')
124dumpTT :: Idris ()
125dumpTT = do ist <- get
126 let sts = sortBy count (M.toList (idris_ttstats ist))
127 mapM_ dump sts
128 return ()
129 where
130 count (_,x) (_,y) = compare y x
131 dump (tm, val) = runIO $ putStrLn (show val ++ ": " ++ show tm)
133addHdr :: Codegen -> String -> Idris ()
134addHdr tgt f = do i <- getIState; putIState $ i { idris_hdrs = nub $ (tgt, f) : idris_hdrs i }
136addImported :: Bool -> FilePath -> Idris ()
137addImported pub f
138 = do i <- getIState
139 putIState $ i { idris_imported = nub $ (f, pub) : idris_imported i }
141addLangExt :: LanguageExt -> Idris ()
142addLangExt e = do i <- getIState
143 putIState $ i {
144 idris_language_extensions = e : idris_language_extensions i
145 }
147-- | Transforms are organised by the function being applied on the lhs
148-- of the transform, to make looking up appropriate transforms quicker
149addTrans :: Name -> (Term, Term) -> Idris ()
150addTrans basefn t
151 = do i <- getIState
152 let t' = case lookupCtxtExact basefn (idris_transforms i) of
153 Just def -> (t : def)
154 Nothing -> [t]
155 putIState $ i { idris_transforms = addDef basefn t'
156 (idris_transforms i) }
158-- | Add transformation rules from a definition, which will reverse the
159-- definition for an error to make it more readable
160addErrRev :: (Term, Term) -> Idris ()
161addErrRev t = do i <- getIState
162 putIState $ i { idris_errRev = t : idris_errRev i }
164-- | Say that the name should always be reduced in error messages, to
165-- help readability/error reflection
166addErrReduce :: Name -> Idris ()
167addErrReduce t = do i <- getIState
168 putIState $ i { idris_errReduce = t : idris_errReduce i }
170addErasureUsage :: Name -> Int -> Idris ()
171addErasureUsage n i = do ist <- getIState
172 putIState $ ist { idris_erasureUsed = (n, i) : idris_erasureUsed ist }
174addExport :: Name -> Idris ()
175addExport n = do ist <- getIState
176 putIState $ ist { idris_exports = n : idris_exports ist }
178addUsedName :: FC -> Name -> Name -> Idris ()
179addUsedName fc n arg
180 = do ist <- getIState
181 case lookupTyName n (tt_ctxt ist) of
182 [(n', ty)] -> addUsage n' 0 ty
183 [] -> throwError (At fc (NoSuchVariable n))
184 xs -> throwError (At fc (CantResolveAlts (map fst xs)))
185 where addUsage n i (Bind x _ sc) | x == arg = do addIBC (IBCUsage (n, i))
186 addErasureUsage n i
187 | otherwise = addUsage n (i + 1) sc
188 addUsage _ _ _ = throwError (At fc (Msg ("No such argument name " ++ show arg)))
190getErasureUsage :: Idris [(Name, Int)]
191getErasureUsage = do ist <- getIState;
192 return (idris_erasureUsed ist)
194getExports :: Idris [Name]
195getExports = do ist <- getIState
196 return (idris_exports ist)
198totcheck :: (FC, Name) -> Idris ()
199totcheck n = do i <- getIState; putIState $ i { idris_totcheck = idris_totcheck i ++ [n] }
201defer_totcheck :: (FC, Name) -> Idris ()
202defer_totcheck n
203 = do i <- getIState;
204 putIState $ i { idris_defertotcheck = nub (idris_defertotcheck i ++ [n]) }
206clear_totcheck :: Idris ()
207clear_totcheck = do i <- getIState; putIState $ i { idris_totcheck = [] }
209setFlags :: Name -> [FnOpt] -> Idris ()
210setFlags n fs = do i <- getIState; putIState $ i { idris_flags = addDef n fs (idris_flags i) }
212addFnOpt :: Name -> FnOpt -> Idris ()
213addFnOpt n f = do i <- getIState
214 let fls = case lookupCtxtExact n (idris_flags i) of
215 Nothing -> []
216 Just x -> x
217 setFlags n (f : fls)
219setFnInfo :: Name -> FnInfo -> Idris ()
220setFnInfo n fs = do i <- getIState; putIState $ i { idris_fninfo = addDef n fs (idris_fninfo i) }
222setAccessibility :: Name -> Accessibility -> Idris ()
223setAccessibility n a
224 = do i <- getIState
225 let ctxt = setAccess n a (tt_ctxt i)
226 putIState $ i { tt_ctxt = ctxt }
228-- | get the accessibility of a name outside this module
229getFromHideList :: Name -> Idris (Maybe Accessibility)
230getFromHideList n = do i <- getIState
231 return $ lookupCtxtExact n (hide_list i)
233setTotality :: Name -> Totality -> Idris ()
234setTotality n a
235 = do i <- getIState
236 let ctxt = setTotal n a (tt_ctxt i)
237 putIState $ i { tt_ctxt = ctxt }
239setInjectivity :: Name -> Injectivity -> Idris ()
240setInjectivity n a
241 = do i <- getIState
242 let ctxt = setInjective n a (tt_ctxt i)
243 putIState $ i { tt_ctxt = ctxt }
245getTotality :: Name -> Idris Totality
246getTotality n
247 = do i <- getIState
248 case lookupTotal n (tt_ctxt i) of
249 [t] -> return t
250 _ -> return (Total [])
252-- Get coercions which might return the required type
253getCoercionsTo :: IState -> Type -> [Name]
254getCoercionsTo i ty =
255 let cs = idris_coercions i
256 (fn,_) = unApply (getRetTy ty) in
257 findCoercions fn cs
258 where findCoercions _ [] = []
259 findCoercions t (n : ns) =
260 let ps = case lookupTy n (tt_ctxt i) of
261 [ty'] -> case unApply (getRetTy (normalise (tt_ctxt i) [] ty')) of
262 (t', _) -> [n | t == t']
263 _ -> [] in
264 ps ++ findCoercions t ns
266addToCG :: Name -> CGInfo -> Idris ()
267addToCG n cg
268 = do i <- getIState
269 putIState $ i { idris_callgraph = addDef n cg (idris_callgraph i) }
271addCalls :: Name -> [Name] -> Idris ()
272addCalls n calls
273 = do i <- getIState
274 case lookupCtxtExact n (idris_callgraph i) of
275 Nothing -> addToCG n (CGInfo calls Nothing [] [])
276 Just (CGInfo cs ans scg used) ->
277 addToCG n (CGInfo (nub (calls ++ cs)) ans scg used)
279addTyInferred :: Name -> Idris ()
280addTyInferred n
281 = do i <- getIState
282 putIState $ i { idris_tyinfodata =
283 addDef n TIPartial (idris_tyinfodata i) }
285addTyInfConstraints :: FC -> [(Term, Term)] -> Idris ()
286addTyInfConstraints fc ts = do logLvl 2 $ "TI missing: " ++ show ts
287 mapM_ addConstraint ts
288 return ()
289 where addConstraint (x, y) = findMVApps x y
291 findMVApps x y
292 = do let (fx, argsx) = unApply x
293 let (fy, argsy) = unApply y
294 if (fx /= fy)
295 then do
296 tryAddMV fx y
297 tryAddMV fy x
298 else mapM_ addConstraint (zip argsx argsy)
300 tryAddMV (P _ mv _) y =
301 do ist <- get
302 case lookup mv (idris_metavars ist) of
303 Just _ -> addConstraintRule mv y
304 _ -> return ()
305 tryAddMV _ _ = return ()
307 addConstraintRule :: Name -> Term -> Idris ()
308 addConstraintRule n t
309 = do ist <- get
310 logLvl 1 $ "TI constraint: " ++ show (n, t)
311 case lookupCtxt n (idris_tyinfodata ist) of
312 [TISolution ts] ->
313 do mapM_ (checkConsistent t) ts
314 let ti' = addDef n (TISolution (t : ts))
315 (idris_tyinfodata ist)
316 put $ ist { idris_tyinfodata = ti' }
317 _ ->
318 do let ti' = addDef n (TISolution [t])
319 (idris_tyinfodata ist)
320 put $ ist { idris_tyinfodata = ti' }
322 -- Check a solution is consistent with previous solutions
323 -- Meaning: If heads are both data types, they had better be the
324 -- same.
325 checkConsistent :: Term -> Term -> Idris ()
326 checkConsistent x y =
327 do let (fx, _) = unApply x
328 let (fy, _) = unApply y
329 case (fx, fy) of
330 (P (TCon _ _) n _, P (TCon _ _) n' _) -> errWhen (n/=n')
331 (P (TCon _ _) n _, Constant _) -> errWhen True
332 (Constant _, P (TCon _ _) n' _) -> errWhen True
333 (P (DCon _ _ _) n _, P (DCon _ _ _) n' _) -> errWhen (n/=n')
334 _ -> return ()
336 where errWhen True
337 = throwError (At fc
338 (CantUnify False (x, Nothing) (y, Nothing) (Msg "") [] 0))
339 errWhen False = return ()
341isTyInferred :: Name -> Idris Bool
342isTyInferred n
343 = do i <- getIState
344 case lookupCtxt n (idris_tyinfodata i) of
345 [TIPartial] -> return True
346 _ -> return False
348-- | Adds error handlers for a particular function and argument. If
349-- names are ambiguous, all matching handlers are updated.
350addFunctionErrorHandlers :: Name -> Name -> [Name] -> Idris ()
351addFunctionErrorHandlers f arg hs =
352 do i <- getIState
353 let oldHandlers = idris_function_errorhandlers i
354 let newHandlers = flip (addDef f) oldHandlers $
355 case lookupCtxtExact f oldHandlers of
356 Nothing -> M.singleton arg (S.fromList hs)
357 Just (oldHandlers) -> M.insertWith S.union arg (S.fromList hs) oldHandlers
358 -- will always be one of those two, thus no extra case
359 putIState $ i { idris_function_errorhandlers = newHandlers }
361-- | Trace all the names in a call graph starting at the given name
362getAllNames :: Name -> Idris [Name]
363getAllNames n = do i <- getIState
364 case getCGAllNames i n of
365 Just ns -> return ns
366 Nothing -> do ns <- allNames [] n
367 addCGAllNames i n ns
368 return ns
370getCGAllNames :: IState -> Name -> Maybe [Name]
371getCGAllNames i n = case lookupCtxtExact n (idris_callgraph i) of
372 Just ci -> allCalls ci
373 _ -> Nothing
375addCGAllNames :: IState -> Name -> [Name] -> Idris ()
376addCGAllNames i n ns
377 = case lookupCtxtExact n (idris_callgraph i) of
378 Just ci -> addToCG n (ci { allCalls = Just ns })
379 _ -> addToCG n (CGInfo [] (Just ns) [] [])
381allNames :: [Name] -> Name -> Idris [Name]
382allNames ns n | n `elem` ns = return []
383allNames ns n = do i <- getIState
384 case getCGAllNames i n of
385 Just ns -> return ns
386 Nothing -> case lookupCtxtExact n (idris_callgraph i) of
387 Just ci ->
388 do more <- mapM (allNames (n:ns)) (calls ci)
389 let ns' = nub (n : concat more)
390 addCGAllNames i n ns'
391 return ns'
392 _ -> return [n]
394addCoercion :: Name -> Idris ()
395addCoercion n = do i <- getIState
396 putIState $ i { idris_coercions = nub $ n : idris_coercions i }
398addDocStr :: Name -> Docstring DocTerm -> [(Name, Docstring DocTerm)] -> Idris ()
399addDocStr n doc args
400 = do i <- getIState
401 putIState $ i { idris_docstrings = addDef n (doc, args) (idris_docstrings i) }
403addNameHint :: Name -> Name -> Idris ()
404addNameHint ty n
405 = do i <- getIState
406 ty' <- case lookupCtxtName ty (idris_implicits i) of
407 [(tyn, _)] -> return tyn
408 [] -> throwError (NoSuchVariable ty)
409 tyns -> throwError (CantResolveAlts (map fst tyns))
410 let ns' = case lookupCtxt ty' (idris_namehints i) of
411 [ns] -> ns ++ [n]
412 _ -> [n]
413 putIState $ i { idris_namehints = addDef ty' ns' (idris_namehints i) }
415getNameHints :: IState -> Name -> [Name]
416getNameHints _ (UN arr) | arr == txt "->" = [sUN "f",sUN "g"]
417getNameHints i n =
418 case lookupCtxt n (idris_namehints i) of
419 [ns] -> ns
420 _ -> []
422addDeprecated :: Name -> String -> Idris ()
423addDeprecated n reason = do
424 i <- getIState
425 putIState $ i { idris_deprecated = addDef n reason (idris_deprecated i) }
427getDeprecated :: Name -> Idris (Maybe String)
428getDeprecated n = do
429 i <- getIState
430 return $ lookupCtxtExact n (idris_deprecated i)
432addFragile :: Name -> String -> Idris ()
433addFragile n reason = do
434 i <- getIState
435 putIState $ i { idris_fragile = addDef n reason (idris_fragile i) }
437getFragile :: Name -> Idris (Maybe String)
438getFragile n = do
439 i <- getIState
440 return $ lookupCtxtExact n (idris_fragile i)
442push_estack :: Name -> Bool -> Idris ()
443push_estack n implementation
444 = do i <- getIState
445 putIState (i { elab_stack = (n, implementation) : elab_stack i })
447pop_estack :: Idris ()
448pop_estack = do i <- getIState
449 putIState (i { elab_stack = ptail (elab_stack i) })
450 where ptail [] = []
451 ptail (_ : xs) = xs
453-- | Add an interface implementation function.
454--
455-- Precondition: the implementation should have the correct type.
456--
457-- Dodgy hack 1: Put integer implementations first in the list so they are
458-- resolved by default.
459--
460-- Dodgy hack 2: put constraint chasers (ParentN) last
461addImplementation :: Bool -- ^ whether the name is an Integer implementation
462 -> Bool -- ^ whether to include the implementation in implementation search
463 -> Name -- ^ the name of the interface
464 -> Name -- ^ the name of the implementation
465 -> Idris ()
466addImplementation int res n i
467 = do ist <- getIState
468 case lookupCtxt n (idris_interfaces ist) of
469 [CI a b c d e f g ins fds] ->
470 do let cs = addDef n (CI a b c d e f g (addI i ins) fds) (idris_interfaces ist)
471 putIState $ ist { idris_interfaces = cs }
472 _ -> do let cs = addDef n (CI (sMN 0 "none") [] [] [] [] [] [] [(i, res)] []) (idris_interfaces ist)
473 putIState $ ist { idris_interfaces = cs }
474 where addI, insI :: Name -> [(Name, Bool)] -> [(Name, Bool)]
475 addI i ins | int = (i, res) : ins
476 | chaser n = ins ++ [(i, res)]
477 | otherwise = insI i ins
478 insI i [] = [(i, res)]
479 insI i (n : ns) | chaser (fst n) = (i, res) : n : ns
480 | otherwise = n : insI i ns
482 chaser (SN (ParentN _ _)) = True
483 chaser (NS n _) = chaser n
484 chaser _ = False
486-- | Add a privileged implementation - one which implementation search will
487-- happily resolve immediately if it is type correct This is used for
488-- naming parent implementations when defining an implementation with
489-- constraints. Returns the old list, so we can revert easily at the
490-- end of a block
491addOpenImpl :: [Name] -> Idris [Name]
492addOpenImpl ns = do ist <- getIState
493 ns' <- mapM (checkValid ist) ns
494 let open = idris_openimpls ist
495 putIState $ ist { idris_openimpls = nub (ns' ++ open) }
496 return open
497 where
498 checkValid ist n
499 = case lookupCtxtName n (idris_implicits ist) of
500 [(n', _)] -> return n'
501 [] -> throwError (NoSuchVariable n)
502 more -> throwError (CantResolveAlts (map fst more))
504setOpenImpl :: [Name] -> Idris ()
505setOpenImpl ns = do ist <- getIState
506 putIState $ ist { idris_openimpls = ns }
508getOpenImpl :: Idris [Name]
509getOpenImpl = do ist <- getIState
510 return (idris_openimpls ist)
512addInterface :: Name -> InterfaceInfo -> Idris ()
513addInterface n i
514 = do ist <- getIState
515 let i' = case lookupCtxt n (idris_interfaces ist) of
516 [c] -> i { interface_implementations = interface_implementations c ++
517 interface_implementations i }
518 _ -> i
519 putIState $ ist { idris_interfaces = addDef n i' (idris_interfaces ist) }
521updateIMethods :: Name -> [(Name, PTerm)] -> Idris ()
522updateIMethods n meths
523 = do ist <- getIState
524 let i = case lookupCtxtExact n (idris_interfaces ist) of
525 Just c -> c { interface_methods = update (interface_methods c) }
526 Nothing -> error "Can't happen updateIMethods"
527 putIState $ ist { idris_interfaces = addDef n i (idris_interfaces ist) }
528 where
529 update [] = []
530 update (m@(n, (b, opts, t)) : rest)
531 | Just ty <- lookup n meths
532 = (n, (b, opts, ty)) : update rest
533 | otherwise = m : update rest
535addRecord :: Name -> RecordInfo -> Idris ()
536addRecord n ri = do ist <- getIState
537 putIState $ ist { idris_records = addDef n ri (idris_records ist) }
539addAutoHint :: Name -> Name -> Idris ()
540addAutoHint n hint =
541 do ist <- getIState
542 case lookupCtxtExact n (idris_autohints ist) of
543 Nothing ->
544 do let hs = addDef n [hint] (idris_autohints ist)
545 putIState $ ist { idris_autohints = hs }
546 Just nhints ->
547 do let hs = addDef n (hint : nhints) (idris_autohints ist)
548 putIState $ ist { idris_autohints = hs }
550getAutoHints :: Name -> Idris [Name]
551getAutoHints n = do ist <- getIState
552 case lookupCtxtExact n (idris_autohints ist) of
553 Nothing -> return []
554 Just ns -> return ns
556addIBC :: IBCWrite -> Idris ()
557addIBC ibc@(IBCDef n)
558 = do i <- getIState
559 when (notDef (ibc_write i)) $
560 putIState $ i { ibc_write = ibc : ibc_write i }
561 where notDef [] = True
562 notDef (IBCDef n': _) | n == n' = False
563 notDef (_ : is) = notDef is
564addIBC ibc = do i <- getIState; putIState $ i { ibc_write = ibc : ibc_write i }
566clearIBC :: Idris ()
567clearIBC = do i <- getIState; putIState $ i { ibc_write = [],
568 idris_inmodule = S.empty }
570resetNameIdx :: Idris ()
571resetNameIdx = do i <- getIState
572 put (i { idris_nameIdx = (0, emptyContext) })
574-- | Used to preserve sharing of names
575addNameIdx :: Name -> Idris (Int, Name)
576addNameIdx n = do i <- getIState
577 let (i', x) = addNameIdx' i n
578 putIState i'
579 return x
581addNameIdx' :: IState -> Name -> (IState, (Int, Name))
582addNameIdx' i n
583 = let idxs = snd (idris_nameIdx i) in
584 case lookupCtxt n idxs of
585 [x] -> (i, x)
586 _ -> let i' = fst (idris_nameIdx i) + 1 in
587 (i { idris_nameIdx = (i', addDef n (i', n) idxs) }, (i', n))
589getSymbol :: Name -> Idris Name
590getSymbol n = do i <- getIState
591 case M.lookup n (idris_symbols i) of
592 Just n' -> return n'
593 Nothing -> do let sym' = M.insert n n (idris_symbols i)
594 put (i { idris_symbols = sym' })
595 return n
597getHdrs :: Codegen -> Idris [String]
598getHdrs tgt = do i <- getIState; return (forCodegen tgt $ idris_hdrs i)
600getImported :: Idris [(FilePath, Bool)]
601getImported = idris_imported `fmap` getIState
603setErrSpan :: FC -> Idris ()
604setErrSpan x = do i <- getIState;
605 case (errSpan i) of
606 Nothing -> putIState $ i { errSpan = Just x }
607 Just _ -> return ()
609clearErr :: Idris ()
610clearErr = do i <- getIState
611 putIState $ i { errSpan = Nothing }
613getSO :: Idris (Maybe String)
614getSO = do i <- getIState
615 return (compiled_so i)
617setSO :: Maybe String -> Idris ()
618setSO s = do i <- getIState
619 putIState (i { compiled_so = s })
621getIState :: Idris IState
622getIState = get
624putIState :: IState -> Idris ()
625putIState = put
627updateIState :: (IState -> IState) -> Idris ()
628updateIState f = do i <- getIState
629 putIState $ f i
631withContext :: (IState -> Ctxt a) -> Name -> b -> (a -> Idris b) -> Idris b
632withContext ctx name dflt action = do
633 ist <- getIState
634 case lookupCtxt name (ctx ist) of
635 [x] -> action x
636 _ -> return dflt
638withContext_ :: (IState -> Ctxt a) -> Name -> (a -> Idris ()) -> Idris ()
639withContext_ ctx name action = withContext ctx name () action
641-- | A version of liftIO that puts errors into the exception type of
642-- the Idris monad
643runIO :: IO a -> Idris a
644runIO x = liftIO (tryIOError x) >>= either (throwError . Msg . show) return
645-- TODO: create specific Idris exceptions for specific IO errors such as "openFile: does not exist"
646--
647-- Issue #1738 on the issue tracker.
648-- https://github.com/idris-lang/Idris-dev/issues/1738
650getName :: Idris Int
651getName = do i <- getIState;
652 let idx = idris_name i;
653 putIState (i { idris_name = idx + 1 })
654 return idx
656-- | InternalApp keeps track of the real function application for
657-- making case splits from, not the application the programmer wrote,
658-- which doesn't have the whole context in any case other than top
659-- level definitions
660addInternalApp :: FilePath -> Int -> PTerm -> Idris ()
661addInternalApp fp l t
662 = do i <- getIState
663 -- We canonicalise the path to make "./Test/Module.idr" equal
664 -- to "Test/Module.idr"
665 exists <- runIO $ doesFileExist fp
666 when exists $
667 do fp' <- runIO $ canonicalizePath fp
668 putIState (i { idris_lineapps = ((fp', l), t) : idris_lineapps i })
670getInternalApp :: FilePath -> Int -> Idris PTerm
671getInternalApp fp l = do i <- getIState
672 -- We canonicalise the path to make
673 -- "./Test/Module.idr" equal to
674 -- "Test/Module.idr"
675 exists <- runIO $ doesFileExist fp
676 if exists
677 then do fp' <- runIO $ canonicalizePath fp
678 case lookup (fp', l) (idris_lineapps i) of
679 Just n' -> return n'
680 Nothing -> return Placeholder
681 -- TODO: What if it's not there?
682 else return Placeholder
684-- | Pattern definitions are only used for coverage checking, so erase
685-- them when we're done
686clearOrigPats :: Idris ()
687clearOrigPats = do i <- get
688 let ps = idris_patdefs i
689 let ps' = mapCtxt (\ (_,miss) -> ([], miss)) ps
690 put (i { idris_patdefs = ps' })
692-- | Erase types from Ps in the context (basically ending up with
693-- what's in the .ibc, which is all we need after all the analysis is
694-- done)
695clearPTypes :: Idris ()
696clearPTypes = do i <- get
697 let ctxt = tt_ctxt i
698 put (i { tt_ctxt = mapDefCtxt pErase ctxt })
699 where pErase (CaseOp c t tys orig _ cds)
700 = CaseOp c t tys orig [] (pErase' cds)
701 pErase x = x
702 pErase' (CaseDefs (cs, c) rs)
703 = let c' = (cs, fmap pEraseType c) in
704 CaseDefs c' rs
706checkUndefined :: FC -> Name -> Idris ()
707checkUndefined fc n
708 = do i <- getContext
709 case lookupTy n i of
710 (_:_) -> throwError . Msg $ show fc ++ ":" ++
711 show n ++ " already defined"
712 _ -> return ()
714isUndefined :: FC -> Name -> Idris Bool
715isUndefined _ n
716 = do i <- getContext
717 case lookupTyExact n i of
718 Just _ -> return False
719 _ -> return True
721setContext :: Context -> Idris ()
722setContext ctxt = do i <- getIState; putIState (i { tt_ctxt = ctxt } )
724updateContext :: (Context -> Context) -> Idris ()
725updateContext f = do i <- getIState; putIState (i { tt_ctxt = f (tt_ctxt i) } )
727addConstraints :: FC -> (Int, [UConstraint]) -> Idris ()
728addConstraints fc (v, cs)
729 = do tit <- typeInType
730 when (not tit) $ do
731 i <- getIState
732 let ctxt = tt_ctxt i
733 let ctxt' = ctxt { next_tvar = v }
734 let ics = insertAll (zip cs (repeat fc)) (idris_constraints i)
735 putIState $ i { tt_ctxt = ctxt', idris_constraints = ics }
736 where
737 insertAll [] c = c
738 insertAll ((ULE (UVal 0) _, fc) : cs) ics = insertAll cs ics
739 insertAll ((ULE x y, fc) : cs) ics | x == y = insertAll cs ics
740 insertAll ((c, fc) : cs) ics
741 = insertAll cs $ S.insert (ConstraintFC c fc) ics
743addDeferred = addDeferred' Ref
744addDeferredTyCon = addDeferred' (TCon 0 0)
746-- | Save information about a name that is not yet defined
747addDeferred' :: NameType
748 -> [(Name, (Int, Maybe Name, Type, [Name], Bool, Bool))]
749 -- ^ The Name is the name being made into a metavar,
750 -- the Int is the number of vars that are part of a
751 -- putative proof context, the Maybe Name is the
752 -- top-level function containing the new metavariable,
753 -- the Type is its type, and the Bool is whether :p is
754 -- allowed
755 -> Idris ()
756addDeferred' nt ns
757 = do mapM_ (\(n, (i, _, t, _, _, _)) -> updateContext (addTyDecl n nt (tidyNames S.empty t))) ns
758 mapM_ (\(n, _) -> when (not (n `elem` primDefs)) $ addIBC (IBCMetavar n)) ns
759 i <- getIState
760 putIState $ i { idris_metavars = map (\(n, (i, top, _, ns, isTopLevel, isDefinable)) ->
761 (n, (top, i, ns, isTopLevel, isDefinable))) ns ++
762 idris_metavars i }
763 where
764 -- 'tidyNames' is to generate user accessible names in case they are
765 -- needed in tactic scripts
766 tidyNames used (Bind (MN i x) b sc)
767 = let n' = uniqueNameSet (UN x) used in
768 Bind n' b $ tidyNames (S.insert n' used) sc
769 tidyNames used (Bind n b sc)
770 = let n' = uniqueNameSet n used in
771 Bind n' b $ tidyNames (S.insert n' used) sc
772 tidyNames _ b = b
774solveDeferred :: FC -> Name -> Idris ()
775solveDeferred fc n
776 = do i <- getIState
777 case lookup n (idris_metavars i) of
778 Just (_, _, _, _, False) ->
779 throwError $ At fc $ Msg ("Can't define hole " ++ show n ++ " as it depends on other holes")
780 _ -> putIState $ i { idris_metavars =
781 filter (\(n', _) -> n/=n')
782 (idris_metavars i),
783 ibc_write =
784 filter (notMV n) (ibc_write i)
785 }
786 where notMV n (IBCMetavar n') = not (n == n')
787 notMV n _ = True
789getUndefined :: Idris [Name]
790getUndefined = do i <- getIState
791 return (map fst (idris_metavars i) \\ primDefs)
793isMetavarName :: Name -> IState -> Bool
794isMetavarName n ist
795 = case lookupNames n (tt_ctxt ist) of
796 (t:_) -> isJust $ lookup t (idris_metavars ist)
797 _ -> False
799getWidth :: Idris ConsoleWidth
800getWidth = fmap idris_consolewidth getIState
802setWidth :: ConsoleWidth -> Idris ()
803setWidth w = do ist <- getIState
804 put ist { idris_consolewidth = w }
806setDepth :: Maybe Int -> Idris ()
807setDepth d = do ist <- getIState
808 put ist { idris_options = (idris_options ist) { opt_printdepth = d } }
810typeDescription :: String
811typeDescription = "The type of types"
814type1Doc :: Doc OutputAnnotation
815type1Doc = (annotate (AnnType "Type" "The type of types, one level up") $ text "Type 1")
818isetPrompt :: String -> Idris ()
819isetPrompt p = do i <- getIState
820 case idris_outputmode i of
821 IdeMode n h -> runIO . hPutStrLn h $ convSExp "set-prompt" p n
823-- | Tell clients how much was parsed and loaded
824isetLoadedRegion :: Idris ()
825isetLoadedRegion = do i <- getIState
826 let span = idris_parsedSpan i
827 case span of
828 Just fc ->
829 case idris_outputmode i of
830 IdeMode n h ->
831 runIO . hPutStrLn h $
832 convSExp "set-loaded-region" fc n
833 Nothing -> return ()
835setLogLevel :: Int -> Idris ()
836setLogLevel l = do i <- getIState
837 let opts = idris_options i
838 let opt' = opts { opt_logLevel = l }
839 putIState $ i { idris_options = opt' }
841setLogCats :: [LogCat] -> Idris ()
842setLogCats cs = do
843 i <- getIState
844 let opts = idris_options i
845 let opt' = opts { opt_logcats = cs }
846 putIState $ i { idris_options = opt' }
848setCmdLine :: [Opt] -> Idris ()
849setCmdLine opts = do i <- getIState
850 let iopts = idris_options i
851 putIState $ i { idris_options = iopts { opt_cmdline = opts } }
853getCmdLine :: Idris [Opt]
854getCmdLine = do i <- getIState
855 return (opt_cmdline (idris_options i))
857getDumpHighlighting :: Idris Bool
858getDumpHighlighting = do ist <- getIState
859 return (findC (opt_cmdline (idris_options ist)))
860 where findC = elem DumpHighlights
862getDumpDefun :: Idris (Maybe FilePath)
863getDumpDefun = do i <- getIState
864 return $ findC (opt_cmdline (idris_options i))
865 where findC [] = Nothing
866 findC (DumpDefun x : _) = Just x
867 findC (_ : xs) = findC xs
869getDumpCases :: Idris (Maybe FilePath)
870getDumpCases = do i <- getIState
871 return $ findC (opt_cmdline (idris_options i))
872 where findC [] = Nothing
873 findC (DumpCases x : _) = Just x
874 findC (_ : xs) = findC xs
876logLevel :: Idris Int
877logLevel = do i <- getIState
878 return (opt_logLevel (idris_options i))
880setAutoImpls :: Bool -> Idris ()
881setAutoImpls b = do i <- getIState
882 let opts = idris_options i
883 let opt' = opts { opt_autoimpls = b }
884 putIState $ i { idris_options = opt' }
886getAutoImpls :: Idris Bool
887getAutoImpls = do i <- getIState
888 return (opt_autoimpls (idris_options i))
890setErrContext :: Bool -> Idris ()
891setErrContext t = do i <- getIState
892 let opts = idris_options i
893 let opts' = opts { opt_errContext = t }
894 putIState $ i { idris_options = opts' }
896errContext :: Idris Bool
897errContext = do i <- getIState
898 return (opt_errContext (idris_options i))
900getOptimise :: Idris [Optimisation]
901getOptimise = do i <- getIState
902 return (opt_optimise (idris_options i))
904setOptimise :: [Optimisation] -> Idris ()
905setOptimise newopts = do i <- getIState
906 let opts = idris_options i
907 let opts' = opts { opt_optimise = newopts }
908 putIState $ i { idris_options = opts' }
910addOptimise :: Optimisation -> Idris ()
911addOptimise opt = do opts <- getOptimise
912 setOptimise (nub (opt : opts))
914removeOptimise :: Optimisation -> Idris ()
915removeOptimise opt = do opts <- getOptimise
916 setOptimise ((nub opts) \\ [opt])
918-- | Set appropriate optimisation set for the given level. We only
919-- have one optimisation that is configurable at the moment, however!
920setOptLevel :: Int -> Idris ()
921setOptLevel n | n <= 0 = setOptimise []
922setOptLevel 1 = setOptimise []
923setOptLevel 2 = setOptimise [PETransform]
924setOptLevel n | n >= 3 = setOptimise [PETransform]
926useREPL :: Idris Bool
927useREPL = do i <- getIState
928 return (opt_repl (idris_options i))
930setREPL :: Bool -> Idris ()
931setREPL t = do i <- getIState
932 let opts = idris_options i
933 let opt' = opts { opt_repl = t }
934 putIState $ i { idris_options = opt' }
936showOrigErr :: Idris Bool
937showOrigErr = do i <- getIState
938 return (opt_origerr (idris_options i))
940setShowOrigErr :: Bool -> Idris ()
941setShowOrigErr b = do i <- getIState
942 let opts = idris_options i
943 let opt' = opts { opt_origerr = b }
944 putIState $ i { idris_options = opt' }
946setAutoSolve :: Bool -> Idris ()
947setAutoSolve b = do i <- getIState
948 let opts = idris_options i
949 let opt' = opts { opt_autoSolve = b }
950 putIState $ i { idris_options = opt' }
952setNoBanner :: Bool -> Idris ()
953setNoBanner n = do i <- getIState
954 let opts = idris_options i
955 let opt' = opts { opt_nobanner = n }
956 putIState $ i { idris_options = opt' }
958getNoBanner :: Idris Bool
959getNoBanner = do i <- getIState
960 let opts = idris_options i
961 return (opt_nobanner opts)
963setEvalTypes :: Bool -> Idris ()
964setEvalTypes n = do i <- getIState
965 let opts = idris_options i
966 let opt' = opts { opt_evaltypes = n }
967 putIState $ i { idris_options = opt' }
969getDesugarNats :: Idris Bool
970getDesugarNats = do i <- getIState
971 let opts = idris_options i
972 return (opt_desugarnats opts)
975setDesugarNats :: Bool -> Idris ()
976setDesugarNats n = do i <- getIState
977 let opts = idris_options i
978 let opt' = opts { opt_desugarnats = n }
979 putIState $ i { idris_options = opt' }
981setQuiet :: Bool -> Idris ()
982setQuiet q = do i <- getIState
983 let opts = idris_options i
984 let opt' = opts { opt_quiet = q }
985 putIState $ i { idris_options = opt' }
987getQuiet :: Idris Bool
988getQuiet = do i <- getIState
989 let opts = idris_options i
990 return (opt_quiet opts)
992setCodegen :: Codegen -> Idris ()
993setCodegen t = do i <- getIState
994 let opts = idris_options i
995 let opt' = opts { opt_codegen = t }
996 putIState $ i { idris_options = opt' }
998codegen :: Idris Codegen
999codegen = do i <- getIState
1000 return (opt_codegen (idris_options i))
1003setOutputTy :: OutputType -> Idris ()
1004setOutputTy t = do i <- getIState
1005 let opts = idris_options i
1006 let opt' = opts { opt_outputTy = t }
1007 putIState $ i { idris_options = opt' }
1009outputTy :: Idris OutputType
1010outputTy = do i <- getIState
1011 return $ opt_outputTy $ idris_options i
1013setIdeMode :: Bool -> Handle -> Idris ()
1014setIdeMode True h = do i <- getIState
1015 putIState $ i { idris_outputmode = IdeMode 0 h
1016 , idris_colourRepl = False
1018setIdeMode False _ = return ()
1020setTargetTriple :: String -> Idris ()
1021setTargetTriple t = do i <- getIState
1022 let opts = idris_options i
1023 opt' = opts { opt_triple = t }
1024 putIState $ i { idris_options = opt' }
1026targetTriple :: Idris String
1027targetTriple = do i <- getIState
1028 return (opt_triple (idris_options i))
1030setTargetCPU :: String -> Idris ()
1031setTargetCPU t = do i <- getIState
1032 let opts = idris_options i
1033 opt' = opts { opt_cpu = t }
1034 putIState $ i { idris_options = opt' }
1036targetCPU :: Idris String
1037targetCPU = do i <- getIState
1038 return (opt_cpu (idris_options i))
1040verbose :: Idris Int
1041verbose = do
1042 i <- getIState
1043 -- Quietness overrides verbosity
1044 let quiet = opt_quiet $ idris_options i
1045 if quiet
1046 then return $ 0
1047 else return $ (opt_verbose $ idris_options i)
1049setVerbose :: Int -> Idris ()
1050setVerbose t = do
1051 i <- getIState
1052 let opts = idris_options i
1053 let opt' = opts { opt_verbose = t }
1054 putIState $ i { idris_options = opt' }
1056iReport :: Int -> String -> Idris ()
1057iReport level msg = do
1058 verbosity <- verbose
1059 i <- getIState
1060 when (level <= verbosity) $
1061 case idris_outputmode i of
1062 RawOutput h -> runIO $ hPutStrLn h msg
1063 IdeMode n h -> runIO . hPutStrLn h $ convSExp "write-string" msg n
1064 return ()
1066typeInType :: Idris Bool
1067typeInType = do i <- getIState
1068 return (opt_typeintype (idris_options i))
1070setTypeInType :: Bool -> Idris ()
1071setTypeInType t = do i <- getIState
1072 let opts = idris_options i
1073 let opt' = opts { opt_typeintype = t }
1074 putIState $ i { idris_options = opt' }
1076coverage :: Idris Bool
1077coverage = do i <- getIState
1078 return (opt_coverage (idris_options i))
1080setCoverage :: Bool -> Idris ()
1081setCoverage t = do i <- getIState
1082 let opts = idris_options i
1083 let opt' = opts { opt_coverage = t }
1084 putIState $ i { idris_options = opt' }
1086setIBCSubDir :: FilePath -> Idris ()
1087setIBCSubDir fp = do i <- getIState
1088 let opts = idris_options i
1089 let opt' = opts { opt_ibcsubdir = fp }
1090 putIState $ i { idris_options = opt' }
1092valIBCSubDir :: IState -> Idris FilePath
1093valIBCSubDir i = return (opt_ibcsubdir (idris_options i))
1095addImportDir :: FilePath -> Idris ()
1096addImportDir fp = do i <- getIState
1097 let opts = idris_options i
1098 let opt' = opts { opt_importdirs = nub $ fp : opt_importdirs opts }
1099 putIState $ i { idris_options = opt' }
1101setImportDirs :: [FilePath] -> Idris ()
1102setImportDirs fps = do i <- getIState
1103 let opts = idris_options i
1104 let opt' = opts { opt_importdirs = fps }
1105 putIState $ i { idris_options = opt' }
1107allImportDirs :: Idris [FilePath]
1108allImportDirs = do i <- getIState
1109 let optdirs = opt_importdirs (idris_options i)
1110 return ("." : reverse optdirs)
1112-- Like allImportDirs but the dirs that are a prefix of
1113-- the files path first. This makes it look in the current
1114-- package first.
1115rankedImportDirs :: FilePath -> Idris [FilePath]
1116rankedImportDirs fp = do ids <- allImportDirs
1117 let (prefixes, rest) = partition (`isPrefixOf`fp) ids
1118 return $ prefixes ++ rest
1120addSourceDir :: FilePath -> Idris ()
1121addSourceDir fp = do i <- getIState
1122 let opts = idris_options i
1123 let opts' = opts { opt_sourcedirs = nub $ fp : opt_sourcedirs opts }
1124 putIState $ i { idris_options = opts' }
1126setSourceDirs :: [FilePath] -> Idris ()
1127setSourceDirs fps = do i <- getIState
1128 let opts = idris_options i
1129 let opts' = opts { opt_sourcedirs = nub $ fps }
1130 putIState $ i { idris_options = opts' }
1132allSourceDirs :: Idris [FilePath]
1133allSourceDirs = do i <- getIState
1134 let optdirs = opt_sourcedirs (idris_options i)
1135 return ("." : reverse optdirs)
1137colourise :: Idris Bool
1138colourise = do i <- getIState
1139 return $ idris_colourRepl i
1141setColourise :: Bool -> Idris ()
1142setColourise b = do i <- getIState
1143 putIState $ i { idris_colourRepl = b }
1145impShow :: Idris Bool
1146impShow = do i <- getIState
1147 return (opt_showimp (idris_options i))
1149setImpShow :: Bool -> Idris ()
1150setImpShow t = do i <- getIState
1151 let opts = idris_options i
1152 let opt' = opts { opt_showimp = t }
1153 putIState $ i { idris_options = opt' }
1155setColour :: ColourType -> IdrisColour -> Idris ()
1156setColour ct c = do i <- getIState
1157 let newTheme = setColour' ct c (idris_colourTheme i)
1158 putIState $ i { idris_colourTheme = newTheme }
1159 where setColour' KeywordColour c t = t { keywordColour = c }
1160 setColour' BoundVarColour c t = t { boundVarColour = c }
1161 setColour' ImplicitColour c t = t { implicitColour = c }
1162 setColour' FunctionColour c t = t { functionColour = c }
1163 setColour' TypeColour c t = t { typeColour = c }
1164 setColour' DataColour c t = t { dataColour = c }
1165 setColour' PromptColour c t = t { promptColour = c }
1166 setColour' PostulateColour c t = t { postulateColour = c }
1168logLvl :: Int -> String -> Idris ()
1169logLvl = logLvlCats []
1171logCoverage :: Int -> String -> Idris ()
1172logCoverage = logLvlCats [ICoverage]
1174logErasure :: Int -> String -> Idris ()
1175logErasure = logLvlCats [IErasure]
1177-- | Log an action of the parser
1178logParser :: Int -> String -> Idris ()
1179logParser = logLvlCats parserCats
1181-- | Log an action of the elaborator.
1182logElab :: Int -> String -> Idris ()
1183logElab = logLvlCats elabCats
1185-- | Log an action of the compiler.
1186logCodeGen :: Int -> String -> Idris ()
1187logCodeGen = logLvlCats codegenCats
1189logIBC :: Int -> String -> Idris ()
1190logIBC = logLvlCats [IIBC]
1192-- | Log aspect of Idris execution
1194-- An empty set of logging levels is used to denote all categories.
1196-- @TODO update IDE protocol
1197logLvlCats :: [LogCat] -- ^ The categories that the message should appear under.
1198 -> Int -- ^ The Logging level the message should appear.
1199 -> String -- ^ The message to show the developer.
1200 -> Idris ()
1201logLvlCats cs l msg = do
1202 i <- getIState
1203 let lvl = opt_logLevel (idris_options i)
1204 let cats = opt_logcats (idris_options i)
1205 when (lvl >= l) $
1206 when (inCat cs cats || null cats) $
1207 case idris_outputmode i of
1208 RawOutput h -> do
1209 runIO $ hPutStrLn h msg
1210 IdeMode n h -> do
1211 let good = SexpList [IntegerAtom (toInteger l), toSExp msg]
1212 runIO . hPutStrLn h $ convSExp "log" good n
1213 where
1214 inCat :: [LogCat] -> [LogCat] -> Bool
1215 inCat cs cats = any (`elem` cats) cs
1217cmdOptType :: Opt -> Idris Bool
1218cmdOptType x = do i <- getIState
1219 return $ x `elem` opt_cmdline (idris_options i)
1221noErrors :: Idris Bool
1222noErrors = do i <- getIState
1223 case errSpan i of
1224 Nothing -> return True
1225 _ -> return False
1227setTypeCase :: Bool -> Idris ()
1228setTypeCase t = do i <- getIState
1229 let opts = idris_options i
1230 let opt' = opts { opt_typecase = t }
1231 putIState $ i { idris_options = opt' }
1233getIndentWith :: Idris Int
1234getIndentWith = do
1235 i <- getIState
1236 return $ interactiveOpts_indentWith (idris_interactiveOpts i)
1238setIndentWith :: Int -> Idris ()
1239setIndentWith indentWith = do
1240 i <- getIState
1241 let opts = idris_interactiveOpts i
1242 let opts' = opts { interactiveOpts_indentWith = indentWith }
1243 putIState $ i { idris_interactiveOpts = opts' }
1245getIndentClause :: Idris Int
1246getIndentClause = do
1247 i <- getIState
1248 return $ interactiveOpts_indentClause (idris_interactiveOpts i)
1250setIndentClause :: Int -> Idris ()
1251setIndentClause indentClause = do
1252 i <- getIState
1253 let opts = idris_interactiveOpts i
1254 let opts' = opts { interactiveOpts_indentClause = indentClause }
1255 putIState $ i { idris_interactiveOpts = opts' }
1257-- Dealing with parameters
1259expandParams :: (Name -> Name) -> [(Name, PTerm)] ->
1260 [Name] -> -- all names
1261 [Name] -> -- names with no declaration
1262 PTerm -> PTerm
1263expandParams dec ps ns infs tm = en 0 tm
1264 where
1265 -- if we shadow a name (say in a lambda binding) that is used in a call to
1266 -- a lifted function, we need access to both names - once in the scope of the
1267 -- binding and once to call the lifted functions. So we'll explicitly shadow
1268 -- it. (Yes, it's a hack. The alternative would be to resolve names earlier
1269 -- but we didn't...)
1271 mkShadow (UN n) = MN 0 n
1272 mkShadow (MN i n) = MN (i+1) n
1273 mkShadow (NS x s) = NS (mkShadow x) s
1275 en :: Int -- ^ The quotation level - only transform terms that are used, not terms
1276 -- that are merely mentioned.
1277 -> PTerm -> PTerm
1278 en 0 (PLam fc n nfc t s)
1279 | n `elem` (map fst ps ++ ns)
1280 = let n' = mkShadow n in
1281 PLam fc n' nfc (en 0 t) (en 0 (shadow n n' s))
1282 | otherwise = PLam fc n nfc (en 0 t) (en 0 s)
1283 en 0 (PPi p n nfc t s)
1284 | n `elem` (map fst ps ++ ns)
1285 = let n' = mkShadow n in -- TODO THINK SHADOWING TacImp?
1286 PPi (enTacImp 0 p) n' nfc (en 0 t) (en 0 (shadow n n' s))
1287 | otherwise = PPi (enTacImp 0 p) n nfc (en 0 t) (en 0 s)
1288 en 0 (PLet fc n nfc ty v s)
1289 | n `elem` (map fst ps ++ ns)
1290 = let n' = mkShadow n in
1291 PLet fc n' nfc (en 0 ty) (en 0 v) (en 0 (shadow n n' s))
1292 | otherwise = PLet fc n nfc (en 0 ty) (en 0 v) (en 0 s)
1293 -- FIXME: Should only do this in a type signature!
1294 en 0 (PDPair f hls p (PRef f' fcs n) t r)
1295 | n `elem` (map fst ps ++ ns) && t /= Placeholder
1296 = let n' = mkShadow n in
1297 PDPair f hls p (PRef f' fcs n') (en 0 t) (en 0 (shadow n n' r))
1298 en 0 (PRewrite f by l r g) = PRewrite f by (en 0 l) (en 0 r) (fmap (en 0) g)
1299 en 0 (PTyped l r) = PTyped (en 0 l) (en 0 r)
1300 en 0 (PPair f hls p l r) = PPair f hls p (en 0 l) (en 0 r)
1301 en 0 (PDPair f hls p l t r) = PDPair f hls p (en 0 l) (en 0 t) (en 0 r)
1302 en 0 (PAlternative ns a as) = PAlternative ns a (map (en 0) as)
1303 en 0 (PHidden t) = PHidden (en 0 t)
1304 en 0 (PUnifyLog t) = PUnifyLog (en 0 t)
1305 en 0 (PDisamb ds t) = PDisamb ds (en 0 t)
1306 en 0 (PNoImplicits t) = PNoImplicits (en 0 t)
1307 en 0 (PDoBlock ds) = PDoBlock (map (fmap (en 0)) ds)
1308 en 0 (PProof ts) = PProof (map (fmap (en 0)) ts)
1309 en 0 (PTactics ts) = PTactics (map (fmap (en 0)) ts)
1311 en 0 (PQuote (Var n))
1312 | n `nselem` ns = PQuote (Var (dec n))
1313 en 0 (PApp fc (PInferRef fc' hl n) as)
1314 | n `nselem` ns = PApp fc (PInferRef fc' hl (dec n))
1315 (map ((pexp . (PRef fc hl)) . fst) ps ++ (map (fmap (en 0)) as))
1316 en 0 (PApp fc (PRef fc' hl n) as)
1317 | n `elem` infs = PApp fc (PInferRef fc' hl (dec n))
1318 (map ((pexp . (PRef fc hl)) . fst) ps ++ (map (fmap (en 0)) as))
1319 | n `nselem` ns = PApp fc (PRef fc' hl (dec n))
1320 (map ((pexp . (PRef fc hl)) . fst) ps ++ (map (fmap (en 0)) as))
1321 en 0 (PAppBind fc (PRef fc' hl n) as)
1322 | n `elem` infs = PAppBind fc (PInferRef fc' hl (dec n))
1323 (map ((pexp . (PRef fc hl)) . fst) ps ++ (map (fmap (en 0)) as))
1324 | n `nselem` ns = PAppBind fc (PRef fc' hl (dec n))
1325 (map ((pexp . (PRef fc hl)) . fst) ps ++ (map (fmap (en 0)) as))
1326 en 0 (PRef fc hl n)
1327 | n `elem` infs = PApp fc (PInferRef fc hl (dec n))
1328 (map ((pexp . (PRef fc hl)) . fst) ps)
1329 | n `nselem` ns = PApp fc (PRef fc hl (dec n))
1330 (map ((pexp . (PRef fc hl)) . fst) ps)
1331 en 0 (PInferRef fc hl n)
1332 | n `nselem` ns = PApp fc (PInferRef fc hl (dec n))
1333 (map ((pexp . (PRef fc hl)) . fst) ps)
1334 en 0 (PApp fc f as) = PApp fc (en 0 f) (map (fmap (en 0)) as)
1335 en 0 (PAppBind fc f as) = PAppBind fc (en 0 f) (map (fmap (en 0)) as)
1336 en 0 (PCase fc c os) = PCase fc (en 0 c) (map (pmap (en 0)) os)
1337 en 0 (PIfThenElse fc c t f) = PIfThenElse fc (en 0 c) (en 0 t) (en 0 f)
1338 en 0 (PRunElab fc tm ns) = PRunElab fc (en 0 tm) ns
1339 en 0 (PConstSugar fc tm) = PConstSugar fc (en 0 tm)
1341 en ql (PQuasiquote tm ty) = PQuasiquote (en (ql + 1) tm) (fmap (en ql) ty)
1342 en ql (PUnquote tm) = PUnquote (en (ql - 1) tm)
1344 en ql t = descend (en ql) t
1346 nselem x [] = False
1347 nselem x (y : xs) | nseq x y = True
1348 | otherwise = nselem x xs
1350 nseq x y = nsroot x == nsroot y
1352 enTacImp ql (TacImp aos st scr rig) = TacImp aos st (en ql scr) rig
1353 enTacImp ql other = other
1355expandParamsD :: Bool -> -- True = RHS only
1356 IState ->
1357 (Name -> Name) -> [(Name, PTerm)] -> [Name] -> PDecl -> PDecl
1358expandParamsD rhsonly ist dec ps ns (PTy doc argdocs syn fc o n nfc ty)
1359 = if n `elem` ns && (not rhsonly)
1360 then -- trace (show (n, expandParams dec ps ns ty)) $
1361 PTy doc argdocs syn fc o (dec n) nfc (piBindp expl_param ps (expandParams dec ps ns [] ty))
1362 else --trace (show (n, expandParams dec ps ns ty)) $
1363 PTy doc argdocs syn fc o n nfc (expandParams dec ps ns [] ty)
1364expandParamsD rhsonly ist dec ps ns (PPostulate e doc syn fc nfc o n ty)
1365 = if n `elem` ns && (not rhsonly)
1366 then -- trace (show (n, expandParams dec ps ns ty)) $
1367 PPostulate e doc syn fc nfc o (dec n)
1368 (piBind ps (expandParams dec ps ns [] ty))
1369 else --trace (show (n, expandParams dec ps ns ty)) $
1370 PPostulate e doc syn fc nfc o n (expandParams dec ps ns [] ty)
1371expandParamsD rhsonly ist dec ps ns (PClauses fc opts n cs)
1372 = let n' = if n `elem` ns then dec n else n in
1373 PClauses fc opts n' (map expandParamsC cs)
1374 where
1375 expandParamsC (PClause fc n lhs ws rhs ds)
1376 = let -- ps' = updateps True (namesIn ist rhs) (zip ps [0..])
1377 ps'' = updateps False (namesIn [] ist lhs) (zip ps [0..])
1378 lhs' = if rhsonly then lhs else (expandParams dec ps'' ns [] lhs)
1379 n' = if n `elem` ns then dec n else n
1380 -- names bound on the lhs should not be expanded on the rhs
1381 ns' = removeBound lhs ns in
1382 PClause fc n' lhs'
1383 (map (expandParams dec ps'' ns' []) ws)
1384 (expandParams dec ps'' ns' [] rhs)
1385 (map (expandParamsD True ist dec ps'' ns') ds)
1386 expandParamsC (PWith fc n lhs ws wval pn ds)
1387 = let -- ps' = updateps True (namesIn ist wval) (zip ps [0..])
1388 ps'' = updateps False (namesIn [] ist lhs) (zip ps [0..])
1389 lhs' = if rhsonly then lhs else (expandParams dec ps'' ns [] lhs)
1390 n' = if n `elem` ns then dec n else n
1391 ns' = removeBound lhs ns in
1392 PWith fc n' lhs'
1393 (map (expandParams dec ps'' ns' []) ws)
1394 (expandParams dec ps'' ns' [] wval)
1395 pn
1396 (map (expandParamsD rhsonly ist dec ps'' ns') ds)
1397 updateps yn nm [] = []
1398 updateps yn nm (((a, t), i):as)
1399 | (a `elem` nm) == yn = (a, t) : updateps yn nm as
1400 | otherwise = (sMN i (show a ++ "_shadow"), t) : updateps yn nm as
1402 removeBound lhs ns = ns \\ nub (bnames lhs)
1404 bnames (PRef _ _ n) = [n]
1405 bnames (PApp _ _ args) = concatMap (bnames . getTm) args
1406 bnames (PPair _ _ _ l r) = bnames l ++ bnames r
1407 bnames (PDPair _ _ _ l Placeholder r) = bnames l ++ bnames r
1408 bnames _ = []
1410-- | Expands parameters defined in parameter and where blocks inside of declarations
1411expandParamsD rhs ist dec ps ns (PData doc argDocs syn fc co pd)
1412 = PData doc argDocs syn fc co (expandPData pd)
1413 where
1414 -- just do the type decl, leave constructors alone (parameters will be
1415 -- added implicitly)
1416 expandPData (PDatadecl n nfc ty cons)
1417 = if n `elem` ns
1418 then PDatadecl (dec n) nfc (piBind ps (expandParams dec ps ns [] ty))
1419 (map econ cons)
1420 else PDatadecl n nfc (expandParams dec ps ns [] ty) (map econ cons)
1421 econ (doc, argDocs, n, nfc, t, fc, fs)
1422 = (doc, argDocs, dec n, nfc, piBindp expl ps (expandParams dec ps ns [] t), fc, fs)
1423expandParamsD rhs ist dec ps ns d@(PRecord doc rsyn fc opts name nfc prs pdocs fls cn cdoc csyn)
1424 = d
1425expandParamsD rhs ist dec ps ns (PParams f params pds)
1426 = PParams f (ps ++ map (mapsnd (expandParams dec ps ns [])) params)
1427 (map (expandParamsD True ist dec ps ns) pds)
1428-- (map (expandParamsD ist dec ps ns) pds)
1429expandParamsD rhs ist dec ps ns (PMutual f pds)
1430 = PMutual f (map (expandParamsD rhs ist dec ps ns) pds)
1431expandParamsD rhs ist dec ps ns (PInterface doc info f cs n nfc params pDocs fds decls cn cd)
1432 = PInterface doc info f
1433 (map (\ (n, t) -> (n, expandParams dec ps ns [] t)) cs)
1434 n nfc
1435 (map (\(n, fc, t) -> (n, fc, expandParams dec ps ns [] t)) params)
1436 pDocs
1437 fds
1438 (map (expandParamsD rhs ist dec ps ns) decls)
1439 cn
1440 cd
1441expandParamsD rhs ist dec ps ns (PImplementation doc argDocs info f cs pnames acc opts n nfc params pextra ty cn decls)
1442 = let cn' = case cn of
1443 Just n -> if n `elem` ns then Just (dec n) else Just n
1444 Nothing -> Nothing in
1445 PImplementation doc argDocs info f
1446 (map (\ (n, t) -> (n, expandParams dec ps ns [] t)) cs)
1447 pnames acc opts n
1448 nfc
1449 (map (expandParams dec ps ns []) params)
1450 (map (\ (n, t) -> (n, expandParams dec ps ns [] t)) pextra)
1451 (expandParams dec ps ns [] ty)
1452 cn'
1453 (map (expandParamsD True ist dec ps ns) decls)
1454expandParamsD rhs ist dec ps ns d = d
1456mapsnd f (x, t) = (x, f t)
1458expandImplementationScope ist dec ps ns (PImplementation doc argDocs info f cs pnames acc opts n nfc params pextra ty cn decls)
1459 = PImplementation doc argDocs info f cs pnames acc opts n nfc params (ps ++ pextra)
1460 ty cn decls
1461expandImplementationScope ist dec ps ns d = d
1463-- | Calculate a priority for a type, for deciding elaboration order
1464-- * if it's just a type variable or concrete type, do it early (0)
1465-- * if there's only type variables and injective constructors, do it next (1)
1466-- * if there's a function type, next (2)
1467-- * finally, everything else (3)
1468getPriority :: IState -> PTerm -> Int
1469getPriority i tm = 1 -- pri tm
1470 where
1471 pri (PRef _ _ n) =
1472 case lookupP n (tt_ctxt i) of
1473 ((P (DCon _ _ _) _ _):_) -> 1
1474 ((P (TCon _ _) _ _):_) -> 1
1475 ((P Ref _ _):_) -> 1
1476 [] -> 0 -- must be locally bound, if it's not an error...
1477 pri (PPi _ _ _ x y) = max 5 (max (pri x) (pri y))
1478 pri (PTrue _ _) = 0
1479 pri (PRewrite _ _ l r _) = max 1 (max (pri l) (pri r))
1480 pri (PApp _ f as) = max 1 (max (pri f) (foldr (max . pri . getTm) 0 as))
1481 pri (PAppBind _ f as) = max 1 (max (pri f) (foldr (max . pri . getTm) 0 as))
1482 pri (PCase _ f as) = max 1 (max (pri f) (foldr (max . pri . snd) 0 as))
1483 pri (PTyped l r) = pri l
1484 pri (PPair _ _ _ l r) = max 1 (max (pri l) (pri r))
1485 pri (PDPair _ _ _ l t r) = max 1 (max (pri l) (max (pri t) (pri r)))
1486 pri (PAlternative _ a as) = maximum (map pri as)
1487 pri (PConstant _ _) = 0
1488 pri Placeholder = 1
1489 pri _ = 3
1492addStatics :: Name -> Term -> PTerm -> Idris ()
1493addStatics n tm ptm =
1494 do let (statics, dynamics) = initStatics tm ptm
1495 ist <- getIState
1496 let paramnames
1497 = nub $ case lookupCtxtExact n (idris_fninfo ist) of
1498 Just p -> getNamesFrom 0 (fn_params p) tm ++
1499 concatMap (getParamNames ist . snd) statics
1500 _ -> concatMap (getParamNames ist . snd) statics
1502 let stnames = nub $ concatMap (freeArgNames . snd) statics
1503 let dnames = (nub $ concatMap (freeArgNames . snd) dynamics)
1504 \\ paramnames
1505 -- also get the arguments which are 'uniquely inferrable' from
1506 -- statics (see sec 4.2 of "Scrapping Your Inefficient Engine")
1507 -- or parameters to the type of a static
1508 let statics' = nub $ map fst statics ++
1509 filter (\x -> not (elem x dnames)) stnames
1510 let stpos = staticList statics' tm
1511 i <- getIState
1512 unless (null statics) $
1513 logLvl 3 $ "Statics for " ++ show n ++ " " ++ show tm ++ "\n"
1514 ++ showTmImpls ptm ++ "\n"
1515 ++ show statics ++ "\n" ++ show dynamics
1516 ++ "\n" ++ show paramnames
1517 ++ "\n" ++ show stpos
1518 putIState $ i { idris_statics = addDef n stpos (idris_statics i) }
1519 addIBC (IBCStatic n)
1520 where
1521 initStatics (Bind n (Pi _ _ ty _) sc) (PPi p n' fc t s)
1522 | n /= n' = let (static, dynamic) = initStatics sc (PPi p n' fc t s) in
1523 (static, (n, ty) : dynamic)
1524 initStatics (Bind n (Pi _ _ ty _) sc) (PPi p n' fc _ s)
1525 = let (static, dynamic) = initStatics (instantiate (P Bound n ty) sc) s in
1526 if pstatic p == Static then ((n, ty) : static, dynamic)
1527 else if (not (searchArg p))
1528 then (static, (n, ty) : dynamic)
1529 else (static, dynamic)
1530 initStatics t pt = ([], [])
1532 getParamNames ist tm | (P _ n _ , args) <- unApply tm
1533 = case lookupCtxtExact n (idris_datatypes ist) of
1534 Just ti -> getNamePos 0 (param_pos ti) args
1535 Nothing -> []
1536 where getNamePos i ps [] = []
1537 getNamePos i ps (P _ n _ : as)
1538 | i `elem` ps = n : getNamePos (i + 1) ps as
1539 getNamePos i ps (_ : as) = getNamePos (i + 1) ps as
1540 getParamNames ist (Bind t (Pi _ _ (P _ n _) _) sc)
1541 = n : getParamNames ist sc
1542 getParamNames ist _ = []
1544 getNamesFrom i ps (Bind n (Pi _ _ _ _) sc)
1545 | i `elem` ps = n : getNamesFrom (i + 1) ps sc
1546 | otherwise = getNamesFrom (i + 1) ps sc
1547 getNamesFrom i ps sc = []
1549 freeArgNames (Bind n (Pi _ _ ty _) sc)
1550 = nub $ freeNames ty ++ freeNames sc -- treat '->' as fn here
1551 freeArgNames tm = let (_, args) = unApply tm in
1552 concatMap freeNames args
1554 -- if a name appears in an interface or tactic implicit index, it doesn't
1555 -- affect its 'uniquely inferrable' from a static status since these are
1556 -- resolved by searching.
1557 searchArg (Constraint _ _ _) = True
1558 searchArg (TacImp _ _ _ _) = True
1559 searchArg _ = False
1561 staticList sts (Bind n (Pi _ _ _ _) sc) = (n `elem` sts) : staticList sts sc
1562 staticList _ _ = []
1564-- Dealing with implicit arguments
1566-- Add some bound implicits to the using block if they aren't there already
1568addToUsing :: [Using] -> [(Name, PTerm)] -> [Using]
1569addToUsing us [] = us
1570addToUsing us ((n, t) : ns)
1571 | n `notElem` mapMaybe impName us = addToUsing (us ++ [UImplicit n t]) ns
1572 | otherwise = addToUsing us ns
1573 where impName (UImplicit n _) = Just n
1574 impName _ = Nothing
1576-- Add constraint bindings from using block
1578addUsingConstraints :: SyntaxInfo -> FC -> PTerm -> Idris PTerm
1579addUsingConstraints syn fc t
1580 = do ist <- get
1581 let ns = namesIn [] ist t
1582 let cs = getConstraints t -- check declared constraints
1583 let addconsts = uconsts \\ cs
1584 return (doAdd addconsts ns t)
1585 where uconsts = filter uconst (using syn)
1586 uconst (UConstraint _ _) = True
1587 uconst _ = False
1589 doAdd [] _ t = t
1590 -- if all of args in ns, then add it
1591 doAdd (UConstraint c args : cs) ns t
1592 | all (\n -> elem n ns) args
1593 = PPi (Constraint [] Dynamic RigW) (sMN 0 "cu") NoFC
1594 (mkConst c args) (doAdd cs ns t)
1595 | otherwise = doAdd cs ns t
1597 mkConst c args = PApp fc (PRef fc [] c)
1598 (map (PExp 0 [] (sMN 0 "carg") . PRef fc []) args)
1600 getConstraints (PPi (Constraint _ _ _) _ _ c sc)
1601 = getcapp c ++ getConstraints sc
1602 getConstraints (PPi _ _ _ c sc) = getConstraints sc
1603 getConstraints _ = []
1605 getcapp (PApp _ (PRef _ _ c) args)
1606 = do ns <- mapM getName args
1607 return (UConstraint c ns)
1608 getcapp _ = []
1610 getName (PExp _ _ _ (PRef _ _ n)) = return n
1611 getName _ = []
1613-- | Add implicit bindings from using block, and bind any missing names
1614addUsingImpls :: SyntaxInfo -> Name -> FC -> PTerm -> Idris PTerm
1615addUsingImpls syn n fc t
1616 = do ist <- getIState
1617 autoimpl <- getAutoImpls
1618 let ns_in = implicitNamesIn (map iname uimpls) ist t
1619 let ns = if autoimpl then ns_in
1620 else filter (\n -> n `elem` (map iname uimpls)) ns_in
1622 let badnames = filter (\n -> not (implicitable n) &&
1623 n `notElem` (map iname uimpls)) ns
1624 unless (null badnames) $
1625 throwError (At fc (Elaborating "type of " n Nothing
1626 (NoSuchVariable (head badnames))))
1627 let cs = getArgnames t -- get already bound names
1628 let addimpls = filter (\n -> iname n `notElem` cs) uimpls
1629 -- if all names in the arguments of addconsts appear in ns,
1630 -- add the constraint implicitly
1631 return (bindFree ns (doAdd addimpls ns t))
1632 where uimpls = filter uimpl (using syn)
1633 uimpl (UImplicit _ _) = True
1634 uimpl _ = False
1636 iname (UImplicit n _) = n
1637 iname (UConstraint _ _) = error "Can't happen addUsingImpls"
1639 doAdd [] _ t = t
1640 -- if all of args in ns, then add it
1641 doAdd (UImplicit n ty : cs) ns t
1642 | elem n ns
1643 = PPi impl_gen n NoFC ty (doAdd cs ns t)
1644 | otherwise = doAdd cs ns t
1646 -- bind the free names which weren't in the using block
1647 bindFree [] tm = tm
1648 bindFree (n:ns) tm
1649 | elem n (map iname uimpls) = bindFree ns tm
1650 | otherwise
1651 = PPi (impl_gen { pargopts = [InaccessibleArg] }) n NoFC Placeholder (bindFree ns tm)
1653 getArgnames (PPi _ n _ c sc)
1654 = n : getArgnames sc
1655 getArgnames _ = []
1657-- Given the original type and the elaborated type, return the implicitness
1658-- status of each pi-bound argument, and whether it's inaccessible (True) or not.
1660getUnboundImplicits :: IState -> Type -> PTerm -> [(Bool, PArg)]
1661getUnboundImplicits i t tm = getImps t (collectImps tm)
1662 where collectImps (PPi p n _ t sc)
1663 = (n, (p, t)) : collectImps sc
1664 collectImps _ = []
1666 scopedimpl (Just i) = not (toplevel_imp i)
1667 scopedimpl _ = False
1669 getImps (Bind n (Pi _ i _ _) sc) imps
1670 | scopedimpl i = getImps sc imps
1671 getImps (Bind n (Pi _ _ t _) sc) imps
1672 | Just (p, t') <- lookup n imps = argInfo n p t' : getImps sc imps
1673 where
1674 argInfo n (Imp opt _ _ _ _ _) Placeholder
1675 = (True, PImp 0 True opt n Placeholder)
1676 argInfo n (Imp opt _ _ _ _ _) t'
1677 = (False, PImp (getPriority i t') True opt n t')
1678 argInfo n (Exp opt _ _ _) t'
1679 = (InaccessibleArg `elem` opt,
1680 PExp (getPriority i t') opt n t')
1681 argInfo n (Constraint opt _ _) t'
1682 = (InaccessibleArg `elem` opt,
1683 PConstraint 10 opt n t')
1684 argInfo n (TacImp opt _ scr _) t'
1685 = (InaccessibleArg `elem` opt,
1686 PTacImplicit 10 opt n scr t')
1687 getImps (Bind n (Pi _ _ t _) sc) imps = impBind n t : getImps sc imps
1688 where impBind n t = (True, PImp 1 True [] n Placeholder)
1689 getImps sc tm = []
1691-- Add implicit Pi bindings for any names in the term which appear in an
1692-- argument position.
1694-- This has become a right mess already. Better redo it some time...
1695-- TODO: This is obsoleted by the new way of elaborating types, (which
1696-- calls addUsingImpls) but there's still a couple of places which use
1697-- it. Clean them up!
1699-- Issue 1739 in the issue tracker
1700-- https://github.com/idris-lang/Idris-dev/issues/1739
1701implicit :: ElabInfo -> SyntaxInfo -> Name -> PTerm -> Idris PTerm
1702implicit info syn n ptm = implicit' info syn [] n ptm
1704implicit' :: ElabInfo -> SyntaxInfo -> [Name] -> Name -> PTerm -> Idris PTerm
1705implicit' info syn ignore n ptm
1706 = do i <- getIState
1707 auto <- getAutoImpls
1708 let (tm', impdata) = implicitise auto syn ignore i ptm
1709 defaultArgCheck (eInfoNames info ++ M.keys (idris_implicits i)) impdata
1710-- let (tm'', spos) = findStatics i tm'
1711 putIState $ i { idris_implicits = addDef n impdata (idris_implicits i) }
1712 addIBC (IBCImp n)
1713 logLvl 5 ("Implicit " ++ show n ++ " " ++ show impdata)
1714-- i <- get
1715-- putIState $ i { idris_statics = addDef n spos (idris_statics i) }
1716 return tm'
1717 where
1718 -- Detect unknown names in default arguments and throw error if found.
1719 defaultArgCheck :: [Name] -> [PArg] -> Idris ()
1720 defaultArgCheck knowns params = foldM_ notFoundInDefault knowns params
1722 notFoundInDefault :: [Name] -> PArg -> Idris [Name]
1723 notFoundInDefault kns (PTacImplicit _ _ n script _)
1724 = do i <- getIState
1725 case notFound kns (namesIn [] i script) of
1726 Nothing -> return (n:kns)
1727 Just name -> throwError (NoSuchVariable name)
1728 notFoundInDefault kns p = return ((pname p):kns)
1730 notFound :: [Name] -> [Name] -> Maybe Name
1731 notFound kns [] = Nothing
1732 notFound kns (SN (WhereN _ _ _) : ns) = notFound kns ns -- Known already
1733 notFound kns (n:ns) = if elem n kns then notFound kns ns else Just n
1735-- | Even if auto_implicits is off, we need to call this so we record
1736-- which arguments are implicit
1737implicitise :: Bool -> SyntaxInfo -> [Name] -> IState -> PTerm -> (PTerm, [PArg])
1738implicitise auto syn ignore ist tm = -- trace ("INCOMING " ++ showImp True tm) $
1739 let (declimps, ns') = execState (imps True [] tm) ([], [])
1740 ns = filter (\n -> auto && implicitable n || elem n (map fst uvars)) $
1741 ns' \\ (map fst pvars ++ no_imp syn ++ ignore)
1742 nsOrder = filter (not . inUsing) ns ++ filter inUsing ns in
1743 if null ns
1744 then (tm, reverse declimps)
1745 else implicitise auto syn ignore ist (pibind uvars nsOrder tm)
1746 where
1747 uvars = map ipair (filter uimplicit (using syn))
1748 pvars = syn_params syn
1750 inUsing n = n `elem` map fst uvars
1752 ipair (UImplicit x y) = (x, y)
1753 uimplicit (UImplicit _ _) = True
1754 uimplicit _ = False
1756 dropAll (x:xs) ys | x `elem` ys = dropAll xs ys
1757 | otherwise = x : dropAll xs ys
1758 dropAll [] ys = []
1760 -- Find names in argument position in a type, suitable for implicit
1761 -- binding
1762 -- Not the function position, but do everything else...
1763 implNamesIn uv (PApp fc f args) = concatMap (implNamesIn uv . getTm) args
1764 implNamesIn uv t = implicitNamesIn (map fst uv) ist t
1766 imps top env ty@(PApp _ f as)
1767 = do (decls, ns) <- get
1768 let isn = nub (implNamesIn uvars ty)
1769 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1770 imps top env (PPi (Imp l _ _ _ _ _) n _ ty sc)
1771 = do let isn = nub (implNamesIn uvars ty) `dropAll` [n]
1772 (decls , ns) <- get
1773 put (PImp (getPriority ist ty) True l n Placeholder : decls,
1774 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1775 imps True (n:env) sc
1776 imps top env (PPi (Exp l _ _ _) n _ ty sc)
1777 = do let isn = nub (implNamesIn uvars ty ++ case sc of
1778 (PRef _ _ x) -> namesIn uvars ist sc `dropAll` [n]
1779 _ -> [])
1780 (decls, ns) <- get -- ignore decls in HO types
1781 put (PExp (getPriority ist ty) l n Placeholder : decls,
1782 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1783 imps True (n:env) sc
1784 imps top env (PPi (Constraint l _ _) n _ ty sc)
1785 = do let isn = nub (implNamesIn uvars ty ++ case sc of
1786 (PRef _ _ x) -> namesIn uvars ist sc `dropAll` [n]
1787 _ -> [])
1788 (decls, ns) <- get -- ignore decls in HO types
1789 put (PConstraint 10 l n Placeholder : decls,
1790 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1791 imps True (n:env) sc
1792 imps top env (PPi (TacImp l _ scr _) n _ ty sc)
1793 = do let isn = nub (implNamesIn uvars ty ++ case sc of
1794 (PRef _ _ x) -> namesIn uvars ist sc `dropAll` [n]
1795 _ -> [])
1796 (decls, ns) <- get -- ignore decls in HO types
1797 put (PTacImplicit 10 l n scr Placeholder : decls,
1798 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1799 imps True (n:env) sc
1800 imps top env (PRewrite _ _ l r _)
1801 = do (decls, ns) <- get
1802 let isn = namesIn uvars ist l ++ namesIn uvars ist r
1803 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1804 imps top env (PTyped l r)
1805 = imps top env l
1806 imps top env (PPair _ _ _ l r)
1807 = do (decls, ns) <- get
1808 let isn = namesIn uvars ist l ++ namesIn uvars ist r
1809 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1810 imps top env (PDPair _ _ _ (PRef _ _ n) t r)
1811 = do (decls, ns) <- get
1812 let isn = nub (namesIn uvars ist t ++ namesIn uvars ist r) \\ [n]
1813 put (decls, nub (ns ++ (isn \\ (env ++ map fst (getImps decls)))))
1814 imps top env (PDPair _ _ _ l t r)
1815 = do (decls, ns) <- get
1816 let isn = namesIn uvars ist l ++ namesIn uvars ist t ++
1817 namesIn uvars ist r
1818 put (decls, nub (ns ++ (isn \\ (env ++ map fst (getImps decls)))))
1819 imps top env (PAlternative ms a as)
1820 = do (decls, ns) <- get
1821 let isn = concatMap (namesIn uvars ist) as
1822 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1823 imps top env (PLam fc n _ ty sc)
1824 = do imps False env ty
1825 imps False (n:env) sc
1826 imps top env (PHidden tm) = imps False env tm
1827 imps top env (PUnifyLog tm) = imps False env tm
1828 imps top env (PNoImplicits tm) = imps False env tm
1829 imps top env (PRunElab fc tm ns) = imps False env tm
1830 imps top env (PConstSugar fc tm) = imps top env tm -- ignore PConstSugar - it's for highlighting only!
1831 imps top env _ = return ()
1833 pibind using [] sc = sc
1834 pibind using (n:ns) sc
1835 = case lookup n using of
1836 Just ty -> PPi impl_gen
1837 n NoFC ty (pibind using ns sc)
1838 Nothing -> PPi (impl_gen { pargopts = [InaccessibleArg] })
1839 n NoFC Placeholder (pibind using ns sc)
1841-- | Add implicit arguments in function calls
1842addImplPat :: IState -> PTerm -> PTerm
1843addImplPat = addImpl' True [] [] []
1845addImplBound :: IState -> [Name] -> PTerm -> PTerm
1846addImplBound ist ns = addImpl' False ns [] [] ist
1848addImplBoundInf :: IState -> [Name] -> [Name] -> PTerm -> PTerm
1849addImplBoundInf ist ns inf = addImpl' False ns inf [] ist
1851-- | Add the implicit arguments to applications in the term [Name]
1852-- gives the names to always expend, even when under a binder of that
1853-- name (this is to expand methods with implicit arguments in
1854-- dependent interfaces).
1855addImpl :: [Name] -> IState -> PTerm -> PTerm
1856addImpl = addImpl' False [] []
1858-- TODO: in patterns, don't add implicits to function names guarded by constructors
1859-- and *not* inside a PHidden
1861addImpl' :: Bool -> [Name] -> [Name] -> [Name] -> IState -> PTerm -> PTerm
1862addImpl' inpat env infns imp_meths ist ptm
1863 = ai inpat False (zip env (repeat Nothing)) [] (mkUniqueNames env [] ptm)
1864 where
1865 topname = case ptm of
1866 PRef _ _ n -> n
1867 PApp _ (PRef _ _ n) _ -> n
1868 _ -> sUN "" -- doesn't matter then
1870 ai :: Bool -> Bool -> [(Name, Maybe PTerm)] -> [[T.Text]] -> PTerm -> PTerm
1871 ai inpat qq env ds (PRef fc fcs f)
1872 | f `elem` infns = PInferRef fc fcs f
1873 | not (f `elem` map fst env) = handleErr $ aiFn topname inpat inpat qq imp_meths ist fc f fc ds []
1874 ai inpat qq env ds (PHidden (PRef fc hl f))
1875 | not (f `elem` map fst env) = PHidden (handleErr $ aiFn topname inpat False qq imp_meths ist fc f fc ds [])
1876 ai inpat qq env ds (PRewrite fc by l r g)
1877 = let l' = ai inpat qq env ds l
1878 r' = ai inpat qq env ds r
1879 g' = fmap (ai inpat qq env ds) g in
1880 PRewrite fc by l' r' g'
1881 ai inpat qq env ds (PTyped l r)
1882 = let l' = ai inpat qq env ds l
1883 r' = ai inpat qq env ds r in
1884 PTyped l' r'
1885 ai inpat qq env ds (PPair fc hls p l r)
1886 = let l' = ai inpat qq env ds l
1887 r' = ai inpat qq env ds r in
1888 PPair fc hls p l' r'
1889 ai inpat qq env ds (PDPair fc hls p l t r)
1890 = let l' = ai inpat qq env ds l
1891 t' = ai inpat qq env ds t
1892 r' = ai inpat qq env ds r in
1893 PDPair fc hls p l' t' r'
1894 ai inpat qq env ds (PAlternative ms a as)
1895 = let as' = map (ai inpat qq env ds) as in
1896 PAlternative ms a as'
1897 ai inpat qq env _ (PDisamb ds' as) = ai inpat qq env ds' as
1898 ai inpat qq env ds (PApp fc (PInferRef ffc hl f) as)
1899 = let as' = map (fmap (ai inpat qq env ds)) as in
1900 PApp fc (PInferRef ffc hl f) as'
1901 ai inpat qq env ds (PApp fc ftm@(PRef ffc hl f) as)
1902 | f `elem` infns = ai inpat qq env ds (PApp fc (PInferRef ffc hl f) as)
1903 | not (f `elem` map fst env)
1904 = let as' = map (fmap (ai inpat qq env ds)) as in
1905 handleErr $ aiFn topname inpat False qq imp_meths ist fc f ffc ds as'
1906 | Just (Just ty) <- lookup f env =
1907 let as' = map (fmap (ai inpat qq env ds)) as
1908 arity = getPArity ty in
1909 mkPApp fc arity ftm as'
1910 ai inpat qq env ds (PApp fc f as)
1911 = let f' = ai inpat qq env ds f
1912 as' = map (fmap (ai inpat qq env ds)) as in
1913 mkPApp fc 1 f' as'
1914 ai inpat qq env ds (PWithApp fc f a)
1915 = PWithApp fc (ai inpat qq env ds f) (ai inpat qq env ds a)
1916 ai inpat qq env ds (PCase fc c os)
1917 = let c' = ai inpat qq env ds c in
1918 -- leave lhs alone, because they get lifted into a new pattern match
1919 -- definition which is passed through addImpl again
1920 PCase fc c' (map aiCase os)
1921 where
1922 aiCase (lhs, rhs)
1923 = (lhs, ai inpat qq (env ++ patnames lhs) ds rhs)
1925 -- Anything beginning with a lower case letter, not applied,
1926 -- and no namespace is a pattern variable
1927 patnames (PApp _ (PRef _ _ f) [])
1928 | implicitable f = [(f, Nothing)]
1929 patnames (PRef _ _ f)
1930 | implicitable f = [(f, Nothing)]
1931 patnames (PApp _ (PRef _ _ _) args)
1932 = concatMap patnames (map getTm args)
1933 patnames (PPair _ _ _ l r) = patnames l ++ patnames r
1934 patnames (PDPair _ _ _ l t r) = patnames l ++ patnames t ++ patnames r
1935 patnames (PAs _ _ t) = patnames t
1936 patnames (PAlternative _ _ ts) = concatMap patnames ts
1937 patnames _ = []
1940 ai inpat qq env ds (PIfThenElse fc c t f) = PIfThenElse fc (ai inpat qq env ds c)
1941 (ai inpat qq env ds t)
1942 (ai inpat qq env ds f)
1944 -- If the name in a lambda is an unapplied data constructor name, do this
1945 -- as a 'case' instead because we'll expect to match on it
1946 ai inpat qq env ds (PLam fc n nfc ty sc)
1947 = if canBeDConName n (tt_ctxt ist)
1948 then ai inpat qq env ds (PLam fc (sMN 0 "lamp") NoFC ty
1949 (PCase fc (PRef fc [] (sMN 0 "lamp") )
1950 [(PRef fc [] n, sc)]))
1951 else let ty' = ai inpat qq env ds ty
1952 sc' = ai inpat qq ((n, Just ty):env) ds sc in
1953 PLam fc n nfc ty' sc'
1954 ai inpat qq env ds (PLet fc n nfc ty val sc)
1955 = if canBeDConName n (tt_ctxt ist)
1956 then ai inpat qq env ds (PCase fc val [(PRef fc [] n, sc)])
1957 else let ty' = ai inpat qq env ds ty
1958 val' = ai inpat qq env ds val
1959 sc' = ai inpat qq ((n, Just ty):env) ds sc in
1960 PLet fc n nfc ty' val' sc'
1961 ai inpat qq env ds (PPi p n nfc ty sc)
1962 = let ty' = ai inpat qq env ds ty
1963 env' = if n `elem` imp_meths then env
1964 else
1965 ((n, Just ty) : env)
1966 sc' = ai inpat qq env' ds sc in
1967 PPi p n nfc ty' sc'
1968 ai inpat qq env ds (PGoal fc r n sc)
1969 = let r' = ai inpat qq env ds r
1970 sc' = ai inpat qq ((n, Nothing):env) ds sc in
1971 PGoal fc r' n sc'
1972 ai inpat qq env ds (PHidden tm) = PHidden (ai inpat qq env ds tm)
1973 -- Don't do PProof or PTactics since implicits get added when scope is
1974 -- properly known in ElabTerm.runTac
1975 ai inpat qq env ds (PUnifyLog tm) = PUnifyLog (ai inpat qq env ds tm)
1976 ai inpat qq env ds (PNoImplicits tm) = PNoImplicits (ai inpat qq env ds tm)
1977 ai inpat qq env ds (PQuasiquote tm g) = PQuasiquote (ai inpat True env ds tm)
1978 (fmap (ai inpat True env ds) g)
1979 ai inpat qq env ds (PUnquote tm) = PUnquote (ai inpat False env ds tm)
1980 ai inpat qq env ds (PRunElab fc tm ns) = PRunElab fc (ai inpat False env ds tm) ns
1981 ai inpat qq env ds (PConstSugar fc tm) = PConstSugar fc (ai inpat qq env ds tm)
1982 ai inpat qq env ds tm = tm
1984 handleErr (Left err) = PElabError err
1985 handleErr (Right x) = x
1987-- if in a pattern, and there are no arguments, and there's no possible
1988-- names with zero explicit arguments, don't add implicits.
1990aiFn :: Name -> Bool -> Bool -> Bool
1991 -> [Name]
1992 -> IState -> FC
1993 -> Name -- ^ function being applied
1994 -> FC -> [[T.Text]]
1995 -> [PArg] -- ^ initial arguments (if in a pattern)
1996 -> Either Err PTerm
1997aiFn topname inpat True qq imp_meths ist fc f ffc ds []
1998 | inpat && implicitable f && unqualified f = Right $ PPatvar ffc f
1999 | otherwise
2000 = case lookupDef f (tt_ctxt ist) of
2001 [] -> Right $ PPatvar ffc f
2002 alts -> let ialts = lookupCtxtName f (idris_implicits ist) in
2003 -- trace (show f ++ " " ++ show (fc, any (all imp) ialts, ialts, any constructor alts)) $
2004 if (not (vname f) || tcname f
2005 || any (conCaf (tt_ctxt ist)) ialts)
2006-- any constructor alts || any allImp ialts))
2007 then aiFn topname inpat False qq imp_meths ist fc f ffc ds [] -- use it as a constructor
2008 else Right $ PPatvar ffc f
2009 where imp (PExp _ _ _ _) = False
2010 imp _ = True
2011-- allImp [] = False
2012 allImp xs = all imp xs
2014 unqualified (NS _ _) = False
2015 unqualified _ = True
2017 constructor (TyDecl (DCon _ _ _) _) = True
2018 constructor _ = False
2020 conCaf ctxt (n, cia) = (isDConName n ctxt || (qq && isTConName n ctxt)) && allImp cia
2022 vname (UN n) = True -- non qualified
2023 vname _ = False
2025aiFn topname inpat expat qq imp_meths ist fc f ffc ds as
2026 | f `elem` primNames = Right $ PApp fc (PRef ffc [ffc] f) as
2027aiFn topname inpat expat qq imp_meths ist fc f ffc ds as
2028 -- This is where namespaces get resolved by adding PAlternative
2029 = do let ns = lookupCtxtName f (idris_implicits ist)
2030 let nh = filter (\(n, _) -> notHidden n) ns
2031 let ns' = case trimAlts ds nh of
2032 [] -> nh
2033 x -> x
2034 case ns' of
2035 [(f',ns)] -> Right $ mkPApp fc (length ns) (PRef ffc [ffc] (isImpName f f'))
2036 (insertImpl ns as)
2037 [] -> case metaVar f (map fst (idris_metavars ist)) of
2038 Just f' -> Right $ PApp fc (PRef ffc [ffc] f') as
2039 Nothing -> Right $ mkPApp fc (length as) (PRef ffc [ffc] f) as
2040 alts -> Right $
2041 PAlternative [] (ExactlyOne True) $
2042 map (\(f', ns) -> mkPApp fc (length ns) (PRef ffc [ffc] (isImpName f f'))
2043 (insertImpl ns as)) alts
2044 where
2045 -- if the name is in imp_meths, we should actually refer to the bound
2046 -- name rather than the global one after expanding implicits
2047 isImpName f f' | f `elem` imp_meths = f
2048 | otherwise = f'
2050 -- If it's a metavariable name, try to qualify it from the list of
2051 -- unsolved metavariables
2052 metaVar f (mvn : ns) | f == nsroot mvn = Just mvn
2053 metaVar f (_ : ns) = metaVar f ns
2054 metaVar f [] = Nothing
2056 trimAlts [] alts = alts
2057 trimAlts ns alts
2058 = filter (\(x, _) -> any (\d -> d `isPrefixOf` nspace x) ns) alts
2060 nspace (NS _ s) = s
2061 nspace _ = []
2063 notHidden n = case getAccessibility n of
2064 Hidden -> False
2065 Private -> False
2066 _ -> True
2068 getAccessibility n
2069 = case lookupDefAccExact n False (tt_ctxt ist) of
2070 Just (n,t) -> t
2071 _ -> Public
2073 insertImpl :: [PArg] -- ^ expected argument types (from idris_implicits)
2074 -> [PArg] -- ^ given arguments
2075 -> [PArg]
2076 insertImpl ps as
2077 = let (as', badimpls) = partition (impIn ps) as in
2078 map addUnknownImp badimpls ++
2079 insImpAcc M.empty ps (filter expArg as') (filter (not . expArg) as')
2081 insImpAcc :: M.Map Name PTerm -- accumulated param names & arg terms
2082 -> [PArg] -- parameters
2083 -> [PArg] -- explicit arguments
2084 -> [PArg] -- implicits given
2085 -> [PArg]
2086 insImpAcc pnas (PExp p l n ty : ps) (PExp _ _ _ tm : given) imps =
2087 PExp p l n tm : insImpAcc (M.insert n tm pnas) ps given imps
2088 insImpAcc pnas (PConstraint p l n ty : ps) (PConstraint _ _ _ tm : given) imps =
2089 PConstraint p l n tm : insImpAcc (M.insert n tm pnas) ps given imps
2090 insImpAcc pnas (PConstraint p l n ty : ps) given imps =
2091 let rtc = PResolveTC fc in
2092 PConstraint p l n rtc : insImpAcc (M.insert n rtc pnas) ps given imps
2093 insImpAcc pnas (PImp p _ l n ty : ps) given imps =
2094 case find n imps [] of
2095 Just (tm, imps') ->
2096 PImp p False l n tm : insImpAcc (M.insert n tm pnas) ps given imps'
2097 Nothing ->
2098 PImp p True l n Placeholder :
2099 insImpAcc (M.insert n Placeholder pnas) ps given imps
2100 insImpAcc pnas (PTacImplicit p l n sc' ty : ps) given imps =
2101 let sc = addImpl imp_meths ist (substMatches (M.toList pnas) sc') in
2102 case find n imps [] of
2103 Just (tm, imps') ->
2104 PTacImplicit p l n sc tm :
2105 insImpAcc (M.insert n tm pnas) ps given imps'
2106 Nothing ->
2107 if inpat
2108 then PTacImplicit p l n sc Placeholder :
2109 insImpAcc (M.insert n Placeholder pnas) ps given imps
2110 else PTacImplicit p l n sc sc :
2111 insImpAcc (M.insert n sc pnas) ps given imps
2112 insImpAcc _ expected [] imps = map addUnknownImp imps -- so that unused implicits give error
2113 insImpAcc _ _ given imps = given ++ imps
2115 addUnknownImp arg = arg { argopts = UnknownImp : argopts arg }
2117 find n [] acc = Nothing
2118 find n (PImp _ _ _ n' t : gs) acc
2119 | n == n' = Just (t, reverse acc ++ gs)
2120 find n (PTacImplicit _ _ n' _ t : gs) acc
2121 | n == n' = Just (t, reverse acc ++ gs)
2122 find n (g : gs) acc = find n gs (g : acc)
2124-- | return True if the second argument is an implicit argument which
2125-- is expected in the implicits, or if it's not an implicit
2126impIn :: [PArg] -> PArg -> Bool
2127impIn ps (PExp _ _ _ _) = True
2128impIn ps (PConstraint _ _ _ _) = True
2129impIn ps arg = any (\p -> not (expArg arg) && pname arg == pname p) ps
2131expArg (PExp _ _ _ _) = True
2132expArg (PConstraint _ _ _ _) = True
2133expArg _ = False
2135-- replace non-linear occurrences with _
2137stripLinear :: IState -> PTerm -> PTerm
2138stripLinear i tm = evalState (sl tm) [] where
2139 sl :: PTerm -> State [Name] PTerm
2140 sl (PRef fc hl f)
2141 | (_:_) <- lookupTy f (tt_ctxt i)
2142 = return $ PRef fc hl f
2143 | otherwise = do ns <- get
2144 if (f `elem` ns)
2145 then return $ PHidden (PRef fc hl f) -- Placeholder
2146 else do put (f : ns)
2147 return (PRef fc hl f)
2148 sl (PPatvar fc f)
2149 = do ns <- get
2150 if (f `elem` ns)
2151 then return $ PHidden (PPatvar fc f) -- Placeholder
2152 else do put (f : ns)
2153 return (PPatvar fc f)
2154 -- Assumption is that variables are all the same in each alternative
2155 sl t@(PAlternative ms b as) = do ns <- get
2156 as' <- slAlts ns as
2157 return (PAlternative ms b as')
2158 where slAlts ns (a : as) = do put ns
2159 a' <- sl a
2160 as' <- slAlts ns as
2161 return (a' : as')
2162 slAlts ns [] = return []
2163 sl (PPair fc hls p l r) = do l' <- sl l; r' <- sl r; return (PPair fc hls p l' r')
2164 sl (PDPair fc hls p l t r) = do l' <- sl l
2165 t' <- sl t
2166 r' <- sl r
2167 return (PDPair fc hls p l' t' r')
2168 sl (PApp fc fn args) = do fn' <- case fn of
2169 -- Just the args, fn isn't matchable as a var
2170 PRef _ _ _ -> return fn
2171 t -> sl t
2172 args' <- mapM slA args
2173 return $ PApp fc fn' args'
2174 where slA (PImp p m l n t) = do t' <- sl t
2175 return $ PImp p m l n t'
2176 slA (PExp p l n t) = do t' <- sl t
2177 return $ PExp p l n t'
2178 slA (PConstraint p l n t)
2179 = do t' <- sl t
2180 return $ PConstraint p l n t'
2181 slA (PTacImplicit p l n sc t)
2182 = do t' <- sl t
2183 return $ PTacImplicit p l n sc t'
2184 sl x = return x
2186-- | Remove functions which aren't applied to anything, which must then
2187-- be resolved by unification. Assume names resolved and alternatives
2188-- filled in (so no ambiguity).
2189stripUnmatchable :: IState -> PTerm -> PTerm
2190stripUnmatchable i (PApp fc fn args) = PApp fc fn (fmap (fmap su) args) where
2191 su :: PTerm -> PTerm
2192 su tm@(PRef fc hl f)
2193 | (Bind n (Pi _ _ t _) sc :_) <- lookupTy f (tt_ctxt i)
2194 = Placeholder
2195 | (TType _ : _) <- lookupTy f (tt_ctxt i),
2196 not (implicitable f)
2197 = PHidden tm
2198 | (UType _ : _) <- lookupTy f (tt_ctxt i),
2199 not (implicitable f)
2200 = PHidden tm
2201 su (PApp fc f@(PRef _ _ fn) args)
2202 -- here we use canBeDConName because the impossible pattern
2203 -- check will not necessarily fully resolve constructor names,
2204 -- and these bare names will otherwise get in the way of
2205 -- impossbility checking.
2206 | -- Just fn <- getFn f,
2207 canBeDConName fn ctxt
2208 = PApp fc f (fmap (fmap su) args)
2209 where getFn (PRef _ _ fn) = Just fn
2210 getFn (PApp _ f args) = getFn f
2211 getFn _ = Nothing
2212 su (PApp fc f args)
2213 = PHidden (PApp fc f args)
2214 su (PAlternative ms b alts)
2215 = let alts' = filter (/= Placeholder) (map su alts) in
2216 if null alts' then Placeholder
2217 else liftHidden $ PAlternative ms b alts'
2218 su (PPair fc hls p l r) = PPair fc hls p (su l) (su r)
2219 su (PDPair fc hls p l t r) = PDPair fc hls p (su l) (su t) (su r)
2220 su t@(PLam fc _ _ _ _) = PHidden t
2221 su t@(PPi _ _ _ _ _) = PHidden t
2222 su t@(PConstant _ c) | isTypeConst c = PHidden t
2223 su t = t
2225 ctxt = tt_ctxt i
2227 -- If the ambiguous terms are all hidden, the PHidden needs to be outside
2228 -- because elaboration of PHidden gets delayed, and we need the elaboration
2229 -- to resolve the ambiguity.
2230 liftHidden tm@(PAlternative ms b as)
2231 | allHidden as = PHidden (PAlternative ms b (map unHide as))
2232 | otherwise = tm
2234 allHidden [] = True
2235 allHidden (PHidden _ : xs) = allHidden xs
2236 allHidden (x : xs) = False
2238 unHide (PHidden t) = t
2239 unHide t = t
2241stripUnmatchable i tm = tm
2243mkPApp fc a f [] = f
2244mkPApp fc a f as = let rest = drop a as in
2245 if a == 0 then appRest fc f rest
2246 else appRest fc (PApp fc f (take a as)) rest
2247 where
2248 appRest fc f [] = f
2249 appRest fc f (a : as) = appRest fc (PApp fc f [a]) as
2253-- | Find 'static' argument positions
2254-- (the declared ones, plus any names in argument position in the declared
2255-- statics)
2256-- FIXME: It's possible that this really has to happen after elaboration
2257findStatics :: IState -> PTerm -> (PTerm, [Bool])
2258findStatics ist tm = let (ns, ss) = fs tm
2259 in runState (pos ns ss tm) []
2260 where fs (PPi p n fc t sc)
2261 | Static <- pstatic p
2262 = let (ns, ss) = fs sc in
2263 (namesIn [] ist t : ns, n : ss)
2264 | otherwise = let (ns, ss) = fs sc in
2265 (ns, ss)
2266 fs _ = ([], [])
2268 inOne n ns = length (filter id (map (elem n) ns)) == 1
2270 pos ns ss (PPi p n fc t sc)
2271 | elem n ss = do sc' <- pos ns ss sc
2272 spos <- get
2273 put (True : spos)
2274 return (PPi (p { pstatic = Static }) n fc t sc')
2275 | otherwise = do sc' <- pos ns ss sc
2276 spos <- get
2277 put (False : spos)
2278 return (PPi p n fc t sc')
2279 pos ns ss t = return t
2281-- for 6.12/7 compatibility
2282data EitherErr a b = LeftErr a | RightOK b deriving ( Functor )
2284instance Applicative (EitherErr a) where
2285 pure = return
2286 (<*>) = ap
2288instance Monad (EitherErr a) where
2289 return = RightOK
2291 (LeftErr e) >>= _ = LeftErr e
2292 RightOK v >>= k = k v
2294toEither :: EitherErr a b -> Either a b
2295toEither (LeftErr e) = Left e
2296toEither (RightOK ho) = Right ho
2298-- | Syntactic match of a against b, returning pair of variables in a
2299-- and what they match. Returns the pair that failed if not a match.
2300matchClause :: IState -> PTerm -> PTerm -> Either (PTerm, PTerm) [(Name, PTerm)]
2301matchClause = matchClause' False
2303matchClause' :: Bool -> IState -> PTerm -> PTerm -> Either (PTerm, PTerm) [(Name, PTerm)]
2304matchClause' names i x y = checkRpts $ match (fullApp x) (fullApp y) where
2305 matchArg x y = match (fullApp (getTm x)) (fullApp (getTm y))
2307 fullApp (PApp _ (PApp fc f args) xs) = fullApp (PApp fc f (args ++ xs))
2308 fullApp x = x
2310 match' x y = match (fullApp x) (fullApp y)
2311 match (PApp _ (PRef _ _ (NS (UN fi) [b])) [_,_,x]) x'
2312 | fi == txt "fromInteger" && b == txt "builtins",
2313 PConstant _ (I _) <- getTm x = match (getTm x) x'
2314 match x' (PApp _ (PRef _ _ (NS (UN fi) [b])) [_,_,x])
2315 | fi == txt "fromInteger" && b == txt "builtins",
2316 PConstant _ (I _) <- getTm x = match (getTm x) x'
2317 match (PApp _ (PRef _ _ (UN l)) [_,x]) x' | l == txt "lazy" = match (getTm x) x'
2318 match x (PApp _ (PRef _ _ (UN l)) [_,x']) | l == txt "lazy" = match x (getTm x')
2319 match (PApp _ f args) (PApp _ f' args')
2320 | length args == length args'
2321 = do mf <- match' f f'
2322 ms <- zipWithM matchArg args args'
2323 return (mf ++ concat ms)
2324 match (PRef f hl n) (PApp _ x []) = match (PRef f hl n) x
2325 match (PPatvar f n) xr = match (PRef f [f] n) xr
2326 match xr (PPatvar f n) = match xr (PRef f [f] n)
2327 match (PApp _ x []) (PRef f hl n) = match x (PRef f hl n)
2328 match (PRef _ _ n) tm@(PRef _ _ n')
2329 | n == n' && not names &&
2330 (not (isConName n (tt_ctxt i) || isFnName n (tt_ctxt i))
2331 || tm == Placeholder)
2332 = return [(n, tm)]
2333 -- if one namespace is missing, drop the other
2334 | n == n' || n == dropNS n' || dropNS n == n' = return []
2335 where dropNS (NS n _) = n
2336 dropNS n = n
2337 match (PRef _ _ n) tm
2338 | not names && (not (isConName n (tt_ctxt i) ||
2339 isFnName n (tt_ctxt i)) || tm == Placeholder)
2340 = return [(n, tm)]
2341 match (PRewrite _ by l r _) (PRewrite _ by' l' r' _) | by == by'
2342 = do ml <- match' l l'
2343 mr <- match' r r'
2344 return (ml ++ mr)
2345 match (PTyped l r) (PTyped l' r') = do ml <- match l l'
2346 mr <- match r r'
2347 return (ml ++ mr)
2348 match (PTyped l r) x = match l x
2349 match x (PTyped l r) = match x l
2350 match (PPair _ _ _ l r) (PPair _ _ _ l' r') = do ml <- match' l l'
2351 mr <- match' r r'
2352 return (ml ++ mr)
2353 match (PDPair _ _ _ l t r) (PDPair _ _ _ l' t' r') = do ml <- match' l l'
2354 mt <- match' t t'
2355 mr <- match' r r'
2356 return (ml ++ mt ++ mr)
2357 match (PAlternative _ a as) (PAlternative _ a' as')
2358 = do ms <- zipWithM match' as as'
2359 return (concat ms)
2360 match a@(PAlternative _ _ as) b
2361 = do let ms = zipWith match' as (repeat b)
2362 case (rights (map toEither ms)) of
2363 (x: _) -> return x
2364 _ -> LeftErr (a, b)
2365 match (PCase _ _ _) _ = return [] -- lifted out
2366 match (PMetavar _ _) _ = return [] -- modified
2367 match (PInferRef _ _ _) _ = return [] -- modified
2368 match (PQuote _) _ = return []
2369 match (PProof _) _ = return []
2370 match (PTactics _) _ = return []
2371 match (PResolveTC _) (PResolveTC _) = return []
2372 match (PTrue _ _) (PTrue _ _) = return []
2373 match (PPi _ _ _ t s) (PPi _ _ _ t' s') = do mt <- match' t t'
2374 ms <- match' s s'
2375 return (mt ++ ms)
2376 match (PLam _ _ _ t s) (PLam _ _ _ t' s') = do mt <- match' t t'
2377 ms <- match' s s'
2378 return (mt ++ ms)
2379 match (PLet _ _ _ t ty s) (PLet _ _ _ t' ty' s') = do mt <- match' t t'
2380 mty <- match' ty ty'
2381 ms <- match' s s'
2382 return (mt ++ mty ++ ms)
2383 match (PHidden x) (PHidden y)
2384 | RightOK xs <- match x y = return xs -- to collect variables
2385 | otherwise = return [] -- Otherwise hidden things are unmatchable
2386 match (PHidden x) y
2387 | RightOK xs <- match x y = return xs
2388 | otherwise = return []
2389 match x (PHidden y)
2390 | RightOK xs <- match x y = return xs
2391 | otherwise = return []
2392 match (PUnifyLog x) y = match' x y
2393 match x (PUnifyLog y) = match' x y
2394 match (PNoImplicits x) y = match' x y
2395 match x (PNoImplicits y) = match' x y
2396 match Placeholder _ = return []
2397 match _ Placeholder = return []
2398 match (PResolveTC _) _ = return []
2399 match a b | a == b = return []
2400 | otherwise = LeftErr (a, b)
2402 checkRpts (RightOK ms) = check ms where
2403 check ((n,t):xs)
2404 | Just t' <- lookup n xs = if t/=t' && t/=Placeholder && t'/=Placeholder
2405 then Left (t, t')
2406 else check xs
2407 check (_:xs) = check xs
2408 check [] = Right ms
2409 checkRpts (LeftErr x) = Left x
2411substMatches :: [(Name, PTerm)] -> PTerm -> PTerm
2412substMatches ms = substMatchesShadow ms []
2414-- substMatchesShadow :: [(Name, PTerm)] -> [Name] -> PTerm -> PTerm
2415-- substMatchesShadow [] shs t = t
2416-- substMatchesShadow ((n,tm):ns) shs t
2417-- = substMatchShadow n shs tm (substMatchesShadow ns shs t)
2419substMatch :: Name -> PTerm -> PTerm -> PTerm
2420substMatch n = substMatchShadow n []
2422substMatchShadow :: Name -> [Name] -> PTerm -> PTerm -> PTerm
2423substMatchShadow n shs tm t = substMatchesShadow [(n, tm)] shs t
2425substMatchesShadow :: [(Name, PTerm)] -> [Name] -> PTerm -> PTerm
2426substMatchesShadow nmap shs t = sm shs t where
2427 sm xs (PRef _ _ n) | Just tm <- lookup n nmap = tm
2428 sm xs (PLam fc x xfc t sc) = PLam fc x xfc (sm xs t) (sm xs sc)
2429 sm xs (PPi p x fc t sc)
2430 | x `elem` xs
2431 = let x' = nextName x in
2432 PPi p x' fc (sm (x':xs) (substMatch x (PRef emptyFC [] x') t))
2433 (sm (x':xs) (substMatch x (PRef emptyFC [] x') sc))
2434 | otherwise = PPi p x fc (sm xs t) (sm (x : xs) sc)
2435 sm xs (PLet fc x xfc val t sc)
2436 = PLet fc x xfc (sm xs val) (sm xs t) (sm xs sc)
2437 sm xs (PApp f x as) = fullApp $ PApp f (sm xs x) (map (fmap (sm xs)) as)
2438 sm xs (PCase f x as) = PCase f (sm xs x) (map (pmap (sm xs)) as)
2439 sm xs (PIfThenElse fc c t f) = PIfThenElse fc (sm xs c) (sm xs t) (sm xs f)
2440 sm xs (PRewrite f by x y tm) = PRewrite f by (sm xs x) (sm xs y)
2441 (fmap (sm xs) tm)
2442 sm xs (PTyped x y) = PTyped (sm xs x) (sm xs y)
2443 sm xs (PPair f hls p x y) = PPair f hls p (sm xs x) (sm xs y)
2444 sm xs (PDPair f hls p x t y) = PDPair f hls p (sm xs x) (sm xs t) (sm xs y)
2445 sm xs (PAlternative ms a as) = PAlternative ms a (map (sm xs) as)
2446 sm xs (PHidden x) = PHidden (sm xs x)
2447 sm xs (PUnifyLog x) = PUnifyLog (sm xs x)
2448 sm xs (PNoImplicits x) = PNoImplicits (sm xs x)
2449 sm xs (PRunElab fc script ns) = PRunElab fc (sm xs script) ns
2450 sm xs (PConstSugar fc tm) = PConstSugar fc (sm xs tm)
2451 sm xs x = x
2453 fullApp (PApp _ (PApp fc f args) xs) = fullApp (PApp fc f (args ++ xs))
2454 fullApp x = x
2456shadow :: Name -> Name -> PTerm -> PTerm
2457shadow n n' t = sm 0 t where
2458 sm 0 (PRef fc hl x) | n == x = PRef fc hl n'
2459 sm 0 (PLam fc x xfc t sc) | n /= x = PLam fc x xfc (sm 0 t) (sm 0 sc)
2460 | otherwise = PLam fc x xfc (sm 0 t) sc
2461 sm 0 (PPi p x fc t sc) | n /= x = PPi p x fc (sm 0 t) (sm 0 sc)
2462 | otherwise = PPi p x fc (sm 0 t) sc
2463 sm 0 (PLet fc x xfc t v sc) | n /= x = PLet fc x xfc (sm 0 t) (sm 0 v) (sm 0 sc)
2464 | otherwise = PLet fc x xfc (sm 0 t) (sm 0 v) sc
2465 sm 0 (PApp f x as) = PApp f (sm 0 x) (map (fmap (sm 0)) as)
2466 sm 0 (PAppBind f x as) = PAppBind f (sm 0 x) (map (fmap (sm 0)) as)
2467 sm 0 (PCase f x as) = PCase f (sm 0 x) (map (pmap (sm 0)) as)
2468 sm 0 (PIfThenElse fc c t f) = PIfThenElse fc (sm 0 c) (sm 0 t) (sm 0 f)
2469 sm 0 (PRewrite f by x y tm) = PRewrite f by (sm 0 x) (sm 0 y) (fmap (sm 0) tm)
2470 sm 0 (PTyped x y) = PTyped (sm 0 x) (sm 0 y)
2471 sm 0 (PPair f hls p x y) = PPair f hls p (sm 0 x) (sm 0 y)
2472 sm 0 (PDPair f hls p x t y) = PDPair f hls p (sm 0 x) (sm 0 t) (sm 0 y)
2473 sm 0 (PAlternative ms a as)
2474 = PAlternative (map shadowAlt ms) a (map (sm 0) as)
2475 sm 0 (PTactics ts) = PTactics (map (fmap (sm 0)) ts)
2476 sm 0 (PProof ts) = PProof (map (fmap (sm 0)) ts)
2477 sm 0 (PHidden x) = PHidden (sm 0 x)
2478 sm 0 (PUnifyLog x) = PUnifyLog (sm 0 x)
2479 sm 0 (PNoImplicits x) = PNoImplicits (sm 0 x)
2480 sm 0 (PCoerced t) = PCoerced (sm 0 t)
2481 sm ql (PQuasiquote tm ty) = PQuasiquote (sm (ql + 1) tm) (fmap (sm ql) ty)
2482 sm ql (PUnquote tm) = PUnquote (sm (ql - 1) tm)
2483 sm ql x = descend (sm ql) x
2485 shadowAlt p@(x, oldn) = (update x, update oldn)
2486 update oldn | n == oldn = n'
2487 | otherwise = oldn
2489-- | Rename any binders which are repeated (so that we don't have to
2490-- mess about with shadowing anywhere else).
2491mkUniqueNames :: [Name] -> [(Name, Name)] -> PTerm -> PTerm
2492mkUniqueNames env shadows tm
2493 = evalState (mkUniq 0 initMap tm) (S.fromList env) where
2495 initMap = M.fromList shadows
2497 inScope :: S.Set Name
2498 inScope = S.fromList $ boundNamesIn tm
2500 mkUniqA ql nmap arg = do t' <- mkUniq ql nmap (getTm arg)
2501 return (arg { getTm = t' })
2503 -- Initialise the unique name with the environment length (so we're not
2504 -- looking for too long...)
2505 initN (UN n) l = UN $ txt (str n ++ show l)
2506 initN (MN i s) l = MN (i+l) s
2507 initN n _ = n
2509 -- FIXME: Probably ought to do this for completeness! It's fine as
2510 -- long as there are no bindings inside tactics though.
2511 mkUniqT _ nmap tac = return tac
2513 mkUniq :: Int -- ^ The number of quotations that we're under
2514 -> M.Map Name Name -> PTerm -> State (S.Set Name) PTerm
2515 mkUniq 0 nmap (PLam fc n nfc ty sc)
2516 = do env <- get
2517 (n', sc') <-
2518 if n `S.member` env
2519 then do let n' = uniqueNameSet (initN n (S.size env))
2520 (S.union env inScope)
2521 return (n', sc) -- shadow n n' sc)
2522 else return (n, sc)
2523 put (S.insert n' env)
2524 let nmap' = M.insert n n' nmap
2525 ty' <- mkUniq 0 nmap ty
2526 sc'' <- mkUniq 0 nmap' sc'
2527 return $! PLam fc n' nfc ty' sc''
2528 mkUniq 0 nmap (PPi p n fc ty sc)
2529 = do env <- get
2530 (n', sc') <-
2531 if n `S.member` env
2532 then do let n' = uniqueNameSet (initN n (S.size env))
2533 (S.union env inScope)
2534 return (n', sc) -- shadow n n' sc)
2535 else return (n, sc)
2536 put (S.insert n' env)
2537 let nmap' = M.insert n n' nmap
2538 ty' <- mkUniq 0 nmap ty
2539 sc'' <- mkUniq 0 nmap' sc'
2540 return $! PPi p n' fc ty' sc''
2541 mkUniq 0 nmap (PLet fc n nfc ty val sc)
2542 = do env <- get
2543 (n', sc') <-
2544 if n `S.member` env
2545 then do let n' = uniqueNameSet (initN n (S.size env))
2546 (S.union env inScope)
2547 return (n', sc) -- shadow n n' sc)
2548 else return (n, sc)
2549 put (S.insert n' env)
2550 let nmap' = M.insert n n' nmap
2551 ty' <- mkUniq 0 nmap ty; val' <- mkUniq 0 nmap val
2552 sc'' <- mkUniq 0 nmap' sc'
2553 return $! PLet fc n' nfc ty' val' sc''
2554 mkUniq 0 nmap (PApp fc t args)
2555 = do t' <- mkUniq 0 nmap t
2556 args' <- mapM (mkUniqA 0 nmap) args
2557 return $! PApp fc t' args'
2558 mkUniq 0 nmap (PAppBind fc t args)
2559 = do t' <- mkUniq 0 nmap t
2560 args' <- mapM (mkUniqA 0 nmap) args
2561 return $! PAppBind fc t' args'
2562 mkUniq 0 nmap (PCase fc t alts)
2563 = do t' <- mkUniq 0 nmap t
2564 alts' <- mapM (\(x,y)-> do x' <- mkUniq 0 nmap x; y' <- mkUniq 0 nmap y
2565 return (x', y')) alts
2566 return $! PCase fc t' alts'
2567 mkUniq 0 nmap (PIfThenElse fc c t f)
2568 = liftM3 (PIfThenElse fc) (mkUniq 0 nmap c) (mkUniq 0 nmap t) (mkUniq 0 nmap f)
2569 mkUniq 0 nmap (PPair fc hls p l r)
2570 = do l' <- mkUniq 0 nmap l; r' <- mkUniq 0 nmap r
2571 return $! PPair fc hls p l' r'
2572 mkUniq 0 nmap (PDPair fc hls p (PRef fc' hls' n) t sc)
2573 | t /= Placeholder
2574 = do env <- get
2575 (n', sc') <- if n `S.member` env
2576 then do let n' = uniqueNameSet n (S.union env inScope)
2577 return (n', sc) -- shadow n n' sc)
2578 else return (n, sc)
2579 put (S.insert n' env)
2580 let nmap' = M.insert n n' nmap
2581 t' <- mkUniq 0 nmap t
2582 sc'' <- mkUniq 0 nmap' sc'
2583 return $! PDPair fc hls p (PRef fc' hls' n') t' sc''
2584 mkUniq 0 nmap (PDPair fc hls p l t r)
2585 = do l' <- mkUniq 0 nmap l; t' <- mkUniq 0 nmap t; r' <- mkUniq 0 nmap r
2586 return $! PDPair fc hls p l' t' r'
2587 mkUniq 0 nmap (PAlternative ns b as)
2588 -- store the nmap and defer the rest until we've pruned the set
2589 -- during elaboration
2590 = return $ PAlternative (ns ++ M.toList nmap) b as
2591 mkUniq 0 nmap (PHidden t) = liftM PHidden (mkUniq 0 nmap t)
2592 mkUniq 0 nmap (PUnifyLog t) = liftM PUnifyLog (mkUniq 0 nmap t)
2593 mkUniq 0 nmap (PDisamb n t) = liftM (PDisamb n) (mkUniq 0 nmap t)
2594 mkUniq 0 nmap (PNoImplicits t) = liftM PNoImplicits (mkUniq 0 nmap t)
2595 mkUniq 0 nmap (PProof ts) = liftM PProof (mapM (mkUniqT 0 nmap) ts)
2596 mkUniq 0 nmap (PTactics ts) = liftM PTactics (mapM (mkUniqT 0 nmap) ts)
2597 mkUniq 0 nmap (PRunElab fc ts ns) = liftM (\tm -> PRunElab fc tm ns) (mkUniq 0 nmap ts)
2598 mkUniq 0 nmap (PConstSugar fc tm) = liftM (PConstSugar fc) (mkUniq 0 nmap tm)
2599 mkUniq 0 nmap (PCoerced tm) = liftM PCoerced (mkUniq 0 nmap tm)
2600 mkUniq 0 nmap t = return $ shadowAll (M.toList nmap) t
2601 where
2602 shadowAll [] t = t
2603 shadowAll ((n, n') : ns) t = shadow n n' (shadowAll ns t)
2605 mkUniq ql nmap (PQuasiquote tm ty) =
2606 do tm' <- mkUniq (ql + 1) nmap tm
2607 ty' <- case ty of
2608 Nothing -> return Nothing
2609 Just t -> fmap Just $ mkUniq ql nmap t
2610 return $! PQuasiquote tm' ty'
2611 mkUniq ql nmap (PUnquote tm) = fmap PUnquote (mkUniq (ql - 1) nmap tm)
2613 mkUniq ql nmap tm = descendM (mkUniq ql nmap) tm