1{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, DeriveFunctor,
2 TypeSynonymInstances, PatternGuards #-}
4module Idris.AbsSyntax(module Idris.AbsSyntax, module Idris.AbsSyntaxTree) where
7import Idris.Core.Evaluate
8import Idris.Core.Elaborate hiding (Tactic(..))
9import Idris.Core.Typecheck
10import Idris.AbsSyntaxTree
12import Idris.Docstrings
13import Idris.IdeMode hiding (Opt(..))
14import IRTS.CodegenCommon
15import Util.DynamicLinker
17import System.Console.Haskeline
19import System.Directory (canonicalizePath, doesFileExist)
21import Control.Applicative
22import Control.Monad (liftM3)
23import Control.Monad.State
25import Data.List hiding (insert,union)
27import qualified Data.Text as T
29import qualified Data.Map as M
31import qualified Data.Set as S
32import Data.Word (Word)
36import System.IO.Error(isUserError, ioeGetErrorString, tryIOError)
42getContext :: Idris Context
43getContext = do i <- getIState; return (tt_ctxt i)
45forCodegen :: Codegen -> [(Codegen, a)] -> [a]
46forCodegen tgt xs = [x | (tgt', x) <- xs, tgt == tgt']
48getObjectFiles :: Codegen -> Idris [FilePath]
49getObjectFiles tgt = do i <- getIState; return (forCodegen tgt $ idris_objs i)
51addObjectFile :: Codegen -> FilePath -> Idris ()
52addObjectFile tgt f = do i <- getIState; putIState $ i { idris_objs = nub $ (tgt, f) : idris_objs i }
54getLibs :: Codegen -> Idris [String]
55getLibs tgt = do i <- getIState; return (forCodegen tgt $ idris_libs i)
57addLib :: Codegen -> String -> Idris ()
58addLib tgt f = do i <- getIState; putIState $ i { idris_libs = nub $ (tgt, f) : idris_libs i }
60getFlags :: Codegen -> Idris [String]
61getFlags tgt = do i <- getIState; return (forCodegen tgt $ idris_cgflags i)
63addFlag :: Codegen -> String -> Idris ()
64addFlag tgt f = do i <- getIState; putIState $ i { idris_cgflags = nub $ (tgt, f) : idris_cgflags i }
66addDyLib :: [String] -> Idris (Either DynamicLib String)
67addDyLib libs = do i <- getIState
68 let ls = idris_dynamic_libs i
69 let importdirs = opt_importdirs (idris_options i)
70 case mapMaybe (findDyLib ls) libs of
71 x:_ -> return (Left x)
73 handle <- lift . lift .
74 mapM (\l -> catchIO (tryLoadLib importdirs l)
75 (\_ -> return Nothing)) $ libs
77 Nothing -> return (Right $ "Could not load dynamic alternatives \"" ++
78 concat (intersperse "," libs) ++ "\"")
79 Just x -> do putIState $ i { idris_dynamic_libs = x:ls }
81 where findDyLib :: [DynamicLib] -> String -> Maybe DynamicLib
82 findDyLib [] l = Nothing
83 findDyLib (lib:libs) l | l == lib_name lib = Just lib
84 | otherwise = findDyLib libs l
86getAutoImports :: Idris [FilePath]
87getAutoImports = do i <- getIState
88 return (opt_autoImport (idris_options i))
90addAutoImport :: FilePath -> Idris ()
91addAutoImport fp = do i <- getIState
92 let opts = idris_options i
93 let autoimps = opt_autoImport opts
94 put (i { idris_options = opts { opt_autoImport =
95 fp : opt_autoImport opts } } )
97addHdr :: Codegen -> String -> Idris ()
98addHdr tgt f = do i <- getIState; putIState $ i { idris_hdrs = nub $ (tgt, f) : idris_hdrs i }
100addImported :: Bool -> FilePath -> Idris ()
103 putIState $ i { idris_imported = nub $ (f, pub) : idris_imported i }
105addLangExt :: LanguageExt -> Idris ()
106addLangExt TypeProviders = do i <- getIState
108 idris_language_extensions = TypeProviders : idris_language_extensions i
110addLangExt ErrorReflection = do i <- getIState
112 idris_language_extensions = ErrorReflection : idris_language_extensions i
115-- Transforms are organised by the function being applied on the lhs of the
116-- transform, to make looking up appropriate transforms quicker
117addTrans :: Name -> (Term, Term) -> Idris ()
120 let t' = case lookupCtxtExact basefn (idris_transforms i) of
121 Just def -> (t : def)
123 putIState $ i { idris_transforms = addDef basefn t'
124 (idris_transforms i) }
126addErrRev :: (Term, Term) -> Idris ()
127addErrRev t = do i <- getIState
128 putIState $ i { idris_errRev = t : idris_errRev i }
130addErasureUsage :: Name -> Int -> Idris ()
131addErasureUsage n i = do ist <- getIState
132 putIState $ ist { idris_erasureUsed = (n, i) : idris_erasureUsed ist }
134addExport :: Name -> Idris ()
135addExport n = do ist <- getIState
136 putIState $ ist { idris_exports = n : idris_exports ist }
138addUsedName :: FC -> Name -> Name -> Idris ()
140 = do ist <- getIState
141 case lookupTyName n (tt_ctxt ist) of
142 [(n', ty)] -> addUsage n' 0 ty
143 [] -> throwError (At fc (NoSuchVariable n))
144 xs -> throwError (At fc (CantResolveAlts (map fst xs)))
145 where addUsage n i (Bind x _ sc) | x == arg = do addIBC (IBCUsage (n, i))
147 | otherwise = addUsage n (i + 1) sc
148 addUsage _ _ _ = throwError (At fc (Msg ("No such argument name " ++ show arg)))
150getErasureUsage :: Idris [(Name, Int)]
151getErasureUsage = do ist <- getIState;
152 return (idris_erasureUsed ist)
154getExports :: Idris [Name]
155getExports = do ist <- getIState
156 return (idris_exports ist)
158totcheck :: (FC, Name) -> Idris ()
159totcheck n = do i <- getIState; putIState $ i { idris_totcheck = idris_totcheck i ++ [n] }
161defer_totcheck :: (FC, Name) -> Idris ()
164 putIState $ i { idris_defertotcheck = nub (idris_defertotcheck i ++ [n]) }
166clear_totcheck :: Idris ()
167clear_totcheck = do i <- getIState; putIState $ i { idris_totcheck = [] }
169setFlags :: Name -> [FnOpt] -> Idris ()
170setFlags n fs = do i <- getIState; putIState $ i { idris_flags = addDef n fs (idris_flags i) }
172setFnInfo :: Name -> FnInfo -> Idris ()
173setFnInfo n fs = do i <- getIState; putIState $ i { idris_fninfo = addDef n fs (idris_fninfo i) }
175setAccessibility :: Name -> Accessibility -> Idris ()
178 let ctxt = setAccess n a (tt_ctxt i)
179 putIState $ i { tt_ctxt = ctxt }
181setTotality :: Name -> Totality -> Idris ()
184 let ctxt = setTotal n a (tt_ctxt i)
185 putIState $ i { tt_ctxt = ctxt }
187getTotality :: Name -> Idris Totality
190 case lookupTotal n (tt_ctxt i) of
192 _ -> return (Total [])
194-- Get coercions which might return the required type
195getCoercionsTo :: IState -> Type -> [Name]
197 let cs = idris_coercions i
198 (fn,_) = unApply (getRetTy ty) in
200 where findCoercions t [] = []
201 findCoercions t (n : ns) =
202 let ps = case lookupTy n (tt_ctxt i) of
203 [ty'] -> case unApply (getRetTy (normalise (tt_ctxt i) [] ty')) of
205 if t == t' then [n] else []
207 ps ++ findCoercions t ns
209addToCG :: Name -> CGInfo -> Idris ()
212 putIState $ i { idris_callgraph = addDef n cg (idris_callgraph i) }
214addTyInferred :: Name -> Idris ()
217 putIState $ i { idris_tyinfodata =
218 addDef n TIPartial (idris_tyinfodata i) }
220addTyInfConstraints :: FC -> [(Term, Term)] -> Idris ()
221addTyInfConstraints fc ts = do logLvl 2 $ "TI missing: " ++ show ts
222 mapM_ addConstraint ts
224 where addConstraint (x, y) = findMVApps x y
227 = do let (fx, argsx) = unApply x
228 let (fy, argsy) = unApply y
233 else mapM_ addConstraint (zip argsx argsy)
235 tryAddMV (P _ mv _) y =
237 case lookup mv (idris_metavars ist) of
238 Just _ -> addConstraintRule mv y
240 tryAddMV _ _ = return ()
242 addConstraintRule :: Name -> Term -> Idris ()
243 addConstraintRule n t
245 logLvl 1 $ "TI constraint: " ++ show (n, t)
246 case lookupCtxt n (idris_tyinfodata ist) of
248 do mapM_ (checkConsistent t) ts
249 let ti' = addDef n (TISolution (t : ts))
250 (idris_tyinfodata ist)
251 put $ ist { idris_tyinfodata = ti' }
253 do let ti' = addDef n (TISolution [t])
254 (idris_tyinfodata ist)
255 put $ ist { idris_tyinfodata = ti' }
257 -- Check a solution is consistent with previous solutions
258 -- Meaning: If heads are both data types, they had better be the
260 checkConsistent :: Term -> Term -> Idris ()
261 checkConsistent x y =
262 do let (fx, _) = unApply x
263 let (fy, _) = unApply y
265 (P (TCon _ _) n _, P (TCon _ _) n' _) -> errWhen (n/=n)
266 (P (TCon _ _) n _, Constant _) -> errWhen True
267 (Constant _, P (TCon _ _) n' _) -> errWhen True
268 (P (DCon _ _ _) n _, P (DCon _ _ _) n' _) -> errWhen (n/=n)
273 (CantUnify False (x, Nothing) (y, Nothing) (Msg "") [] 0))
274 errWhen False = return ()
276isTyInferred :: Name -> Idris Bool
279 case lookupCtxt n (idris_tyinfodata i) of
280 [TIPartial] -> return True
283-- | Adds error handlers for a particular function and argument. If names are
284-- ambiguous, all matching handlers are updated.
285addFunctionErrorHandlers :: Name -> Name -> [Name] -> Idris ()
286addFunctionErrorHandlers f arg hs =
288 let oldHandlers = idris_function_errorhandlers i
289 let newHandlers = flip (addDef f) oldHandlers $
290 case lookupCtxtExact f oldHandlers of
291 Nothing -> M.singleton arg (S.fromList hs)
292 Just (oldHandlers) -> M.insertWith S.union arg (S.fromList hs) oldHandlers
293 -- will always be one of those two, thus no extra case
294 putIState $ i { idris_function_errorhandlers = newHandlers }
296getFunctionErrorHandlers :: Name -> Name -> Idris [Name]
297getFunctionErrorHandlers f arg = do i <- getIState
298 return . maybe [] S.toList $
299 undefined --lookup arg =<< lookupCtxtExact f (idris_function_errorhandlers i)
302-- Trace all the names in a call graph starting at the given name
303getAllNames :: Name -> Idris [Name]
304getAllNames n = allNames [] n
306allNames :: [Name] -> Name -> Idris [Name]
307allNames ns n | n `elem` ns = return []
308allNames ns n = do i <- getIState
309 case lookupCtxtExact n (idris_callgraph i) of
310 Just ns' -> do more <- mapM (allNames (n:ns)) (map fst (calls ns'))
311 return (nub (n : concat more))
314addCoercion :: Name -> Idris ()
315addCoercion n = do i <- getIState
316 putIState $ i { idris_coercions = nub $ n : idris_coercions i }
318addDocStr :: Name -> Docstring DocTerm -> [(Name, Docstring DocTerm)] -> Idris ()
321 putIState $ i { idris_docstrings = addDef n (doc, args) (idris_docstrings i) }
323addNameHint :: Name -> Name -> Idris ()
326 ty' <- case lookupCtxtName ty (idris_implicits i) of
327 [(tyn, _)] -> return tyn
328 [] -> throwError (NoSuchVariable ty)
329 tyns -> throwError (CantResolveAlts (map fst tyns))
330 let ns' = case lookupCtxt ty' (idris_namehints i) of
333 putIState $ i { idris_namehints = addDef ty' ns' (idris_namehints i) }
335getNameHints :: IState -> Name -> [Name]
336getNameHints i (UN arr) | arr == txt "->" = [sUN "f",sUN "g"]
338 case lookupCtxt n (idris_namehints i) of
342-- Issue #1737 in the Issue Tracker.
343-- https://github.com/idris-lang/Idris-dev/issues/1737
344addToCalledG :: Name -> [Name] -> Idris ()
345addToCalledG n ns = return () -- TODO
347push_estack :: Name -> Bool -> Idris ()
350 putIState (i { elab_stack = (n, inst) : elab_stack i })
352pop_estack :: Idris ()
353pop_estack = do i <- getIState
354 putIState (i { elab_stack = ptail (elab_stack i) })
358-- | Add a class instance function.
360-- Precondition: the instance should have the correct type.
362-- Dodgy hack 1: Put integer instances first in the list so they are
363-- resolved by default.
365-- Dodgy hack 2: put constraint chasers (@@) last
366addInstance :: Bool -- ^ whether the name is an Integer instance
367 -> Bool -- ^ whether to include the instance in instance search
368 -> Name -- ^ the name of the class
369 -> Name -- ^ the name of the instance
371addInstance int res n i
372 = do ist <- getIState
373 case lookupCtxt n (idris_classes ist) of
374 [CI a b c d e ins fds] ->
375 do let cs = addDef n (CI a b c d e (addI i ins) fds) (idris_classes ist)
376 putIState $ ist { idris_classes = cs }
377 _ -> do let cs = addDef n (CI (sMN 0 "none") [] [] [] [] [(i, res)] []) (idris_classes ist)
378 putIState $ ist { idris_classes = cs }
379 where addI, insI :: Name -> [(Name, Bool)] -> [(Name, Bool)]
380 addI i ins | int = (i, res) : ins
381 | chaser n = ins ++ [(i, res)]
382 | otherwise = insI i ins
383 insI i [] = [(i, res)]
384 insI i (n : ns) | chaser (fst n) = (i, res) : n : ns
385 | otherwise = n : insI i ns
388 | ('@':'@':_) <- str nm = True
389 chaser (NS n _) = chaser n
392addClass :: Name -> ClassInfo -> Idris ()
394 = do ist <- getIState
395 let i' = case lookupCtxt n (idris_classes ist) of
396 [c] -> c { class_instances = class_instances i }
398 putIState $ ist { idris_classes = addDef n i' (idris_classes ist) }
400addRecord :: Name -> RecordInfo -> Idris ()
401addRecord n ri = do ist <- getIState
402 putIState $ ist { idris_records = addDef n ri (idris_records ist) }
404addAutoHint :: Name -> Name -> Idris ()
407 case lookupCtxtExact n (idris_autohints ist) of
409 do let hs = addDef n [hint] (idris_autohints ist)
410 putIState $ ist { idris_autohints = hs }
412 do let hs = addDef n (hint : nhints) (idris_autohints ist)
413 putIState $ ist { idris_autohints = hs }
415getAutoHints :: Name -> Idris [Name]
416getAutoHints n = do ist <- getIState
417 case lookupCtxtExact n (idris_autohints ist) of
421addIBC :: IBCWrite -> Idris ()
424 when (notDef (ibc_write i)) $
425 putIState $ i { ibc_write = ibc : ibc_write i }
426 where notDef [] = True
427 notDef (IBCDef n': is) | n == n' = False
428 notDef (_ : is) = notDef is
429addIBC ibc = do i <- getIState; putIState $ i { ibc_write = ibc : ibc_write i }
432clearIBC = do i <- getIState; putIState $ i { ibc_write = [] }
434resetNameIdx :: Idris ()
435resetNameIdx = do i <- getIState
436 put (i { idris_nameIdx = (0, emptyContext) })
438-- Used to preserve sharing of names
439addNameIdx :: Name -> Idris (Int, Name)
440addNameIdx n = do i <- getIState
441 let (i', x) = addNameIdx' i n
445addNameIdx' :: IState -> Name -> (IState, (Int, Name))
447 = let idxs = snd (idris_nameIdx i) in
448 case lookupCtxt n idxs of
450 _ -> let i' = fst (idris_nameIdx i) + 1 in
451 (i { idris_nameIdx = (i', addDef n (i', n) idxs) }, (i', n))
453getSymbol :: Name -> Idris Name
454getSymbol n = do i <- getIState
455 case M.lookup n (idris_symbols i) of
457 Nothing -> do let sym' = M.insert n n (idris_symbols i)
458 put (i { idris_symbols = sym' })
461getHdrs :: Codegen -> Idris [String]
462getHdrs tgt = do i <- getIState; return (forCodegen tgt $ idris_hdrs i)
464getImported :: Idris [(FilePath, Bool)]
465getImported = do i <- getIState; return (idris_imported i)
467setErrSpan :: FC -> Idris ()
468setErrSpan x = do i <- getIState;
470 Nothing -> putIState $ i { errSpan = Just x }
474clearErr = do i <- getIState
475 putIState $ i { errSpan = Nothing }
477getSO :: Idris (Maybe String)
478getSO = do i <- getIState
479 return (compiled_so i)
481setSO :: Maybe String -> Idris ()
482setSO s = do i <- getIState
483 putIState $ (i { compiled_so = s })
485getIState :: Idris IState
488putIState :: IState -> Idris ()
491updateIState :: (IState -> IState) -> Idris ()
492updateIState f = do i <- getIState
495withContext :: (IState -> Ctxt a) -> Name -> b -> (a -> Idris b) -> Idris b
496withContext ctx name dflt action = do
498 case lookupCtxt name (ctx ist) of
502withContext_ :: (IState -> Ctxt a) -> Name -> (a -> Idris ()) -> Idris ()
503withContext_ ctx name action = withContext ctx name () action
505-- | A version of liftIO that puts errors into the exception type of the Idris monad
506runIO :: IO a -> Idris a
507runIO x = liftIO (tryIOError x) >>= either (throwError . Msg . show) return
508-- TODO: create specific Idris exceptions for specific IO errors such as "openFile: does not exist"
510-- Issue #1738 on the issue tracker.
511-- https://github.com/idris-lang/Idris-dev/issues/1738
514getName = do i <- getIState;
515 let idx = idris_name i;
516 putIState $ (i { idris_name = idx + 1 })
519-- InternalApp keeps track of the real function application for making case splits from, not the application the
520-- programmer wrote, which doesn't have the whole context in any case other than top level definitions
521addInternalApp :: FilePath -> Int -> PTerm -> Idris ()
524 -- We canonicalise the path to make "./Test/Module.idr" equal
525 -- to "Test/Module.idr"
526 exists <- runIO $ doesFileExist fp
528 do fp' <- runIO $ canonicalizePath fp
529 putIState (i { idris_lineapps = ((fp', l), t) : idris_lineapps i })
531getInternalApp :: FilePath -> Int -> Idris PTerm
532getInternalApp fp l = do i <- getIState
533 -- We canonicalise the path to make
534 -- "./Test/Module.idr" equal to
536 exists <- runIO $ doesFileExist fp
538 then do fp' <- runIO $ canonicalizePath fp
539 case lookup (fp', l) (idris_lineapps i) of
541 Nothing -> return Placeholder
542 -- TODO: What if it's not there?
543 else return Placeholder
545-- Pattern definitions are only used for coverage checking, so erase them
547clearOrigPats :: Idris ()
548clearOrigPats = do i <- get
549 let ps = idris_patdefs i
550 let ps' = mapCtxt (\ (_,miss) -> ([], miss)) ps
551 put (i { idris_patdefs = ps' })
553-- Erase types from Ps in the context (basically ending up with what's in
554-- the .ibc, which is all we need after all the analysis is done)
555clearPTypes :: Idris ()
556clearPTypes = do i <- get
558 put (i { tt_ctxt = mapDefCtxt pErase ctxt })
559 where pErase (CaseOp c t tys orig tot cds)
560 = CaseOp c t tys orig [] (pErase' cds)
562 pErase' (CaseDefs _ (cs, c) _ rs)
563 = let c' = (cs, fmap pEraseType c) in
566checkUndefined :: FC -> Name -> Idris ()
570 (_:_) -> throwError . Msg $ show fc ++ ":" ++
571 show n ++ " already defined"
574isUndefined :: FC -> Name -> Idris Bool
577 case lookupTyExact n i of
578 Just _ -> return False
581setContext :: Context -> Idris ()
582setContext ctxt = do i <- getIState; putIState $ (i { tt_ctxt = ctxt } )
584updateContext :: (Context -> Context) -> Idris ()
585updateContext f = do i <- getIState; putIState $ (i { tt_ctxt = f (tt_ctxt i) } )
587addConstraints :: FC -> (Int, [UConstraint]) -> Idris ()
588addConstraints fc (v, cs)
591 let ctxt' = ctxt { next_tvar = v }
592 let ics = insertAll (zip cs (repeat fc)) (idris_constraints i)
593 putIState $ i { tt_ctxt = ctxt', idris_constraints = ics }
596 insertAll ((c, fc) : cs) ics
597 = insertAll cs $ S.insert (ConstraintFC c fc) ics
599addDeferred = addDeferred' Ref
600addDeferredTyCon = addDeferred' (TCon 0 0)
602-- | Save information about a name that is not yet defined
603addDeferred' :: NameType
604 -> [(Name, (Int, Maybe Name, Type, [Name], Bool))]
605 -- ^ The Name is the name being made into a metavar,
606 -- the Int is the number of vars that are part of a
607 -- putative proof context, the Maybe Name is the
608 -- top-level function containing the new metavariable,
609 -- the Type is its type, and the Bool is whether :p is
613 = do mapM_ (\(n, (i, _, t, _, _)) -> updateContext (addTyDecl n nt (tidyNames S.empty t))) ns
614 mapM_ (\(n, _) -> when (not (n `elem` primDefs)) $ addIBC (IBCMetavar n)) ns
616 putIState $ i { idris_metavars = map (\(n, (i, top, _, ns, isTopLevel)) -> (n, (top, i, ns, isTopLevel))) ns ++
619 -- 'tidyNames' is to generate user accessible names in case they are
620 -- needed in tactic scripts
621 tidyNames used (Bind (MN i x) b sc)
622 = let n' = uniqueNameSet (UN x) used in
623 Bind n' b $ tidyNames (S.insert n' used) sc
624 tidyNames used (Bind n b sc)
625 = let n' = uniqueNameSet n used in
626 Bind n' b $ tidyNames (S.insert n' used) sc
629solveDeferred :: Name -> Idris ()
630solveDeferred n = do i <- getIState
631 putIState $ i { idris_metavars =
632 filter (\(n', _) -> n/=n')
635 filter (notMV n) (ibc_write i)
637 where notMV n (IBCMetavar n') = not (n == n')
640getUndefined :: Idris [Name]
641getUndefined = do i <- getIState
642 return (map fst (idris_metavars i) \\ primDefs)
644isMetavarName :: Name -> IState -> Bool
646 = case lookupNames n (tt_ctxt ist) of
647 (t:_) -> isJust $ lookup t (idris_metavars ist)
650getWidth :: Idris ConsoleWidth
651getWidth = fmap idris_consolewidth getIState
653setWidth :: ConsoleWidth -> Idris ()
654setWidth w = do ist <- getIState
655 put ist { idris_consolewidth = w }
657setDepth :: Maybe Int -> Idris ()
658setDepth d = do ist <- getIState
659 put ist { idris_options = (idris_options ist) { opt_printdepth = d } }
661typeDescription :: String
662typeDescription = "The type of types"
665type1Doc :: Doc OutputAnnotation
666type1Doc = (annotate (AnnType "Type" "The type of types, one level up") $ text "Type 1")
669isetPrompt :: String -> Idris ()
670isetPrompt p = do i <- getIState
671 case idris_outputmode i of
672 IdeMode n h -> runIO . hPutStrLn h $ convSExp "set-prompt" p n
674-- | Tell clients how much was parsed and loaded
675isetLoadedRegion :: Idris ()
676isetLoadedRegion = do i <- getIState
677 let span = idris_parsedSpan i
680 case idris_outputmode i of
682 runIO . hPutStrLn h $
683 convSExp "set-loaded-region" fc n
686setLogLevel :: Int -> Idris ()
687setLogLevel l = do i <- getIState
688 let opts = idris_options i
689 let opt' = opts { opt_logLevel = l }
690 putIState $ i { idris_options = opt' }
692setCmdLine :: [Opt] -> Idris ()
693setCmdLine opts = do i <- getIState
694 let iopts = idris_options i
695 putIState $ i { idris_options = iopts { opt_cmdline = opts } }
697getCmdLine :: Idris [Opt]
698getCmdLine = do i <- getIState
699 return (opt_cmdline (idris_options i))
701getDumpHighlighting :: Idris Bool
702getDumpHighlighting = do ist <- getIState
703 return (findC (opt_cmdline (idris_options ist)))
704 where findC = elem DumpHighlights
706getDumpDefun :: Idris (Maybe FilePath)
707getDumpDefun = do i <- getIState
708 return $ findC (opt_cmdline (idris_options i))
709 where findC [] = Nothing
710 findC (DumpDefun x : _) = Just x
711 findC (_ : xs) = findC xs
713getDumpCases :: Idris (Maybe FilePath)
714getDumpCases = do i <- getIState
715 return $ findC (opt_cmdline (idris_options i))
716 where findC [] = Nothing
717 findC (DumpCases x : _) = Just x
718 findC (_ : xs) = findC xs
721logLevel = do i <- getIState
722 return (opt_logLevel (idris_options i))
724setErrContext :: Bool -> Idris ()
725setErrContext t = do i <- getIState
726 let opts = idris_options i
727 let opts' = opts { opt_errContext = t }
728 putIState $ i { idris_options = opts' }
730errContext :: Idris Bool
731errContext = do i <- getIState
732 return (opt_errContext (idris_options i))
734getOptimise :: Idris [Optimisation]
735getOptimise = do i <- getIState
736 return (opt_optimise (idris_options i))
738setOptimise :: [Optimisation] -> Idris ()
739setOptimise newopts = do i <- getIState
740 let opts = idris_options i
741 let opts' = opts { opt_optimise = newopts }
742 putIState $ i { idris_options = opts' }
744addOptimise :: Optimisation -> Idris ()
745addOptimise opt = do opts <- getOptimise
746 setOptimise (nub (opt : opts))
748removeOptimise :: Optimisation -> Idris ()
749removeOptimise opt = do opts <- getOptimise
750 setOptimise ((nub opts) \\ [opt])
752-- Set appropriate optimisation set for the given level. We only have
753-- one optimisation that is configurable at the moment, however!
754setOptLevel :: Int -> Idris ()
755setOptLevel n | n <= 0 = setOptimise []
756setOptLevel 1 = setOptimise []
757setOptLevel 2 = setOptimise [PETransform]
758setOptLevel n | n >= 3 = setOptimise [PETransform]
761useREPL = do i <- getIState
762 return (opt_repl (idris_options i))
764setREPL :: Bool -> Idris ()
765setREPL t = do i <- getIState
766 let opts = idris_options i
767 let opt' = opts { opt_repl = t }
768 putIState $ i { idris_options = opt' }
770showOrigErr :: Idris Bool
771showOrigErr = do i <- getIState
772 return (opt_origerr (idris_options i))
774setShowOrigErr :: Bool -> Idris ()
775setShowOrigErr b = do i <- getIState
776 let opts = idris_options i
777 let opt' = opts { opt_origerr = b }
778 putIState $ i { idris_options = opt' }
780setAutoSolve :: Bool -> Idris ()
781setAutoSolve b = do i <- getIState
782 let opts = idris_options i
783 let opt' = opts { opt_autoSolve = b }
784 putIState $ i { idris_options = opt' }
786setNoBanner :: Bool -> Idris ()
787setNoBanner n = do i <- getIState
788 let opts = idris_options i
789 let opt' = opts { opt_nobanner = n }
790 putIState $ i { idris_options = opt' }
792getNoBanner :: Idris Bool
793getNoBanner = do i <- getIState
794 let opts = idris_options i
795 return (opt_nobanner opts)
797setEvalTypes :: Bool -> Idris ()
798setEvalTypes n = do i <- getIState
799 let opts = idris_options i
800 let opt' = opts { opt_evaltypes = n }
801 putIState $ i { idris_options = opt' }
803setQuiet :: Bool -> Idris ()
804setQuiet q = do i <- getIState
805 let opts = idris_options i
806 let opt' = opts { opt_quiet = q }
807 putIState $ i { idris_options = opt' }
809getQuiet :: Idris Bool
810getQuiet = do i <- getIState
811 let opts = idris_options i
812 return (opt_quiet opts)
814setCodegen :: Codegen -> Idris ()
815setCodegen t = do i <- getIState
816 let opts = idris_options i
817 let opt' = opts { opt_codegen = t }
818 putIState $ i { idris_options = opt' }
820codegen :: Idris Codegen
821codegen = do i <- getIState
822 return (opt_codegen (idris_options i))
824setOutputTy :: OutputType -> Idris ()
825setOutputTy t = do i <- getIState
826 let opts = idris_options i
827 let opt' = opts { opt_outputTy = t }
828 putIState $ i { idris_options = opt' }
830outputTy :: Idris OutputType
831outputTy = do i <- getIState
832 return $ opt_outputTy $ idris_options i
834setIdeMode :: Bool -> Handle -> Idris ()
835setIdeMode True h = do i <- getIState
836 putIState $ i { idris_outputmode = IdeMode 0 h
837 , idris_colourRepl = False
839setIdeMode False _ = return ()
841setTargetTriple :: String -> Idris ()
842setTargetTriple t = do i <- getIState
843 let opts = idris_options i
844 opt' = opts { opt_triple = t }
845 putIState $ i { idris_options = opt' }
847targetTriple :: Idris String
848targetTriple = do i <- getIState
849 return (opt_triple (idris_options i))
851setTargetCPU :: String -> Idris ()
852setTargetCPU t = do i <- getIState
853 let opts = idris_options i
854 opt' = opts { opt_cpu = t }
855 putIState $ i { idris_options = opt' }
857targetCPU :: Idris String
858targetCPU = do i <- getIState
859 return (opt_cpu (idris_options i))
862verbose = do i <- getIState
863 -- Quietness overrides verbosity
864 return (not (opt_quiet (idris_options i)) &&
865 opt_verbose (idris_options i))
867setVerbose :: Bool -> Idris ()
868setVerbose t = do i <- getIState
869 let opts = idris_options i
870 let opt' = opts { opt_verbose = t }
871 putIState $ i { idris_options = opt' }
873typeInType :: Idris Bool
874typeInType = do i <- getIState
875 return (opt_typeintype (idris_options i))
877setTypeInType :: Bool -> Idris ()
878setTypeInType t = do i <- getIState
879 let opts = idris_options i
880 let opt' = opts { opt_typeintype = t }
881 putIState $ i { idris_options = opt' }
883coverage :: Idris Bool
884coverage = do i <- getIState
885 return (opt_coverage (idris_options i))
887setCoverage :: Bool -> Idris ()
888setCoverage t = do i <- getIState
889 let opts = idris_options i
890 let opt' = opts { opt_coverage = t }
891 putIState $ i { idris_options = opt' }
893setIBCSubDir :: FilePath -> Idris ()
894setIBCSubDir fp = do i <- getIState
895 let opts = idris_options i
896 let opt' = opts { opt_ibcsubdir = fp }
897 putIState $ i { idris_options = opt' }
899valIBCSubDir :: IState -> Idris FilePath
900valIBCSubDir i = return (opt_ibcsubdir (idris_options i))
902addImportDir :: FilePath -> Idris ()
903addImportDir fp = do i <- getIState
904 let opts = idris_options i
905 let opt' = opts { opt_importdirs = nub $ fp : opt_importdirs opts }
906 putIState $ i { idris_options = opt' }
908setImportDirs :: [FilePath] -> Idris ()
909setImportDirs fps = do i <- getIState
910 let opts = idris_options i
911 let opt' = opts { opt_importdirs = fps }
912 putIState $ i { idris_options = opt' }
914allImportDirs :: Idris [FilePath]
915allImportDirs = do i <- getIState
916 let optdirs = opt_importdirs (idris_options i)
917 return ("." : reverse optdirs)
919colourise :: Idris Bool
920colourise = do i <- getIState
921 return $ idris_colourRepl i
923setColourise :: Bool -> Idris ()
924setColourise b = do i <- getIState
925 putIState $ i { idris_colourRepl = b }
928impShow = do i <- getIState
929 return (opt_showimp (idris_options i))
931setImpShow :: Bool -> Idris ()
932setImpShow t = do i <- getIState
933 let opts = idris_options i
934 let opt' = opts { opt_showimp = t }
935 putIState $ i { idris_options = opt' }
937setColour :: ColourType -> IdrisColour -> Idris ()
938setColour ct c = do i <- getIState
939 let newTheme = setColour' ct c (idris_colourTheme i)
940 putIState $ i { idris_colourTheme = newTheme }
941 where setColour' KeywordColour c t = t { keywordColour = c }
942 setColour' BoundVarColour c t = t { boundVarColour = c }
943 setColour' ImplicitColour c t = t { implicitColour = c }
944 setColour' FunctionColour c t = t { functionColour = c }
945 setColour' TypeColour c t = t { typeColour = c }
946 setColour' DataColour c t = t { dataColour = c }
947 setColour' PromptColour c t = t { promptColour = c }
948 setColour' PostulateColour c t = t { postulateColour = c }
950logLvl :: Int -> String -> Idris ()
951logLvl l str = do i <- getIState
952 let lvl = opt_logLevel (idris_options i)
954 case idris_outputmode i of
955 RawOutput h -> do runIO $ hPutStrLn h str
957 do let good = SexpList [IntegerAtom (toInteger l), toSExp str]
958 runIO . hPutStrLn h $ convSExp "log" good n
960cmdOptType :: Opt -> Idris Bool
961cmdOptType x = do i <- getIState
962 return $ x `elem` opt_cmdline (idris_options i)
964noErrors :: Idris Bool
965noErrors = do i <- getIState
967 Nothing -> return True
970setTypeCase :: Bool -> Idris ()
971setTypeCase t = do i <- getIState
972 let opts = idris_options i
973 let opt' = opts { opt_typecase = t }
974 putIState $ i { idris_options = opt' }
977-- Dealing with parameters
979expandParams :: (Name -> Name) -> [(Name, PTerm)] ->
980 [Name] -> -- all names
981 [Name] -> -- names with no declaration
983expandParams dec ps ns infs tm = en tm
985 -- if we shadow a name (say in a lambda binding) that is used in a call to
986 -- a lifted function, we need access to both names - once in the scope of the
987 -- binding and once to call the lifted functions. So we'll explicitly shadow
988 -- it. (Yes, it's a hack. The alternative would be to resolve names earlier
991 mkShadow (UN n) = MN 0 n
992 mkShadow (MN i n) = MN (i+1) n
993 mkShadow (NS x s) = NS (mkShadow x) s
995 en (PLam fc n nfc t s)
996 | n `elem` (map fst ps ++ ns)
997 = let n' = mkShadow n in
998 PLam fc n' nfc (en t) (en (shadow n n' s))
999 | otherwise = PLam fc n nfc (en t) (en s)
1000 en (PPi p n nfc t s)
1001 | n `elem` (map fst ps ++ ns)
1002 = let n' = mkShadow n in -- TODO THINK SHADOWING TacImp?
1003 PPi (enTacImp p) n' nfc (en t) (en (shadow n n' s))
1004 | otherwise = PPi (enTacImp p) n nfc (en t) (en s)
1005 en (PLet fc n nfc ty v s)
1006 | n `elem` (map fst ps ++ ns)
1007 = let n' = mkShadow n in
1008 PLet fc n' nfc (en ty) (en v) (en (shadow n n' s))
1009 | otherwise = PLet fc n nfc (en ty) (en v) (en s)
1010 -- FIXME: Should only do this in a type signature!
1011 en (PDPair f hls p (PRef f' fcs n) t r)
1012 | n `elem` (map fst ps ++ ns) && t /= Placeholder
1013 = let n' = mkShadow n in
1014 PDPair f hls p (PRef f' fcs n') (en t) (en (shadow n n' r))
1015 en (PRewrite f l r g) = PRewrite f (en l) (en r) (fmap en g)
1016 en (PTyped l r) = PTyped (en l) (en r)
1017 en (PPair f hls p l r) = PPair f hls p (en l) (en r)
1018 en (PDPair f hls p l t r) = PDPair f hls p (en l) (en t) (en r)
1019 en (PAlternative ns a as) = PAlternative ns a (map en as)
1020 en (PHidden t) = PHidden (en t)
1021 en (PUnifyLog t) = PUnifyLog (en t)
1022 en (PDisamb ds t) = PDisamb ds (en t)
1023 en (PNoImplicits t) = PNoImplicits (en t)
1024 en (PDoBlock ds) = PDoBlock (map (fmap en) ds)
1025 en (PProof ts) = PProof (map (fmap en) ts)
1026 en (PTactics ts) = PTactics (map (fmap en) ts)
1029 | n `nselem` ns = PQuote (Var (dec n))
1030 en (PApp fc (PInferRef fc' hl n) as)
1031 | n `nselem` ns = PApp fc (PInferRef fc' hl (dec n))
1032 (map (pexp . (PRef fc hl)) (map fst ps) ++ (map (fmap en) as))
1033 en (PApp fc (PRef fc' hl n) as)
1034 | n `elem` infs = PApp fc (PInferRef fc' hl (dec n))
1035 (map (pexp . (PRef fc hl)) (map fst ps) ++ (map (fmap en) as))
1036 | n `nselem` ns = PApp fc (PRef fc' hl (dec n))
1037 (map (pexp . (PRef fc hl)) (map fst ps) ++ (map (fmap en) as))
1038 en (PAppBind fc (PRef fc' hl n) as)
1039 | n `elem` infs = PAppBind fc (PInferRef fc' hl (dec n))
1040 (map (pexp . (PRef fc hl)) (map fst ps) ++ (map (fmap en) as))
1041 | n `nselem` ns = PAppBind fc (PRef fc' hl (dec n))
1042 (map (pexp . (PRef fc hl)) (map fst ps) ++ (map (fmap en) as))
1044 | n `elem` infs = PApp fc (PInferRef fc hl (dec n))
1045 (map (pexp . (PRef fc hl)) (map fst ps))
1046 | n `nselem` ns = PApp fc (PRef fc hl (dec n))
1047 (map (pexp . (PRef fc hl)) (map fst ps))
1048 en (PInferRef fc hl n)
1049 | n `nselem` ns = PApp fc (PInferRef fc hl (dec n))
1050 (map (pexp . (PRef fc hl)) (map fst ps))
1051 en (PApp fc f as) = PApp fc (en f) (map (fmap en) as)
1052 en (PAppBind fc f as) = PAppBind fc (en f) (map (fmap en) as)
1053 en (PCase fc c os) = PCase fc (en c) (map (pmap en) os)
1054 en (PIfThenElse fc c t f) = PIfThenElse fc (en c) (en t) (en f)
1055 en (PRunElab fc tm ns) = PRunElab fc (en tm) ns
1056 en (PConstSugar fc tm) = PConstSugar fc (en tm)
1060 nselem x (y : xs) | nseq x y = True
1061 | otherwise = nselem x xs
1063 nseq x y = nsroot x == nsroot y
1065 enTacImp (TacImp aos st scr) = TacImp aos st (en scr)
1066 enTacImp other = other
1068expandParamsD :: Bool -> -- True = RHS only
1070 (Name -> Name) -> [(Name, PTerm)] -> [Name] -> PDecl -> PDecl
1071expandParamsD rhsonly ist dec ps ns (PTy doc argdocs syn fc o n nfc ty)
1072 = if n `elem` ns && (not rhsonly)
1073 then -- trace (show (n, expandParams dec ps ns ty)) $
1074 PTy doc argdocs syn fc o (dec n) nfc (piBindp expl_param ps (expandParams dec ps ns [] ty))
1075 else --trace (show (n, expandParams dec ps ns ty)) $
1076 PTy doc argdocs syn fc o n nfc (expandParams dec ps ns [] ty)
1077expandParamsD rhsonly ist dec ps ns (PPostulate e doc syn fc nfc o n ty)
1078 = if n `elem` ns && (not rhsonly)
1079 then -- trace (show (n, expandParams dec ps ns ty)) $
1080 PPostulate e doc syn fc nfc o (dec n)
1081 (piBind ps (expandParams dec ps ns [] ty))
1082 else --trace (show (n, expandParams dec ps ns ty)) $
1083 PPostulate e doc syn fc nfc o n (expandParams dec ps ns [] ty)
1084expandParamsD rhsonly ist dec ps ns (PClauses fc opts n cs)
1085 = let n' = if n `elem` ns then dec n else n in
1086 PClauses fc opts n' (map expandParamsC cs)
1088 expandParamsC (PClause fc n lhs ws rhs ds)
1089 = let -- ps' = updateps True (namesIn ist rhs) (zip ps [0..])
1090 ps'' = updateps False (namesIn [] ist lhs) (zip ps [0..])
1091 lhs' = if rhsonly then lhs else (expandParams dec ps'' ns [] lhs)
1092 n' = if n `elem` ns then dec n else n
1093 -- names bound on the lhs should not be expanded on the rhs
1094 ns' = removeBound lhs ns in
1096 (map (expandParams dec ps'' ns' []) ws)
1097 (expandParams dec ps'' ns' [] rhs)
1098 (map (expandParamsD True ist dec ps'' ns') ds)
1099 expandParamsC (PWith fc n lhs ws wval pn ds)
1100 = let -- ps' = updateps True (namesIn ist wval) (zip ps [0..])
1101 ps'' = updateps False (namesIn [] ist lhs) (zip ps [0..])
1102 lhs' = if rhsonly then lhs else (expandParams dec ps'' ns [] lhs)
1103 n' = if n `elem` ns then dec n else n
1104 ns' = removeBound lhs ns in
1106 (map (expandParams dec ps'' ns' []) ws)
1107 (expandParams dec ps'' ns' [] wval)
1109 (map (expandParamsD rhsonly ist dec ps'' ns') ds)
1110 updateps yn nm [] = []
1111 updateps yn nm (((a, t), i):as)
1112 | (a `elem` nm) == yn = (a, t) : updateps yn nm as
1113 | otherwise = (sMN i ('_' : show n ++ "_u"), t) : updateps yn nm as
1115 removeBound lhs ns = ns \\ nub (bnames lhs)
1117 bnames (PRef _ _ n) = [n]
1118 bnames (PApp _ _ args) = concatMap bnames (map getTm args)
1119 bnames (PPair _ _ _ l r) = bnames l ++ bnames r
1120 bnames (PDPair _ _ _ l Placeholder r) = bnames l ++ bnames r
1123-- | Expands parameters defined in parameter and where blocks inside of declarations
1124expandParamsD rhs ist dec ps ns (PData doc argDocs syn fc co pd)
1125 = PData doc argDocs syn fc co (expandPData pd)
1127 -- just do the type decl, leave constructors alone (parameters will be
1128 -- added implicitly)
1129 expandPData (PDatadecl n nfc ty cons)
1131 then PDatadecl (dec n) nfc (piBind ps (expandParams dec ps ns [] ty))
1133 else PDatadecl n nfc (expandParams dec ps ns [] ty) (map econ cons)
1134 econ (doc, argDocs, n, nfc, t, fc, fs)
1135 = (doc, argDocs, dec n, nfc, piBindp expl ps (expandParams dec ps ns [] t), fc, fs)
1136expandParamsD rhs ist dec ps ns d@(PRecord doc rsyn fc opts name nfc prs pdocs fls cn cdoc csyn)
1138expandParamsD rhs ist dec ps ns (PParams f params pds)
1139 = PParams f (ps ++ map (mapsnd (expandParams dec ps ns [])) params)
1140 (map (expandParamsD True ist dec ps ns) pds)
1141-- (map (expandParamsD ist dec ps ns) pds)
1142expandParamsD rhs ist dec ps ns (PMutual f pds)
1143 = PMutual f (map (expandParamsD rhs ist dec ps ns) pds)
1144expandParamsD rhs ist dec ps ns (PClass doc info f cs n nfc params pDocs fds decls cn cd)
1146 (map (\ (n, t) -> (n, expandParams dec ps ns [] t)) cs)
1148 (map (\(n, fc, t) -> (n, fc, expandParams dec ps ns [] t)) params)
1151 (map (expandParamsD rhs ist dec ps ns) decls)
1154expandParamsD rhs ist dec ps ns (PInstance doc argDocs info f cs n nfc params ty cn decls)
1155 = PInstance doc argDocs info f
1156 (map (\ (n, t) -> (n, expandParams dec ps ns [] t)) cs)
1159 (map (expandParams dec ps ns []) params)
1160 (expandParams dec ps ns [] ty)
1162 (map (expandParamsD rhs ist dec ps ns) decls)
1163expandParamsD rhs ist dec ps ns d = d
1165mapsnd f (x, t) = (x, f t)
1167-- Calculate a priority for a type, for deciding elaboration order
1168-- * if it's just a type variable or concrete type, do it early (0)
1169-- * if there's only type variables and injective constructors, do it next (1)
1170-- * if there's a function type, next (2)
1171-- * finally, everything else (3)
1173getPriority :: IState -> PTerm -> Int
1174getPriority i tm = 1 -- pri tm
1177 case lookupP n (tt_ctxt i) of
1178 ((P (DCon _ _ _) _ _):_) -> 1
1179 ((P (TCon _ _) _ _):_) -> 1
1180 ((P Ref _ _):_) -> 1
1181 [] -> 0 -- must be locally bound, if it's not an error...
1182 pri (PPi _ _ _ x y) = max 5 (max (pri x) (pri y))
1184 pri (PRewrite _ l r _) = max 1 (max (pri l) (pri r))
1185 pri (PApp _ f as) = max 1 (max (pri f) (foldr max 0 (map (pri.getTm) as)))
1186 pri (PAppBind _ f as) = max 1 (max (pri f) (foldr max 0 (map (pri.getTm) as)))
1187 pri (PCase _ f as) = max 1 (max (pri f) (foldr max 0 (map (pri.snd) as)))
1188 pri (PTyped l r) = pri l
1189 pri (PPair _ _ _ l r) = max 1 (max (pri l) (pri r))
1190 pri (PDPair _ _ _ l t r) = max 1 (max (pri l) (max (pri t) (pri r)))
1191 pri (PAlternative _ a as) = maximum (map pri as)
1192 pri (PConstant _ _) = 0
1197addStatics :: Name -> Term -> PTerm -> Idris ()
1198addStatics n tm ptm =
1199 do let (statics, dynamics) = initStatics tm ptm
1202 = nub $ case lookupCtxtExact n (idris_fninfo ist) of
1203 Just p -> getNamesFrom 0 (fn_params p) tm ++
1204 concatMap (getParamNames ist) (map snd statics)
1205 _ -> concatMap (getParamNames ist) (map snd statics)
1207 let stnames = nub $ concatMap freeArgNames (map snd statics)
1208 let dnames = (nub $ concatMap freeArgNames (map snd dynamics))
1210 -- also get the arguments which are 'uniquely inferrable' from
1211 -- statics (see sec 4.2 of "Scrapping Your Inefficient Engine")
1212 -- or parameters to the type of a static
1213 let statics' = nub $ map fst statics ++
1214 filter (\x -> not (elem x dnames)) stnames
1215 let stpos = staticList statics' tm
1217 when (not (null statics)) $
1218 logLvl 3 $ "Statics for " ++ show n ++ " " ++ show tm ++ "\n"
1219 ++ showTmImpls ptm ++ "\n"
1220 ++ show statics ++ "\n" ++ show dynamics
1221 ++ "\n" ++ show paramnames
1222 ++ "\n" ++ show stpos
1223 putIState $ i { idris_statics = addDef n stpos (idris_statics i) }
1224 addIBC (IBCStatic n)
1226 initStatics (Bind n (Pi _ ty _) sc) (PPi p n' fc t s)
1227 | n /= n' = let (static, dynamic) = initStatics sc (PPi p n' fc t s) in
1228 (static, (n, ty) : dynamic)
1229 initStatics (Bind n (Pi _ ty _) sc) (PPi p n' fc _ s)
1230 = let (static, dynamic) = initStatics (instantiate (P Bound n ty) sc) s in
1231 if pstatic p == Static then ((n, ty) : static, dynamic)
1232 else if (not (searchArg p))
1233 then (static, (n, ty) : dynamic)
1234 else (static, dynamic)
1235 initStatics t pt = ([], [])
1237 getParamNames ist tm | (P _ n _ , args) <- unApply tm
1238 = case lookupCtxtExact n (idris_datatypes ist) of
1239 Just ti -> getNamePos 0 (param_pos ti) args
1241 where getNamePos i ps [] = []
1242 getNamePos i ps (P _ n _ : as)
1243 | i `elem` ps = n : getNamePos (i + 1) ps as
1244 getNamePos i ps (_ : as) = getNamePos (i + 1) ps as
1245 getParamNames ist (Bind t (Pi _ (P _ n _) _) sc)
1246 = n : getParamNames ist sc
1247 getParamNames ist _ = []
1249 getNamesFrom i ps (Bind n (Pi _ _ _) sc)
1250 | i `elem` ps = n : getNamesFrom (i + 1) ps sc
1251 | otherwise = getNamesFrom (i + 1) ps sc
1252 getNamesFrom i ps sc = []
1254 freeArgNames (Bind n (Pi _ ty _) sc)
1255 = nub $ freeNames ty ++ freeNames sc -- treat '->' as fn here
1256 freeArgNames tm = let (_, args) = unApply tm in
1257 concatMap freeNames args
1259 -- if a name appears in a type class or tactic implicit index, it doesn't
1260 -- affect its 'uniquely inferrable' from a static status since these are
1261 -- resolved by searching.
1262 searchArg (Constraint _ _) = True
1263 searchArg (TacImp _ _ _) = True
1266 staticList sts (Bind n (Pi _ _ _) sc) = (n `elem` sts) : staticList sts sc
1269-- Dealing with implicit arguments
1271-- Add some bound implicits to the using block if they aren't there already
1273addToUsing :: [Using] -> [(Name, PTerm)] -> [Using]
1274addToUsing us [] = us
1275addToUsing us ((n, t) : ns)
1276 | n `notElem` mapMaybe impName us = addToUsing (us ++ [UImplicit n t]) ns
1277 | otherwise = addToUsing us ns
1278 where impName (UImplicit n _) = Just n
1281-- Add constraint bindings from using block
1283addUsingConstraints :: SyntaxInfo -> FC -> PTerm -> Idris PTerm
1284addUsingConstraints syn fc t
1286 let ns = namesIn [] ist t
1287 let cs = getConstraints t -- check declared constraints
1288 let addconsts = uconsts \\ cs
1289 return (doAdd addconsts ns t)
1290 where uconsts = filter uconst (using syn)
1291 uconst (UConstraint _ _) = True
1295 -- if all of args in ns, then add it
1296 doAdd (UConstraint c args : cs) ns t
1297 | all (\n -> elem n ns) args
1298 = PPi (Constraint [] Dynamic) (sMN 0 "cu") NoFC
1299 (mkConst c args) (doAdd cs ns t)
1300 | otherwise = doAdd cs ns t
1302 mkConst c args = PApp fc (PRef fc [] c)
1303 (map (\n -> PExp 0 [] (sMN 0 "carg") (PRef fc [] n)) args)
1305 getConstraints (PPi (Constraint _ _) _ _ c sc)
1306 = getcapp c ++ getConstraints sc
1307 getConstraints (PPi _ _ _ c sc) = getConstraints sc
1308 getConstraints _ = []
1310 getcapp (PApp _ (PRef _ _ c) args)
1311 = do ns <- mapM getName args
1312 return (UConstraint c ns)
1315 getName (PExp _ _ _ (PRef _ _ n)) = return n
1318-- Add implicit bindings from using block, and bind any missing names
1319addUsingImpls :: SyntaxInfo -> Name -> FC -> PTerm -> Idris PTerm
1320addUsingImpls syn n fc t
1321 = do ist <- getIState
1322 let ns = implicitNamesIn (map iname uimpls) ist t
1323 let badnames = filter (\n -> not (implicitable n) &&
1324 n `notElem` (map iname uimpls)) ns
1325 when (not (null badnames)) $
1326 throwError (At fc (Elaborating "type of " n
1327 (NoSuchVariable (head badnames))))
1328 let cs = getArgnames t -- get already bound names
1329 let addimpls = filter (\n -> iname n `notElem` cs) uimpls
1330 -- if all names in the arguments of addconsts appear in ns,
1331 -- add the constraint implicitly
1332 return (bindFree ns (doAdd addimpls ns t))
1333 where uimpls = filter uimpl (using syn)
1334 uimpl (UImplicit _ _) = True
1337 iname (UImplicit n _) = n
1338 iname (UConstraint _ _) = error "Can't happen addUsingImpls"
1341 -- if all of args in ns, then add it
1342 doAdd (UImplicit n ty : cs) ns t
1344 = PPi (Imp [] Dynamic False Nothing) n NoFC ty (doAdd cs ns t)
1345 | otherwise = doAdd cs ns t
1347 -- bind the free names which weren't in the using block
1350 | elem n (map iname uimpls) = bindFree ns tm
1352 = PPi (Imp [InaccessibleArg] Dynamic False Nothing) n NoFC Placeholder (bindFree ns tm)
1354 getArgnames (PPi _ n _ c sc)
1355 = n : getArgnames sc
1358-- Given the original type and the elaborated type, return the implicitness
1359-- status of each pi-bound argument, and whether it's inaccessible (True) or not.
1361getUnboundImplicits :: IState -> Type -> PTerm -> [(Bool, PArg)]
1362getUnboundImplicits i t tm = getImps t (collectImps tm)
1363 where collectImps (PPi p n _ t sc)
1364 = (n, (p, t)) : collectImps sc
1367 getImps (Bind n (Pi (Just _) _ _) sc) imps = getImps sc imps
1368 getImps (Bind n (Pi _ t _) sc) imps
1369 | Just (p, t') <- lookup n imps = argInfo n p t' : getImps sc imps
1371 argInfo n (Imp opt _ _ _) Placeholder
1372 = (True, PImp 0 True opt n Placeholder)
1373 argInfo n (Imp opt _ _ _) t'
1374 = (False, PImp (getPriority i t') True opt n t')
1375 argInfo n (Exp opt _ _) t'
1376 = (InaccessibleArg `elem` opt,
1377 PExp (getPriority i t') opt n t')
1378 argInfo n (Constraint opt _) t'
1379 = (InaccessibleArg `elem` opt,
1380 PConstraint 10 opt n t')
1381 argInfo n (TacImp opt _ scr) t'
1382 = (InaccessibleArg `elem` opt,
1383 PTacImplicit 10 opt n scr t')
1384 getImps (Bind n (Pi _ t _) sc) imps = impBind n t : getImps sc imps
1385 where impBind n t = (True, PImp 1 True [] n Placeholder)
1388-- Add implicit Pi bindings for any names in the term which appear in an
1389-- argument position.
1391-- This has become a right mess already. Better redo it some time...
1392-- TODO: This is obsoleted by the new way of elaborating types, (which
1393-- calls addUsingImpls) but there's still a couple of places which use
1394-- it. Clean them up!
1396-- Issue 1739 in the issue tracker
1397-- https://github.com/idris-lang/Idris-dev/issues/1739
1398implicit :: ElabInfo -> SyntaxInfo -> Name -> PTerm -> Idris PTerm
1399implicit info syn n ptm = implicit' info syn [] n ptm
1401implicit' :: ElabInfo -> SyntaxInfo -> [Name] -> Name -> PTerm -> Idris PTerm
1402implicit' info syn ignore n ptm
1404 let (tm', impdata) = implicitise syn ignore i ptm
1405 defaultArgCheck (eInfoNames info ++ M.keys (idris_implicits i)) impdata
1406-- let (tm'', spos) = findStatics i tm'
1407 putIState $ i { idris_implicits = addDef n impdata (idris_implicits i) }
1409 logLvl 5 ("Implicit " ++ show n ++ " " ++ show impdata)
1411-- putIState $ i { idris_statics = addDef n spos (idris_statics i) }
1414 -- Detect unknown names in default arguments and throw error if found.
1415 defaultArgCheck :: [Name] -> [PArg] -> Idris ()
1416 defaultArgCheck knowns params = foldM_ notFoundInDefault knowns params
1418 notFoundInDefault :: [Name] -> PArg -> Idris [Name]
1419 notFoundInDefault kns (PTacImplicit _ _ n script _)
1421 case notFound kns (namesIn [] i script) of
1422 Nothing -> return (n:kns)
1423 Just name -> throwError (NoSuchVariable name)
1424 notFoundInDefault kns p = return ((pname p):kns)
1426 notFound :: [Name] -> [Name] -> Maybe Name
1427 notFound kns [] = Nothing
1428 notFound kns (SN (WhereN _ _ _) : ns) = notFound kns ns -- Known already
1429 notFound kns (n:ns) = if elem n kns then notFound kns ns else Just n
1431implicitise :: SyntaxInfo -> [Name] -> IState -> PTerm -> (PTerm, [PArg])
1432implicitise syn ignore ist tm = -- trace ("INCOMING " ++ showImp True tm) $
1433 let (declimps, ns') = execState (imps True [] tm) ([], [])
1434 ns = filter (\n -> implicitable n || elem n (map fst uvars)) $
1435 ns' \\ (map fst pvars ++ no_imp syn ++ ignore)
1436 nsOrder = filter (not . inUsing) ns ++ filter inUsing ns in
1438 then (tm, reverse declimps)
1439 else implicitise syn ignore ist (pibind uvars nsOrder tm)
1441 uvars = map ipair (filter uimplicit (using syn))
1442 pvars = syn_params syn
1444 inUsing n = n `elem` map fst uvars
1446 ipair (UImplicit x y) = (x, y)
1447 uimplicit (UImplicit _ _) = True
1450 dropAll (x:xs) ys | x `elem` ys = dropAll xs ys
1451 | otherwise = x : dropAll xs ys
1454 -- Find names in argument position in a type, suitable for implicit
1456 -- Not the function position, but do everything else...
1457 implNamesIn uv (PApp fc f args) = concatMap (implNamesIn uv) (map getTm args)
1458 implNamesIn uv t = namesIn uv ist t
1460 imps top env (PApp _ f as)
1461 = do (decls, ns) <- get
1462 let isn = concatMap (namesIn uvars ist) (map getTm as)
1463 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1464 imps top env (PPi (Imp l _ _ _) n _ ty sc)
1465 = do let isn = nub (implNamesIn uvars ty) `dropAll` [n]
1467 put (PImp (getPriority ist ty) True l n Placeholder : decls,
1468 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1469 imps True (n:env) sc
1470 imps top env (PPi (Exp l _ _) n _ ty sc)
1471 = do let isn = nub (implNamesIn uvars ty ++ case sc of
1472 (PRef _ _ x) -> namesIn uvars ist sc `dropAll` [n]
1474 (decls, ns) <- get -- ignore decls in HO types
1475 put (PExp (getPriority ist ty) l n Placeholder : decls,
1476 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1477 imps True (n:env) sc
1478 imps top env (PPi (Constraint l _) n _ ty sc)
1479 = do let isn = nub (implNamesIn uvars ty ++ case sc of
1480 (PRef _ _ x) -> namesIn uvars ist sc `dropAll` [n]
1482 (decls, ns) <- get -- ignore decls in HO types
1483 put (PConstraint 10 l n Placeholder : decls,
1484 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1485 imps True (n:env) sc
1486 imps top env (PPi (TacImp l _ scr) n _ ty sc)
1487 = do let isn = nub (implNamesIn uvars ty ++ case sc of
1488 (PRef _ _ x) -> namesIn uvars ist sc `dropAll` [n]
1490 (decls, ns) <- get -- ignore decls in HO types
1491 put (PTacImplicit 10 l n scr Placeholder : decls,
1492 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1493 imps True (n:env) sc
1494 imps top env (PRewrite _ l r _)
1495 = do (decls, ns) <- get
1496 let isn = namesIn uvars ist l ++ namesIn uvars ist r
1497 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1498 imps top env (PTyped l r)
1500 imps top env (PPair _ _ _ l r)
1501 = do (decls, ns) <- get
1502 let isn = namesIn uvars ist l ++ namesIn uvars ist r
1503 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1504 imps top env (PDPair _ _ _ (PRef _ _ n) t r)
1505 = do (decls, ns) <- get
1506 let isn = nub (namesIn uvars ist t ++ namesIn uvars ist r) \\ [n]
1507 put (decls, nub (ns ++ (isn \\ (env ++ map fst (getImps decls)))))
1508 imps top env (PDPair _ _ _ l t r)
1509 = do (decls, ns) <- get
1510 let isn = namesIn uvars ist l ++ namesIn uvars ist t ++
1512 put (decls, nub (ns ++ (isn \\ (env ++ map fst (getImps decls)))))
1513 imps top env (PAlternative ms a as)
1514 = do (decls, ns) <- get
1515 let isn = concatMap (namesIn uvars ist) as
1516 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1517 imps top env (PLam fc n _ ty sc)
1518 = do imps False env ty
1519 imps False (n:env) sc
1520 imps top env (PHidden tm) = imps False env tm
1521 imps top env (PUnifyLog tm) = imps False env tm
1522 imps top env (PNoImplicits tm) = imps False env tm
1523 imps top env (PRunElab fc tm ns) = imps False env tm
1524 imps top env (PConstSugar fc tm) = imps top env tm -- ignore PConstSugar - it's for highlighting only!
1525 imps top env _ = return ()
1527 pibind using [] sc = sc
1528 pibind using (n:ns) sc
1529 = case lookup n using of
1530 Just ty -> PPi (Imp [] Dynamic False Nothing)
1531 n NoFC ty (pibind using ns sc)
1532 Nothing -> PPi (Imp [InaccessibleArg] Dynamic False Nothing)
1533 n NoFC Placeholder (pibind using ns sc)
1535-- Add implicit arguments in function calls
1536addImplPat :: IState -> PTerm -> PTerm
1537addImplPat = addImpl' True [] [] []
1539addImplBound :: IState -> [Name] -> PTerm -> PTerm
1540addImplBound ist ns = addImpl' False ns [] [] ist
1542addImplBoundInf :: IState -> [Name] -> [Name] -> PTerm -> PTerm
1543addImplBoundInf ist ns inf = addImpl' False ns inf [] ist
1545-- | Add the implicit arguments to applications in the term
1546-- [Name] gives the names to always expend, even when under a binder of
1547-- that name (this is to expand methods with implicit arguments in dependent
1549addImpl :: [Name] -> IState -> PTerm -> PTerm
1550addImpl = addImpl' False [] []
1552-- TODO: in patterns, don't add implicits to function names guarded by constructors
1553-- and *not* inside a PHidden
1555addImpl' :: Bool -> [Name] -> [Name] -> [Name] -> IState -> PTerm -> PTerm
1556addImpl' inpat env infns imp_meths ist ptm
1557 = mkUniqueNames env [] (ai inpat False (zip env (repeat Nothing)) [] ptm)
1559 topname = case ptm of
1561 PApp _ (PRef _ _ n) _ -> n
1562 _ -> sUN "" -- doesn't matter then
1564 ai :: Bool -> Bool -> [(Name, Maybe PTerm)] -> [[T.Text]] -> PTerm -> PTerm
1565 ai inpat qq env ds (PRef fc fcs f)
1566 | f `elem` infns = PInferRef fc fcs f
1567 | not (f `elem` map fst env) = handleErr $ aiFn topname inpat inpat qq imp_meths ist fc f fc ds [] []
1568 ai inpat qq env ds (PHidden (PRef fc hl f))
1569 | not (f `elem` map fst env) = PHidden (handleErr $ aiFn topname inpat False qq imp_meths ist fc f fc ds [] [])
1570 ai inpat qq env ds (PRewrite fc l r g)
1571 = let l' = ai inpat qq env ds l
1572 r' = ai inpat qq env ds r
1573 g' = fmap (ai inpat qq env ds) g in
1574 PRewrite fc l' r' g'
1575 ai inpat qq env ds (PTyped l r)
1576 = let l' = ai inpat qq env ds l
1577 r' = ai inpat qq env ds r in
1579 ai inpat qq env ds (PPair fc hls p l r)
1580 = let l' = ai inpat qq env ds l
1581 r' = ai inpat qq env ds r in
1582 PPair fc hls p l' r'
1583 ai inpat qq env ds (PDPair fc hls p l t r)
1584 = let l' = ai inpat qq env ds l
1585 t' = ai inpat qq env ds t
1586 r' = ai inpat qq env ds r in
1587 PDPair fc hls p l' t' r'
1588 ai inpat qq env ds (PAlternative ms a as)
1589 = let as' = map (ai inpat qq env ds) as in
1590 PAlternative ms a as'
1591 ai inpat qq env _ (PDisamb ds' as) = ai inpat qq env ds' as
1592 ai inpat qq env ds (PApp fc (PInferRef ffc hl f) as)
1593 = let as' = map (fmap (ai inpat qq env ds)) as in
1594 PApp fc (PInferRef ffc hl f) as'
1595 ai inpat qq env ds (PApp fc ftm@(PRef ffc hl f) as)
1596 | f `elem` infns = ai inpat qq env ds (PApp fc (PInferRef ffc hl f) as)
1597 | not (f `elem` map fst env)
1598 = let as' = map (fmap (ai inpat qq env ds)) as
1599 asdotted' = map (fmap (ai False qq env ds)) as in
1600 handleErr $ aiFn topname inpat False qq imp_meths ist fc f ffc ds as' asdotted'
1601 | Just (Just ty) <- lookup f env =
1602 let as' = map (fmap (ai inpat qq env ds)) as
1603 arity = getPArity ty in
1604 mkPApp fc arity ftm as'
1605 ai inpat qq env ds (PApp fc f as)
1606 = let f' = ai inpat qq env ds f
1607 as' = map (fmap (ai inpat qq env ds)) as in
1609 ai inpat qq env ds (PCase fc c os)
1610 = let c' = ai inpat qq env ds c in
1611 -- leave os alone, because they get lifted into a new pattern match
1612 -- definition which is passed through addImpl agai inpatn with more scope
1616 ai inpat qq env ds (PIfThenElse fc c t f) = PIfThenElse fc (ai inpat qq env ds c)
1617 (ai inpat qq env ds t)
1618 (ai inpat qq env ds f)
1620 -- If the name in a lambda is a constructor name, do this as a 'case'
1621 -- instead (it is harmless to do so, especially since the lambda will
1622 -- be lifted anyway!)
1623 ai inpat qq env ds (PLam fc n nfc ty sc)
1624 = case lookupDef n (tt_ctxt ist) of
1625 [] -> let ty' = ai inpat qq env ds ty
1626 sc' = ai inpat qq ((n, Just ty):env) ds sc in
1627 PLam fc n nfc ty' sc'
1628 _ -> ai inpat qq env ds (PLam fc (sMN 0 "lamp") NoFC ty
1629 (PCase fc (PRef fc [] (sMN 0 "lamp") )
1630 [(PRef fc [] n, sc)]))
1631 ai inpat qq env ds (PLet fc n nfc ty val sc)
1632 = case lookupDef n (tt_ctxt ist) of
1633 [] -> let ty' = ai inpat qq env ds ty
1634 val' = ai inpat qq env ds val
1635 sc' = ai inpat qq ((n, Just ty):env) ds sc in
1636 PLet fc n nfc ty' val' sc'
1638 ai inpat qq env ds (PCase fc val [(PRef fc [] n, sc)])
1639 ai inpat qq env ds (PPi p n nfc ty sc)
1640 = let ty' = ai inpat qq env ds ty
1641 env' = if n `elem` imp_meths then env
1642 else ((n, Just ty) : env)
1643 sc' = ai inpat qq env' ds sc in
1645 ai inpat qq env ds (PGoal fc r n sc)
1646 = let r' = ai inpat qq env ds r
1647 sc' = ai inpat qq ((n, Nothing):env) ds sc in
1649 ai inpat qq env ds (PHidden tm) = PHidden (ai inpat qq env ds tm)
1650 -- Don't do PProof or PTactics since implicits get added when scope is
1651 -- properly known in ElabTerm.runTac
1652 ai inpat qq env ds (PUnifyLog tm) = PUnifyLog (ai inpat qq env ds tm)
1653 ai inpat qq env ds (PNoImplicits tm) = PNoImplicits (ai inpat qq env ds tm)
1654 ai inpat qq env ds (PQuasiquote tm g) = PQuasiquote (ai inpat True env ds tm)
1655 (fmap (ai inpat True env ds) g)
1656 ai inpat qq env ds (PUnquote tm) = PUnquote (ai inpat False env ds tm)
1657 ai inpat qq env ds (PRunElab fc tm ns) = PRunElab fc (ai inpat False env ds tm) ns
1658 ai inpat qq env ds (PConstSugar fc tm) = PConstSugar fc (ai inpat qq env ds tm)
1659 ai inpat qq env ds tm = tm
1661 handleErr (Left err) = PElabError err
1662 handleErr (Right x) = x
1664-- if in a pattern, and there are no arguments, and there's no possible
1665-- names with zero explicit arguments, don't add implicits.
1667aiFn :: Name -> Bool -> Bool -> Bool
1670 -> Name -- ^ function being applied
1672 -> [PArg] -- ^ initial arguments (if in a pattern)
1673 -> [PArg] -- ^ initial arguments (if in an expression)
1675aiFn topname inpat True qq imp_meths ist fc f ffc ds [] _
1676 = case lookupDef f (tt_ctxt ist) of
1677 [] -> Right $ PPatvar ffc f
1678 alts -> let ialts = lookupCtxtName f (idris_implicits ist) in
1679 -- trace (show f ++ " " ++ show (fc, any (all imp) ialts, ialts, any constructor alts)) $
1680 if (not (vname f) || tcname f
1681 || any (conCaf (tt_ctxt ist)) ialts)
1682-- any constructor alts || any allImp ialts))
1683 then aiFn topname inpat False qq imp_meths ist fc f ffc ds [] [] -- use it as a constructor
1684 else Right $ PPatvar ffc f
1685 where imp (PExp _ _ _ _) = False
1688 allImp xs = all imp xs
1689 constructor (TyDecl (DCon _ _ _) _) = True
1690 constructor _ = False
1692 conCaf ctxt (n, cia) = (isDConName n ctxt || (qq && isTConName n ctxt)) && allImp cia
1694 vname (UN n) = True -- non qualified
1697aiFn topname inpat expat qq imp_meths ist fc f ffc ds as asexp
1698 | f `elem` primNames = Right $ PApp fc (PRef ffc [ffc] f) as
1699aiFn topname inpat expat qq imp_meths ist fc f ffc ds as asexp
1700 -- This is where namespaces get resolved by adding PAlternative
1701 = do let ns = lookupCtxtName f (idris_implicits ist)
1702 let nh = filter (\(n, _) -> notHidden n) ns
1703 let ns' = case trimAlts ds nh of
1707 [(f',ns)] -> Right $ mkPApp fc (length ns) (PRef ffc [ffc] (isImpName f f'))
1708 (insertImpl ns (chooseArgs f' as asexp))
1709 [] -> if f `elem` (map fst (idris_metavars ist))
1710 then Right $ PApp fc (PRef ffc [ffc] f) as
1711 else Right $ mkPApp fc (length as) (PRef ffc [ffc] f) as
1713 PAlternative [] (ExactlyOne True) $
1714 map (\(f', ns) -> mkPApp fc (length ns) (PRef ffc [ffc] (isImpName f f'))
1715 (insertImpl ns (chooseArgs f' as asexp))) alts
1717 -- choose whether to treat the arguments as patterns or expressions
1718 -- if 'f' is a defined function, treat as expression, otherwise do the default.
1719 -- This is so any names which later go under a PHidden are treated
1720 -- as function names rather than bound pattern variables
1721 chooseArgs f as asexp | isConName f (tt_ctxt ist) = as
1723 | Nothing <- lookupDefExact f (tt_ctxt ist) = as
1726 -- if the name is in imp_meths, we should actually refer to the bound
1727 -- name rather than the global one after expanding implicits
1728 isImpName f f' | f `elem` imp_meths = f
1731 trimAlts [] alts = alts
1733 = filter (\(x, _) -> any (\d -> d `isPrefixOf` nspace x) ns) alts
1738 notHidden n = case getAccessibility n of
1743 = case lookupDefAccExact n False (tt_ctxt ist) of
1747 insertImpl :: [PArg] -- ^ expected argument types (from idris_implicits)
1748 -> [PArg] -- ^ given arguments
1751 = let (as', badimpls) = partition (impIn ps) as in
1752 map addUnknownImp badimpls ++
1753 insImpAcc M.empty ps (filter expArg as') (filter (not . expArg) as')
1755 insImpAcc :: M.Map Name PTerm -- accumulated param names & arg terms
1756 -> [PArg] -- parameters
1757 -> [PArg] -- explicit arguments
1758 -> [PArg] -- implicits given
1760 insImpAcc pnas (PExp p l n ty : ps) (PExp _ _ _ tm : given) imps =
1761 PExp p l n tm : insImpAcc (M.insert n tm pnas) ps given imps
1762 insImpAcc pnas (PConstraint p l n ty : ps) (PConstraint _ _ _ tm : given) imps =
1763 PConstraint p l n tm : insImpAcc (M.insert n tm pnas) ps given imps
1764 insImpAcc pnas (PConstraint p l n ty : ps) given imps =
1765 let rtc = PResolveTC fc in
1766 PConstraint p l n rtc : insImpAcc (M.insert n rtc pnas) ps given imps
1767 insImpAcc pnas (PImp p _ l n ty : ps) given imps =
1768 case find n imps [] of
1770 PImp p False l n tm : insImpAcc (M.insert n tm pnas) ps given imps'
1771 Nothing -> let ph = if f `elem` imp_meths then PRef fc [] n else Placeholder in
1772 PImp p True l n ph :
1773 insImpAcc (M.insert n ph pnas) ps given imps
1774 insImpAcc pnas (PTacImplicit p l n sc' ty : ps) given imps =
1775 let sc = addImpl imp_meths ist (substMatches (M.toList pnas) sc') in
1776 case find n imps [] of
1778 PTacImplicit p l n sc tm :
1779 insImpAcc (M.insert n tm pnas) ps given imps'
1782 then PTacImplicit p l n sc Placeholder :
1783 insImpAcc (M.insert n Placeholder pnas) ps given imps
1784 else PTacImplicit p l n sc sc :
1785 insImpAcc (M.insert n sc pnas) ps given imps
1786 insImpAcc _ expected [] imps = map addUnknownImp imps -- so that unused implicits give error
1787 insImpAcc _ _ given imps = given ++ imps
1789 addUnknownImp arg = arg { argopts = UnknownImp : argopts arg }
1791 find n [] acc = Nothing
1792 find n (PImp _ _ _ n' t : gs) acc
1793 | n == n' = Just (t, reverse acc ++ gs)
1794 find n (PTacImplicit _ _ n' _ t : gs) acc
1795 | n == n' = Just (t, reverse acc ++ gs)
1796 find n (g : gs) acc = find n gs (g : acc)
1798-- return True if the second argument is an implicit argument which is
1799-- expected in the implicits, or if it's not an implicit
1800impIn :: [PArg] -> PArg -> Bool
1801impIn ps (PExp _ _ _ _) = True
1802impIn ps (PConstraint _ _ _ _) = True
1803impIn ps arg = any (\p -> not (expArg arg) && pname arg == pname p) ps
1805expArg (PExp _ _ _ _) = True
1806expArg (PConstraint _ _ _ _) = True
1809-- replace non-linear occurrences with _
1811stripLinear :: IState -> PTerm -> PTerm
1812stripLinear i tm = evalState (sl tm) [] where
1813 sl :: PTerm -> State [Name] PTerm
1815 | (_:_) <- lookupTy f (tt_ctxt i)
1816 = return $ PRef fc hl f
1817 | otherwise = do ns <- get
1819 then return $ PHidden (PRef fc hl f) -- Placeholder
1820 else do put (f : ns)
1821 return (PRef fc hl f)
1825 then return $ PHidden (PPatvar fc f) -- Placeholder
1826 else do put (f : ns)
1827 return (PPatvar fc f)
1828 -- Assumption is that variables are all the same in each alternative
1829 sl t@(PAlternative ms b as) = do ns <- get
1831 return (PAlternative ms b as')
1832 where slAlts ns (a : as) = do put ns
1836 slAlts ns [] = return []
1837 sl (PPair fc hls p l r) = do l' <- sl l; r' <- sl r; return (PPair fc hls p l' r')
1838 sl (PDPair fc hls p l t r) = do l' <- sl l
1841 return (PDPair fc hls p l' t' r')
1842 sl (PApp fc fn args) = do fn' <- case fn of
1843 -- Just the args, fn isn't matchable as a var
1844 PRef _ _ _ -> return fn
1846 args' <- mapM slA args
1847 return $ PApp fc fn' args'
1848 where slA (PImp p m l n t) = do t' <- sl t
1849 return $ PImp p m l n t'
1850 slA (PExp p l n t) = do t' <- sl t
1851 return $ PExp p l n t'
1852 slA (PConstraint p l n t)
1854 return $ PConstraint p l n t'
1855 slA (PTacImplicit p l n sc t)
1857 return $ PTacImplicit p l n sc t'
1860-- | Remove functions which aren't applied to anything, which must then
1861-- be resolved by unification. Assume names resolved and alternatives
1862-- filled in (so no ambiguity).
1863stripUnmatchable :: IState -> PTerm -> PTerm
1864stripUnmatchable i (PApp fc fn args) = PApp fc fn (fmap (fmap su) args) where
1865 su :: PTerm -> PTerm
1866 su tm@(PRef fc hl f)
1867 | (Bind n (Pi _ t _) sc :_) <- lookupTy f (tt_ctxt i)
1869 | (TType _ : _) <- lookupTy f (tt_ctxt i)
1871 | (UType _ : _) <- lookupTy f (tt_ctxt i)
1873 su (PApp fc f@(PRef _ _ fn) args)
1874 -- here we use canBeDConName because the impossible pattern
1875 -- check will not necessarily fully resolve constructor names,
1876 -- and these bare names will otherwise get in the way of
1877 -- impossbility checking.
1878 | canBeDConName fn ctxt
1879 = PApp fc f (fmap (fmap su) args)
1881 = PHidden (PApp fc f args)
1882 su (PAlternative ms b alts)
1883 = let alts' = filter (/= Placeholder) (map su alts) in
1884 if null alts' then Placeholder
1885 else PAlternative ms b alts'
1886 su (PPair fc hls p l r) = PPair fc hls p (su l) (su r)
1887 su (PDPair fc hls p l t r) = PDPair fc hls p (su l) (su t) (su r)
1888 su t@(PLam fc _ _ _ _) = PHidden t
1889 su t@(PPi _ _ _ _ _) = PHidden t
1890 su t@(PConstant _ c) | isTypeConst c = PHidden t
1895stripUnmatchable i tm = tm
1898mkPApp fc a f as = let rest = drop a as in
1899 if a == 0 then appRest fc f rest
1900 else appRest fc (PApp fc f (take a as)) rest
1903 appRest fc f (a : as) = appRest fc (PApp fc f [a]) as
1905-- Find 'static' argument positions
1906-- (the declared ones, plus any names in argument position in the declared
1908-- FIXME: It's possible that this really has to happen after elaboration
1910findStatics :: IState -> PTerm -> (PTerm, [Bool])
1911findStatics ist tm = let (ns, ss) = fs tm
1912 in runState (pos ns ss tm) []
1913 where fs (PPi p n fc t sc)
1914 | Static <- pstatic p
1915 = let (ns, ss) = fs sc in
1916 (namesIn [] ist t : ns, n : ss)
1917 | otherwise = let (ns, ss) = fs sc in
1921 inOne n ns = length (filter id (map (elem n) ns)) == 1
1923 pos ns ss (PPi p n fc t sc)
1924 | elem n ss = do sc' <- pos ns ss sc
1927 return (PPi (p { pstatic = Static }) n fc t sc')
1928 | otherwise = do sc' <- pos ns ss sc
1931 return (PPi p n fc t sc')
1932 pos ns ss t = return t
1934-- for 6.12/7 compatibility
1935data EitherErr a b = LeftErr a | RightOK b deriving ( Functor )
1937instance Applicative (EitherErr a) where
1941instance Monad (EitherErr a) where
1944 (LeftErr e) >>= k = LeftErr e
1945 RightOK v >>= k = k v
1947toEither (LeftErr e) = Left e
1948toEither (RightOK ho) = Right ho
1950-- | Syntactic match of a against b, returning pair of variables in a
1951-- and what they match. Returns the pair that failed if not a match.
1952matchClause :: IState -> PTerm -> PTerm -> Either (PTerm, PTerm) [(Name, PTerm)]
1953matchClause = matchClause' False
1955matchClause' :: Bool -> IState -> PTerm -> PTerm -> Either (PTerm, PTerm) [(Name, PTerm)]
1956matchClause' names i x y = checkRpts $ match (fullApp x) (fullApp y) where
1957 matchArg x y = match (fullApp (getTm x)) (fullApp (getTm y))
1959 fullApp (PApp _ (PApp fc f args) xs) = fullApp (PApp fc f (args ++ xs))
1962 match' x y = match (fullApp x) (fullApp y)
1963 match (PApp _ (PRef _ _ (NS (UN fi) [b])) [_,_,x]) x'
1964 | fi == txt "fromInteger" && b == txt "builtins",
1965 PConstant _ (I _) <- getTm x = match (getTm x) x'
1966 match x' (PApp _ (PRef _ _ (NS (UN fi) [b])) [_,_,x])
1967 | fi == txt "fromInteger" && b == txt "builtins",
1968 PConstant _ (I _) <- getTm x = match (getTm x) x'
1969 match (PApp _ (PRef _ _ (UN l)) [_,x]) x' | l == txt "lazy" = match (getTm x) x'
1970 match x (PApp _ (PRef _ _ (UN l)) [_,x']) | l == txt "lazy" = match x (getTm x')
1971 match (PApp _ f args) (PApp _ f' args')
1972 | length args == length args'
1973 = do mf <- match' f f'
1974 ms <- zipWithM matchArg args args'
1975 return (mf ++ concat ms)
1976 match (PRef f hl n) (PApp _ x []) = match (PRef f hl n) x
1977 match (PPatvar f n) xr = match (PRef f [f] n) xr
1978 match xr (PPatvar f n) = match xr (PRef f [f] n)
1979 match (PApp _ x []) (PRef f hl n) = match x (PRef f hl n)
1980 match (PRef _ _ n) tm@(PRef _ _ n')
1981 | n == n' && not names &&
1982 (not (isConName n (tt_ctxt i) || isFnName n (tt_ctxt i))
1983 || tm == Placeholder)
1985 -- if one namespace is missing, drop the other
1986 | n == n' || n == dropNS n' || dropNS n == n' = return []
1987 where dropNS (NS n _) = n
1989 match (PRef _ _ n) tm
1990 | not names && (not (isConName n (tt_ctxt i) ||
1991 isFnName n (tt_ctxt i)) || tm == Placeholder)
1993 match (PRewrite _ l r _) (PRewrite _ l' r' _)
1994 = do ml <- match' l l'
1997 match (PTyped l r) (PTyped l' r') = do ml <- match l l'
2000 match (PTyped l r) x = match l x
2001 match x (PTyped l r) = match x l
2002 match (PPair _ _ _ l r) (PPair _ _ _ l' r') = do ml <- match' l l'
2005 match (PDPair _ _ _ l t r) (PDPair _ _ _ l' t' r') = do ml <- match' l l'
2008 return (ml ++ mt ++ mr)
2009 match (PAlternative _ a as) (PAlternative _ a' as')
2010 = do ms <- zipWithM match' as as'
2012 match a@(PAlternative _ _ as) b
2013 = do let ms = zipWith match' as (repeat b)
2014 case (rights (map toEither ms)) of
2017 match (PCase _ _ _) _ = return [] -- lifted out
2018 match (PMetavar _ _) _ = return [] -- modified
2019 match (PInferRef _ _ _) _ = return [] -- modified
2020 match (PQuote _) _ = return []
2021 match (PProof _) _ = return []
2022 match (PTactics _) _ = return []
2023 match (PResolveTC _) (PResolveTC _) = return []
2024 match (PTrue _ _) (PTrue _ _) = return []
2025 match (PReturn _) (PReturn _) = return []
2026 match (PPi _ _ _ t s) (PPi _ _ _ t' s') = do mt <- match' t t'
2029 match (PLam _ _ _ t s) (PLam _ _ _ t' s') = do mt <- match' t t'
2032 match (PLet _ _ _ t ty s) (PLet _ _ _ t' ty' s') = do mt <- match' t t'
2033 mty <- match' ty ty'
2035 return (mt ++ mty ++ ms)
2036 match (PHidden x) (PHidden y)
2037 | RightOK xs <- match x y = return xs -- to collect variables
2038 | otherwise = return [] -- Otherwise hidden things are unmatchable
2040 | RightOK xs <- match x y = return xs
2041 | otherwise = return []
2043 | RightOK xs <- match x y = return xs
2044 | otherwise = return []
2045 match (PUnifyLog x) y = match' x y
2046 match x (PUnifyLog y) = match' x y
2047 match (PNoImplicits x) y = match' x y
2048 match x (PNoImplicits y) = match' x y
2049 match Placeholder _ = return []
2050 match _ Placeholder = return []
2051 match (PResolveTC _) _ = return []
2052 match a b | a == b = return []
2053 | otherwise = LeftErr (a, b)
2055 checkRpts (RightOK ms) = check ms where
2057 | Just t' <- lookup n xs = if t/=t' && t/=Placeholder && t'/=Placeholder
2060 check (_:xs) = check xs
2062 checkRpts (LeftErr x) = Left x
2064substMatches :: [(Name, PTerm)] -> PTerm -> PTerm
2065substMatches ms = substMatchesShadow ms []
2067substMatchesShadow :: [(Name, PTerm)] -> [Name] -> PTerm -> PTerm
2068substMatchesShadow [] shs t = t
2069substMatchesShadow ((n,tm):ns) shs t
2070 = substMatchShadow n shs tm (substMatchesShadow ns shs t)
2072substMatch :: Name -> PTerm -> PTerm -> PTerm
2073substMatch n = substMatchShadow n []
2075substMatchShadow :: Name -> [Name] -> PTerm -> PTerm -> PTerm
2076substMatchShadow n shs tm t = sm shs t where
2077 sm xs (PRef _ _ n') | n == n' = tm
2078 sm xs (PLam fc x xfc t sc) = PLam fc x xfc (sm xs t) (sm xs sc)
2079 sm xs (PPi p x fc t sc)
2081 = let x' = nextName x in
2082 PPi p x' fc (sm (x':xs) (substMatch x (PRef emptyFC [] x') t))
2083 (sm (x':xs) (substMatch x (PRef emptyFC [] x') sc))
2084 | otherwise = PPi p x fc (sm xs t) (sm (x : xs) sc)
2085 sm xs (PApp f x as) = fullApp $ PApp f (sm xs x) (map (fmap (sm xs)) as)
2086 sm xs (PCase f x as) = PCase f (sm xs x) (map (pmap (sm xs)) as)
2087 sm xs (PIfThenElse fc c t f) = PIfThenElse fc (sm xs c) (sm xs t) (sm xs f)
2088 sm xs (PRewrite f x y tm) = PRewrite f (sm xs x) (sm xs y)
2090 sm xs (PTyped x y) = PTyped (sm xs x) (sm xs y)
2091 sm xs (PPair f hls p x y) = PPair f hls p (sm xs x) (sm xs y)
2092 sm xs (PDPair f hls p x t y) = PDPair f hls p (sm xs x) (sm xs t) (sm xs y)
2093 sm xs (PAlternative ms a as) = PAlternative ms a (map (sm xs) as)
2094 sm xs (PHidden x) = PHidden (sm xs x)
2095 sm xs (PUnifyLog x) = PUnifyLog (sm xs x)
2096 sm xs (PNoImplicits x) = PNoImplicits (sm xs x)
2097 sm xs (PRunElab fc script ns) = PRunElab fc (sm xs script) ns
2098 sm xs (PConstSugar fc tm) = PConstSugar fc (sm xs tm)
2101 fullApp (PApp _ (PApp fc f args) xs) = fullApp (PApp fc f (args ++ xs))
2104shadow :: Name -> Name -> PTerm -> PTerm
2105shadow n n' t = sm t where
2106 sm (PRef fc hl x) | n == x = PRef fc hl n'
2107 sm (PLam fc x xfc t sc) | n /= x = PLam fc x xfc (sm t) (sm sc)
2108 | otherwise = PLam fc x xfc (sm t) sc
2109 sm (PPi p x fc t sc) | n /= x = PPi p x fc (sm t) (sm sc)
2110 | otherwise = PPi p x fc (sm t) sc
2111 sm (PLet fc x xfc t v sc) | n /= x = PLet fc x xfc (sm t) (sm v) (sm sc)
2112 | otherwise = PLet fc x xfc (sm t) (sm v) sc
2113 sm (PApp f x as) = PApp f (sm x) (map (fmap sm) as)
2114 sm (PAppBind f x as) = PAppBind f (sm x) (map (fmap sm) as)
2115 sm (PCase f x as) = PCase f (sm x) (map (pmap sm) as)
2116 sm (PIfThenElse fc c t f) = PIfThenElse fc (sm c) (sm t) (sm f)
2117 sm (PRewrite f x y tm) = PRewrite f (sm x) (sm y) (fmap sm tm)
2118 sm (PTyped x y) = PTyped (sm x) (sm y)
2119 sm (PPair f hls p x y) = PPair f hls p (sm x) (sm y)
2120 sm (PDPair f hls p x t y) = PDPair f hls p (sm x) (sm t) (sm y)
2121 sm (PAlternative ms a as) = PAlternative ms a (map sm as)
2122 sm (PTactics ts) = PTactics (map (fmap sm) ts)
2123 sm (PProof ts) = PProof (map (fmap sm) ts)
2124 sm (PHidden x) = PHidden (sm x)
2125 sm (PUnifyLog x) = PUnifyLog (sm x)
2126 sm (PNoImplicits x) = PNoImplicits (sm x)
2127 sm (PCoerced t) = PCoerced (sm t)
2130-- | Rename any binders which are repeated (so that we don't have to mess
2131-- about with shadowing anywhere else).
2132mkUniqueNames :: [Name] -> [(Name, Name)] -> PTerm -> PTerm
2133mkUniqueNames env shadows tm
2134 = evalState (mkUniq initMap tm) (S.fromList env) where
2136 initMap = M.fromList shadows
2138 inScope :: S.Set Name
2139 inScope = S.fromList $ boundNamesIn tm
2141 mkUniqA nmap arg = do t' <- mkUniq nmap (getTm arg)
2142 return (arg { getTm = t' })
2144 -- Initialise the unique name with the environment length (so we're not
2145 -- looking for too long...)
2146 initN (UN n) l = UN $ txt (str n ++ show l)
2147 initN (MN i s) l = MN (i+l) s
2150 -- FIXME: Probably ought to do this for completeness! It's fine as
2151 -- long as there are no bindings inside tactics though.
2152 mkUniqT nmap tac = return tac
2154 mkUniq :: M.Map Name Name -> PTerm -> State (S.Set Name) PTerm
2155 mkUniq nmap (PLam fc n nfc ty sc)
2159 then do let n' = uniqueNameSet (initN n (S.size env))
2160 (S.union env inScope)
2161 return (n', sc) -- shadow n n' sc)
2163 put (S.insert n' env)
2164 let nmap' = M.insert n n' nmap
2165 ty' <- mkUniq nmap ty
2166 sc'' <- mkUniq nmap' sc'
2167 return $! PLam fc n' nfc ty' sc''
2168 mkUniq nmap (PPi p n fc ty sc)
2172 then do let n' = uniqueNameSet (initN n (S.size env))
2173 (S.union env inScope)
2174 return (n', sc) -- shadow n n' sc)
2176 put (S.insert n' env)
2177 let nmap' = M.insert n n' nmap
2178 ty' <- mkUniq nmap ty
2179 sc'' <- mkUniq nmap' sc'
2180 return $! PPi p n' fc ty' sc''
2181 mkUniq nmap (PLet fc n nfc ty val sc)
2185 then do let n' = uniqueNameSet (initN n (S.size env))
2186 (S.union env inScope)
2187 return (n', sc) -- shadow n n' sc)
2189 put (S.insert n' env)
2190 let nmap' = M.insert n n' nmap
2191 ty' <- mkUniq nmap ty; val' <- mkUniq nmap val
2192 sc'' <- mkUniq nmap' sc'
2193 return $! PLet fc n' nfc ty' val' sc''
2194 mkUniq nmap (PApp fc t args)
2195 = do t' <- mkUniq nmap t
2196 args' <- mapM (mkUniqA nmap) args
2197 return $! PApp fc t' args'
2198 mkUniq nmap (PAppBind fc t args)
2199 = do t' <- mkUniq nmap t
2200 args' <- mapM (mkUniqA nmap) args
2201 return $! PAppBind fc t' args'
2202 mkUniq nmap (PCase fc t alts)
2203 = do t' <- mkUniq nmap t
2204 alts' <- mapM (\(x,y)-> do x' <- mkUniq nmap x; y' <- mkUniq nmap y
2205 return (x', y')) alts
2206 return $! PCase fc t' alts'
2207 mkUniq nmap (PIfThenElse fc c t f)
2208 = liftM3 (PIfThenElse fc) (mkUniq nmap c) (mkUniq nmap t) (mkUniq nmap f)
2209 mkUniq nmap (PPair fc hls p l r)
2210 = do l' <- mkUniq nmap l; r' <- mkUniq nmap r
2211 return $! PPair fc hls p l' r'
2212 mkUniq nmap (PDPair fc hls p (PRef fc' hls' n) t sc)
2215 (n', sc') <- if n `S.member` env
2216 then do let n' = uniqueNameSet n (S.union env inScope)
2217 return (n', sc) -- shadow n n' sc)
2219 put (S.insert n' env)
2220 let nmap' = M.insert n n' nmap
2222 sc'' <- mkUniq nmap' sc'
2223 return $! PDPair fc hls p (PRef fc' hls' n') t' sc''
2224 mkUniq nmap (PDPair fc hls p l t r)
2225 = do l' <- mkUniq nmap l; t' <- mkUniq nmap t; r' <- mkUniq nmap r
2226 return $! PDPair fc hls p l' t' r'
2227 mkUniq nmap (PAlternative ns b as)
2228 -- store the nmap and defer the rest until we've pruned the set
2229 -- during elaboration
2230 = return $ PAlternative (M.toList nmap ++ ns) b as
2231 mkUniq nmap (PHidden t) = liftM PHidden (mkUniq nmap t)
2232 mkUniq nmap (PUnifyLog t) = liftM PUnifyLog (mkUniq nmap t)
2233 mkUniq nmap (PDisamb n t) = liftM (PDisamb n) (mkUniq nmap t)
2234 mkUniq nmap (PNoImplicits t) = liftM PNoImplicits (mkUniq nmap t)
2235 mkUniq nmap (PProof ts) = liftM PProof (mapM (mkUniqT nmap) ts)
2236 mkUniq nmap (PTactics ts) = liftM PTactics (mapM (mkUniqT nmap) ts)
2237 mkUniq nmap (PRunElab fc ts ns) = liftM (\tm -> PRunElab fc tm ns) (mkUniq nmap ts)
2238 mkUniq nmap (PConstSugar fc tm) = liftM (PConstSugar fc) (mkUniq nmap tm)
2239 mkUniq nmap (PCoerced tm) = liftM PCoerced (mkUniq nmap tm)
2240 mkUniq nmap t = return $ shadowAll (M.toList nmap) t
2243 shadowAll ((n, n') : ns) t = shadow n n' (shadowAll ns t)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list