on 47cd264 help sign in
Idris-dev/src/Idris/AbsSyntax.hs
1884 lines 79 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 qualified Data.Map as M
29import Data.Maybe
30import qualified Data.Set as S
31import Data.Word (Word)
33import Debug.Trace
35import Control.Monad.Error (throwError, catchError)
36import System.IO.Error(isUserError, ioeGetErrorString, tryIOError)
38import Util.Pretty
39import Util.ScreenSize
40import Util.System
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)
72 [] -> do
73 handle <- lift . lift .
74 mapM (\l -> catchIO (tryLoadLib importdirs l)
75 (\_ -> return Nothing)) $ libs
76 case msum handle of
77 Nothing -> return (Right $ "Could not load dynamic alternatives \"" ++
78 concat (intersperse "," libs) ++ "\"")
79 Just x -> do putIState $ i { idris_dynamic_libs = x:ls }
80 return (Left x)
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
87addHdr :: Codegen -> String -> Idris ()
88addHdr tgt f = do i <- getIState; putIState $ i { idris_hdrs = nub $ (tgt, f) : idris_hdrs i }
90addLangExt :: LanguageExt -> Idris ()
91addLangExt TypeProviders = do i <- getIState
92 putIState $ i {
93 idris_language_extensions = TypeProviders : idris_language_extensions i
94 }
95addLangExt ErrorReflection = do i <- getIState
96 putIState $ i {
97 idris_language_extensions = ErrorReflection : idris_language_extensions i
98 }
100addTrans :: (Term, Term) -> Idris ()
101addTrans t = do i <- getIState
102 putIState $ i { idris_transforms = t : idris_transforms i }
104addErrRev :: (Term, Term) -> Idris ()
105addErrRev t = do i <- getIState
106 putIState $ i { idris_errRev = t : idris_errRev i }
108totcheck :: (FC, Name) -> Idris ()
109totcheck n = do i <- getIState; putIState $ i { idris_totcheck = idris_totcheck i ++ [n] }
111defer_totcheck :: (FC, Name) -> Idris ()
112defer_totcheck n
113 = do i <- getIState;
114 putIState $ i { idris_defertotcheck = nub (idris_defertotcheck i ++ [n]) }
116clear_totcheck :: Idris ()
117clear_totcheck = do i <- getIState; putIState $ i { idris_totcheck = [] }
119setFlags :: Name -> [FnOpt] -> Idris ()
120setFlags n fs = do i <- getIState; putIState $ i { idris_flags = addDef n fs (idris_flags i) }
122setAccessibility :: Name -> Accessibility -> Idris ()
123setAccessibility n a
124 = do i <- getIState
125 let ctxt = setAccess n a (tt_ctxt i)
126 putIState $ i { tt_ctxt = ctxt }
128setTotality :: Name -> Totality -> Idris ()
129setTotality n a
130 = do i <- getIState
131 let ctxt = setTotal n a (tt_ctxt i)
132 putIState $ i { tt_ctxt = ctxt }
134getTotality :: Name -> Idris Totality
135getTotality n
136 = do i <- getIState
137 case lookupTotal n (tt_ctxt i) of
138 [t] -> return t
139 _ -> return (Total [])
141-- Get coercions which might return the required type
142getCoercionsTo :: IState -> Type -> [Name]
143getCoercionsTo i ty =
144 let cs = idris_coercions i
145 (fn,_) = unApply (getRetTy ty) in
146 findCoercions fn cs
147 where findCoercions t [] = []
148 findCoercions t (n : ns) =
149 let ps = case lookupTy n (tt_ctxt i) of
150 [ty'] -> case unApply (getRetTy ty') of
151 (t', _) ->
152 if t == t' then [n] else []
153 _ -> [] in
154 ps ++ findCoercions t ns
156addToCG :: Name -> CGInfo -> Idris ()
157addToCG n cg
158 = do i <- getIState
159 putIState $ i { idris_callgraph = addDef n cg (idris_callgraph i) }
161addTyInferred :: Name -> Idris ()
162addTyInferred n
163 = do i <- getIState
164 putIState $ i { idris_tyinfodata =
165 addDef n TIPartial (idris_tyinfodata i) }
167addTyInfConstraints :: FC -> [(Term, Term)] -> Idris ()
168addTyInfConstraints fc ts = do logLvl 2 $ "TI missing: " ++ show ts
169 mapM_ addConstraint ts
170 return ()
171 where addConstraint (x, y) = findMVApps x y
173 findMVApps x y
174 = do let (fx, argsx) = unApply x
175 let (fy, argsy) = unApply y
176 if (not (fx == fy))
177 then do
178 tryAddMV fx y
179 tryAddMV fy x
180 else mapM_ addConstraint (zip argsx argsy)
182 tryAddMV (P _ mv _) y =
183 do ist <- get
184 case lookup mv (idris_metavars ist) of
185 Just _ -> addConstraintRule mv y
186 _ -> return ()
187 tryAddMV _ _ = return ()
189 addConstraintRule :: Name -> Term -> Idris ()
190 addConstraintRule n t
191 = do ist <- get
192 logLvl 1 $ "TI constraint: " ++ show (n, t)
193 case lookupCtxt n (idris_tyinfodata ist) of
194 [TISolution ts] ->
195 do mapM_ (checkConsistent t) ts
196 let ti' = addDef n (TISolution (t : ts))
197 (idris_tyinfodata ist)
198 put $ ist { idris_tyinfodata = ti' }
199 _ ->
200 do let ti' = addDef n (TISolution [t])
201 (idris_tyinfodata ist)
202 put $ ist { idris_tyinfodata = ti' }
204 -- Check a solution is consistent with previous solutions
205 -- Meaning: If heads are both data types, they had better be the
206 -- same.
207 checkConsistent :: Term -> Term -> Idris ()
208 checkConsistent x y =
209 do let (fx, _) = unApply x
210 let (fy, _) = unApply y
211 case (fx, fy) of
212 (P (TCon _ _) n _, P (TCon _ _) n' _) -> errWhen (n/=n)
213 (P (TCon _ _) n _, Constant _) -> errWhen True
214 (Constant _, P (TCon _ _) n' _) -> errWhen True
215 (P (DCon _ _) n _, P (DCon _ _) n' _) -> errWhen (n/=n)
216 _ -> return ()
218 where errWhen True
219 = throwError (At fc
220 (CantUnify False x y (Msg "") [] 0))
221 errWhen False = return ()
223isTyInferred :: Name -> Idris Bool
224isTyInferred n
225 = do i <- getIState
226 case lookupCtxt n (idris_tyinfodata i) of
227 [TIPartial] -> return True
228 _ -> return False
230-- | Adds error handlers for a particular function and argument. If names are
231-- ambiguous, all matching handlers are updated.
232addFunctionErrorHandlers :: Name -> Name -> [Name] -> Idris ()
233addFunctionErrorHandlers f arg hs =
234 do i <- getIState
235 let oldHandlers = idris_function_errorhandlers i
236 let newHandlers = flip (addDef f) oldHandlers $
237 case lookupCtxtExact f oldHandlers of
238 Nothing -> M.singleton arg (S.fromList hs)
239 Just (oldHandlers) -> M.insertWith S.union arg (S.fromList hs) oldHandlers
240 -- will always be one of those two, thus no extra case
241 putIState $ i { idris_function_errorhandlers = newHandlers }
243getFunctionErrorHandlers :: Name -> Name -> Idris [Name]
244getFunctionErrorHandlers f arg = do i <- getIState
245 return . maybe [] S.toList $
246 undefined --lookup arg =<< lookupCtxtExact f (idris_function_errorhandlers i)
249-- Trace all the names in a call graph starting at the given name
250getAllNames :: Name -> Idris [Name]
251getAllNames n = allNames [] n
253allNames :: [Name] -> Name -> Idris [Name]
254allNames ns n | n `elem` ns = return []
255allNames ns n = do i <- getIState
256 case lookupCtxtExact n (idris_callgraph i) of
257 Just ns' -> do more <- mapM (allNames (n:ns)) (map fst (calls ns'))
258 return (nub (n : concat more))
259 _ -> return [n]
261addCoercion :: Name -> Idris ()
262addCoercion n = do i <- getIState
263 putIState $ i { idris_coercions = nub $ n : idris_coercions i }
265addDocStr :: Name -> String -> Idris ()
266addDocStr n doc
267 = do i <- getIState
268 putIState $ i { idris_docstrings = addDef n doc (idris_docstrings i) }
270addNameHint :: Name -> Name -> Idris ()
271addNameHint ty n
272 = do i <- getIState
273 ty' <- case lookupCtxtName ty (idris_implicits i) of
274 [(tyn, _)] -> return tyn
275 [] -> throwError (NoSuchVariable ty)
276 tyns -> throwError (CantResolveAlts (map show (map fst tyns)))
277 let ns' = case lookupCtxt ty' (idris_namehints i) of
278 [ns] -> ns ++ [n]
279 _ -> [n]
280 putIState $ i { idris_namehints = addDef ty' ns' (idris_namehints i) }
282getNameHints :: IState -> Name -> [Name]
283getNameHints i (UN arr) | arr == txt "->" = [sUN "f",sUN "g"]
284getNameHints i n =
285 case lookupCtxt n (idris_namehints i) of
286 [ns] -> ns
287 _ -> []
289addToCalledG :: Name -> [Name] -> Idris ()
290addToCalledG n ns = return () -- TODO
292-- Add a class instance function. Dodgy hack: Put integer instances first in the
293-- list so they are resolved by default.
294-- Dodgy hack 2: put constraint chasers (@@) last
296addInstance :: Bool -> Name -> Name -> Idris ()
297addInstance int n i
298 = do ist <- getIState
299 case lookupCtxt n (idris_classes ist) of
300 [CI a b c d e ins] ->
301 do let cs = addDef n (CI a b c d e (addI i ins)) (idris_classes ist)
302 putIState $ ist { idris_classes = cs }
303 _ -> do let cs = addDef n (CI (sMN 0 "none") [] [] [] [] [i]) (idris_classes ist)
304 putIState $ ist { idris_classes = cs }
305 where addI i ins | int = i : ins
306 | chaser n = ins ++ [i]
307 | otherwise = insI i ins
308 insI i [] = [i]
309 insI i (n : ns) | chaser n = i : n : ns
310 | otherwise = n : insI i ns
312 chaser (UN nm)
313 | ('@':'@':_) <- str nm = True
314 chaser (NS n _) = chaser n
315 chaser _ = False
317addClass :: Name -> ClassInfo -> Idris ()
318addClass n i
319 = do ist <- getIState
320 let i' = case lookupCtxt n (idris_classes ist) of
321 [c] -> c { class_instances = class_instances i }
322 _ -> i
323 putIState $ ist { idris_classes = addDef n i' (idris_classes ist) }
325addIBC :: IBCWrite -> Idris ()
326addIBC ibc@(IBCDef n)
327 = do i <- getIState
328 when (notDef (ibc_write i)) $
329 putIState $ i { ibc_write = ibc : ibc_write i }
330 where notDef [] = True
331 notDef (IBCDef n': is) | n == n' = False
332 notDef (_ : is) = notDef is
333addIBC ibc = do i <- getIState; putIState $ i { ibc_write = ibc : ibc_write i }
335clearIBC :: Idris ()
336clearIBC = do i <- getIState; putIState $ i { ibc_write = [] }
338resetNameIdx :: Idris ()
339resetNameIdx = do i <- getIState
340 put (i { idris_nameIdx = (0, emptyContext) })
342-- Used to preserve sharing of names
343addNameIdx :: Name -> Idris (Int, Name)
344addNameIdx n = do i <- getIState
345 let (i', x) = addNameIdx' i n
346 return x
348addNameIdx' :: IState -> Name -> (IState, (Int, Name))
349addNameIdx' i n
350 = let idxs = snd (idris_nameIdx i) in
351 case lookupCtxt n idxs of
352 [x] -> (i, x)
353 _ -> let i' = fst (idris_nameIdx i) + 1 in
354 (i { idris_nameIdx = (i', addDef n (i', n) idxs) }, (i', n))
356getHdrs :: Codegen -> Idris [String]
357getHdrs tgt = do i <- getIState; return (forCodegen tgt $ idris_hdrs i)
359setErrLine :: Int -> Idris ()
360setErrLine x = do i <- getIState;
361 case (errLine i) of
362 Nothing -> putIState $ i { errLine = Just x }
363 Just _ -> return ()
365clearErr :: Idris ()
366clearErr = do i <- getIState
367 putIState $ i { errLine = Nothing }
369getSO :: Idris (Maybe String)
370getSO = do i <- getIState
371 return (compiled_so i)
373setSO :: Maybe String -> Idris ()
374setSO s = do i <- getIState
375 putIState $ (i { compiled_so = s })
377getIState :: Idris IState
378getIState = get
380putIState :: IState -> Idris ()
381putIState = put
383-- | A version of liftIO that puts errors into the exception type of the Idris monad
384runIO :: IO a -> Idris a
385runIO x = liftIO (tryIOError x) >>= either (throwError . Msg . show) return
386-- TODO: create specific Idris exceptions for specific IO errors such as "openFile: does not exist"
388getName :: Idris Int
389getName = do i <- getIState;
390 let idx = idris_name i;
391 putIState $ (i { idris_name = idx + 1 })
392 return idx
394addInternalApp :: FilePath -> Int -> PTerm -> Idris ()
395addInternalApp fp l t
396 = do i <- getIState
397 putIState (i { idris_lineapps = ((fp, l), t) : idris_lineapps i })
399getInternalApp :: FilePath -> Int -> Idris PTerm
400getInternalApp fp l = do i <- getIState
401 case lookup (fp, l) (idris_lineapps i) of
402 Just n' -> return n'
403 Nothing -> return Placeholder
404 -- TODO: What if it's not there?
406-- Pattern definitions are only used for coverage checking, so erase them
407-- when we're done
408clearOrigPats :: Idris ()
409clearOrigPats = do i <- get
410 let ps = idris_patdefs i
411 let ps' = mapCtxt (\ (_,miss) -> ([], miss)) ps
412 put (i { idris_patdefs = ps' })
414-- Erase types from Ps in the context (basically ending up with what's in
415-- the .ibc, which is all we need after all the analysis is done)
416clearPTypes :: Idris ()
417clearPTypes = do i <- get
418 let ctxt = tt_ctxt i
419 put (i { tt_ctxt = mapDefCtxt pErase ctxt })
420 where pErase (CaseOp c t tys orig tot cds)
421 = CaseOp c t tys orig [] (pErase' cds)
422 pErase x = x
423 pErase' (CaseDefs _ (cs, c) _ rs)
424 = let c' = (cs, fmap pEraseType c) in
425 CaseDefs c' c' c' rs
427checkUndefined :: FC -> Name -> Idris ()
428checkUndefined fc n
429 = do i <- getContext
430 case lookupTy n i of
431 (_:_) -> throwError . Msg $ show fc ++ ":" ++
432 show n ++ " already defined"
433 _ -> return ()
435isUndefined :: FC -> Name -> Idris Bool
436isUndefined fc n
437 = do i <- getContext
438 case lookupTy n i of
439 (_:_) -> return False
440 _ -> return True
442setContext :: Context -> Idris ()
443setContext ctxt = do i <- getIState; putIState $ (i { tt_ctxt = ctxt } )
445updateContext :: (Context -> Context) -> Idris ()
446updateContext f = do i <- getIState; putIState $ (i { tt_ctxt = f (tt_ctxt i) } )
448addConstraints :: FC -> (Int, [UConstraint]) -> Idris ()
449addConstraints fc (v, cs)
450 = do i <- getIState
451 let ctxt = tt_ctxt i
452 let ctxt' = ctxt { uconstraints = cs ++ uconstraints ctxt,
453 next_tvar = v }
454 let ics = zip cs (repeat fc) ++ idris_constraints i
455 putIState $ i { tt_ctxt = ctxt', idris_constraints = ics }
457addDeferred = addDeferred' Ref
458addDeferredTyCon = addDeferred' (TCon 0 0)
460addDeferred' :: NameType -> [(Name, (Int, Maybe Name, Type, Bool))] -> Idris ()
461addDeferred' nt ns
462 = do mapM_ (\(n, (i, _, t, _)) -> updateContext (addTyDecl n nt (tidyNames [] t))) ns
463 mapM_ (\(n, _) -> when (not (n `elem` primDefs)) $ addIBC (IBCMetavar n)) ns
464 i <- getIState
465 putIState $ i { idris_metavars = map (\(n, (i, top, _, isTopLevel)) -> (n, (top, i, isTopLevel))) ns ++
466 idris_metavars i }
467 where tidyNames used (Bind (MN i x) b sc)
468 = let n' = uniqueName (UN x) used in
469 Bind n' b $ tidyNames (n':used) sc
470 tidyNames used (Bind n b sc)
471 = let n' = uniqueName n used in
472 Bind n' b $ tidyNames (n':used) sc
473 tidyNames used b = b
475solveDeferred :: Name -> Idris ()
476solveDeferred n = do i <- getIState
477 putIState $ i { idris_metavars =
478 filter (\(n', _) -> n/=n')
479 (idris_metavars i),
480 ibc_write =
481 filter (notMV n) (ibc_write i)
482 }
483 where notMV n (IBCMetavar n') = not (n == n')
484 notMV n _ = True
486getUndefined :: Idris [Name]
487getUndefined = do i <- getIState
488 return (map fst (idris_metavars i) \\ primDefs)
490getWidth :: Idris ConsoleWidth
491getWidth = fmap idris_consolewidth getIState
493setWidth :: ConsoleWidth -> Idris ()
494setWidth w = do ist <- getIState
495 put ist { idris_consolewidth = w }
497renderWidth :: Idris Int
498renderWidth = do iw <- getWidth
499 case iw of
500 InfinitelyWide -> return 100000000
501 ColsWide n -> return (max n 1)
502 AutomaticWidth -> runIO getScreenWidth
505iRender :: Doc a -> Idris (SimpleDoc a)
506iRender d = do w <- getWidth
507 ist <- getIState
508 let ideSlave = case idris_outputmode ist of
509 IdeSlave _ -> True
510 _ -> False
511 case w of
512 InfinitelyWide -> return $ renderPretty 1.0 1000000000 d
513 ColsWide n -> return $
514 if n < 1
515 then renderPretty 1.0 1000000000 d
516 else renderPretty 0.8 n d
517 AutomaticWidth | ideSlave -> return $ renderPretty 1.0 1000000000 d
518 | otherwise -> do width <- runIO getScreenWidth
519 return $ renderPretty 0.8 width d
521ihPrintResult :: Handle -> String -> Idris ()
522ihPrintResult h s = do i <- getIState
523 case idris_outputmode i of
524 RawOutput -> case s of
525 "" -> return ()
526 s -> runIO $ hPutStrLn h s
527 IdeSlave n ->
528 let good = SexpList [SymbolAtom "ok", toSExp s] in
529 runIO $ hPutStrLn h $ convSExp "return" good n
531-- | Write a pretty-printed term to the console with semantic coloring
532consoleDisplayAnnotated :: Handle -> Doc OutputAnnotation -> Idris ()
533consoleDisplayAnnotated h output = do ist <- getIState
534 rendered <- iRender $ output
535 runIO . hPutStrLn h .
536 displayDecorated (consoleDecorate ist) $
537 rendered
540-- | Write pretty-printed output to IDESlave with semantic annotations
541ideSlaveReturnAnnotated :: Integer -> Handle -> Doc OutputAnnotation -> Idris ()
542ideSlaveReturnAnnotated n h out = do ist <- getIState
543 (str, spans) <- fmap displaySpans .
544 iRender .
545 fmap (fancifyAnnots ist) $
546 out
547 let good = [SymbolAtom "ok", toSExp str, toSExp spans]
548 runIO . hPutStrLn h $ convSExp "return" good n
550ihPrintTermWithType :: Handle -> Doc OutputAnnotation -> Doc OutputAnnotation -> Idris ()
551ihPrintTermWithType h tm ty = do ist <- getIState
552 let output = tm <+> colon <+> ty
553 case idris_outputmode ist of
554 RawOutput -> consoleDisplayAnnotated h output
555 IdeSlave n -> ideSlaveReturnAnnotated n h output
557-- | Pretty-print a collection of overloadings to REPL or IDESlave - corresponds to :t name
558ihPrintFunTypes :: Handle -> [(Name, Bool)] -> Name -> [(Name, PTerm)] -> Idris ()
559ihPrintFunTypes h bnd n [] = ihPrintError h $ "No such variable " ++ show n
560ihPrintFunTypes h bnd n overloads = do imp <- impShow
561 ist <- getIState
562 let output = vsep (map (uncurry (ppOverload imp)) overloads)
563 case idris_outputmode ist of
564 RawOutput -> consoleDisplayAnnotated h output
565 IdeSlave n -> ideSlaveReturnAnnotated n h output
566 where fullName n = prettyName True bnd n
567 ppOverload imp n tm = fullName n <+> colon <+> align (pprintPTerm imp bnd tm)
569ihRenderResult :: Handle -> Doc OutputAnnotation -> Idris ()
570ihRenderResult h d = do ist <- getIState
571 case idris_outputmode ist of
572 RawOutput -> consoleDisplayAnnotated h d
573 IdeSlave n -> ideSlaveReturnAnnotated n h d
575fancifyAnnots :: IState -> OutputAnnotation -> OutputAnnotation
576fancifyAnnots ist annot@(AnnName n _ _) =
577 do let ctxt = tt_ctxt ist
578 case () of
579 _ | isDConName n ctxt -> AnnName n (Just DataOutput) Nothing
580 _ | isFnName n ctxt -> AnnName n (Just FunOutput) Nothing
581 _ | isTConName n ctxt -> AnnName n (Just TypeOutput) Nothing
582 _ | otherwise -> annot
583fancifyAnnots _ annot = annot
585type1Doc :: Doc OutputAnnotation
586type1Doc = (annotate AnnConstType $ text "Type 1")
588-- | Show an error with semantic highlighting
589ihRenderError :: Handle -> Doc OutputAnnotation -> Idris ()
590ihRenderError h e = do ist <- getIState
591 case idris_outputmode ist of
592 RawOutput -> consoleDisplayAnnotated h e
593 IdeSlave n -> do
594 (str, spans) <- fmap displaySpans .
595 iRender .
596 fmap (fancifyAnnots ist) $
597 e
598 let good = [SymbolAtom "error", toSExp str, toSExp spans]
599 runIO . hPutStrLn h $ convSExp "return" good n
601ihPrintError :: Handle -> String -> Idris ()
602ihPrintError h s = do i <- getIState
603 case idris_outputmode i of
604 RawOutput -> case s of
605 "" -> return ()
606 s -> runIO $ hPutStrLn h s
607 IdeSlave n ->
608 let good = SexpList [SymbolAtom "error", toSExp s] in
609 runIO . hPutStrLn h $ convSExp "return" good n
611ihputStrLn :: Handle -> String -> Idris ()
612ihputStrLn h s = do i <- getIState
613 case idris_outputmode i of
614 RawOutput -> runIO $ hPutStrLn h s
615 IdeSlave n -> runIO . hPutStrLn h $ convSExp "write-string" s n
617iputStrLn = ihputStrLn stdout
618iPrintError = ihPrintError stdout
619iPrintResult = ihPrintResult stdout
620iWarn = ihWarn stdout
622ideslavePutSExp :: SExpable a => String -> a -> Idris ()
623ideslavePutSExp cmd info = do i <- getIState
624 case idris_outputmode i of
625 IdeSlave n -> runIO . putStrLn $ convSExp cmd info n
626 _ -> return ()
628-- this needs some typing magic and more structured output towards emacs
629iputGoal :: SimpleDoc OutputAnnotation -> Idris ()
630iputGoal g = do i <- getIState
631 case idris_outputmode i of
632 RawOutput -> runIO $ putStrLn (displayDecorated (consoleDecorate i) g)
633 IdeSlave n -> runIO . putStrLn $
634 convSExp "write-goal" (displayS (fmap (fancifyAnnots i) g) "") n
636isetPrompt :: String -> Idris ()
637isetPrompt p = do i <- getIState
638 case idris_outputmode i of
639 IdeSlave n -> runIO . putStrLn $ convSExp "set-prompt" p n
641ihWarn :: Handle -> FC -> Doc OutputAnnotation -> Idris ()
642ihWarn h fc err = do i <- getIState
643 err' <- iRender . fmap (fancifyAnnots i) $ err
644 case idris_outputmode i of
645 RawOutput ->
646 runIO $
647 hPutStrLn h (show fc ++ ":" ++ displayDecorated (consoleDecorate i) err')
648 IdeSlave n ->
649 do let (str, spans) = displaySpans err'
650 runIO . hPutStrLn h $
651 convSExp "warning" (fc_fname fc, fc_line fc, fc_column fc, str, spans) n
653setLogLevel :: Int -> Idris ()
654setLogLevel l = do i <- getIState
655 let opts = idris_options i
656 let opt' = opts { opt_logLevel = l }
657 putIState $ i { idris_options = opt' }
659setCmdLine :: [Opt] -> Idris ()
660setCmdLine opts = do i <- getIState
661 let iopts = idris_options i
662 putIState $ i { idris_options = iopts { opt_cmdline = opts } }
664getCmdLine :: Idris [Opt]
665getCmdLine = do i <- getIState
666 return (opt_cmdline (idris_options i))
668getDumpDefun :: Idris (Maybe FilePath)
669getDumpDefun = do i <- getIState
670 return $ findC (opt_cmdline (idris_options i))
671 where findC [] = Nothing
672 findC (DumpDefun x : _) = Just x
673 findC (_ : xs) = findC xs
675getDumpCases :: Idris (Maybe FilePath)
676getDumpCases = do i <- getIState
677 return $ findC (opt_cmdline (idris_options i))
678 where findC [] = Nothing
679 findC (DumpCases x : _) = Just x
680 findC (_ : xs) = findC xs
682logLevel :: Idris Int
683logLevel = do i <- getIState
684 return (opt_logLevel (idris_options i))
686setErrContext :: Bool -> Idris ()
687setErrContext t = do i <- getIState
688 let opts = idris_options i
689 let opt' = opts { opt_errContext = t }
690 putIState $ i { idris_options = opt' }
692errContext :: Idris Bool
693errContext = do i <- getIState
694 return (opt_errContext (idris_options i))
696useREPL :: Idris Bool
697useREPL = do i <- getIState
698 return (opt_repl (idris_options i))
700setREPL :: Bool -> Idris ()
701setREPL t = do i <- getIState
702 let opts = idris_options i
703 let opt' = opts { opt_repl = t }
704 putIState $ i { idris_options = opt' }
706showOrigErr :: Idris Bool
707showOrigErr = do i <- getIState
708 return (opt_origerr (idris_options i))
710setShowOrigErr :: Bool -> Idris ()
711setShowOrigErr b = do i <- getIState
712 let opts = idris_options i
713 let opt' = opts { opt_origerr = b }
714 putIState $ i { idris_options = opt' }
716setNoBanner :: Bool -> Idris ()
717setNoBanner n = do i <- getIState
718 let opts = idris_options i
719 let opt' = opts { opt_nobanner = n }
720 putIState $ i { idris_options = opt' }
722getNoBanner :: Idris Bool
723getNoBanner = do i <- getIState
724 let opts = idris_options i
725 return (opt_nobanner opts)
727setQuiet :: Bool -> Idris ()
728setQuiet q = do i <- getIState
729 let opts = idris_options i
730 let opt' = opts { opt_quiet = q }
731 putIState $ i { idris_options = opt' }
733getQuiet :: Idris Bool
734getQuiet = do i <- getIState
735 let opts = idris_options i
736 return (opt_quiet opts)
738setCodegen :: Codegen -> Idris ()
739setCodegen t = do i <- getIState
740 let opts = idris_options i
741 let opt' = opts { opt_codegen = t }
742 putIState $ i { idris_options = opt' }
744codegen :: Idris Codegen
745codegen = do i <- getIState
746 return (opt_codegen (idris_options i))
748setOutputTy :: OutputType -> Idris ()
749setOutputTy t = do i <- getIState
750 let opts = idris_options i
751 let opt' = opts { opt_outputTy = t }
752 putIState $ i { idris_options = opt' }
754outputTy :: Idris OutputType
755outputTy = do i <- getIState
756 return $ opt_outputTy $ idris_options i
758setIdeSlave :: Bool -> Idris ()
759setIdeSlave True = do i <- getIState
760 putIState $ i { idris_outputmode = (IdeSlave 0), idris_colourRepl = False }
761setIdeSlave False = return ()
763setTargetTriple :: String -> Idris ()
764setTargetTriple t = do i <- getIState
765 let opts = idris_options i
766 opt' = opts { opt_triple = t }
767 putIState $ i { idris_options = opt' }
769targetTriple :: Idris String
770targetTriple = do i <- getIState
771 return (opt_triple (idris_options i))
773setTargetCPU :: String -> Idris ()
774setTargetCPU t = do i <- getIState
775 let opts = idris_options i
776 opt' = opts { opt_cpu = t }
777 putIState $ i { idris_options = opt' }
779targetCPU :: Idris String
780targetCPU = do i <- getIState
781 return (opt_cpu (idris_options i))
783setOptLevel :: Word -> Idris ()
784setOptLevel t = do i <- getIState
785 let opts = idris_options i
786 opt' = opts { opt_optLevel = t }
787 putIState $ i { idris_options = opt' }
789optLevel :: Idris Word
790optLevel = do i <- getIState
791 return (opt_optLevel (idris_options i))
793verbose :: Idris Bool
794verbose = do i <- getIState
795 return (opt_verbose (idris_options i))
797setVerbose :: Bool -> Idris ()
798setVerbose t = do i <- getIState
799 let opts = idris_options i
800 let opt' = opts { opt_verbose = t }
801 putIState $ i { idris_options = opt' }
803typeInType :: Idris Bool
804typeInType = do i <- getIState
805 return (opt_typeintype (idris_options i))
807setTypeInType :: Bool -> Idris ()
808setTypeInType t = do i <- getIState
809 let opts = idris_options i
810 let opt' = opts { opt_typeintype = t }
811 putIState $ i { idris_options = opt' }
813coverage :: Idris Bool
814coverage = do i <- getIState
815 return (opt_coverage (idris_options i))
817setCoverage :: Bool -> Idris ()
818setCoverage t = do i <- getIState
819 let opts = idris_options i
820 let opt' = opts { opt_coverage = t }
821 putIState $ i { idris_options = opt' }
823setIBCSubDir :: FilePath -> Idris ()
824setIBCSubDir fp = do i <- getIState
825 let opts = idris_options i
826 let opt' = opts { opt_ibcsubdir = fp }
827 putIState $ i { idris_options = opt' }
829valIBCSubDir :: IState -> Idris FilePath
830valIBCSubDir i = return (opt_ibcsubdir (idris_options i))
832addImportDir :: FilePath -> Idris ()
833addImportDir fp = do i <- getIState
834 let opts = idris_options i
835 let opt' = opts { opt_importdirs = fp : opt_importdirs opts }
836 putIState $ i { idris_options = opt' }
838setImportDirs :: [FilePath] -> Idris ()
839setImportDirs fps = do i <- getIState
840 let opts = idris_options i
841 let opt' = opts { opt_importdirs = fps }
842 putIState $ i { idris_options = opt' }
844allImportDirs :: Idris [FilePath]
845allImportDirs = do i <- getIState
846 let optdirs = opt_importdirs (idris_options i)
847 return ("." : reverse optdirs)
849colourise :: Idris Bool
850colourise = do i <- getIState
851 return $ idris_colourRepl i
853setColourise :: Bool -> Idris ()
854setColourise b = do i <- getIState
855 putIState $ i { idris_colourRepl = b }
857setOutH :: Handle -> Idris ()
858setOutH h = do i <- getIState
859 putIState $ i { idris_outh = h }
861impShow :: Idris Bool
862impShow = do i <- getIState
863 return (opt_showimp (idris_options i))
865setImpShow :: Bool -> Idris ()
866setImpShow t = do i <- getIState
867 let opts = idris_options i
868 let opt' = opts { opt_showimp = t }
869 putIState $ i { idris_options = opt' }
871setColour :: ColourType -> IdrisColour -> Idris ()
872setColour ct c = do i <- getIState
873 let newTheme = setColour' ct c (idris_colourTheme i)
874 putIState $ i { idris_colourTheme = newTheme }
875 where setColour' KeywordColour c t = t { keywordColour = c }
876 setColour' BoundVarColour c t = t { boundVarColour = c }
877 setColour' ImplicitColour c t = t { implicitColour = c }
878 setColour' FunctionColour c t = t { functionColour = c }
879 setColour' TypeColour c t = t { typeColour = c }
880 setColour' DataColour c t = t { dataColour = c }
881 setColour' PromptColour c t = t { promptColour = c }
883logLvl :: Int -> String -> Idris ()
884logLvl l str = do i <- getIState
885 let lvl = opt_logLevel (idris_options i)
886 when (lvl >= l) $
887 case idris_outputmode i of
888 RawOutput -> do runIO $ putStrLn str
889 IdeSlave n ->
890 do let good = SexpList [IntegerAtom (toInteger l), toSExp str]
891 runIO $ putStrLn $ convSExp "log" good n
893cmdOptType :: Opt -> Idris Bool
894cmdOptType x = do i <- getIState
895 return $ x `elem` opt_cmdline (idris_options i)
897iLOG :: String -> Idris ()
898iLOG = logLvl 1
900noErrors :: Idris Bool
901noErrors = do i <- getIState
902 case errLine i of
903 Nothing -> return True
904 _ -> return False
906setTypeCase :: Bool -> Idris ()
907setTypeCase t = do i <- getIState
908 let opts = idris_options i
909 let opt' = opts { opt_typecase = t }
910 putIState $ i { idris_options = opt' }
913-- Dealing with parameters
915expandParams :: (Name -> Name) -> [(Name, PTerm)] ->
916 [Name] -> -- all names
917 [Name] -> -- names with no declaration
918 PTerm -> PTerm
919expandParams dec ps ns infs tm = en tm
920 where
921 -- if we shadow a name (say in a lambda binding) that is used in a call to
922 -- a lifted function, we need access to both names - once in the scope of the
923 -- binding and once to call the lifted functions. So we'll explicitly shadow
924 -- it. (Yes, it's a hack. The alternative would be to resolve names earlier
925 -- but we didn't...)
927 mkShadow (UN n) = MN 0 n
928 mkShadow (MN i n) = MN (i+1) n
929 mkShadow (NS x s) = NS (mkShadow x) s
931 en (PLam n t s)
932 | n `elem` (map fst ps ++ ns)
933 = let n' = mkShadow n in
934 PLam n' (en t) (en (shadow n n' s))
935 | otherwise = PLam n (en t) (en s)
936 en (PPi p n t s)
937 | n `elem` (map fst ps ++ ns)
938 = let n' = mkShadow n in
939 PPi p n' (en t) (en (shadow n n' s))
940 | otherwise = PPi p n (en t) (en s)
941 en (PLet n ty v s)
942 | n `elem` (map fst ps ++ ns)
943 = let n' = mkShadow n in
944 PLet n' (en ty) (en v) (en (shadow n n' s))
945 | otherwise = PLet n (en ty) (en v) (en s)
946 -- FIXME: Should only do this in a type signature!
947 en (PDPair f p (PRef f' n) t r)
948 | n `elem` (map fst ps ++ ns) && t /= Placeholder
949 = let n' = mkShadow n in
950 PDPair f p (PRef f' n') (en t) (en (shadow n n' r))
951 en (PEq f l r) = PEq f (en l) (en r)
952 en (PRewrite f l r g) = PRewrite f (en l) (en r) (fmap en g)
953 en (PTyped l r) = PTyped (en l) (en r)
954 en (PPair f p l r) = PPair f p (en l) (en r)
955 en (PDPair f p l t r) = PDPair f p (en l) (en t) (en r)
956 en (PAlternative a as) = PAlternative a (map en as)
957 en (PHidden t) = PHidden (en t)
958 en (PUnifyLog t) = PUnifyLog (en t)
959 en (PDisamb ds t) = PDisamb ds (en t)
960 en (PNoImplicits t) = PNoImplicits (en t)
961 en (PDoBlock ds) = PDoBlock (map (fmap en) ds)
962 en (PProof ts) = PProof (map (fmap en) ts)
963 en (PTactics ts) = PTactics (map (fmap en) ts)
965 en (PQuote (Var n))
966 | n `nselem` ns = PQuote (Var (dec n))
967 en (PApp fc (PInferRef fc' n) as)
968 | n `nselem` ns = PApp fc (PInferRef fc' (dec n))
969 (map (pexp . (PRef fc)) (map fst ps) ++ (map (fmap en) as))
970 en (PApp fc (PRef fc' n) as)
971 | n `elem` infs = PApp fc (PInferRef fc' (dec n))
972 (map (pexp . (PRef fc)) (map fst ps) ++ (map (fmap en) as))
973 | n `nselem` ns = PApp fc (PRef fc' (dec n))
974 (map (pexp . (PRef fc)) (map fst ps) ++ (map (fmap en) as))
975 en (PAppBind fc (PRef fc' n) as)
976 | n `elem` infs = PAppBind fc (PInferRef fc' (dec n))
977 (map (pexp . (PRef fc)) (map fst ps) ++ (map (fmap en) as))
978 | n `nselem` ns = PAppBind fc (PRef fc' (dec n))
979 (map (pexp . (PRef fc)) (map fst ps) ++ (map (fmap en) as))
980 en (PRef fc n)
981 | n `elem` infs = PApp fc (PInferRef fc (dec n))
982 (map (pexp . (PRef fc)) (map fst ps))
983 | n `nselem` ns = PApp fc (PRef fc (dec n))
984 (map (pexp . (PRef fc)) (map fst ps))
985 en (PInferRef fc n)
986 | n `nselem` ns = PApp fc (PInferRef fc (dec n))
987 (map (pexp . (PRef fc)) (map fst ps))
988 en (PApp fc f as) = PApp fc (en f) (map (fmap en) as)
989 en (PAppBind fc f as) = PAppBind fc (en f) (map (fmap en) as)
990 en (PCase fc c os) = PCase fc (en c) (map (pmap en) os)
991 en t = t
993 nselem x [] = False
994 nselem x (y : xs) | nseq x y = True
995 | otherwise = nselem x xs
997 nseq x y = nsroot x == nsroot y
999expandParamsD :: Bool -> -- True = RHS only
1000 IState ->
1001 (Name -> Name) -> [(Name, PTerm)] -> [Name] -> PDecl -> PDecl
1002expandParamsD rhsonly ist dec ps ns (PTy doc syn fc o n ty)
1003 = if n `elem` ns && (not rhsonly)
1004 then -- trace (show (n, expandParams dec ps ns ty)) $
1005 PTy doc syn fc o (dec n) (piBindp expl_param ps (expandParams dec ps ns [] ty))
1006 else --trace (show (n, expandParams dec ps ns ty)) $
1007 PTy doc syn fc o n (expandParams dec ps ns [] ty)
1008expandParamsD rhsonly ist dec ps ns (PPostulate doc syn fc o n ty)
1009 = if n `elem` ns && (not rhsonly)
1010 then -- trace (show (n, expandParams dec ps ns ty)) $
1011 PPostulate doc syn fc o (dec n) (piBind ps
1012 (expandParams dec ps ns [] ty))
1013 else --trace (show (n, expandParams dec ps ns ty)) $
1014 PPostulate doc syn fc o n (expandParams dec ps ns [] ty)
1015expandParamsD rhsonly ist dec ps ns (PClauses fc opts n cs)
1016 = let n' = if n `elem` ns then dec n else n in
1017 PClauses fc opts n' (map expandParamsC cs)
1018 where
1019 expandParamsC (PClause fc n lhs ws rhs ds)
1020 = let -- ps' = updateps True (namesIn ist rhs) (zip ps [0..])
1021 ps'' = updateps False (namesIn [] ist lhs) (zip ps [0..])
1022 lhs' = if rhsonly then lhs else (expandParams dec ps'' ns [] lhs)
1023 n' = if n `elem` ns then dec n else n
1024 -- names bound on the lhs should not be expanded on the rhs
1025 ns' = removeBound lhs ns in
1026 PClause fc n' lhs'
1027 (map (expandParams dec ps'' ns' []) ws)
1028 (expandParams dec ps'' ns' [] rhs)
1029 (map (expandParamsD True ist dec ps'' ns') ds)
1030 expandParamsC (PWith fc n lhs ws wval ds)
1031 = let -- ps' = updateps True (namesIn ist wval) (zip ps [0..])
1032 ps'' = updateps False (namesIn [] ist lhs) (zip ps [0..])
1033 lhs' = if rhsonly then lhs else (expandParams dec ps'' ns [] lhs)
1034 n' = if n `elem` ns then dec n else n
1035 ns' = removeBound lhs ns in
1036 PWith fc n' lhs'
1037 (map (expandParams dec ps'' ns' []) ws)
1038 (expandParams dec ps'' ns' [] wval)
1039 (map (expandParamsD rhsonly ist dec ps'' ns') ds)
1040 updateps yn nm [] = []
1041 updateps yn nm (((a, t), i):as)
1042 | (a `elem` nm) == yn = (a, t) : updateps yn nm as
1043 | otherwise = (sMN i (show n ++ "_u"), t) : updateps yn nm as
1045 removeBound lhs ns = ns \\ nub (bnames lhs)
1047 bnames (PRef _ n) = [n]
1048 bnames (PApp _ _ args) = concatMap bnames (map getTm args)
1049 bnames (PPair _ _ l r) = bnames l ++ bnames r
1050 bnames (PDPair _ _ l Placeholder r) = bnames l ++ bnames r
1051 bnames _ = []
1053expandParamsD rhs ist dec ps ns (PData doc syn fc co pd)
1054 = PData doc syn fc co (expandPData pd)
1055 where
1056 -- just do the type decl, leave constructors alone (parameters will be
1057 -- added implicitly)
1058 expandPData (PDatadecl n ty cons)
1059 = if n `elem` ns
1060 then PDatadecl (dec n) (piBind ps (expandParams dec ps ns [] ty))
1061 (map econ cons)
1062 else PDatadecl n (expandParams dec ps ns [] ty) (map econ cons)
1063 econ (doc, n, t, fc, fs)
1064 = (doc, dec n, piBindp impl ps (expandParams dec ps ns [] t), fc, fs)
1065expandParamsD rhs ist dec ps ns (PRecord doc syn fc tn tty cdoc cn cty)
1066 = if tn `elem` ns
1067 then PRecord doc syn fc (dec tn) (piBind ps (expandParams dec ps ns [] tty))
1068 cdoc (dec cn) conty
1069 else PRecord doc syn fc (dec tn) (expandParams dec ps ns [] tty)
1070 cdoc (dec cn) conty
1071 where conty = piBindp impl ps (expandParams dec ps ns [] cty)
1072expandParamsD rhs ist dec ps ns (PParams f params pds)
1073 = PParams f (ps ++ map (mapsnd (expandParams dec ps ns [])) params)
1074 (map (expandParamsD True ist dec ps ns) pds)
1075-- (map (expandParamsD ist dec ps ns) pds)
1076expandParamsD rhs ist dec ps ns (PMutual f pds)
1077 = PMutual f (map (expandParamsD rhs ist dec ps ns) pds)
1078expandParamsD rhs ist dec ps ns (PClass doc info f cs n params decls)
1079 = PClass doc info f
1080 (map (expandParams dec ps ns []) cs)
1082 (map (mapsnd (expandParams dec ps ns [])) params)
1083 (map (expandParamsD rhs ist dec ps ns) decls)
1084expandParamsD rhs ist dec ps ns (PInstance info f cs n params ty cn decls)
1085 = PInstance info f
1086 (map (expandParams dec ps ns []) cs)
1088 (map (expandParams dec ps ns []) params)
1089 (expandParams dec ps ns [] ty)
1090 cn
1091 (map (expandParamsD rhs ist dec ps ns) decls)
1092expandParamsD rhs ist dec ps ns d = d
1094mapsnd f (x, t) = (x, f t)
1096-- Calculate a priority for a type, for deciding elaboration order
1097-- * if it's just a type variable or concrete type, do it early (0)
1098-- * if there's only type variables and injective constructors, do it next (1)
1099-- * if there's a function type, next (2)
1100-- * finally, everything else (3)
1102getPriority :: IState -> PTerm -> Int
1103getPriority i tm = 1 -- pri tm
1104 where
1105 pri (PRef _ n) =
1106 case lookupP n (tt_ctxt i) of
1107 ((P (DCon _ _) _ _):_) -> 1
1108 ((P (TCon _ _) _ _):_) -> 1
1109 ((P Ref _ _):_) -> 1
1110 [] -> 0 -- must be locally bound, if it's not an error...
1111 pri (PPi _ _ x y) = max 5 (max (pri x) (pri y))
1112 pri (PTrue _ _) = 0
1113 pri (PFalse _) = 0
1114 pri (PRefl _ _) = 1
1115 pri (PEq _ l r) = max 1 (max (pri l) (pri r))
1116 pri (PRewrite _ l r _) = max 1 (max (pri l) (pri r))
1117 pri (PApp _ f as) = max 1 (max (pri f) (foldr max 0 (map (pri.getTm) as)))
1118 pri (PAppBind _ f as) = max 1 (max (pri f) (foldr max 0 (map (pri.getTm) as)))
1119 pri (PCase _ f as) = max 1 (max (pri f) (foldr max 0 (map (pri.snd) as)))
1120 pri (PTyped l r) = pri l
1121 pri (PPair _ _ l r) = max 1 (max (pri l) (pri r))
1122 pri (PDPair _ _ l t r) = max 1 (max (pri l) (max (pri t) (pri r)))
1123 pri (PAlternative a as) = maximum (map pri as)
1124 pri (PConstant _) = 0
1125 pri Placeholder = 1
1126 pri _ = 3
1128addStatics :: Name -> Term -> PTerm -> Idris ()
1129addStatics n tm ptm =
1130 do let (statics, dynamics) = initStatics tm ptm
1131 let stnames = nub $ concatMap freeArgNames (map snd statics)
1132 let dnames = nub $ concatMap freeArgNames (map snd dynamics)
1133 -- also get the arguments which are 'uniquely inferrable' from
1134 -- statics (see sec 4.2 of "Scrapping Your Inefficient Engine")
1135 let statics' = nub $ map fst statics ++
1136 filter (\x -> not (elem x dnames)) stnames
1137 let stpos = staticList statics' tm
1138 i <- getIState
1139 when (not (null statics)) $
1140 logLvl 5 $ show n ++ " " ++ show statics' ++ "\n" ++ show dynamics
1141 ++ "\n" ++ show stnames ++ "\n" ++ show dnames
1142 putIState $ i { idris_statics = addDef n stpos (idris_statics i) }
1143 addIBC (IBCStatic n)
1144 where
1145 initStatics (Bind n (Pi ty) sc) (PPi p _ _ s)
1146 = let (static, dynamic) = initStatics (instantiate (P Bound n ty) sc) s in
1147 if pstatic p == Static then ((n, ty) : static, dynamic)
1148 else if (not (searchArg p))
1149 then (static, (n, ty) : dynamic)
1150 else (static, dynamic)
1151 initStatics t pt = ([], [])
1153 freeArgNames (Bind n (Pi ty) sc)
1154 = nub $ freeArgNames ty
1155 freeArgNames tm = let (_, args) = unApply tm in
1156 concatMap freeNames args
1158 -- if a name appears in a type class or tactic implicit index, it doesn't
1159 -- affect its 'uniquely inferrable' from a static status since these are
1160 -- resolved by searching.
1161 searchArg (Constraint _ _ _) = True
1162 searchArg (TacImp _ _ _ _) = True
1163 searchArg _ = False
1165 staticList sts (Bind n (Pi _) sc) = (n `elem` sts) : staticList sts sc
1166 staticList _ _ = []
1168-- Dealing with implicit arguments
1170-- Add constraint bindings from using block
1172addUsingConstraints :: SyntaxInfo -> FC -> PTerm -> Idris PTerm
1173addUsingConstraints syn fc t
1174 = do ist <- get
1175 let ns = namesIn [] ist t
1176 let cs = getConstraints t -- check declared constraints
1177 let addconsts = uconsts \\ cs
1178 -- if all names in the arguments of addconsts appear in ns,
1179 -- add the constraint implicitly
1180 return (doAdd addconsts ns t)
1181 where uconsts = filter uconst (using syn)
1182 uconst (UConstraint _ _) = True
1183 uconst _ = False
1185 doAdd [] _ t = t
1186 -- if all of args in ns, then add it
1187 doAdd (UConstraint c args : cs) ns t
1188 | all (\n -> elem n ns) args
1189 = PPi (Constraint [] Dynamic "") (sMN 0 "cu")
1190 (mkConst c args) (doAdd cs ns t)
1191 | otherwise = doAdd cs ns t
1193 mkConst c args = PApp fc (PRef fc c)
1194 (map (\n -> PExp 0 [] (PRef fc n) "") args)
1196 getConstraints (PPi (Constraint _ _ _) _ c sc)
1197 = getcapp c ++ getConstraints sc
1198 getConstraints (PPi _ _ c sc) = getConstraints sc
1199 getConstraints _ = []
1201 getcapp (PApp _ (PRef _ c) args)
1202 = do ns <- mapM getName args
1203 return (UConstraint c ns)
1204 getcapp _ = []
1206 getName (PExp _ _ (PRef _ n) _) = return n
1207 getName _ = []
1209-- Add implicit Pi bindings for any names in the term which appear in an
1210-- argument position.
1212-- This has become a right mess already. Better redo it some time...
1214implicit :: SyntaxInfo -> Name -> PTerm -> Idris PTerm
1215implicit syn n ptm = implicit' syn [] n ptm
1217implicit' :: SyntaxInfo -> [Name] -> Name -> PTerm -> Idris PTerm
1218implicit' syn ignore n ptm
1219 = do i <- getIState
1220 let (tm', impdata) = implicitise syn ignore i ptm
1221-- let (tm'', spos) = findStatics i tm'
1222 putIState $ i { idris_implicits = addDef n impdata (idris_implicits i) }
1223 addIBC (IBCImp n)
1224 logLvl 5 ("Implicit " ++ show n ++ " " ++ show impdata)
1225-- i <- get
1226-- putIState $ i { idris_statics = addDef n spos (idris_statics i) }
1227 return tm'
1229implicitise :: SyntaxInfo -> [Name] -> IState -> PTerm -> (PTerm, [PArg])
1230implicitise syn ignore ist tm = -- trace ("INCOMING " ++ showImp True tm) $
1231 let (declimps, ns') = execState (imps True [] tm) ([], [])
1232 ns = filter (\n -> implicitable n || elem n (map fst uvars)) $
1233 ns' \\ (map fst pvars ++ no_imp syn ++ ignore)
1234 nsOrder = filter (not . inUsing) ns ++ filter inUsing ns in
1235 if null ns
1236 then (tm, reverse declimps)
1237 else implicitise syn ignore ist (pibind uvars nsOrder tm)
1238 where
1239 uvars = map ipair (filter uimplicit (using syn))
1240 pvars = syn_params syn
1242 inUsing n = n `elem` map fst uvars
1244 ipair (UImplicit x y) = (x, y)
1245 uimplicit (UImplicit _ _) = True
1246 uimplicit _ = False
1248 dropAll (x:xs) ys | x `elem` ys = dropAll xs ys
1249 | otherwise = x : dropAll xs ys
1250 dropAll [] ys = []
1252 imps top env (PApp _ f as)
1253 = do (decls, ns) <- get
1254 let isn = concatMap (namesIn uvars ist) (map getTm as)
1255 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1256 imps top env (PPi (Imp l _ doc _) n ty sc)
1257 = do let isn = nub (namesIn uvars ist ty) `dropAll` [n]
1258 (decls , ns) <- get
1259 put (PImp (getPriority ist ty) True l n Placeholder doc : decls,
1260 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1261 imps True (n:env) sc
1262 imps top env (PPi (Exp l _ doc _) n ty sc)
1263 = do let isn = nub (namesIn uvars ist ty ++ case sc of
1264 (PRef _ x) -> namesIn uvars ist sc `dropAll` [n]
1265 _ -> [])
1266 (decls, ns) <- get -- ignore decls in HO types
1267 put (PExp (getPriority ist ty) l Placeholder doc : decls,
1268 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1269 imps True (n:env) sc
1270 imps top env (PPi (Constraint l _ doc) n ty sc)
1271 = do let isn = nub (namesIn uvars ist ty ++ case sc of
1272 (PRef _ x) -> namesIn uvars ist sc `dropAll` [n]
1273 _ -> [])
1274 (decls, ns) <- get -- ignore decls in HO types
1275 put (PConstraint 10 l Placeholder doc : decls,
1276 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1277 imps True (n:env) sc
1278 imps top env (PPi (TacImp l _ scr doc) n ty sc)
1279 = do let isn = nub (namesIn uvars ist ty ++ case sc of
1280 (PRef _ x) -> namesIn uvars ist sc `dropAll` [n]
1281 _ -> [])
1282 (decls, ns) <- get -- ignore decls in HO types
1283 put (PTacImplicit 10 l n scr Placeholder doc : decls,
1284 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1285 imps True (n:env) sc
1286 imps top env (PEq _ l r)
1287 = do (decls, ns) <- get
1288 let isn = namesIn uvars ist l ++ namesIn uvars ist r
1289 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1290 imps top env (PRewrite _ l r _)
1291 = do (decls, ns) <- get
1292 let isn = namesIn uvars ist l ++ namesIn uvars ist r
1293 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1294 imps top env (PTyped l r)
1295 = imps top env l
1296 imps top env (PPair _ _ l r)
1297 = do (decls, ns) <- get
1298 let isn = namesIn uvars ist l ++ namesIn uvars ist r
1299 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1300 imps top env (PDPair _ _ (PRef _ n) t r)
1301 = do (decls, ns) <- get
1302 let isn = nub (namesIn uvars ist t ++ namesIn uvars ist r) \\ [n]
1303 put (decls, nub (ns ++ (isn \\ (env ++ map fst (getImps decls)))))
1304 imps top env (PDPair _ _ l t r)
1305 = do (decls, ns) <- get
1306 let isn = namesIn uvars ist l ++ namesIn uvars ist t ++
1307 namesIn uvars ist r
1308 put (decls, nub (ns ++ (isn \\ (env ++ map fst (getImps decls)))))
1309 imps top env (PAlternative a as)
1310 = do (decls, ns) <- get
1311 let isn = concatMap (namesIn uvars ist) as
1312 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
1313 imps top env (PLam n ty sc)
1314 = do imps False env ty
1315 imps False (n:env) sc
1316 imps top env (PHidden tm) = imps False env tm
1317 imps top env (PUnifyLog tm) = imps False env tm
1318 imps top env (PNoImplicits tm) = imps False env tm
1319 imps top env _ = return ()
1321 pibind using [] sc = sc
1322 pibind using (n:ns) sc
1323 = case lookup n using of
1324 Just ty -> PPi (Imp [] Dynamic "" False) n ty (pibind using ns sc)
1325 Nothing -> PPi (Imp [] Dynamic "" False) n Placeholder
1326 (pibind using ns sc)
1328-- Add implicit arguments in function calls
1329addImplPat :: IState -> PTerm -> PTerm
1330addImplPat = addImpl' True [] []
1332addImplBound :: IState -> [Name] -> PTerm -> PTerm
1333addImplBound ist ns = addImpl' False ns [] ist
1335addImplBoundInf :: IState -> [Name] -> [Name] -> PTerm -> PTerm
1336addImplBoundInf ist ns inf = addImpl' False ns inf ist
1338addImpl :: IState -> PTerm -> PTerm
1339addImpl = addImpl' False [] []
1341-- TODO: in patterns, don't add implicits to function names guarded by constructors
1342-- and *not* inside a PHidden
1344addImpl' :: Bool -> [Name] -> [Name] -> IState -> PTerm -> PTerm
1345addImpl' inpat env infns ist ptm
1346 = mkUniqueNames env (ai (zip env (repeat Nothing)) [] ptm)
1347 where
1348 ai env ds (PRef fc f)
1349 | f `elem` infns = PInferRef fc f
1350 | not (f `elem` map fst env) = handleErr $ aiFn inpat inpat ist fc f ds []
1351 ai env ds (PHidden (PRef fc f))
1352 | not (f `elem` map fst env) = handleErr $ aiFn inpat False ist fc f ds []
1353 ai env ds (PEq fc l r)
1354 = let l' = ai env ds l
1355 r' = ai env ds r in
1356 PEq fc l' r'
1357 ai env ds (PRewrite fc l r g)
1358 = let l' = ai env ds l
1359 r' = ai env ds r
1360 g' = fmap (ai env ds) g in
1361 PRewrite fc l' r' g'
1362 ai env ds (PTyped l r)
1363 = let l' = ai env ds l
1364 r' = ai env ds r in
1365 PTyped l' r'
1366 ai env ds (PPair fc p l r)
1367 = let l' = ai env ds l
1368 r' = ai env ds r in
1369 PPair fc p l' r'
1370 ai env ds (PDPair fc p l t r)
1371 = let l' = ai env ds l
1372 t' = ai env ds t
1373 r' = ai env ds r in
1374 PDPair fc p l' t' r'
1375 ai env ds (PAlternative a as)
1376 = let as' = map (ai env ds) as in
1377 PAlternative a as'
1378 ai env _ (PDisamb ds' as) = ai env ds' as
1379 ai env ds (PApp fc (PInferRef _ f) as)
1380 = let as' = map (fmap (ai env ds)) as in
1381 PApp fc (PInferRef fc f) as'
1382 ai env ds (PApp fc ftm@(PRef _ f) as)
1383 | f `elem` infns = ai env ds (PApp fc (PInferRef fc f) as)
1384 | not (f `elem` map fst env)
1385 = let as' = map (fmap (ai env ds)) as in
1386 handleErr $ aiFn inpat False ist fc f ds as'
1387 | Just (Just ty) <- lookup f env =
1388 let as' = map (fmap (ai env ds)) as
1389 arity = getPArity ty in
1390 mkPApp fc arity ftm as'
1391 ai env ds (PApp fc f as)
1392 = let f' = ai env ds f
1393 as' = map (fmap (ai env ds)) as in
1394 mkPApp fc 1 f' as'
1395 ai env ds (PCase fc c os)
1396 = let c' = ai env ds c
1397 os' = map (pmap (ai env ds)) os in
1398 PCase fc c' os'
1399 ai env ds (PLam n ty sc)
1400 = let ty' = ai env ds ty
1401 sc' = ai ((n, Just ty):env) ds sc in
1402 PLam n ty' sc'
1403 ai env ds (PLet n ty val sc)
1404 = let ty' = ai env ds ty
1405 val' = ai env ds val
1406 sc' = ai ((n, Just ty):env) ds sc in
1407 PLet n ty' val' sc'
1408 ai env ds (PPi p n ty sc)
1409 = let ty' = ai env ds ty
1410 sc' = ai ((n, Just ty):env) ds sc in
1411 PPi p n ty' sc'
1412 ai env ds (PGoal fc r n sc)
1413 = let r' = ai env ds r
1414 sc' = ai ((n, Nothing):env) ds sc in
1415 PGoal fc r' n sc'
1416 ai env ds (PHidden tm) = PHidden (ai env ds tm)
1417 ai env ds (PProof ts) = PProof (map (fmap (ai env ds)) ts)
1418 ai env ds (PTactics ts) = PTactics (map (fmap (ai env ds)) ts)
1419 ai env ds (PRefl fc tm) = PRefl fc (ai env ds tm)
1420 ai env ds (PUnifyLog tm) = PUnifyLog (ai env ds tm)
1421 ai env ds (PNoImplicits tm) = PNoImplicits (ai env ds tm)
1422 ai env ds tm = tm
1424 handleErr (Left err) = PElabError err
1425 handleErr (Right x) = x
1427-- if in a pattern, and there are no arguments, and there's no possible
1428-- names with zero explicit arguments, don't add implicits.
1430aiFn :: Bool -> Bool -> IState -> FC -> Name -> [[T.Text]] -> [PArg] -> Either Err PTerm
1431aiFn inpat True ist fc f ds []
1432 = case lookupDef f (tt_ctxt ist) of
1433 [] -> Right $ PPatvar fc f
1434 alts -> let ialts = lookupCtxtName f (idris_implicits ist) in
1435 -- trace (show f ++ " " ++ show (fc, any (all imp) ialts, ialts, any constructor alts)) $
1436 if (not (vname f) || tcname f
1437 || any (conCaf (tt_ctxt ist)) ialts)
1438-- any constructor alts || any allImp ialts))
1439 then aiFn inpat False ist fc f ds [] -- use it as a constructor
1440 else Right $ PPatvar fc f
1441 where imp (PExp _ _ _ _) = False
1442 imp _ = True
1443-- allImp [] = False
1444 allImp xs = all imp xs
1445 constructor (TyDecl (DCon _ _) _) = True
1446 constructor _ = False
1448 conCaf ctxt (n, cia) = isDConName n ctxt && allImp cia
1450 vname (UN n) = True -- non qualified
1451 vname _ = False
1453aiFn inpat expat ist fc f ds as
1454 | f `elem` primNames = Right $ PApp fc (PRef fc f) as
1455aiFn inpat expat ist fc f ds as
1456 -- This is where namespaces get resolved by adding PAlternative
1457 = do let ns = lookupCtxtName f (idris_implicits ist)
1458 let nh = filter (\(n, _) -> notHidden n) ns
1459 let ns' = case trimAlts ds nh of
1460 [] -> nh
1461 x -> x
1462 case ns' of
1463 [(f',ns)] -> Right $ mkPApp fc (length ns) (PRef fc f') (insertImpl ns as)
1464 [] -> if f `elem` (map fst (idris_metavars ist))
1465 then Right $ PApp fc (PRef fc f) as
1466 else Right $ mkPApp fc (length as) (PRef fc f) as
1467 alts -> Right $
1468 PAlternative True $
1469 map (\(f', ns) -> mkPApp fc (length ns) (PRef fc f')
1470 (insertImpl ns as)) alts
1471 where
1472 trimAlts [] alts = alts
1473 trimAlts ns alts
1474 = filter (\(x, _) -> any (\d -> d `isPrefixOf` nspace x) ns) alts
1476 nspace (NS _ s) = s
1477 nspace _ = []
1479 notHidden n = case getAccessibility n of
1480 Hidden -> False
1481 _ -> True
1483 getAccessibility n
1484 = case lookupDefAcc n False (tt_ctxt ist) of
1485 [(n,t)] -> t
1486 _ -> Public
1489 insertImpl :: [PArg] -> [PArg] -> [PArg]
1490 insertImpl (PExp p l ty _ : ps) (PExp _ _ tm d : given) =
1491 PExp p l tm d : insertImpl ps given
1492 insertImpl (PConstraint p l ty _ : ps) (PConstraint _ _ tm d : given) =
1493 PConstraint p l tm d : insertImpl ps given
1494 insertImpl (PConstraint p l ty d : ps) given =
1495 PConstraint p l (PResolveTC fc) d : insertImpl ps given
1496 insertImpl (PImp p _ l n ty d : ps) given =
1497 case find n given [] of
1498 Just (tm, given') -> PImp p False l n tm "" : insertImpl ps given'
1499 Nothing -> PImp p True l n Placeholder "" : insertImpl ps given
1500 insertImpl (PTacImplicit p l n sc' ty d : ps) given =
1501 let sc = addImpl ist sc' in
1502 case find n given [] of
1503 Just (tm, given') -> PTacImplicit p l n sc tm "" : insertImpl ps given'
1504 Nothing -> if inpat
1505 then PTacImplicit p l n sc Placeholder "" : insertImpl ps given
1506 else PTacImplicit p l n sc sc "" : insertImpl ps given
1507 insertImpl expected [] = []
1508 insertImpl _ given = given
1510 find n [] acc = Nothing
1511 find n (PImp _ _ _ n' t _ : gs) acc
1512 | n == n' = Just (t, reverse acc ++ gs)
1513 find n (PTacImplicit _ _ n' _ t _ : gs) acc
1514 | n == n' = Just (t, reverse acc ++ gs)
1515 find n (g : gs) acc = find n gs (g : acc)
1517-- replace non-linear occurrences with _
1518-- ASSUMPTION: This is called before adding 'alternatives' because otherwise
1519-- it is hard to get right!
1521stripLinear :: IState -> PTerm -> PTerm
1522stripLinear i tm = evalState (sl tm) [] where
1523 sl :: PTerm -> State [Name] PTerm
1524 sl (PRef fc f)
1525 | (_:_) <- lookupTy f (tt_ctxt i)
1526 = return $ PRef fc f
1527 | otherwise = do ns <- get
1528 if (f `elem` ns)
1529 then return Placeholder
1530 else do put (f : ns)
1531 return (PRef fc f)
1532 sl (PPatvar fc f)
1533 = do ns <- get
1534 if (f `elem` ns)
1535 then return Placeholder
1536 else do put (f : ns)
1537 return (PPatvar fc f)
1538 sl t@(PAlternative _ (a : as)) = do sl a
1539 return t
1540 sl (PApp fc fn args) = do fn' <- sl fn
1541 args' <- mapM slA args
1542 return $ PApp fc fn' args'
1543 where slA (PImp p m l n t d) = do t' <- sl t
1544 return $ PImp p m l n t' d
1545 slA (PExp p l t d) = do t' <- sl t
1546 return $ PExp p l t' d
1547 slA (PConstraint p l t d)
1548 = do t' <- sl t
1549 return $ PConstraint p l t' d
1550 slA (PTacImplicit p l n sc t d)
1551 = do t' <- sl t
1552 return $ PTacImplicit p l n sc t' d
1553 sl x = return x
1555-- Remove functions which aren't applied to anything, which must then
1556-- be resolved by unification. Assume names resolved and alternatives
1557-- filled in (so no ambiguity).
1559stripUnmatchable :: IState -> PTerm -> PTerm
1560stripUnmatchable i (PApp fc fn args) = PApp fc fn (fmap (fmap su) args) where
1561 su :: PTerm -> PTerm
1562 su (PRef fc f)
1563 | (Bind n (Pi t) sc :_) <- lookupTy f (tt_ctxt i)
1564 = Placeholder
1565 su (PApp fc fn args)
1566 = PApp fc fn (fmap (fmap su) args)
1567 su (PAlternative b alts)
1568 = let alts' = filter (/= Placeholder) (map su alts) in
1569 if null alts' then Placeholder
1570 else PAlternative b alts'
1571 su (PPair fc p l r) = PPair fc p (su l) (su r)
1572 su (PDPair fc p l t r) = PDPair fc p (su l) (su t) (su r)
1573 su t = t
1574stripUnmatchable i tm = tm
1576mkPApp fc a f [] = f
1577mkPApp fc a f as = let rest = drop a as in
1578 appRest fc (PApp fc f (take a as)) rest
1579 where
1580 appRest fc f [] = f
1581 appRest fc f (a : as) = appRest fc (PApp fc f [a]) as
1583-- Find 'static' argument positions
1584-- (the declared ones, plus any names in argument position in the declared
1585-- statics)
1586-- FIXME: It's possible that this really has to happen after elaboration
1588findStatics :: IState -> PTerm -> (PTerm, [Bool])
1589findStatics ist tm = trace (show tm) $
1590 let (ns, ss) = fs tm in
1591 runState (pos ns ss tm) []
1592 where fs (PPi p n t sc)
1593 | Static <- pstatic p
1594 = let (ns, ss) = fs sc in
1595 (namesIn [] ist t : ns, n : ss)
1596 | otherwise = let (ns, ss) = fs sc in
1597 (ns, ss)
1598 fs _ = ([], [])
1600 inOne n ns = length (filter id (map (elem n) ns)) == 1
1602 pos ns ss (PPi p n t sc)
1603 | elem n ss = do sc' <- pos ns ss sc
1604 spos <- get
1605 put (True : spos)
1606 return (PPi (p { pstatic = Static }) n t sc')
1607 | otherwise = do sc' <- pos ns ss sc
1608 spos <- get
1609 put (False : spos)
1610 return (PPi p n t sc')
1611 pos ns ss t = return t
1613-- for 6.12/7 compatibility
1614data EitherErr a b = LeftErr a | RightOK b
1616instance Monad (EitherErr a) where
1617 return = RightOK
1619 (LeftErr e) >>= k = LeftErr e
1620 RightOK v >>= k = k v
1622toEither (LeftErr e) = Left e
1623toEither (RightOK ho) = Right ho
1625-- syntactic match of a against b, returning pair of variables in a
1626-- and what they match. Returns the pair that failed if not a match.
1628matchClause :: IState -> PTerm -> PTerm -> Either (PTerm, PTerm) [(Name, PTerm)]
1629matchClause = matchClause' False
1631matchClause' :: Bool -> IState -> PTerm -> PTerm -> Either (PTerm, PTerm) [(Name, PTerm)]
1632matchClause' names i x y = checkRpts $ match (fullApp x) (fullApp y) where
1633 matchArg x y = match (fullApp (getTm x)) (fullApp (getTm y))
1635 fullApp (PApp _ (PApp fc f args) xs) = fullApp (PApp fc f (args ++ xs))
1636 fullApp x = x
1638 match' x y = match (fullApp x) (fullApp y)
1639 match (PApp _ (PRef _ (NS (UN fi) [b])) [_,_,x]) x'
1640 | fi == txt "fromInteger" && b == txt "builtins",
1641 PConstant (I _) <- getTm x = match (getTm x) x'
1642 match x' (PApp _ (PRef _ (NS (UN fi) [b])) [_,_,x])
1643 | fi == txt "fromInteger" && b == txt "builtins",
1644 PConstant (I _) <- getTm x = match (getTm x) x'
1645 match (PApp _ (PRef _ (UN l)) [_,x]) x' | l == txt "lazy" = match (getTm x) x'
1646 match x (PApp _ (PRef _ (UN l)) [_,x']) | l == txt "lazy" = match x (getTm x')
1647 match (PApp _ f args) (PApp _ f' args')
1648 | length args == length args'
1649 = do mf <- match' f f'
1650 ms <- zipWithM matchArg args args'
1651 return (mf ++ concat ms)
1652-- match (PRef _ n) (PRef _ n') | n == n' = return []
1653-- | otherwise = Nothing
1654 match (PRef f n) (PApp _ x []) = match (PRef f n) x
1655 match (PPatvar f n) xr = match (PRef f n) xr
1656 match xr (PPatvar f n) = match xr (PRef f n)
1657 match (PApp _ x []) (PRef f n) = match x (PRef f n)
1658 match (PRef _ n) tm@(PRef _ n')
1659 | n == n' && not names &&
1660 (not (isConName n (tt_ctxt i) || isFnName n (tt_ctxt i))
1661 || tm == Placeholder)
1662 = return [(n, tm)]
1663 | n == n' = return []
1664 match (PRef _ n) tm
1665 | not names && (not (isConName n (tt_ctxt i) ||
1666 isFnName n (tt_ctxt i)) || tm == Placeholder)
1667 = return [(n, tm)]
1668 match (PEq _ l r) (PEq _ l' r') = do ml <- match' l l'
1669 mr <- match' r r'
1670 return (ml ++ mr)
1671 match (PRewrite _ l r _) (PRewrite _ l' r' _)
1672 = do ml <- match' l l'
1673 mr <- match' r r'
1674 return (ml ++ mr)
1675 match (PTyped l r) (PTyped l' r') = do ml <- match l l'
1676 mr <- match r r'
1677 return (ml ++ mr)
1678 match (PTyped l r) x = match l x
1679 match x (PTyped l r) = match x l
1680 match (PPair _ _ l r) (PPair _ _ l' r') = do ml <- match' l l'
1681 mr <- match' r r'
1682 return (ml ++ mr)
1683 match (PDPair _ _ l t r) (PDPair _ _ l' t' r') = do ml <- match' l l'
1684 mt <- match' t t'
1685 mr <- match' r r'
1686 return (ml ++ mt ++ mr)
1687 match (PAlternative a as) (PAlternative a' as')
1688 = do ms <- zipWithM match' as as'
1689 return (concat ms)
1690 match a@(PAlternative _ as) b
1691 = do let ms = zipWith match' as (repeat b)
1692 case (rights (map toEither ms)) of
1693 (x: _) -> return x
1694 _ -> LeftErr (a, b)
1695 match (PCase _ _ _) _ = return [] -- lifted out
1696 match (PMetavar _) _ = return [] -- modified
1697 match (PInferRef _ _) _ = return [] -- modified
1698 match (PQuote _) _ = return []
1699 match (PProof _) _ = return []
1700 match (PTactics _) _ = return []
1701 match (PRefl _ _) (PRefl _ _) = return []
1702 match (PResolveTC _) (PResolveTC _) = return []
1703 match (PTrue _ _) (PTrue _ _) = return []
1704 match (PFalse _) (PFalse _) = return []
1705 match (PReturn _) (PReturn _) = return []
1706 match (PPi _ _ t s) (PPi _ _ t' s') = do mt <- match' t t'
1707 ms <- match' s s'
1708 return (mt ++ ms)
1709 match (PLam _ t s) (PLam _ t' s') = do mt <- match' t t'
1710 ms <- match' s s'
1711 return (mt ++ ms)
1712 match (PLet _ t ty s) (PLet _ t' ty' s') = do mt <- match' t t'
1713 mty <- match' ty ty'
1714 ms <- match' s s'
1715 return (mt ++ mty ++ ms)
1716 match (PHidden x) (PHidden y) = match' x y
1717 match (PUnifyLog x) y = match' x y
1718 match x (PUnifyLog y) = match' x y
1719 match (PNoImplicits x) y = match' x y
1720 match x (PNoImplicits y) = match' x y
1721 match Placeholder _ = return []
1722 match _ Placeholder = return []
1723 match (PResolveTC _) _ = return []
1724 match a b | a == b = return []
1725 | otherwise = LeftErr (a, b)
1727 checkRpts (RightOK ms) = check ms where
1728 check ((n,t):xs)
1729 | Just t' <- lookup n xs = if t/=t' && t/=Placeholder && t'/=Placeholder
1730 then Left (t, t')
1731 else check xs
1732 check (_:xs) = check xs
1733 check [] = Right ms
1734 checkRpts (LeftErr x) = Left x
1736substMatches :: [(Name, PTerm)] -> PTerm -> PTerm
1737substMatches ms = substMatchesShadow ms []
1739substMatchesShadow :: [(Name, PTerm)] -> [Name] -> PTerm -> PTerm
1740substMatchesShadow [] shs t = t
1741substMatchesShadow ((n,tm):ns) shs t
1742 = substMatchShadow n shs tm (substMatchesShadow ns shs t)
1744substMatch :: Name -> PTerm -> PTerm -> PTerm
1745substMatch n = substMatchShadow n []
1747substMatchShadow :: Name -> [Name] -> PTerm -> PTerm -> PTerm
1748substMatchShadow n shs tm t = sm shs t where
1749 sm xs (PRef _ n') | n == n' = tm
1750 sm xs (PLam x t sc) = PLam x (sm xs t) (sm xs sc)
1751 sm xs (PPi p x t sc)
1752 | x `elem` xs
1753 = let x' = nextName x in
1754 PPi p x' (sm (x':xs) (substMatch x (PRef emptyFC x') t))
1755 (sm (x':xs) (substMatch x (PRef emptyFC x') sc))
1756 | otherwise = PPi p x (sm xs t) (sm (x : xs) sc)
1757 sm xs (PApp f x as) = fullApp $ PApp f (sm xs x) (map (fmap (sm xs)) as)
1758 sm xs (PCase f x as) = PCase f (sm xs x) (map (pmap (sm xs)) as)
1759 sm xs (PEq f x y) = PEq f (sm xs x) (sm xs y)
1760 sm xs (PRewrite f x y tm) = PRewrite f (sm xs x) (sm xs y)
1761 (fmap (sm xs) tm)
1762 sm xs (PTyped x y) = PTyped (sm xs x) (sm xs y)
1763 sm xs (PPair f p x y) = PPair f p (sm xs x) (sm xs y)
1764 sm xs (PDPair f p x t y) = PDPair f p (sm xs x) (sm xs t) (sm xs y)
1765 sm xs (PAlternative a as) = PAlternative a (map (sm xs) as)
1766 sm xs (PHidden x) = PHidden (sm xs x)
1767 sm xs (PUnifyLog x) = PUnifyLog (sm xs x)
1768 sm xs (PNoImplicits x) = PNoImplicits (sm xs x)
1769 sm xs x = x
1771 fullApp (PApp _ (PApp fc f args) xs) = fullApp (PApp fc f (args ++ xs))
1772 fullApp x = x
1774shadow :: Name -> Name -> PTerm -> PTerm
1775shadow n n' t = sm t where
1776 sm (PRef fc x) | n == x = PRef fc n'
1777 sm (PLam x t sc) | n /= x = PLam x (sm t) (sm sc)
1778 sm (PPi p x t sc) | n /=x = PPi p x (sm t) (sm sc)
1779 sm (PLet x t v sc) | n /= x = PLet x (sm t) (sm v) (sm sc)
1780 sm (PApp f x as) = PApp f (sm x) (map (fmap sm) as)
1781 sm (PAppBind f x as) = PAppBind f (sm x) (map (fmap sm) as)
1782 sm (PCase f x as) = PCase f (sm x) (map (pmap sm) as)
1783 sm (PEq f x y) = PEq f (sm x) (sm y)
1784 sm (PRewrite f x y tm) = PRewrite f (sm x) (sm y) (fmap sm tm)
1785 sm (PTyped x y) = PTyped (sm x) (sm y)
1786 sm (PPair f p x y) = PPair f p (sm x) (sm y)
1787 sm (PDPair f p x t y) = PDPair f p (sm x) (sm t) (sm y)
1788 sm (PAlternative a as) = PAlternative a (map sm as)
1789 sm (PTactics ts) = PTactics (map (fmap sm) ts)
1790 sm (PProof ts) = PProof (map (fmap sm) ts)
1791 sm (PHidden x) = PHidden (sm x)
1792 sm (PUnifyLog x) = PUnifyLog (sm x)
1793 sm (PNoImplicits x) = PNoImplicits (sm x)
1794 sm x = x
1796-- Rename any binders which are repeated (so that we don't have to mess
1797-- about with shadowing anywhere else).
1799mkUniqueNames :: [Name] -> PTerm -> PTerm
1800mkUniqueNames env tm = evalState (mkUniq tm) env where
1801 inScope = boundNamesIn tm
1803 mkUniqA arg = do t' <- mkUniq (getTm arg)
1804 return (arg { getTm = t' })
1806 -- FIXME: Probably ought to do this for completeness! It's fine as
1807 -- long as there are no bindings inside tactics though.
1808 mkUniqT tac = return tac
1810 mkUniq :: PTerm -> State [Name] PTerm
1811 mkUniq (PLam n ty sc)
1812 = do env <- get
1813 (n', sc') <-
1814 if n `elem` env
1815 then do let n' = uniqueName n (env ++ inScope)
1816 return (n', shadow n n' sc)
1817 else return (n, sc)
1818 put (n' : env)
1819 ty' <- mkUniq ty
1820 sc'' <- mkUniq sc'
1821 return $! PLam n' ty' sc''
1822 mkUniq (PPi p n ty sc)
1823 = do env <- get
1824 (n', sc') <-
1825 if n `elem` env
1826 then do let n' = uniqueName n (env ++ inScope)
1827 return (n', shadow n n' sc)
1828 else return (n, sc)
1829 put (n' : env)
1830 ty' <- mkUniq ty
1831 sc'' <- mkUniq sc'
1832 return $! PPi p n' ty' sc''
1833 mkUniq (PLet n ty val sc)
1834 = do env <- get
1835 (n', sc') <-
1836 if n `elem` env
1837 then do let n' = uniqueName n (env ++ inScope)
1838 return (n', shadow n n' sc)
1839 else return (n, sc)
1840 put (n' : env)
1841 ty' <- mkUniq ty; val' <- mkUniq val
1842 sc'' <- mkUniq sc'
1843 return $! PLet n' ty' val' sc''
1844 mkUniq (PApp fc t args)
1845 = do t' <- mkUniq t
1846 args' <- mapM mkUniqA args
1847 return $! PApp fc t' args'
1848 mkUniq (PAppBind fc t args)
1849 = do t' <- mkUniq t
1850 args' <- mapM mkUniqA args
1851 return $! PAppBind fc t' args'
1852 mkUniq (PCase fc t alts)
1853 = do t' <- mkUniq t
1854 alts' <- mapM (\(x,y)-> do x' <- mkUniq x; y' <- mkUniq y
1855 return (x', y')) alts
1856 return $! PCase fc t' alts'
1857 mkUniq (PPair fc p l r)
1858 = do l' <- mkUniq l; r' <- mkUniq r
1859 return $! PPair fc p l' r'
1860 mkUniq (PDPair fc p (PRef fc' n) t sc)
1861 | t /= Placeholder
1862 = do env <- get
1863 (n', sc') <- if n `elem` env
1864 then do let n' = uniqueName n (env ++ inScope)
1865 return (n', shadow n n' sc)
1866 else return (n, sc)
1867 put (n' : env)
1868 t' <- mkUniq t
1869 sc'' <- mkUniq sc'
1870 return $! PDPair fc p (PRef fc' n') t' sc''
1871 mkUniq (PDPair fc p l t r)
1872 = do l' <- mkUniq l; t' <- mkUniq t; r' <- mkUniq r
1873 return $! PDPair fc p l' t' r'
1874 mkUniq (PAlternative b as)
1875 = liftM (PAlternative b) (mapM mkUniq as)
1876 mkUniq (PHidden t) = liftM PHidden (mkUniq t)
1877 mkUniq (PUnifyLog t) = liftM PUnifyLog (mkUniq t)
1878 mkUniq (PDisamb n t) = liftM (PDisamb n) (mkUniq t)
1879 mkUniq (PNoImplicits t) = liftM PNoImplicits (mkUniq t)
1880 mkUniq (PProof ts) = liftM PProof (mapM mkUniqT ts)
1881 mkUniq (PTactics ts) = liftM PTactics (mapM mkUniqT ts)
1882 mkUniq t = return t