on 40e5b77 help sign in
Idris-dev/src/Idris/AbsSyntax.hs
1728 lines 71 kB history raw
1{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, DeriveFunctor,
2 TypeSynonymInstances, PatternGuards #-}
4module Idris.AbsSyntax(module Idris.AbsSyntax, module Idris.AbsSyntaxTree) where
6import Idris.Core.TT
7import Idris.Core.Evaluate
8import Idris.Core.Elaborate hiding (Tactic(..))
9import Idris.Core.Typecheck
10import Idris.AbsSyntaxTree
11import Idris.Colours
12import Idris.IdeSlave
13import IRTS.CodegenCommon
14import Util.DynamicLinker
16import Paths_idris
18import System.Console.Haskeline
19import System.IO
21import Control.Monad.State
22import Control.Monad.Error(throwError)
24import Data.List
25import Data.Char
26import qualified Data.Text as T
27import Data.Either
28import Data.Maybe
29import Data.Word (Word)
31import Debug.Trace
33import Control.Monad.Error (throwError, catchError)
34import System.IO.Error(isUserError, ioeGetErrorString, tryIOError)
36import Util.Pretty
37import Util.System
39getContext :: Idris Context
40getContext = do i <- getIState; return (tt_ctxt i)
42forCodegen :: Codegen -> [(Codegen, a)] -> [a]
43forCodegen tgt xs = [x | (tgt', x) <- xs, tgt == tgt']
45getObjectFiles :: Codegen -> Idris [FilePath]
46getObjectFiles tgt = do i <- getIState; return (forCodegen tgt $ idris_objs i)
48addObjectFile :: Codegen -> FilePath -> Idris ()
49addObjectFile tgt f = do i <- getIState; putIState $ i { idris_objs = nub $ (tgt, f) : idris_objs i }
51getLibs :: Codegen -> Idris [String]
52getLibs tgt = do i <- getIState; return (forCodegen tgt $ idris_libs i)
54addLib :: Codegen -> String -> Idris ()
55addLib tgt f = do i <- getIState; putIState $ i { idris_libs = nub $ (tgt, f) : idris_libs i }
57getFlags :: Codegen -> Idris [String]
58getFlags tgt = do i <- getIState; return (forCodegen tgt $ idris_cgflags i)
60addFlag :: Codegen -> String -> Idris ()
61addFlag tgt f = do i <- getIState; putIState $ i { idris_cgflags = nub $ (tgt, f) : idris_cgflags i }
63addDyLib :: [String] -> Idris (Either DynamicLib String)
64addDyLib libs = do i <- getIState
65 let ls = idris_dynamic_libs i
66 case mapMaybe (findDyLib ls) libs of
67 x:_ -> return (Left x)
68 [] -> do
69 handle <- lift . lift $ mapM (\l -> catchIO (tryLoadLib l) (\_ -> return Nothing)) $ libs
70 case msum handle of
71 Nothing -> return (Right $ "Could not load dynamic alternatives \"" ++
72 concat (intersperse "," libs) ++ "\"")
73 Just x -> do putIState $ i { idris_dynamic_libs = x:ls }
74 return (Left x)
75 where findDyLib :: [DynamicLib] -> String -> Maybe DynamicLib
76 findDyLib [] l = Nothing
77 findDyLib (lib:libs) l | l == lib_name lib = Just lib
78 | otherwise = findDyLib libs l
81addHdr :: Codegen -> String -> Idris ()
82addHdr tgt f = do i <- getIState; putIState $ i { idris_hdrs = nub $ (tgt, f) : idris_hdrs i }
84addLangExt :: LanguageExt -> Idris ()
85addLangExt TypeProviders = do i <- getIState
86 putIState $ i {
87 idris_language_extensions = TypeProviders : idris_language_extensions i
88 }
89addLangExt ErrorReflection = do i <- getIState
90 putIState $ i {
91 idris_language_extensions = ErrorReflection : idris_language_extensions i
92 }
94addTrans :: (Term, Term) -> Idris ()
95addTrans t = do i <- getIState
96 putIState $ i { idris_transforms = t : idris_transforms i }
98addErrRev :: (Term, Term) -> Idris ()
99addErrRev t = do i <- getIState
100 putIState $ i { idris_errRev = t : idris_errRev i }
102totcheck :: (FC, Name) -> Idris ()
103totcheck n = do i <- getIState; putIState $ i { idris_totcheck = idris_totcheck i ++ [n] }
105defer_totcheck :: (FC, Name) -> Idris ()
106defer_totcheck n
107 = do i <- getIState;
108 putIState $ i { idris_defertotcheck = nub (idris_defertotcheck i ++ [n]) }
110clear_totcheck :: Idris ()
111clear_totcheck = do i <- getIState; putIState $ i { idris_totcheck = [] }
113setFlags :: Name -> [FnOpt] -> Idris ()
114setFlags n fs = do i <- getIState; putIState $ i { idris_flags = addDef n fs (idris_flags i) }
116setAccessibility :: Name -> Accessibility -> Idris ()
117setAccessibility n a
118 = do i <- getIState
119 let ctxt = setAccess n a (tt_ctxt i)
120 putIState $ i { tt_ctxt = ctxt }
122setTotality :: Name -> Totality -> Idris ()
123setTotality n a
124 = do i <- getIState
125 let ctxt = setTotal n a (tt_ctxt i)
126 putIState $ i { tt_ctxt = ctxt }
128getTotality :: Name -> Idris Totality
129getTotality n
130 = do i <- getIState
131 case lookupTotal n (tt_ctxt i) of
132 [t] -> return t
133 _ -> return (Total [])
135-- Get coercions which might return the required type
136getCoercionsTo :: IState -> Type -> [Name]
137getCoercionsTo i ty =
138 let cs = idris_coercions i
139 (fn,_) = unApply (getRetTy ty) in
140 findCoercions fn cs
141 where findCoercions t [] = []
142 findCoercions t (n : ns) =
143 let ps = case lookupTy n (tt_ctxt i) of
144 [ty'] -> case unApply (getRetTy ty') of
145 (t', _) ->
146 if t == t' then [n] else []
147 _ -> [] in
148 ps ++ findCoercions t ns
150addToCG :: Name -> CGInfo -> Idris ()
151addToCG n cg
152 = do i <- getIState
153 putIState $ i { idris_callgraph = addDef n cg (idris_callgraph i) }
155-- Trace all the names in a call graph starting at the given name
156getAllNames :: Name -> Idris [Name]
157getAllNames n = allNames [] n
159allNames :: [Name] -> Name -> Idris [Name]
160allNames ns n | n `elem` ns = return []
161allNames ns n = do i <- getIState
162 case lookupCtxtExact n (idris_callgraph i) of
163 [ns'] -> do more <- mapM (allNames (n:ns)) (map fst (calls ns'))
164 return (nub (n : concat more))
165 _ -> return [n]
167addCoercion :: Name -> Idris ()
168addCoercion n = do i <- getIState
169 putIState $ i { idris_coercions = nub $ n : idris_coercions i }
171addDocStr :: Name -> String -> Idris ()
172addDocStr n doc
173 = do i <- getIState
174 putIState $ i { idris_docstrings = addDef n doc (idris_docstrings i) }
176addNameHint :: Name -> Name -> Idris ()
177addNameHint ty n
178 = do i <- getIState
179 ty' <- case lookupCtxtName ty (idris_implicits i) of
180 [(tyn, _)] -> return tyn
181 [] -> throwError (NoSuchVariable ty)
182 tyns -> throwError (CantResolveAlts (map show (map fst tyns)))
183 let ns' = case lookupCtxt ty' (idris_namehints i) of
184 [ns] -> ns ++ [n]
185 _ -> [n]
186 putIState $ i { idris_namehints = addDef ty' ns' (idris_namehints i) }
188getNameHints :: IState -> Name -> [Name]
189getNameHints i (UN arr) | arr == txt "->" = [sUN "f",sUN "g"]
190getNameHints i n =
191 case lookupCtxt n (idris_namehints i) of
192 [ns] -> ns
193 _ -> []
195addToCalledG :: Name -> [Name] -> Idris ()
196addToCalledG n ns = return () -- TODO
198-- Add a class instance function. Dodgy hack: Put integer instances first in the
199-- list so they are resolved by default.
200-- Dodgy hack 2: put constraint chasers (@@) last
202addInstance :: Bool -> Name -> Name -> Idris ()
203addInstance int n i
204 = do ist <- getIState
205 case lookupCtxt n (idris_classes ist) of
206 [CI a b c d e ins] ->
207 do let cs = addDef n (CI a b c d e (addI i ins)) (idris_classes ist)
208 putIState $ ist { idris_classes = cs }
209 _ -> do let cs = addDef n (CI (sMN 0 "none") [] [] [] [] [i]) (idris_classes ist)
210 putIState $ ist { idris_classes = cs }
211 where addI i ins | int = i : ins
212 | chaser n = ins ++ [i]
213 | otherwise = insI i ins
214 insI i [] = [i]
215 insI i (n : ns) | chaser n = i : n : ns
216 | otherwise = n : insI i ns
218 chaser (UN nm)
219 | ('@':'@':_) <- str nm = True
220 chaser (NS n _) = chaser n
221 chaser _ = False
223addClass :: Name -> ClassInfo -> Idris ()
224addClass n i
225 = do ist <- getIState
226 let i' = case lookupCtxt n (idris_classes ist) of
227 [c] -> c { class_instances = class_instances i }
228 _ -> i
229 putIState $ ist { idris_classes = addDef n i' (idris_classes ist) }
231addIBC :: IBCWrite -> Idris ()
232addIBC ibc@(IBCDef n)
233 = do i <- getIState
234 when (notDef (ibc_write i)) $
235 putIState $ i { ibc_write = ibc : ibc_write i }
236 where notDef [] = True
237 notDef (IBCDef n': is) | n == n' = False
238 notDef (_ : is) = notDef is
239addIBC ibc = do i <- getIState; putIState $ i { ibc_write = ibc : ibc_write i }
241clearIBC :: Idris ()
242clearIBC = do i <- getIState; putIState $ i { ibc_write = [] }
244resetNameIdx :: Idris ()
245resetNameIdx = do i <- getIState
246 put (i { idris_nameIdx = (0, emptyContext) })
248-- Used to preserve sharing of names
249addNameIdx :: Name -> Idris (Int, Name)
250addNameIdx n = do i <- getIState
251 let (i', x) = addNameIdx' i n
252 return x
254addNameIdx' :: IState -> Name -> (IState, (Int, Name))
255addNameIdx' i n
256 = let idxs = snd (idris_nameIdx i) in
257 case lookupCtxt n idxs of
258 [x] -> (i, x)
259 _ -> let i' = fst (idris_nameIdx i) + 1 in
260 (i { idris_nameIdx = (i', addDef n (i', n) idxs) }, (i', n))
262getHdrs :: Codegen -> Idris [String]
263getHdrs tgt = do i <- getIState; return (forCodegen tgt $ idris_hdrs i)
265setErrLine :: Int -> Idris ()
266setErrLine x = do i <- getIState;
267 case (errLine i) of
268 Nothing -> putIState $ i { errLine = Just x }
269 Just _ -> return ()
271clearErr :: Idris ()
272clearErr = do i <- getIState
273 putIState $ i { errLine = Nothing }
275getSO :: Idris (Maybe String)
276getSO = do i <- getIState
277 return (compiled_so i)
279setSO :: Maybe String -> Idris ()
280setSO s = do i <- getIState
281 putIState $ (i { compiled_so = s })
283getIState :: Idris IState
284getIState = get
286putIState :: IState -> Idris ()
287putIState = put
289-- | A version of liftIO that puts errors into the exception type of the Idris monad
290runIO :: IO a -> Idris a
291runIO x = liftIO (tryIOError x) >>= either (throwError . Msg . show) return
292-- TODO: create specific Idris exceptions for specific IO errors such as "openFile: does not exist"
294getName :: Idris Int
295getName = do i <- getIState;
296 let idx = idris_name i;
297 putIState $ (i { idris_name = idx + 1 })
298 return idx
300addInternalApp :: FilePath -> Int -> PTerm -> Idris ()
301addInternalApp fp l t
302 = do i <- getIState
303 putIState (i { idris_lineapps = ((fp, l), t) : idris_lineapps i })
305getInternalApp :: FilePath -> Int -> Idris PTerm
306getInternalApp fp l = do i <- getIState
307 case lookup (fp, l) (idris_lineapps i) of
308 Just n' -> return n'
309 Nothing -> return Placeholder
310 -- TODO: What if it's not there?
312-- Pattern definitions are only used for coverage checking, so erase them
313-- when we're done
314clearOrigPats :: Idris ()
315clearOrigPats = do i <- get
316 let ps = idris_patdefs i
317 let ps' = mapCtxt (\ (_,miss) -> ([], miss)) ps
318 put (i { idris_patdefs = ps' })
320-- Erase types from Ps in the context (basically ending up with what's in
321-- the .ibc, which is all we need after all the analysis is done)
322clearPTypes :: Idris ()
323clearPTypes = do i <- get
324 let ctxt = tt_ctxt i
325 put (i { tt_ctxt = mapDefCtxt pErase ctxt })
326 where pErase (CaseOp c t tys orig tot cds)
327 = CaseOp c t tys orig [] (pErase' cds)
328 pErase x = x
329 pErase' (CaseDefs _ (cs, c) _ rs)
330 = let c' = (cs, fmap pEraseType c) in
331 CaseDefs c' c' c' rs
333checkUndefined :: FC -> Name -> Idris ()
334checkUndefined fc n
335 = do i <- getContext
336 case lookupTy n i of
337 (_:_) -> throwError . Msg $ show fc ++ ":" ++
338 show n ++ " already defined"
339 _ -> return ()
341isUndefined :: FC -> Name -> Idris Bool
342isUndefined fc n
343 = do i <- getContext
344 case lookupTy n i of
345 (_:_) -> return False
346 _ -> return True
348setContext :: Context -> Idris ()
349setContext ctxt = do i <- getIState; putIState $ (i { tt_ctxt = ctxt } )
351updateContext :: (Context -> Context) -> Idris ()
352updateContext f = do i <- getIState; putIState $ (i { tt_ctxt = f (tt_ctxt i) } )
354addConstraints :: FC -> (Int, [UConstraint]) -> Idris ()
355addConstraints fc (v, cs)
356 = do i <- getIState
357 let ctxt = tt_ctxt i
358 let ctxt' = ctxt { uconstraints = cs ++ uconstraints ctxt,
359 next_tvar = v }
360 let ics = zip cs (repeat fc) ++ idris_constraints i
361 putIState $ i { tt_ctxt = ctxt', idris_constraints = ics }
363addDeferred = addDeferred' Ref
364addDeferredTyCon = addDeferred' (TCon 0 0)
366addDeferred' :: NameType -> [(Name, (Int, Maybe Name, Type, Bool))] -> Idris ()
367addDeferred' nt ns
368 = do mapM_ (\(n, (i, _, t, _)) -> updateContext (addTyDecl n nt (tidyNames [] t))) ns
369 i <- getIState
370 putIState $ i { idris_metavars = map (\(n, (i, top, _, isTopLevel)) -> (n, (top, i, isTopLevel))) ns ++
371 idris_metavars i }
372 where tidyNames used (Bind (MN i x) b sc)
373 = let n' = uniqueName (UN x) used in
374 Bind n' b $ tidyNames (n':used) sc
375 tidyNames used (Bind n b sc)
376 = let n' = uniqueName n used in
377 Bind n' b $ tidyNames (n':used) sc
378 tidyNames used b = b
380solveDeferred :: Name -> Idris ()
381solveDeferred n = do i <- getIState
382 putIState $ i { idris_metavars =
383 filter (\(n', _) -> n/=n')
384 (idris_metavars i) }
386getUndefined :: Idris [Name]
387getUndefined = do i <- getIState
388 return (map fst (idris_metavars i) \\ primDefs)
390ihPrintResult :: Handle -> String -> Idris ()
391ihPrintResult h s = do i <- getIState
392 case idris_outputmode i of
393 RawOutput -> case s of
394 "" -> return ()
395 s -> runIO $ hPutStrLn h s
396 IdeSlave n ->
397 let good = SexpList [SymbolAtom "ok", toSExp s] in
398 runIO $ hPutStrLn h $ convSExp "return" good n
400ihPrintError :: Handle -> String -> Idris ()
401ihPrintError h s = do i <- getIState
402 case idris_outputmode i of
403 RawOutput -> case s of
404 "" -> return ()
405 s -> runIO $ hPutStrLn h s
406 IdeSlave n ->
407 let good = SexpList [SymbolAtom "error", toSExp s] in
408 runIO . hPutStrLn h $ convSExp "return" good n
410ihputStrLn :: Handle -> String -> Idris ()
411ihputStrLn h s = do i <- getIState
412 case idris_outputmode i of
413 RawOutput -> runIO $ hPutStrLn h s
414 IdeSlave n -> runIO . hPutStrLn h $ convSExp "write-string" s n
416iputStrLn = ihputStrLn stdout
417iPrintError = ihPrintError stdout
418iPrintResult = ihPrintResult stdout
419iWarn = ihWarn stdout
421ideslavePutSExp :: SExpable a => String -> a -> Idris ()
422ideslavePutSExp cmd info = do i <- getIState
423 case idris_outputmode i of
424 IdeSlave n -> runIO . putStrLn $ convSExp cmd info n
425 _ -> return ()
427-- this needs some typing magic and more structured output towards emacs
428iputGoal :: String -> Idris ()
429iputGoal s = do i <- getIState
430 case idris_outputmode i of
431 RawOutput -> runIO $ putStrLn s
432 IdeSlave n -> runIO . putStrLn $ convSExp "write-goal" s n
434isetPrompt :: String -> Idris ()
435isetPrompt p = do i <- getIState
436 case idris_outputmode i of
437 IdeSlave n -> runIO . putStrLn $ convSExp "set-prompt" p n
439ihWarn :: Handle -> FC -> String -> Idris ()
440ihWarn h fc err = do i <- getIState
441 case idris_outputmode i of
442 RawOutput -> runIO $ hPutStrLn h (show fc ++ ":" ++ err)
443 IdeSlave n -> runIO $ hPutStrLn h $ convSExp "warning" (fc_fname fc, fc_line fc, fc_column fc, err) n
445setLogLevel :: Int -> Idris ()
446setLogLevel l = do i <- getIState
447 let opts = idris_options i
448 let opt' = opts { opt_logLevel = l }
449 putIState $ i { idris_options = opt' }
451setCmdLine :: [Opt] -> Idris ()
452setCmdLine opts = do i <- getIState
453 let iopts = idris_options i
454 putIState $ i { idris_options = iopts { opt_cmdline = opts } }
456getCmdLine :: Idris [Opt]
457getCmdLine = do i <- getIState
458 return (opt_cmdline (idris_options i))
460getDumpDefun :: Idris (Maybe FilePath)
461getDumpDefun = do i <- getIState
462 return $ findC (opt_cmdline (idris_options i))
463 where findC [] = Nothing
464 findC (DumpDefun x : _) = Just x
465 findC (_ : xs) = findC xs
467getDumpCases :: Idris (Maybe FilePath)
468getDumpCases = do i <- getIState
469 return $ findC (opt_cmdline (idris_options i))
470 where findC [] = Nothing
471 findC (DumpCases x : _) = Just x
472 findC (_ : xs) = findC xs
474logLevel :: Idris Int
475logLevel = do i <- getIState
476 return (opt_logLevel (idris_options i))
478setErrContext :: Bool -> Idris ()
479setErrContext t = do i <- getIState
480 let opts = idris_options i
481 let opt' = opts { opt_errContext = t }
482 putIState $ i { idris_options = opt' }
484errContext :: Idris Bool
485errContext = do i <- getIState
486 return (opt_errContext (idris_options i))
488useREPL :: Idris Bool
489useREPL = do i <- getIState
490 return (opt_repl (idris_options i))
492setREPL :: Bool -> Idris ()
493setREPL t = do i <- getIState
494 let opts = idris_options i
495 let opt' = opts { opt_repl = t }
496 putIState $ i { idris_options = opt' }
498setNoBanner :: Bool -> Idris ()
499setNoBanner n = do i <- getIState
500 let opts = idris_options i
501 let opt' = opts {opt_nobanner = n}
502 putIState $ i { idris_options = opt' }
504getNoBanner :: Idris Bool
505getNoBanner = do i <- getIState
506 let opts = idris_options i
507 return (opt_nobanner opts)
509setQuiet :: Bool -> Idris ()
510setQuiet q = do i <- getIState
511 let opts = idris_options i
512 let opt' = opts { opt_quiet = q }
513 putIState $ i { idris_options = opt' }
515getQuiet :: Idris Bool
516getQuiet = do i <- getIState
517 let opts = idris_options i
518 return (opt_quiet opts)
520setCodegen :: Codegen -> Idris ()
521setCodegen t = do i <- getIState
522 let opts = idris_options i
523 let opt' = opts { opt_codegen = t }
524 putIState $ i { idris_options = opt' }
526codegen :: Idris Codegen
527codegen = do i <- getIState
528 return (opt_codegen (idris_options i))
530setOutputTy :: OutputType -> Idris ()
531setOutputTy t = do i <- getIState
532 let opts = idris_options i
533 let opt' = opts { opt_outputTy = t }
534 putIState $ i { idris_options = opt' }
536outputTy :: Idris OutputType
537outputTy = do i <- getIState
538 return $ opt_outputTy $ idris_options i
540setIdeSlave :: Bool -> Idris ()
541setIdeSlave True = do i <- getIState
542 putIState $ i { idris_outputmode = (IdeSlave 0), idris_colourRepl = False }
543setIdeSlave False = return ()
545setTargetTriple :: String -> Idris ()
546setTargetTriple t = do i <- getIState
547 let opts = idris_options i
548 opt' = opts { opt_triple = t }
549 putIState $ i { idris_options = opt' }
551targetTriple :: Idris String
552targetTriple = do i <- getIState
553 return (opt_triple (idris_options i))
555setTargetCPU :: String -> Idris ()
556setTargetCPU t = do i <- getIState
557 let opts = idris_options i
558 opt' = opts { opt_cpu = t }
559 putIState $ i { idris_options = opt' }
561targetCPU :: Idris String
562targetCPU = do i <- getIState
563 return (opt_cpu (idris_options i))
565setOptLevel :: Word -> Idris ()
566setOptLevel t = do i <- getIState
567 let opts = idris_options i
568 opt' = opts { opt_optLevel = t }
569 putIState $ i { idris_options = opt' }
571optLevel :: Idris Word
572optLevel = do i <- getIState
573 return (opt_optLevel (idris_options i))
575verbose :: Idris Bool
576verbose = do i <- getIState
577 return (opt_verbose (idris_options i))
579setVerbose :: Bool -> Idris ()
580setVerbose t = do i <- getIState
581 let opts = idris_options i
582 let opt' = opts { opt_verbose = t }
583 putIState $ i { idris_options = opt' }
585typeInType :: Idris Bool
586typeInType = do i <- getIState
587 return (opt_typeintype (idris_options i))
589setTypeInType :: Bool -> Idris ()
590setTypeInType t = do i <- getIState
591 let opts = idris_options i
592 let opt' = opts { opt_typeintype = t }
593 putIState $ i { idris_options = opt' }
595coverage :: Idris Bool
596coverage = do i <- getIState
597 return (opt_coverage (idris_options i))
599setCoverage :: Bool -> Idris ()
600setCoverage t = do i <- getIState
601 let opts = idris_options i
602 let opt' = opts { opt_coverage = t }
603 putIState $ i { idris_options = opt' }
605setIBCSubDir :: FilePath -> Idris ()
606setIBCSubDir fp = do i <- getIState
607 let opts = idris_options i
608 let opt' = opts { opt_ibcsubdir = fp }
609 putIState $ i { idris_options = opt' }
611valIBCSubDir :: IState -> Idris FilePath
612valIBCSubDir i = return (opt_ibcsubdir (idris_options i))
614addImportDir :: FilePath -> Idris ()
615addImportDir fp = do i <- getIState
616 let opts = idris_options i
617 let opt' = opts { opt_importdirs = fp : opt_importdirs opts }
618 putIState $ i { idris_options = opt' }
620setImportDirs :: [FilePath] -> Idris ()
621setImportDirs fps = do i <- getIState
622 let opts = idris_options i
623 let opt' = opts { opt_importdirs = fps }
624 putIState $ i { idris_options = opt' }
626allImportDirs :: Idris [FilePath]
627allImportDirs = do i <- getIState
628 let optdirs = opt_importdirs (idris_options i)
629 return ("." : reverse optdirs)
631colourise :: Idris Bool
632colourise = do i <- getIState
633 return $ idris_colourRepl i
635setColourise :: Bool -> Idris ()
636setColourise b = do i <- getIState
637 putIState $ i { idris_colourRepl = b }
639setOutH :: Handle -> Idris ()
640setOutH h = do i <- getIState
641 putIState $ i { idris_outh = h }
643impShow :: Idris Bool
644impShow = do i <- getIState
645 return (opt_showimp (idris_options i))
647setImpShow :: Bool -> Idris ()
648setImpShow t = do i <- getIState
649 let opts = idris_options i
650 let opt' = opts { opt_showimp = t }
651 putIState $ i { idris_options = opt' }
653setColour :: ColourType -> IdrisColour -> Idris ()
654setColour ct c = do i <- getIState
655 let newTheme = setColour' ct c (idris_colourTheme i)
656 putIState $ i { idris_colourTheme = newTheme }
657 where setColour' KeywordColour c t = t { keywordColour = c }
658 setColour' BoundVarColour c t = t { boundVarColour = c }
659 setColour' ImplicitColour c t = t { implicitColour = c }
660 setColour' FunctionColour c t = t { functionColour = c }
661 setColour' TypeColour c t = t { typeColour = c }
662 setColour' DataColour c t = t { dataColour = c }
663 setColour' PromptColour c t = t { promptColour = c }
665logLvl :: Int -> String -> Idris ()
666logLvl l str = do i <- getIState
667 let lvl = opt_logLevel (idris_options i)
668 when (lvl >= l) $
669 case idris_outputmode i of
670 RawOutput -> do runIO $ putStrLn str
671 IdeSlave n ->
672 do let good = SexpList [IntegerAtom (toInteger l), toSExp str]
673 runIO $ putStrLn $ convSExp "log" good n
675cmdOptType :: Opt -> Idris Bool
676cmdOptType x = do i <- getIState
677 return $ x `elem` opt_cmdline (idris_options i)
679iLOG :: String -> Idris ()
680iLOG = logLvl 1
682noErrors :: Idris Bool
683noErrors = do i <- getIState
684 case errLine i of
685 Nothing -> return True
686 _ -> return False
688setTypeCase :: Bool -> Idris ()
689setTypeCase t = do i <- getIState
690 let opts = idris_options i
691 let opt' = opts { opt_typecase = t }
692 putIState $ i { idris_options = opt' }
695-- For inferring types of things
697bi = fileFC "builtin"
699inferTy = sMN 0 "__Infer"
700inferCon = sMN 0 "__infer"
701inferDecl = PDatadecl inferTy
702 PType
703 [("", inferCon, PPi impl (sMN 0 "iType") PType (
704 PPi expl (sMN 0 "ival") (PRef bi (sMN 0 "iType"))
705 (PRef bi inferTy)), bi, [])]
706inferOpts = []
708infTerm t = PApp bi (PRef bi inferCon) [pimp (sMN 0 "iType") Placeholder True, pexp t]
709infP = P (TCon 6 0) inferTy (TType (UVal 0))
711getInferTerm, getInferType :: Term -> Term
712getInferTerm (Bind n b sc) = Bind n b $ getInferTerm sc
713getInferTerm (App (App _ _) tm) = tm
714getInferTerm tm = tm -- error ("getInferTerm " ++ show tm)
716getInferType (Bind n b sc) = Bind n b $ getInferType sc
717getInferType (App (App _ ty) _) = ty
719-- Handy primitives: Unit, False, Pair, MkPair, =, mkForeign, Elim type class
721primNames = [unitTy, unitCon,
722 falseTy, pairTy, pairCon,
723 eqTy, eqCon, inferTy, inferCon]
725unitTy = sMN 0 "__Unit"
726unitCon = sMN 0 "__II"
727unitDecl = PDatadecl unitTy PType
728 [("", unitCon, PRef bi unitTy, bi, [])]
729unitOpts = [DefaultEliminator]
731falseTy = sMN 0 "__False"
732falseDecl = PDatadecl falseTy PType []
733falseOpts = []
735pairTy = sMN 0 "__Pair"
736pairCon = sMN 0 "__MkPair"
737pairDecl = PDatadecl pairTy (piBind [(n "A", PType), (n "B", PType)] PType)
738 [("", pairCon, PPi impl (n "A") PType (
739 PPi impl (n "B") PType (
740 PPi expl (n "a") (PRef bi (n "A")) (
741 PPi expl (n "b") (PRef bi (n "B"))
742 (PApp bi (PRef bi pairTy) [pexp (PRef bi (n "A")),
743 pexp (PRef bi (n "B"))])))), bi, [])]
744 where n a = sMN 0 a
745pairOpts = []
747eqTy = sUN "="
748eqCon = sUN "refl"
749eqDecl = PDatadecl eqTy (piBind [(n "A", PType), (n "B", PType),
750 (n "x", PRef bi (n "A")), (n "y", PRef bi (n "B"))]
751 PType)
752 [("", eqCon, PPi impl (n "A") PType (
753 PPi impl (n "x") (PRef bi (n "A"))
754 (PApp bi (PRef bi eqTy) [pimp (n "A") Placeholder False,
755 pimp (n "B") Placeholder False,
756 pexp (PRef bi (n "x")),
757 pexp (PRef bi (n "x"))])), bi, [])]
758 where n a = sMN 0 a
759eqOpts = []
761elimName = sUN "__Elim"
762elimMethElimTy = sUN "__elimTy"
763elimMethElim = sUN "elim"
764elimDecl = PClass "Type class for eliminators" defaultSyntax bi [] elimName [(sUN "scrutineeType", PType)]
765 [PTy "" defaultSyntax bi [TotalFn] elimMethElimTy PType,
766 PTy "" defaultSyntax bi [TotalFn] elimMethElim (PRef bi elimMethElimTy)]
768-- Defined in builtins.idr
769sigmaTy = sUN "Exists"
770existsCon = sUN "Ex_intro"
772piBind :: [(Name, PTerm)] -> PTerm -> PTerm
773piBind = piBindp expl
775piBindp :: Plicity -> [(Name, PTerm)] -> PTerm -> PTerm
776piBindp p [] t = t
777piBindp p ((n, ty):ns) t = PPi p n ty (piBindp p ns t)
779-- Dealing with parameters
781expandParams :: (Name -> Name) -> [(Name, PTerm)] ->
782 [Name] -> -- all names
783 [Name] -> -- names with no declaration
784 PTerm -> PTerm
785expandParams dec ps ns infs tm = en tm
786 where
787 -- if we shadow a name (say in a lambda binding) that is used in a call to
788 -- a lifted function, we need access to both names - once in the scope of the
789 -- binding and once to call the lifted functions. So we'll explicitly shadow
790 -- it. (Yes, it's a hack. The alternative would be to resolve names earlier
791 -- but we didn't...)
793 mkShadow (UN n) = MN 0 n
794 mkShadow (MN i n) = MN (i+1) n
795 mkShadow (NS x s) = NS (mkShadow x) s
797 en (PLam n t s)
798 | n `elem` (map fst ps ++ ns)
799 = let n' = mkShadow n in
800 PLam n' (en t) (en (shadow n n' s))
801 | otherwise = PLam n (en t) (en s)
802 en (PPi p n t s)
803 | n `elem` (map fst ps ++ ns)
804 = let n' = mkShadow n in
805 PPi p n' (en t) (en (shadow n n' s))
806 | otherwise = PPi p n (en t) (en s)
807 en (PLet n ty v s)
808 | n `elem` (map fst ps ++ ns)
809 = let n' = mkShadow n in
810 PLet n' (en ty) (en v) (en (shadow n n' s))
811 | otherwise = PLet n (en ty) (en v) (en s)
812 -- FIXME: Should only do this in a type signature!
813 en (PDPair f (PRef f' n) t r)
814 | n `elem` (map fst ps ++ ns) && t /= Placeholder
815 = let n' = mkShadow n in
816 PDPair f (PRef f' n') (en t) (en (shadow n n' r))
817 en (PEq f l r) = PEq f (en l) (en r)
818 en (PRewrite f l r g) = PRewrite f (en l) (en r) (fmap en g)
819 en (PTyped l r) = PTyped (en l) (en r)
820 en (PPair f l r) = PPair f (en l) (en r)
821 en (PDPair f l t r) = PDPair f (en l) (en t) (en r)
822 en (PAlternative a as) = PAlternative a (map en as)
823 en (PHidden t) = PHidden (en t)
824 en (PUnifyLog t) = PUnifyLog (en t)
825 en (PNoImplicits t) = PNoImplicits (en t)
826 en (PDoBlock ds) = PDoBlock (map (fmap en) ds)
827 en (PProof ts) = PProof (map (fmap en) ts)
828 en (PTactics ts) = PTactics (map (fmap en) ts)
830 en (PQuote (Var n))
831 | n `nselem` ns = PQuote (Var (dec n))
832 en (PApp fc (PInferRef fc' n) as)
833 | n `nselem` ns = PApp fc (PInferRef fc' (dec n))
834 (map (pexp . (PRef fc)) (map fst ps) ++ (map (fmap en) as))
835 en (PApp fc (PRef fc' n) as)
836 | n `elem` infs = PApp fc (PInferRef fc' (dec n))
837 (map (pexp . (PRef fc)) (map fst ps) ++ (map (fmap en) as))
838 | n `nselem` ns = PApp fc (PRef fc' (dec n))
839 (map (pexp . (PRef fc)) (map fst ps) ++ (map (fmap en) as))
840 en (PAppBind fc (PRef fc' n) as)
841 | n `elem` infs = PAppBind fc (PInferRef fc' (dec n))
842 (map (pexp . (PRef fc)) (map fst ps) ++ (map (fmap en) as))
843 | n `nselem` ns = PAppBind fc (PRef fc' (dec n))
844 (map (pexp . (PRef fc)) (map fst ps) ++ (map (fmap en) as))
845 en (PRef fc n)
846 | n `elem` infs = PApp fc (PInferRef fc (dec n))
847 (map (pexp . (PRef fc)) (map fst ps))
848 | n `nselem` ns = PApp fc (PRef fc (dec n))
849 (map (pexp . (PRef fc)) (map fst ps))
850 en (PInferRef fc n)
851 | n `nselem` ns = PApp fc (PInferRef fc (dec n))
852 (map (pexp . (PRef fc)) (map fst ps))
853 en (PApp fc f as) = PApp fc (en f) (map (fmap en) as)
854 en (PAppBind fc f as) = PAppBind fc (en f) (map (fmap en) as)
855 en (PCase fc c os) = PCase fc (en c) (map (pmap en) os)
856 en t = t
858 nselem x [] = False
859 nselem x (y : xs) | nseq x y = True
860 | otherwise = nselem x xs
862 nseq x y = nsroot x == nsroot y
864expandParamsD :: Bool -> -- True = RHS only
865 IState ->
866 (Name -> Name) -> [(Name, PTerm)] -> [Name] -> PDecl -> PDecl
867expandParamsD rhsonly ist dec ps ns (PTy doc syn fc o n ty)
868 = if n `elem` ns && (not rhsonly)
869 then -- trace (show (n, expandParams dec ps ns ty)) $
870 PTy doc syn fc o (dec n) (piBindp expl_param ps (expandParams dec ps ns [] ty))
871 else --trace (show (n, expandParams dec ps ns ty)) $
872 PTy doc syn fc o n (expandParams dec ps ns [] ty)
873expandParamsD rhsonly ist dec ps ns (PPostulate doc syn fc o n ty)
874 = if n `elem` ns && (not rhsonly)
875 then -- trace (show (n, expandParams dec ps ns ty)) $
876 PPostulate doc syn fc o (dec n) (piBind ps
877 (expandParams dec ps ns [] ty))
878 else --trace (show (n, expandParams dec ps ns ty)) $
879 PPostulate doc syn fc o n (expandParams dec ps ns [] ty)
880expandParamsD rhsonly ist dec ps ns (PClauses fc opts n cs)
881 = let n' = if n `elem` ns then dec n else n in
882 PClauses fc opts n' (map expandParamsC cs)
883 where
884 expandParamsC (PClause fc n lhs ws rhs ds)
885 = let -- ps' = updateps True (namesIn ist rhs) (zip ps [0..])
886 ps'' = updateps False (namesIn [] ist lhs) (zip ps [0..])
887 lhs' = if rhsonly then lhs else (expandParams dec ps'' ns [] lhs)
888 n' = if n `elem` ns then dec n else n
889 -- names bound on the lhs should not be expanded on the rhs
890 ns' = removeBound lhs ns in
891 PClause fc n' lhs'
892 (map (expandParams dec ps'' ns' []) ws)
893 (expandParams dec ps'' ns' [] rhs)
894 (map (expandParamsD True ist dec ps'' ns') ds)
895 expandParamsC (PWith fc n lhs ws wval ds)
896 = let -- ps' = updateps True (namesIn ist wval) (zip ps [0..])
897 ps'' = updateps False (namesIn [] ist lhs) (zip ps [0..])
898 lhs' = if rhsonly then lhs else (expandParams dec ps'' ns [] lhs)
899 n' = if n `elem` ns then dec n else n
900 ns' = removeBound lhs ns in
901 PWith fc n' lhs'
902 (map (expandParams dec ps'' ns' []) ws)
903 (expandParams dec ps'' ns' [] wval)
904 (map (expandParamsD rhsonly ist dec ps'' ns') ds)
905 updateps yn nm [] = []
906 updateps yn nm (((a, t), i):as)
907 | (a `elem` nm) == yn = (a, t) : updateps yn nm as
908 | otherwise = (sMN i (show n ++ "_u"), t) : updateps yn nm as
910 removeBound lhs ns = ns \\ nub (bnames lhs)
912 bnames (PRef _ n) = [n]
913 bnames (PApp _ _ args) = concatMap bnames (map getTm args)
914 bnames (PPair _ l r) = bnames l ++ bnames r
915 bnames (PDPair _ l Placeholder r) = bnames l ++ bnames r
916 bnames _ = []
918expandParamsD rhs ist dec ps ns (PData doc syn fc co pd)
919 = PData doc syn fc co (expandPData pd)
920 where
921 -- just do the type decl, leave constructors alone (parameters will be
922 -- added implicitly)
923 expandPData (PDatadecl n ty cons)
924 = if n `elem` ns
925 then PDatadecl (dec n) (piBind ps (expandParams dec ps ns [] ty))
926 (map econ cons)
927 else PDatadecl n (expandParams dec ps ns [] ty) (map econ cons)
928 econ (doc, n, t, fc, fs)
929 = (doc, dec n, piBindp expl ps (expandParams dec ps ns [] t), fc, fs)
930expandParamsD rhs ist dec ps ns (PParams f params pds)
931 = PParams f (ps ++ map (mapsnd (expandParams dec ps ns [])) params)
932 (map (expandParamsD True ist dec ps ns) pds)
933-- (map (expandParamsD ist dec ps ns) pds)
934expandParamsD rhs ist dec ps ns (PMutual f pds)
935 = PMutual f (map (expandParamsD rhs ist dec ps ns) pds)
936expandParamsD rhs ist dec ps ns (PClass doc info f cs n params decls)
937 = PClass doc info f
938 (map (expandParams dec ps ns []) cs)
939 n
940 (map (mapsnd (expandParams dec ps ns [])) params)
941 (map (expandParamsD rhs ist dec ps ns) decls)
942expandParamsD rhs ist dec ps ns (PInstance info f cs n params ty cn decls)
943 = PInstance info f
944 (map (expandParams dec ps ns []) cs)
945 n
946 (map (expandParams dec ps ns []) params)
947 (expandParams dec ps ns [] ty)
948 cn
949 (map (expandParamsD rhs ist dec ps ns) decls)
950expandParamsD rhs ist dec ps ns d = d
952mapsnd f (x, t) = (x, f t)
954-- Calculate a priority for a type, for deciding elaboration order
955-- * if it's just a type variable or concrete type, do it early (0)
956-- * if there's only type variables and injective constructors, do it next (1)
957-- * if there's a function type, next (2)
958-- * finally, everything else (3)
960getPriority :: IState -> PTerm -> Int
961getPriority i tm = 1 -- pri tm
962 where
963 pri (PRef _ n) =
964 case lookupP n (tt_ctxt i) of
965 ((P (DCon _ _) _ _):_) -> 1
966 ((P (TCon _ _) _ _):_) -> 1
967 ((P Ref _ _):_) -> 1
968 [] -> 0 -- must be locally bound, if it's not an error...
969 pri (PPi _ _ x y) = max 5 (max (pri x) (pri y))
970 pri (PTrue _) = 0
971 pri (PFalse _) = 0
972 pri (PRefl _ _) = 1
973 pri (PEq _ l r) = max 1 (max (pri l) (pri r))
974 pri (PRewrite _ l r _) = max 1 (max (pri l) (pri r))
975 pri (PApp _ f as) = max 1 (max (pri f) (foldr max 0 (map (pri.getTm) as)))
976 pri (PAppBind _ f as) = max 1 (max (pri f) (foldr max 0 (map (pri.getTm) as)))
977 pri (PCase _ f as) = max 1 (max (pri f) (foldr max 0 (map (pri.snd) as)))
978 pri (PTyped l r) = pri l
979 pri (PPair _ l r) = max 1 (max (pri l) (pri r))
980 pri (PDPair _ l t r) = max 1 (max (pri l) (max (pri t) (pri r)))
981 pri (PAlternative a as) = maximum (map pri as)
982 pri (PConstant _) = 0
983 pri Placeholder = 1
984 pri _ = 3
986addStatics :: Name -> Term -> PTerm -> Idris ()
987addStatics n tm ptm =
988 do let (statics, dynamics) = initStatics tm ptm
989 let stnames = nub $ concatMap freeArgNames (map snd statics)
990 let dnames = nub $ concatMap freeArgNames (map snd dynamics)
991 -- also get the arguments which are 'uniquely inferrable' from
992 -- statics (see sec 4.2 of "Scrapping Your Inefficient Engine")
993 let statics' = nub $ map fst statics ++
994 filter (\x -> not (elem x dnames)) stnames
995 let stpos = staticList statics' tm
996 i <- getIState
997 when (not (null statics)) $
998 logLvl 5 $ show n ++ " " ++ show statics' ++ "\n" ++ show dynamics
999 ++ "\n" ++ show stnames ++ "\n" ++ show dnames
1000 putIState $ i { idris_statics = addDef n stpos (idris_statics i) }
1001 addIBC (IBCStatic n)
1002 where
1003 initStatics (Bind n (Pi ty) sc) (PPi p _ _ s)
1004 = let (static, dynamic) = initStatics (instantiate (P Bound n ty) sc) s in
1005 if pstatic p == Static then ((n, ty) : static, dynamic)
1006 else if (not (searchArg p))
1007 then (static, (n, ty) : dynamic)
1008 else (static, dynamic)
1009 initStatics t pt = ([], [])
1011 freeArgNames (Bind n (Pi ty) sc)
1012 = nub $ freeArgNames ty
1013 freeArgNames tm = let (_, args) = unApply tm in
1014 concatMap freeNames args
1016 -- if a name appears in a type class or tactic implicit index, it doesn't
1017 -- affect its 'uniquely inferrable' from a static status since these are
1018 -- resolved by searching.
1019 searchArg (Constraint _ _ _) = True
1020 searchArg (TacImp _ _ _ _) = True
1021 searchArg _ = False
1023 staticList sts (Bind n (Pi _) sc) = (n `elem` sts) : staticList sts sc
1024 staticList _ _ = []
1026-- Dealing with implicit arguments
1028-- Add constraint bindings from using block
1030addUsingConstraints :: SyntaxInfo -> FC -> PTerm -> Idris PTerm
1031addUsingConstraints syn fc t
1032 = do ist <- get
1033 let ns = namesIn [] ist t
1034 let cs = getConstraints t -- check declared constraints
1035 let addconsts = uconsts \\ cs
1036 -- if all names in the arguments of addconsts appear in ns,
1037 -- add the constraint implicitly
1038 return (doAdd addconsts ns t)
1039 where uconsts = filter uconst (using syn)
1040 uconst (UConstraint _ _) = True
1041 uconst _ = False
1043 doAdd [] _ t = t
1044 -- if all of args in ns, then add it
1045 doAdd (UConstraint c args : cs) ns t
1046 | all (\n -> elem n ns) args
1047 = PPi (Constraint [] Dynamic "") (sMN 0 "cu")
1048 (mkConst c args) (doAdd cs ns t)
1049 | otherwise = doAdd cs ns t
1051 mkConst c args = PApp fc (PRef fc c)
1052 (map (\n -> PExp 0 [] (PRef fc n) "") args)
1054 getConstraints (PPi (Constraint _ _ _) _ c sc)
1055 = getcapp c ++ getConstraints sc
1056 getConstraints (PPi _ _ c sc) = getConstraints sc
1057 getConstraints _ = []
1059 getcapp (PApp _ (PRef _ c) args)
1060 = do ns <- mapM getName args
1061 return (UConstraint c ns)
1062 getcapp _ = []
1064 getName (PExp _ _ (PRef _ n) _) = return n
1065 getName _ = []
1067-- Add implicit Pi bindings for any names in the term which appear in an
1068-- argument position.
1070-- This has become a right mess already. Better redo it some time...
1072implicit :: SyntaxInfo -> Name -> PTerm -> Idris PTerm
1073implicit syn n ptm = implicit' syn [] n ptm
1075implicit' :: SyntaxInfo -> [Name] -> Name -> PTerm -> Idris PTerm
1076implicit' syn ignore n ptm
1077 = do i <- getIState
1078 let (tm', impdata) = implicitise syn ignore i ptm
1079-- let (tm'', spos) = findStatics i tm'
1080 putIState $ i { idris_implicits = addDef n impdata (idris_implicits i) }
1081 addIBC (IBCImp n)
1082 logLvl 5 ("Implicit " ++ show n ++ " " ++ show impdata)
1083-- i <- get
1084-- putIState $ i { idris_statics = addDef n spos (idris_statics i) }
1085 return tm'
1087implicitise :: SyntaxInfo -> [Name] -> IState -> PTerm -> (PTerm, [PArg])
1088implicitise syn ignore ist tm = -- trace ("INCOMING " ++ showImp True tm) $
1089 let (declimps, ns') = execState (imps True [] tm) ([], [])
1090 ns = filter (\n -> implicitable n || elem n (map fst uvars)) $
1091 ns' \\ (map fst pvars ++ no_imp syn ++ ignore)
1092 nsOrder = filter (not . inUsing) ns ++ filter inUsing ns in
1093 if null ns
1094 then (tm, reverse declimps)
1095 else implicitise syn ignore ist (pibind uvars nsOrder tm)
1096 where
1097 uvars = map ipair (filter uimplicit (using syn))
1098 pvars = syn_params syn
1100 inUsing n = n `elem` map fst uvars
1102 ipair (UImplicit x y) = (x, y)
1103 uimplicit (UImplicit _ _) = True
1104 uimplicit _ = False
1106 dropAll (x:xs) ys | x `elem` ys = dropAll xs ys
1107 | otherwise = x : dropAll xs ys
1108 dropAll [] ys = []
1110 imps top env (PApp _ f as)
1111 = do (decls, ns) <- get
1112 let isn = concatMap (namesIn uvars ist) (map getTm as)
1113 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1114 imps top env (PPi (Imp l _ doc _) n ty sc)
1115 = do let isn = nub (namesIn uvars ist ty) `dropAll` [n]
1116 (decls , ns) <- get
1117 put (PImp (getPriority ist ty) True l n Placeholder doc : decls,
1118 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1119 imps True (n:env) sc
1120 imps top env (PPi (Exp l _ doc _) n ty sc)
1121 = do let isn = nub (namesIn uvars ist ty ++ case sc of
1122 (PRef _ x) -> namesIn uvars ist sc `dropAll` [n]
1123 _ -> [])
1124 (decls, ns) <- get -- ignore decls in HO types
1125 put (PExp (getPriority ist ty) l Placeholder doc : decls,
1126 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1127 imps True (n:env) sc
1128 imps top env (PPi (Constraint l _ doc) n ty sc)
1129 = do let isn = nub (namesIn uvars ist ty ++ case sc of
1130 (PRef _ x) -> namesIn uvars ist sc `dropAll` [n]
1131 _ -> [])
1132 (decls, ns) <- get -- ignore decls in HO types
1133 put (PConstraint 10 l Placeholder doc : decls,
1134 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1135 imps True (n:env) sc
1136 imps top env (PPi (TacImp l _ scr doc) n ty sc)
1137 = do let isn = nub (namesIn uvars ist ty ++ case sc of
1138 (PRef _ x) -> namesIn uvars ist sc `dropAll` [n]
1139 _ -> [])
1140 (decls, ns) <- get -- ignore decls in HO types
1141 put (PTacImplicit 10 l n scr Placeholder doc : decls,
1142 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1143 imps True (n:env) sc
1144 imps top env (PEq _ l r)
1145 = do (decls, ns) <- get
1146 let isn = namesIn uvars ist l ++ namesIn uvars ist r
1147 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1148 imps top env (PRewrite _ l r _)
1149 = do (decls, ns) <- get
1150 let isn = namesIn uvars ist l ++ namesIn uvars ist r
1151 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1152 imps top env (PTyped l r)
1153 = imps top env l
1154 imps top env (PPair _ l r)
1155 = do (decls, ns) <- get
1156 let isn = namesIn uvars ist l ++ namesIn uvars ist r
1157 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1158 imps top env (PDPair _ (PRef _ n) t r)
1159 = do (decls, ns) <- get
1160 let isn = nub (namesIn uvars ist t ++ namesIn uvars ist r) \\ [n]
1161 put (decls, nub (ns ++ (isn \\ (env ++ map fst (getImps decls)))))
1162 imps top env (PDPair _ l t r)
1163 = do (decls, ns) <- get
1164 let isn = namesIn uvars ist l ++ namesIn uvars ist t ++
1165 namesIn uvars ist r
1166 put (decls, nub (ns ++ (isn \\ (env ++ map fst (getImps decls)))))
1167 imps top env (PAlternative a as)
1168 = do (decls, ns) <- get
1169 let isn = concatMap (namesIn uvars ist) as
1170 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1171 imps top env (PLam n ty sc)
1172 = do imps False env ty
1173 imps False (n:env) sc
1174 imps top env (PHidden tm) = imps False env tm
1175 imps top env (PUnifyLog tm) = imps False env tm
1176 imps top env (PNoImplicits tm) = imps False env tm
1177 imps top env _ = return ()
1179 pibind using [] sc = sc
1180 pibind using (n:ns) sc
1181 = case lookup n using of
1182 Just ty -> PPi (Imp [] Dynamic "" False) n ty (pibind using ns sc)
1183 Nothing -> PPi (Imp [] Dynamic "" False) n Placeholder
1184 (pibind using ns sc)
1186-- Add implicit arguments in function calls
1187addImplPat :: IState -> PTerm -> PTerm
1188addImplPat = addImpl' True [] []
1190addImplBound :: IState -> [Name] -> PTerm -> PTerm
1191addImplBound ist ns = addImpl' False ns [] ist
1193addImplBoundInf :: IState -> [Name] -> [Name] -> PTerm -> PTerm
1194addImplBoundInf ist ns inf = addImpl' False ns inf ist
1196addImpl :: IState -> PTerm -> PTerm
1197addImpl = addImpl' False [] []
1199-- TODO: in patterns, don't add implicits to function names guarded by constructors
1200-- and *not* inside a PHidden
1202addImpl' :: Bool -> [Name] -> [Name] -> IState -> PTerm -> PTerm
1203addImpl' inpat env infns ist ptm
1204 = mkUniqueNames env (ai (zip env (repeat Nothing)) [] ptm)
1205 where
1206 ai env ds (PRef fc f)
1207 | f `elem` infns = PInferRef fc f
1208 | not (f `elem` map fst env) = handleErr $ aiFn inpat inpat ist fc f ds []
1209 ai env ds (PHidden (PRef fc f))
1210 | not (f `elem` map fst env) = handleErr $ aiFn inpat False ist fc f ds []
1211 ai env ds (PEq fc l r)
1212 = let l' = ai env ds l
1213 r' = ai env ds r in
1214 PEq fc l' r'
1215 ai env ds (PRewrite fc l r g)
1216 = let l' = ai env ds l
1217 r' = ai env ds r
1218 g' = fmap (ai env ds) g in
1219 PRewrite fc l' r' g'
1220 ai env ds (PTyped l r)
1221 = let l' = ai env ds l
1222 r' = ai env ds r in
1223 PTyped l' r'
1224 ai env ds (PPair fc l r)
1225 = let l' = ai env ds l
1226 r' = ai env ds r in
1227 PPair fc l' r'
1228 ai env ds (PDPair fc l t r)
1229 = let l' = ai env ds l
1230 t' = ai env ds t
1231 r' = ai env ds r in
1232 PDPair fc l' t' r'
1233 ai env ds (PAlternative a as)
1234 = let as' = map (ai env ds) as in
1235 PAlternative a as'
1236 ai env _ (PDisamb ds' as) = ai env ds' as
1237 ai env ds (PApp fc (PInferRef _ f) as)
1238 = let as' = map (fmap (ai env ds)) as in
1239 PApp fc (PInferRef fc f) as'
1240 ai env ds (PApp fc ftm@(PRef _ f) as)
1241 | f `elem` infns = ai env ds (PApp fc (PInferRef fc f) as)
1242 | not (f `elem` map fst env)
1243 = let as' = map (fmap (ai env ds)) as in
1244 handleErr $ aiFn inpat False ist fc f ds as'
1245 | Just (Just ty) <- lookup f env =
1246 let as' = map (fmap (ai env ds)) as
1247 arity = getPArity ty in
1248 mkPApp fc arity ftm as'
1249 ai env ds (PApp fc f as)
1250 = let f' = ai env ds f
1251 as' = map (fmap (ai env ds)) as in
1252 mkPApp fc 1 f' as'
1253 ai env ds (PCase fc c os)
1254 = let c' = ai env ds c
1255 os' = map (pmap (ai env ds)) os in
1256 PCase fc c' os'
1257 ai env ds (PLam n ty sc)
1258 = let ty' = ai env ds ty
1259 sc' = ai ((n, Just ty):env) ds sc in
1260 PLam n ty' sc'
1261 ai env ds (PLet n ty val sc)
1262 = let ty' = ai env ds ty
1263 val' = ai env ds val
1264 sc' = ai ((n, Just ty):env) ds sc in
1265 PLet n ty' val' sc'
1266 ai env ds (PPi p n ty sc)
1267 = let ty' = ai env ds ty
1268 sc' = ai ((n, Just ty):env) ds sc in
1269 PPi p n ty' sc'
1270 ai env ds (PGoal fc r n sc)
1271 = let r' = ai env ds r
1272 sc' = ai ((n, Nothing):env) ds sc in
1273 PGoal fc r' n sc'
1274 ai env ds (PHidden tm) = PHidden (ai env ds tm)
1275 ai env ds (PProof ts) = PProof (map (fmap (ai env ds)) ts)
1276 ai env ds (PTactics ts) = PTactics (map (fmap (ai env ds)) ts)
1277 ai env ds (PRefl fc tm) = PRefl fc (ai env ds tm)
1278 ai env ds (PUnifyLog tm) = PUnifyLog (ai env ds tm)
1279 ai env ds (PNoImplicits tm) = PNoImplicits (ai env ds tm)
1280 ai env ds tm = tm
1282 handleErr (Left err) = PElabError err
1283 handleErr (Right x) = x
1285-- if in a pattern, and there are no arguments, and there's no possible
1286-- names with zero explicit arguments, don't add implicits.
1288aiFn :: Bool -> Bool -> IState -> FC -> Name -> [[T.Text]] -> [PArg] -> Either Err PTerm
1289aiFn inpat True ist fc f ds []
1290 = case lookupDef f (tt_ctxt ist) of
1291 [] -> Right $ PPatvar fc f
1292 alts -> let ialts = lookupCtxtName f (idris_implicits ist) in
1293 -- trace (show f ++ " " ++ show (fc, any (all imp) ialts, ialts, any constructor alts)) $
1294 if (not (vname f) || tcname f
1295 || any (conCaf (tt_ctxt ist)) ialts)
1296-- any constructor alts || any allImp ialts))
1297 then aiFn inpat False ist fc f ds [] -- use it as a constructor
1298 else Right $ PPatvar fc f
1299 where imp (PExp _ _ _ _) = False
1300 imp _ = True
1301-- allImp [] = False
1302 allImp xs = all imp xs
1303 constructor (TyDecl (DCon _ _) _) = True
1304 constructor _ = False
1306 conCaf ctxt (n, cia) = isDConName n ctxt && allImp cia
1308 vname (UN n) = True -- non qualified
1309 vname _ = False
1311aiFn inpat expat ist fc f ds as
1312 | f `elem` primNames = Right $ PApp fc (PRef fc f) as
1313aiFn inpat expat ist fc f ds as
1314 -- This is where namespaces get resolved by adding PAlternative
1315 = do let ns = lookupCtxtName f (idris_implicits ist)
1316 let nh = filter (\(n, _) -> notHidden n) ns
1317 let ns' = case trimAlts ds nh of
1318 [] -> nh
1319 x -> x
1320 case ns' of
1321 [(f',ns)] -> Right $ mkPApp fc (length ns) (PRef fc f') (insertImpl ns as)
1322 [] -> if f `elem` (map fst (idris_metavars ist))
1323 then Right $ PApp fc (PRef fc f) as
1324 else Right $ mkPApp fc (length as) (PRef fc f) as
1325 alts -> Right $
1326 PAlternative True $
1327 map (\(f', ns) -> mkPApp fc (length ns) (PRef fc f')
1328 (insertImpl ns as)) alts
1329 where
1330 trimAlts [] alts = alts
1331 trimAlts ns alts
1332 = filter (\(x, _) -> any (\d -> d `isPrefixOf` nspace x) ns) alts
1334 nspace (NS _ s) = s
1335 nspace _ = []
1337 notHidden n = case getAccessibility n of
1338 Hidden -> False
1339 _ -> True
1341 getAccessibility n
1342 = case lookupDefAcc n False (tt_ctxt ist) of
1343 [(n,t)] -> t
1344 _ -> Public
1347 insertImpl :: [PArg] -> [PArg] -> [PArg]
1348 insertImpl (PExp p l ty _ : ps) (PExp _ _ tm d : given) =
1349 PExp p l tm d : insertImpl ps given
1350 insertImpl (PConstraint p l ty _ : ps) (PConstraint _ _ tm d : given) =
1351 PConstraint p l tm d : insertImpl ps given
1352 insertImpl (PConstraint p l ty d : ps) given =
1353 PConstraint p l (PResolveTC fc) d : insertImpl ps given
1354 insertImpl (PImp p _ l n ty d : ps) given =
1355 case find n given [] of
1356 Just (tm, given') -> PImp p False l n tm "" : insertImpl ps given'
1357 Nothing -> PImp p True l n Placeholder "" : insertImpl ps given
1358 insertImpl (PTacImplicit p l n sc' ty d : ps) given =
1359 let sc = addImpl ist sc' in
1360 case find n given [] of
1361 Just (tm, given') -> PTacImplicit p l n sc tm "" : insertImpl ps given'
1362 Nothing -> if inpat
1363 then PTacImplicit p l n sc Placeholder "" : insertImpl ps given
1364 else PTacImplicit p l n sc sc "" : insertImpl ps given
1365 insertImpl expected [] = []
1366 insertImpl _ given = given
1368 find n [] acc = Nothing
1369 find n (PImp _ _ _ n' t _ : gs) acc
1370 | n == n' = Just (t, reverse acc ++ gs)
1371 find n (PTacImplicit _ _ n' _ t _ : gs) acc
1372 | n == n' = Just (t, reverse acc ++ gs)
1373 find n (g : gs) acc = find n gs (g : acc)
1375-- replace non-linear occurrences with _
1376-- ASSUMPTION: This is called before adding 'alternatives' because otherwise
1377-- it is hard to get right!
1379stripLinear :: IState -> PTerm -> PTerm
1380stripLinear i tm = evalState (sl tm) [] where
1381 sl :: PTerm -> State [Name] PTerm
1382 sl (PRef fc f)
1383 | (_:_) <- lookupTy f (tt_ctxt i)
1384 = return $ PRef fc f
1385 | otherwise = do ns <- get
1386 if (f `elem` ns)
1387 then return Placeholder
1388 else do put (f : ns)
1389 return (PRef fc f)
1390 sl (PPatvar fc f)
1391 = do ns <- get
1392 if (f `elem` ns)
1393 then return Placeholder
1394 else do put (f : ns)
1395 return (PPatvar fc f)
1396 sl (PApp fc fn args) = do fn' <- sl fn
1397 args' <- mapM slA args
1398 return $ PApp fc fn' args'
1399 where slA (PImp p m l n t d) = do t' <- sl t
1400 return $ PImp p m l n t' d
1401 slA (PExp p l t d) = do t' <- sl t
1402 return $ PExp p l t' d
1403 slA (PConstraint p l t d)
1404 = do t' <- sl t
1405 return $ PConstraint p l t' d
1406 slA (PTacImplicit p l n sc t d)
1407 = do t' <- sl t
1408 return $ PTacImplicit p l n sc t' d
1409 sl x = return x
1411-- Remove functions which aren't applied to anything, which must then
1412-- be resolved by unification. Assume names resolved and alternatives
1413-- filled in (so no ambiguity).
1415stripUnmatchable :: IState -> PTerm -> PTerm
1416stripUnmatchable i (PApp fc fn args) = PApp fc fn (fmap (fmap su) args) where
1417 su :: PTerm -> PTerm
1418 su (PRef fc f)
1419 | (Bind n (Pi t) sc :_) <- lookupTy f (tt_ctxt i)
1420 = Placeholder
1421 su (PApp fc fn args)
1422 = PApp fc fn (fmap (fmap su) args)
1423 su (PAlternative b alts)
1424 = let alts' = filter (/= Placeholder) (map su alts) in
1425 if null alts' then Placeholder
1426 else PAlternative b alts'
1427 su (PPair fc l r) = PPair fc (su l) (su r)
1428 su (PDPair fc l t r) = PDPair fc (su l) (su t) (su r)
1429 su t = t
1430stripUnmatchable i tm = tm
1432mkPApp fc a f [] = f
1433mkPApp fc a f as = let rest = drop a as in
1434 appRest fc (PApp fc f (take a as)) rest
1435 where
1436 appRest fc f [] = f
1437 appRest fc f (a : as) = appRest fc (PApp fc f [a]) as
1439-- Find 'static' argument positions
1440-- (the declared ones, plus any names in argument position in the declared
1441-- statics)
1442-- FIXME: It's possible that this really has to happen after elaboration
1444findStatics :: IState -> PTerm -> (PTerm, [Bool])
1445findStatics ist tm = trace (showImp Nothing True False tm) $
1446 let (ns, ss) = fs tm in
1447 runState (pos ns ss tm) []
1448 where fs (PPi p n t sc)
1449 | Static <- pstatic p
1450 = let (ns, ss) = fs sc in
1451 (namesIn [] ist t : ns, n : ss)
1452 | otherwise = let (ns, ss) = fs sc in
1453 (ns, ss)
1454 fs _ = ([], [])
1456 inOne n ns = length (filter id (map (elem n) ns)) == 1
1458 pos ns ss (PPi p n t sc)
1459 | elem n ss = do sc' <- pos ns ss sc
1460 spos <- get
1461 put (True : spos)
1462 return (PPi (p { pstatic = Static }) n t sc')
1463 | otherwise = do sc' <- pos ns ss sc
1464 spos <- get
1465 put (False : spos)
1466 return (PPi p n t sc')
1467 pos ns ss t = return t
1469-- for 6.12/7 compatibility
1470data EitherErr a b = LeftErr a | RightOK b
1472instance Monad (EitherErr a) where
1473 return = RightOK
1475 (LeftErr e) >>= k = LeftErr e
1476 RightOK v >>= k = k v
1478toEither (LeftErr e) = Left e
1479toEither (RightOK ho) = Right ho
1481-- syntactic match of a against b, returning pair of variables in a
1482-- and what they match. Returns the pair that failed if not a match.
1484matchClause :: IState -> PTerm -> PTerm -> Either (PTerm, PTerm) [(Name, PTerm)]
1485matchClause = matchClause' False
1487matchClause' :: Bool -> IState -> PTerm -> PTerm -> Either (PTerm, PTerm) [(Name, PTerm)]
1488matchClause' names i x y = checkRpts $ match (fullApp x) (fullApp y) where
1489 matchArg x y = match (fullApp (getTm x)) (fullApp (getTm y))
1491 fullApp (PApp _ (PApp fc f args) xs) = fullApp (PApp fc f (args ++ xs))
1492 fullApp x = x
1494 match' x y = match (fullApp x) (fullApp y)
1495 match (PApp _ (PRef _ (NS (UN fi) [b])) [_,_,x]) x'
1496 | fi == txt "fromInteger" && b == txt "builtins",
1497 PConstant (I _) <- getTm x = match (getTm x) x'
1498 match x' (PApp _ (PRef _ (NS (UN fi) [b])) [_,_,x])
1499 | fi == txt "fromInteger" && b == txt "builtins",
1500 PConstant (I _) <- getTm x = match (getTm x) x'
1501 match (PApp _ (PRef _ (UN l)) [_,x]) x' | l == txt "lazy" = match (getTm x) x'
1502 match x (PApp _ (PRef _ (UN l)) [_,x']) | l == txt "lazy" = match x (getTm x')
1503 match (PApp _ f args) (PApp _ f' args')
1504 | length args == length args'
1505 = do mf <- match' f f'
1506 ms <- zipWithM matchArg args args'
1507 return (mf ++ concat ms)
1508-- match (PRef _ n) (PRef _ n') | n == n' = return []
1509-- | otherwise = Nothing
1510 match (PRef f n) (PApp _ x []) = match (PRef f n) x
1511 match (PPatvar f n) xr = match (PRef f n) xr
1512 match xr (PPatvar f n) = match xr (PRef f n)
1513 match (PApp _ x []) (PRef f n) = match x (PRef f n)
1514 match (PRef _ n) tm@(PRef _ n')
1515 | n == n' && not names &&
1516 (not (isConName n (tt_ctxt i) || isFnName n (tt_ctxt i))
1517 || tm == Placeholder)
1518 = return [(n, tm)]
1519 | n == n' = return []
1520 match (PRef _ n) tm
1521 | not names && (not (isConName n (tt_ctxt i) ||
1522 isFnName n (tt_ctxt i)) || tm == Placeholder)
1523 = return [(n, tm)]
1524 match (PEq _ l r) (PEq _ l' r') = do ml <- match' l l'
1525 mr <- match' r r'
1526 return (ml ++ mr)
1527 match (PRewrite _ l r _) (PRewrite _ l' r' _)
1528 = do ml <- match' l l'
1529 mr <- match' r r'
1530 return (ml ++ mr)
1531 match (PTyped l r) (PTyped l' r') = do ml <- match l l'
1532 mr <- match r r'
1533 return (ml ++ mr)
1534 match (PTyped l r) x = match l x
1535 match x (PTyped l r) = match x l
1536 match (PPair _ l r) (PPair _ l' r') = do ml <- match' l l'
1537 mr <- match' r r'
1538 return (ml ++ mr)
1539 match (PDPair _ l t r) (PDPair _ l' t' r') = do ml <- match' l l'
1540 mt <- match' t t'
1541 mr <- match' r r'
1542 return (ml ++ mt ++ mr)
1543 match (PAlternative a as) (PAlternative a' as')
1544 = do ms <- zipWithM match' as as'
1545 return (concat ms)
1546 match a@(PAlternative _ as) b
1547 = do let ms = zipWith match' as (repeat b)
1548 case (rights (map toEither ms)) of
1549 (x: _) -> return x
1550 _ -> LeftErr (a, b)
1551 match (PCase _ _ _) _ = return [] -- lifted out
1552 match (PMetavar _) _ = return [] -- modified
1553 match (PInferRef _ _) _ = return [] -- modified
1554 match (PQuote _) _ = return []
1555 match (PProof _) _ = return []
1556 match (PTactics _) _ = return []
1557 match (PRefl _ _) (PRefl _ _) = return []
1558 match (PResolveTC _) (PResolveTC _) = return []
1559 match (PTrue _) (PTrue _) = return []
1560 match (PFalse _) (PFalse _) = return []
1561 match (PReturn _) (PReturn _) = return []
1562 match (PPi _ _ t s) (PPi _ _ t' s') = do mt <- match' t t'
1563 ms <- match' s s'
1564 return (mt ++ ms)
1565 match (PLam _ t s) (PLam _ t' s') = do mt <- match' t t'
1566 ms <- match' s s'
1567 return (mt ++ ms)
1568 match (PLet _ t ty s) (PLet _ t' ty' s') = do mt <- match' t t'
1569 mty <- match' ty ty'
1570 ms <- match' s s'
1571 return (mt ++ mty ++ ms)
1572 match (PHidden x) (PHidden y) = match' x y
1573 match (PUnifyLog x) y = match' x y
1574 match x (PUnifyLog y) = match' x y
1575 match (PNoImplicits x) y = match' x y
1576 match x (PNoImplicits y) = match' x y
1577 match Placeholder _ = return []
1578 match _ Placeholder = return []
1579 match (PResolveTC _) _ = return []
1580 match a b | a == b = return []
1581 | otherwise = LeftErr (a, b)
1583 checkRpts (RightOK ms) = check ms where
1584 check ((n,t):xs)
1585 | Just t' <- lookup n xs = if t/=t' && t/=Placeholder && t'/=Placeholder
1586 then Left (t, t')
1587 else check xs
1588 check (_:xs) = check xs
1589 check [] = Right ms
1590 checkRpts (LeftErr x) = Left x
1592substMatches :: [(Name, PTerm)] -> PTerm -> PTerm
1593substMatches ms = substMatchesShadow ms []
1595substMatchesShadow :: [(Name, PTerm)] -> [Name] -> PTerm -> PTerm
1596substMatchesShadow [] shs t = t
1597substMatchesShadow ((n,tm):ns) shs t
1598 = substMatchShadow n shs tm (substMatchesShadow ns shs t)
1600substMatch :: Name -> PTerm -> PTerm -> PTerm
1601substMatch n = substMatchShadow n []
1603substMatchShadow :: Name -> [Name] -> PTerm -> PTerm -> PTerm
1604substMatchShadow n shs tm t = sm shs t where
1605 sm xs (PRef _ n') | n == n' = tm
1606 sm xs (PLam x t sc) = PLam x (sm xs t) (sm xs sc)
1607 sm xs (PPi p x t sc)
1608 | x `elem` xs
1609 = let x' = nextName x in
1610 PPi p x' (sm (x':xs) (substMatch x (PRef emptyFC x') t))
1611 (sm (x':xs) (substMatch x (PRef emptyFC x') sc))
1612 | otherwise = PPi p x (sm xs t) (sm (x : xs) sc)
1613 sm xs (PApp f x as) = fullApp $ PApp f (sm xs x) (map (fmap (sm xs)) as)
1614 sm xs (PCase f x as) = PCase f (sm xs x) (map (pmap (sm xs)) as)
1615 sm xs (PEq f x y) = PEq f (sm xs x) (sm xs y)
1616 sm xs (PRewrite f x y tm) = PRewrite f (sm xs x) (sm xs y)
1617 (fmap (sm xs) tm)
1618 sm xs (PTyped x y) = PTyped (sm xs x) (sm xs y)
1619 sm xs (PPair f x y) = PPair f (sm xs x) (sm xs y)
1620 sm xs (PDPair f x t y) = PDPair f (sm xs x) (sm xs t) (sm xs y)
1621 sm xs (PAlternative a as) = PAlternative a (map (sm xs) as)
1622 sm xs (PHidden x) = PHidden (sm xs x)
1623 sm xs (PUnifyLog x) = PUnifyLog (sm xs x)
1624 sm xs (PNoImplicits x) = PNoImplicits (sm xs x)
1625 sm xs x = x
1627 fullApp (PApp _ (PApp fc f args) xs) = fullApp (PApp fc f (args ++ xs))
1628 fullApp x = x
1630shadow :: Name -> Name -> PTerm -> PTerm
1631shadow n n' t = sm t where
1632 sm (PRef fc x) | n == x = PRef fc n'
1633 sm (PLam x t sc) | n /= x = PLam x (sm t) (sm sc)
1634 sm (PPi p x t sc) | n /=x = PPi p x (sm t) (sm sc)
1635 sm (PLet x t v sc) | n /= x = PLet x (sm t) (sm v) (sm sc)
1636 sm (PApp f x as) = PApp f (sm x) (map (fmap sm) as)
1637 sm (PAppBind f x as) = PAppBind f (sm x) (map (fmap sm) as)
1638 sm (PCase f x as) = PCase f (sm x) (map (pmap sm) as)
1639 sm (PEq f x y) = PEq f (sm x) (sm y)
1640 sm (PRewrite f x y tm) = PRewrite f (sm x) (sm y) (fmap sm tm)
1641 sm (PTyped x y) = PTyped (sm x) (sm y)
1642 sm (PPair f x y) = PPair f (sm x) (sm y)
1643 sm (PDPair f x t y) = PDPair f (sm x) (sm t) (sm y)
1644 sm (PAlternative a as) = PAlternative a (map sm as)
1645 sm (PTactics ts) = PTactics (map (fmap sm) ts)
1646 sm (PProof ts) = PProof (map (fmap sm) ts)
1647 sm (PHidden x) = PHidden (sm x)
1648 sm (PUnifyLog x) = PUnifyLog (sm x)
1649 sm (PNoImplicits x) = PNoImplicits (sm x)
1650 sm x = x
1652-- Rename any binders which are repeated (so that we don't have to mess
1653-- about with shadowing anywhere else).
1655mkUniqueNames :: [Name] -> PTerm -> PTerm
1656mkUniqueNames env tm = evalState (mkUniq tm) env where
1657 inScope = boundNamesIn tm
1659 mkUniqA arg = do t' <- mkUniq (getTm arg)
1660 return (arg { getTm = t' })
1662 -- FIXME: Probably ought to do this for completeness! It's fine as
1663 -- long as there are no bindings inside tactics though.
1664 mkUniqT tac = return tac
1666 mkUniq :: PTerm -> State [Name] PTerm
1667 mkUniq (PLam n ty sc)
1668 = do env <- get
1669 (n', sc') <-
1670 if n `elem` env
1671 then do let n' = uniqueName n (env ++ inScope)
1672 return (n', shadow n n' sc)
1673 else return (n, sc)
1674 put (n' : env)
1675 ty' <- mkUniq ty
1676 sc'' <- mkUniq sc'
1677 return $! PLam n' ty' sc''
1678 mkUniq (PPi p n ty sc)
1679 = do env <- get
1680 (n', sc') <-
1681 if n `elem` env
1682 then do let n' = uniqueName n (env ++ inScope)
1683 return (n', shadow n n' sc)
1684 else return (n, sc)
1685 put (n' : env)
1686 ty' <- mkUniq ty
1687 sc'' <- mkUniq sc'
1688 return $! PPi p n' ty' sc''
1689 mkUniq (PLet n ty val sc)
1690 = do env <- get
1691 (n', sc') <-
1692 if n `elem` env
1693 then do let n' = uniqueName n (env ++ inScope)
1694 return (n', shadow n n' sc)
1695 else return (n, sc)
1696 put (n' : env)
1697 ty' <- mkUniq ty; val' <- mkUniq val
1698 sc'' <- mkUniq sc'
1699 return $! PLet n' ty' val' sc''
1700 mkUniq (PApp fc t args)
1701 = do t' <- mkUniq t
1702 args' <- mapM mkUniqA args
1703 return $! PApp fc t' args'
1704 mkUniq (PAppBind fc t args)
1705 = do t' <- mkUniq t
1706 args' <- mapM mkUniqA args
1707 return $! PAppBind fc t' args'
1708 mkUniq (PCase fc t alts)
1709 = do t' <- mkUniq t
1710 alts' <- mapM (\(x,y)-> do x' <- mkUniq x; y' <- mkUniq y
1711 return (x', y')) alts
1712 return $! PCase fc t' alts'
1713 mkUniq (PPair fc l r)
1714 = do l' <- mkUniq l; r' <- mkUniq r
1715 return $! PPair fc l' r'
1716 mkUniq (PDPair fc l t r)
1717 = do l' <- mkUniq l; t' <- mkUniq t; r' <- mkUniq r
1718 return $! PDPair fc l' t' r'
1719 mkUniq (PAlternative b as)
1720 = liftM (PAlternative b) (mapM mkUniq as)
1721 mkUniq (PHidden t) = liftM PHidden (mkUniq t)
1722 mkUniq (PUnifyLog t) = liftM PUnifyLog (mkUniq t)
1723 mkUniq (PDisamb n t) = liftM (PDisamb n) (mkUniq t)
1724 mkUniq (PNoImplicits t) = liftM PNoImplicits (mkUniq t)
1725 mkUniq (PProof ts) = liftM PProof (mapM mkUniqT ts)
1726 mkUniq (PTactics ts) = liftM PTactics (mapM mkUniqT ts)
1727 mkUniq t = return t