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