1{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, DeriveFunctor,
2 TypeSynonymInstances, PatternGuards #-}
4module Idris.AbsSyntax where
11import Control.Monad.State
16import qualified Epic.Epic as E
18data IOption = IOption { opt_logLevel :: Int,
23defaultOpts = IOption 0 False
25-- TODO: Add 'module data' to IState, which can be saved out and reloaded quickly (i.e
26-- without typechecking).
27-- This will include all the functions and data declarations, plus fixity declarations
30data IState = IState { tt_ctxt :: Context,
31 idris_infixes :: [FixDecl],
32 idris_implicits :: Ctxt [PArg],
33 idris_statics :: Ctxt [Bool],
34 idris_classes :: Ctxt ClassInfo,
36 idris_options :: IOption,
38 idris_metavars :: [Name],
39 syntax_rules :: [Syntax],
40 syntax_keywords :: [String],
41 imported :: [FilePath],
42 idris_prims :: [(Name, ([E.Name], E.Term))],
43 idris_objs :: [FilePath],
44 idris_libs :: [String],
45 idris_hdrs :: [String],
49idrisInit = IState emptyContext [] emptyContext emptyContext emptyContext
50 "" defaultOpts 6 [] [] [] [] [] [] [] [] Nothing
52-- The monad for the main REPL - reading and processing files and updating
53-- global state (hence the IO inner monad).
54type Idris a = StateT IState IO a
56getContext :: Idris Context
57getContext = do i <- get; return (tt_ctxt i)
59getObjectFiles :: Idris [FilePath]
60getObjectFiles = do i <- get; return (idris_objs i)
62addObjectFile :: FilePath -> Idris ()
63addObjectFile f = do i <- get; put (i { idris_objs = f : idris_objs i })
65getLibs :: Idris [String]
66getLibs = do i <- get; return (idris_libs i)
68addLib :: String -> Idris ()
69addLib f = do i <- get; put (i { idris_libs = f : idris_libs i })
71addHdr :: String -> Idris ()
72addHdr f = do i <- get; put (i { idris_hdrs = f : idris_hdrs i })
74getHdrs :: Idris [String]
75getHdrs = do i <- get; return (idris_hdrs i)
77setErrLine :: Int -> Idris ()
78setErrLine x = do i <- get;
80 Nothing -> put (i { errLine = Just x })
85 put (i { errLine = Nothing })
87getIState :: Idris IState
90putIState :: IState -> Idris ()
95 let idx = idris_name i;
96 put (i { idris_name = idx + 1 })
99checkUndefined :: FC -> Name -> Idris ()
102 case lookupCtxt n i of
103 Just _ -> fail $ show fc ++ ":" ++
104 show n ++ " already defined"
107setContext :: Context -> Idris ()
108setContext ctxt = do i <- get; put (i { tt_ctxt = ctxt } )
110updateContext :: (Context -> Context) -> Idris ()
111updateContext f = do i <- get; put (i { tt_ctxt = f (tt_ctxt i) } )
113addDeferred :: [(Name, Type)] -> Idris ()
114addDeferred ns = do mapM_ (\(n, t) -> updateContext (addTyDecl n (tidyNames [] t))) ns
116 put (i { idris_metavars = map fst ns ++ idris_metavars i })
117 where tidyNames used (Bind (MN i x) b sc)
118 = let n' = uniqueName (UN [x]) used in
119 Bind n' b $ tidyNames (n':used) sc
120 tidyNames used (Bind n b sc)
121 = let n' = uniqueName n used in
122 Bind n' b $ tidyNames (n':used) sc
125solveDeferred :: Name -> Idris ()
126solveDeferred n = do i <- get
127 put (i { idris_metavars = idris_metavars i \\ [n] })
129iputStrLn :: String -> Idris ()
130iputStrLn = lift.putStrLn
132setLogLevel :: Int -> Idris ()
133setLogLevel l = do i <- get
134 let opts = idris_options i
135 let opt' = opts { opt_logLevel = l }
136 put (i { idris_options = opt' } )
139logLevel = do i <- get
140 return (opt_logLevel (idris_options i))
142logLvl :: Int -> String -> Idris ()
143logLvl l str = do i <- get
144 let lvl = opt_logLevel (idris_options i)
146 $ do lift (putStrLn str)
147 put (i { idris_log = idris_log i ++ str ++ "\n" } )
149iLOG :: String -> Idris ()
152noErrors :: Idris Bool
153noErrors = do i <- get
155 Nothing -> return True
158setTypeCase :: Bool -> Idris ()
159setTypeCase t = do i <- get
160 let opts = idris_options i
161 let opt' = opts { opt_typecase = t }
162 put (i { idris_options = opt' })
164-- Commands in the REPL
166data Command = Quit | Help | Eval PTerm | Check PTerm | Reload | Edit
167 | Compile String | Execute String
168 | Metavars | Prove Name
170 | LogLvl Int | Spec PTerm | HNF PTerm | Defn Name
173-- Parsed declarations
175data Fixity = Infixl { prec :: Int }
176 | Infixr { prec :: Int }
177 | InfixN { prec :: Int }
178 | PrefixN { prec :: Int }
181instance Show Fixity where
182 show (Infixl i) = "infixl " ++ show i
183 show (Infixr i) = "infixr " ++ show i
184 show (InfixN i) = "infix " ++ show i
185 show (PrefixN i) = "prefix " ++ show i
187data FixDecl = Fix Fixity String
190instance Ord FixDecl where
191 compare (Fix x _) (Fix y _) = compare (prec x) (prec y)
194data Static = Static | Dynamic
197-- Mark bindings with their explicitness, and laziness
198data Plicity = Imp { plazy :: Bool,
200 | Exp { plazy :: Bool,
202 | Constraint { plazy :: Bool,
206impl = Imp False Dynamic
207expl = Exp False Dynamic
208constraint = Constraint False Static
210type FnOpts = Bool -- just inlinable, for now
212inlinable :: FnOpts -> Bool
215data PDecl' t = PFix FC Fixity [String] -- fixity declaration
216 | PTy SyntaxInfo FC Name t -- type declaration
217 | PClauses FC FnOpts Name [PClause' t] -- pattern clause
218 | PData SyntaxInfo FC (PData' t) -- data declaration
219 | PParams FC [(Name, t)] [PDecl' t] -- params block
220 | PClass SyntaxInfo FC
223 [(Name, t)] -- parameters
224 [PDecl' t] -- declarations
225 | PInstance SyntaxInfo FC [t] -- constraints
228 t -- full instance type
231 | PDirective (Idris ())
234data PClause' t = PClause Name t [t] t [PDecl' t]
235 | PWith Name t [t] t [PDecl' t]
238data PData' t = PDatadecl { d_name :: Name,
240 d_cons :: [(Name, t, FC)] }
243-- Handy to get a free function for applying PTerm -> PTerm functions
244-- across a program, by deriving Functor
246type PDecl = PDecl' PTerm
247type PData = PData' PTerm
248type PClause = PClause' PTerm
250-- get all the names declared in a decl
252declared :: PDecl -> [Name]
253declared (PFix _ _ _) = []
254declared (PTy _ _ n t) = [n]
255declared (PClauses _ _ n _) = [] -- not a declaration
256declared (PData _ _ (PDatadecl n _ ts)) = n : map fstt ts
257 where fstt (a, _, _) = a
258declared (PParams _ _ ds) = concatMap declared ds
259-- declared (PImport _) = []
261updateN :: [(Name, Name)] -> Name -> Name
262updateN ns n | Just n' <- lookup n ns = n'
265updateNs :: [(Name, Name)] -> PTerm -> PTerm
267updateNs ns t = mapPT updateRef t
268 where updateRef (PRef fc f) = PRef fc (updateN ns f)
271-- updateDNs :: [(Name, Name)] -> PDecl -> PDecl
273-- updateDNs ns (PTy s f n t) | Just n' <- lookup n ns = PTy s f n' t
274-- updateDNs ns (PClauses f n c) | Just n' <- lookup n ns = PClauses f n' (map updateCNs c)
275-- where updateCNs ns (PClause n l ts r ds)
276-- = PClause (updateN ns n) (fmap (updateNs ns) l)
277-- (map (fmap (updateNs ns)) ts)
278-- (fmap (updateNs ns) r)
279-- (map (updateDNs ns) ds)
282-- High level language terms
284data PTerm = PQuote Raw
286 | PLam Name PTerm PTerm
287 | PPi Plicity Name PTerm PTerm
288 | PLet Name PTerm PTerm PTerm
289 | PApp FC PTerm [PArg]
295 | PPair FC PTerm PTerm
296 | PDPair FC PTerm PTerm PTerm
297 | PHidden PTerm -- irrelevant or hidden pattern
305 | PTactics [PTactic] -- as PProof, but no auto solving
306 | PElabError String -- error to report on elaboration
309mapPT :: (PTerm -> PTerm) -> PTerm -> PTerm
310mapPT f t = f (mpt t) where
311 mpt (PLam n t s) = PLam n (mapPT f t) (mapPT f s)
312 mpt (PPi p n t s) = PPi p n (mapPT f t) (mapPT f s)
313 mpt (PLet n ty v s) = PLet n (mapPT f ty) (mapPT f v) (mapPT f s)
314 mpt (PApp fc t as) = PApp fc (mapPT f t) (map (fmap (mapPT f)) as)
315 mpt (PEq fc l r) = PEq fc (mapPT f l) (mapPT f r)
316 mpt (PPair fc l r) = PPair fc (mapPT f l) (mapPT f r)
317 mpt (PDPair fc l t r) = PDPair fc (mapPT f l) (mapPT f t) (mapPT f r)
318 mpt (PHidden t) = PHidden (mapPT f t)
319 mpt (PDoBlock ds) = PDoBlock (map (fmap (mapPT f)) ds)
320 mpt (PProof ts) = PProof (map (fmap (mapPT f)) ts)
321 mpt (PTactics ts) = PTactics (map (fmap (mapPT f)) ts)
325data PTactic' t = Intro [Name] | Focus Name
326 | Refine Name [Bool] | Rewrite t | LetTac Name t
327 | Exact t | Compute | Trivial
330 | ProofState | ProofTerm | Undo
331 | Try (PTactic' t) (PTactic' t)
332 | TSeq (PTactic' t) (PTactic' t)
334 deriving (Show, Eq, Functor)
336type PTactic = PTactic' PTerm
338data PDo' t = DoExp FC t
341 deriving (Eq, Functor)
345-- The priority gives a hint as to elaboration order. Best to elaborate
346-- things early which will help give a more concrete type to other
347-- variables, e.g. a before (interpTy a).
349data PArg' t = PImp { priority :: Int,
350 lazyarg :: Bool, pname :: Name, getTm :: t }
351 | PExp { priority :: Int,
352 lazyarg :: Bool, getTm :: t }
353 | PConstraint { priority :: Int,
354 lazyarg :: Bool, getTm :: t }
355 deriving (Show, Eq, Functor)
359pconst = PConstraint 0 False
361type PArg = PArg' PTerm
365data ClassInfo = CI { instanceName :: Name,
366 class_methods :: [(Name, PTerm)],
367 class_params :: [Name] }
370-- Syntactic sugar info (TODO: namespaces, modules)
372data DSL = DSL { dsl_bind :: Name,
376data SynContext = PatternSyntax | TermSyntax | AnySyntax
379data Syntax = Rule [SSymbol] PTerm SynContext
382data SSymbol = Keyword Name
387initDSL = DSL (UN [">>="]) (UN ["return"])
389data SyntaxInfo = Syn { using :: [(Name, PTerm)],
390 syn_params :: [(Name, PTerm)],
392 decoration :: Name -> Name,
397defaultSyntax = Syn [] [] [] id False initDSL
399--- Pretty printing declarations and terms
401instance Show PTerm where
402 show tm = showImp False tm
404instance Show PDecl where
405 show (PFix _ f ops) = show f ++ " " ++ showSep ", " ops
406 show (PTy _ _ n ty) = show n ++ " : " ++ show ty
407 show (PClauses _ _ n c) = showSep "\n" (map show c)
408 show (PData _ _ d) = show d
410instance Show PClause where
411 show c = showCImp True c
413instance Show PData where
414 show d = showDImp False d
416showCImp :: Bool -> PClause -> String
417showCImp impl (PClause n l ws r w)
418 = showImp impl l ++ showWs ws ++ " = " ++ showImp impl r
419 ++ " where " ++ show w
422 showWs (x : xs) = " | " ++ showImp impl x ++ showWs xs
423showCImp impl (PWith n l ws r w)
424 = showImp impl l ++ showWs ws ++ " with " ++ showImp impl r
425 ++ " { " ++ show w ++ " } "
428 showWs (x : xs) = " | " ++ showImp impl x ++ showWs xs
431showDImp :: Bool -> PData -> String
432showDImp impl (PDatadecl n ty cons)
433 = "data " ++ show n ++ " : " ++ showImp impl ty ++ " where\n\t"
435 (map (\ (n, t, _) -> show n ++ " : " ++ showImp impl t) cons)
437getImps :: [PArg] -> [(Name, PTerm)]
439getImps (PImp _ _ n tm : xs) = (n, tm) : getImps xs
440getImps (_ : xs) = getImps xs
442getExps :: [PArg] -> [PTerm]
444getExps (PExp _ _ tm : xs) = tm : getExps xs
445getExps (_ : xs) = getExps xs
447getConsts :: [PArg] -> [PTerm]
449getConsts (PConstraint _ _ tm : xs) = tm : getConsts xs
450getConsts (_ : xs) = getConsts xs
452getAll :: [PArg] -> [PTerm]
455showImp :: Bool -> PTerm -> String
456showImp impl tm = se 10 tm where
457 se p (PQuote r) = "![" ++ show r ++ "]"
458 se p (PRef _ n) = show n
459 se p (PLam n ty sc) = bracket p 2 $ "\\ " ++ show n ++ " => " ++ show sc
460 se p (PLet n ty v sc) = bracket p 2 $ "let " ++ show n ++ " = " ++ se 10 v ++
462 se p (PPi (Exp l s) n ty sc)
463 | n `elem` allNamesIn sc = bracket p 2 $
464 if l then "|(" else "(" ++
465 show n ++ " : " ++ se 10 ty ++
468 | otherwise = bracket p 2 $ se 0 ty ++ " " ++ st ++ "-> " ++ se 10 sc
470 Static -> "[static] "
472 se p (PPi (Imp l s) n ty sc)
473 | impl = bracket p 2 $ if l then "|{" else "{" ++
474 show n ++ " : " ++ se 10 ty ++
475 "} " ++ st ++ "-> " ++ se 10 sc
476 | otherwise = se 10 sc
478 Static -> "[static] "
480 se p (PPi (Constraint _ _) n ty sc)
481 = bracket p 2 $ se 10 ty ++ " => " ++ se 10 sc
482 se p (PApp _ (PRef _ f) [])
484 se p (PApp _ (PRef _ op@(UN [f:_])) args)
485 | length (getExps args) == 2 && not impl && not (isAlpha f)
486 = let [l, r] = getExps args in
487 bracket p 1 $ se 1 l ++ " " ++ show op ++ " " ++ se 0 r
489 = let args = getExps as in
490 bracket p 1 $ se 1 f ++ if impl then concatMap sArg as
491 else concatMap seArg args
492 se p (PHidden tm) = "." ++ se 0 tm
493 se p (PRefl _) = "refl"
494 se p (PResolveTC _) = "resolvetc"
495 se p (PTrue _) = "()"
496 se p (PFalse _) = "_|_"
497 se p (PEq _ l r) = bracket p 2 $ se 10 l ++ " = " ++ se 10 r
498 se p (PPair _ l r) = "(" ++ se 10 l ++ ", " ++ se 10 r ++ ")"
499 se p (PDPair _ l t r) = "(" ++ se 10 l ++ " ** " ++ se 10 r ++ ")"
501 se p (PConstant c) = show c
502 se p (PProof ts) = "proof { " ++ show ts ++ "}"
503 se p (PTactics ts) = "tactics { " ++ show ts ++ "}"
504 se p (PMetavar n) = "?" ++ show n
505 se p Placeholder = "_"
507 sArg (PImp _ _ n tm) = siArg (n, tm)
508 sArg (PExp _ _ tm) = seArg tm
509 sArg (PConstraint _ _ tm) = scArg tm
511 seArg arg = " " ++ se 0 arg
512 siArg (n, val) = " {" ++ show n ++ " = " ++ se 10 val ++ "}"
513 scArg val = " {{" ++ se 10 val ++ "}}"
515 bracket outer inner str | inner > outer = "(" ++ str ++ ")"
518allNamesIn :: PTerm -> [Name]
519allNamesIn tm = nub $ ni [] tm
522 | not (n `elem` env) = [n]
523 ni env (PApp _ f as) = ni env f ++ concatMap (ni env) (map getTm as)
524 ni env (PLam n ty sc) = ni env ty ++ ni (n:env) sc
525 ni env (PPi _ n ty sc) = ni env ty ++ ni (n:env) sc
526 ni env (PHidden tm) = ni env tm
527 ni env (PEq _ l r) = ni env l ++ ni env r
528 ni env (PPair _ l r) = ni env l ++ ni env r
529 ni env (PDPair _ l t r) = ni env l ++ ni env t ++ ni env r
532namesIn :: IState -> PTerm -> [Name]
533namesIn ist tm = nub $ ni [] tm
537 = case lookupCtxt n (tt_ctxt ist) of
540 ni env (PApp _ f as) = ni env f ++ concatMap (ni env) (map getTm as)
541 ni env (PLam n ty sc) = ni env ty ++ ni (n:env) sc
542 ni env (PPi _ n ty sc) = ni env ty ++ ni (n:env) sc
543 ni env (PEq _ l r) = ni env l ++ ni env r
544 ni env (PPair _ l r) = ni env l ++ ni env r
545 ni env (PDPair _ l t r) = ni env l ++ ni env t ++ ni env r
546 ni env (PHidden tm) = ni env tm
549-- For inferring types of things
553inferTy = MN 0 "__Infer"
554inferCon = MN 0 "__infer"
555inferDecl = PDatadecl inferTy
557 [(inferCon, PPi impl (MN 0 "A") PSet (
558 PPi expl (MN 0 "a") (PRef bi (MN 0 "A"))
559 (PRef bi inferTy)), bi)]
561infTerm t = PApp bi (PRef bi inferCon) [pimp (MN 0 "A") Placeholder, pexp t]
562infP = P (TCon 6 0) inferTy (Set 0)
564getInferTerm, getInferType :: Term -> Term
565getInferTerm (Bind n b sc) = Bind n b $ getInferTerm sc
566getInferTerm (App (App _ _) tm) = tm
567getInferTerm tm = error ("getInferTerm " ++ show tm)
569getInferType (Bind n b sc) = Bind n b $ getInferType sc
570getInferType (App (App _ ty) _) = ty
572-- Handy primitives: Unit, False, Pair, MkPair, =, mkForeign
574primNames = [unitTy, unitCon,
575 falseTy, pairTy, pairCon,
576 eqTy, eqCon, inferTy, inferCon]
578unitTy = MN 0 "__Unit"
580unitDecl = PDatadecl unitTy PSet
581 [(unitCon, PRef bi unitTy, bi)]
583falseTy = MN 0 "__False"
584falseDecl = PDatadecl falseTy PSet []
586pairTy = MN 0 "__Pair"
587pairCon = MN 0 "__MkPair"
588pairDecl = PDatadecl pairTy (piBind [(n "A", PSet), (n "B", PSet)] PSet)
589 [(pairCon, PPi impl (n "A") PSet (
590 PPi impl (n "B") PSet (
591 PPi expl (n "a") (PRef bi (n "A")) (
592 PPi expl (n "b") (PRef bi (n "B"))
593 (PApp bi (PRef bi pairTy) [pexp (PRef bi (n "A")),
594 pexp (PRef bi (n "B"))])))), bi)]
599eqDecl = PDatadecl eqTy (piBind [(n "a", PSet), (n "b", PSet),
600 (n "x", PRef bi (n "a")), (n "y", PRef bi (n "b"))]
602 [(eqCon, PPi impl (n "a") PSet (
603 PPi impl (n "x") (PRef bi (n "a"))
604 (PApp bi (PRef bi eqTy) [pimp (n "a") Placeholder,
605 pimp (n "b") Placeholder,
606 pexp (PRef bi (n "x")),
607 pexp (PRef bi (n "x"))])), bi)]
610-- Defined in builtins.idr
611sigmaTy = UN ["Sigma"]
612existsCon = UN ["Exists"]
614piBind :: [(Name, PTerm)] -> PTerm -> PTerm
616piBind ((n, ty):ns) t = PPi expl n ty (piBind ns t)
618-- Dealing with parameters
620expandParams :: (Name -> Name) -> [(Name, PTerm)] -> [Name] -> PTerm -> PTerm
621expandParams dec ps ns tm = en tm
623 en (PLam n t s) = PLam n (en t) (en s)
624 en (PPi p n t s) = PPi p n (en t) (en s)
625 en (PLet n ty v s) = PLet n (en ty) (en v) (en s)
626 en (PEq f l r) = PEq f (en l) (en r)
627 en (PPair f l r) = PPair f (en l) (en r)
628 en (PDPair f l t r) = PDPair f (en l) (en t) (en r)
629 en (PHidden t) = PHidden (en t)
630 en (PDoBlock ds) = PDoBlock (map (fmap en) ds)
631 en (PProof ts) = PProof (map (fmap en) ts)
632 en (PTactics ts) = PTactics (map (fmap en) ts)
635 | n `elem` ns = PQuote (Var (dec n))
636 en (PApp fc (PRef fc' n) as)
637 | n `elem` ns = PApp fc (PRef fc' (dec n))
638 (map (pexp . (PRef fc)) (map fst ps) ++ (map (fmap en) as))
640 | n `elem` ns = PApp fc (PRef fc (dec n))
641 (map (pexp . (PRef fc)) (map fst ps))
642 en (PApp fc f as) = PApp fc (en f) (map (fmap en) as)
645expandParamsD :: IState ->
646 (Name -> Name) -> [(Name, PTerm)] -> [Name] -> PDecl -> PDecl
647expandParamsD ist dec ps ns (PTy syn fc n ty)
649 then PTy syn fc (dec n) (piBind ps (expandParams dec ps ns ty))
650 else PTy syn fc n (expandParams dec ps ns ty)
651expandParamsD ist dec ps ns (PClauses fc opts n cs)
652 = let n' = if n `elem` ns then dec n else n in
653 PClauses fc opts n' (map expandParamsC cs)
655 expandParamsC (PClause n lhs ws rhs ds)
656 = let -- ps' = updateps True (namesIn ist rhs) (zip ps [0..])
657 ps'' = updateps False (namesIn ist lhs) (zip ps [0..])
658 n' = if n `elem` ns then dec n else n in
659 PClause n' (expandParams dec ps'' ns lhs)
660 (map (expandParams dec ps'' ns) ws)
661 (expandParams dec ps'' ns rhs)
662 (map (expandParamsD ist dec ps'' ns) ds)
663 expandParamsC (PWith n lhs ws wval ds)
664 = let -- ps' = updateps True (namesIn ist wval) (zip ps [0..])
665 ps'' = updateps False (namesIn ist lhs) (zip ps [0..])
666 n' = if n `elem` ns then dec n else n in
667 PWith n' (expandParams dec ps'' ns lhs)
668 (map (expandParams dec ps'' ns) ws)
669 (expandParams dec ps'' ns wval)
670 (map (expandParamsD ist dec ps'' ns) ds)
671 updateps yn nm [] = []
672 updateps yn nm (((a, t), i):as)
673 | (a `elem` nm) == yn = (a, t) : updateps yn nm as
674 | otherwise = (MN i (show n ++ "_u"), t) : updateps yn nm as
676expandParamsD ist dec ps ns d = d
678-- Calculate a priority for a type, for deciding elaboration order
679-- * if it's just a type variable or concrete type, do it early (0)
680-- * if there's only type variables and injective constructors, do it next (1)
681-- * if there's a function type, next (2)
682-- * finally, everything else (3)
684getPriority :: IState -> PTerm -> Int
685getPriority i tm = pri tm
688 case lookupP n (tt_ctxt i) of
689 Just (P (DCon _ _) _ _) -> 1
690 Just (P (TCon _ _) _ _) -> 1
691 Just (P Ref _ _) -> 3
692 Nothing -> 0 -- must be locally bound, if it's not an error...
693 pri (PPi _ _ x y) = max 4 (max (pri x) (pri y))
697 pri (PEq _ l r) = max 1 (max (pri l) (pri r))
698 pri (PApp _ f as) = max 1 (max (pri f) (foldr max 0 (map (pri.getTm) as)))
699 pri (PPair _ l r) = max 1 (max (pri l) (pri r))
700 pri (PDPair _ l t r) = max 1 (max (pri l) (max (pri t) (pri r)))
701 pri (PConstant _) = 0
705-- Dealing with implicit arguments
707-- Add implicit Pi bindings for any names in the term which appear in an
710-- This has become a right mess already. Better redo it some time...
712implicit :: SyntaxInfo -> Name -> PTerm -> Idris PTerm
715 let (tm', impdata) = implicitise syn i ptm
716 let (tm'', spos) = findStatics i tm'
717 put (i { idris_implicits = addDef n impdata (idris_implicits i) })
718 logLvl 5 ("Implicit " ++ show n ++ " " ++ show impdata)
720 put (i { idris_statics = addDef n spos (idris_statics i) })
723implicitise :: SyntaxInfo -> IState -> PTerm -> (PTerm, [PArg])
724implicitise syn ist tm
725 = let uvars = using syn
726 pvars = syn_params syn
727 (declimps, ns') = execState (imps True [] tm) ([], [])
728 ns = ns' \\ (map fst pvars ++ no_imp syn) in
730 then (tm, reverse declimps)
731 else implicitise syn ist (pibind uvars ns tm)
733 dropAll (x:xs) ys | x `elem` ys = dropAll xs ys
734 | otherwise = x : dropAll xs ys
737 imps top env (PApp _ f as)
738 = do (decls, ns) <- get
739 let isn = concatMap (namesIn ist) (map getTm as)
740 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
741 imps top env (PPi (Imp l _) n ty sc)
742 = do let isn = nub (namesIn ist ty) `dropAll` [n]
744 put (PImp (getPriority ist ty) l n ty : decls,
745 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
747 imps top env (PPi (Exp l _) n ty sc)
748 = do let isn = nub (namesIn ist ty ++ case sc of
749 (PRef _ x) -> namesIn ist sc `dropAll` [n]
751 (decls, ns) <- get -- ignore decls in HO types
752 put (PExp (getPriority ist ty) l ty : decls,
753 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
755 imps top env (PPi (Constraint l _) n ty sc)
756 = do let isn = nub (namesIn ist ty ++ case sc of
757 (PRef _ x) -> namesIn ist sc `dropAll` [n]
759 (decls, ns) <- get -- ignore decls in HO types
760 put (PConstraint 10 l ty : decls,
761 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
763 imps top env (PEq _ l r)
764 = do (decls, ns) <- get
765 let isn = namesIn ist l ++ namesIn ist r
766 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
767 imps top env (PPair _ l r)
768 = do (decls, ns) <- get
769 let isn = namesIn ist l ++ namesIn ist r
770 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
771 imps top env (PDPair _ (PRef _ n) t r)
772 = do (decls, ns) <- get
773 let isn = nub (namesIn ist t ++ namesIn ist r) \\ [n]
774 put (decls, nub (ns ++ (isn \\ (env ++ map fst (getImps decls)))))
775 imps top env (PDPair _ l t r)
776 = do (decls, ns) <- get
777 let isn = namesIn ist l ++ namesIn ist t ++ namesIn ist r
778 put (decls, nub (ns ++ (isn \\ (env ++ map fst (getImps decls)))))
779 imps top env (PLam n ty sc)
780 = do imps False env ty
781 imps False (n:env) sc
782 imps top env (PHidden tm) = imps False env tm
783 imps top env _ = return ()
785 pibind using [] sc = sc
786 pibind using (n:ns) sc
787 = case lookup n using of
788 Just ty -> PPi (Imp False Dynamic) n ty (pibind using ns sc)
789 Nothing -> PPi (Imp False Dynamic) n Placeholder (pibind using ns sc)
791-- Add implicit arguments in function calls
793addImpl :: IState -> PTerm -> PTerm
794addImpl ist ptm = ai [] ptm
796 ai env (PRef fc f) = aiFn ist fc f []
797 ai env (PEq fc l r) = let l' = ai env l
800 ai env (PPair fc l r) = let l' = ai env l
803 ai env (PDPair fc l t r) = let l' = ai env l
807 ai env (PApp fc (PRef _ f) as)
808 = let as' = map (fmap (ai env)) as in
810 ai env (PApp fc f as) = let f' = ai env f
811 as' = map (fmap (ai env)) as in
813 ai env (PLam n ty sc) = let ty' = ai env ty
814 sc' = ai (n:env) sc in
816 ai env (PLet n ty val sc)
817 = let ty' = ai env ty
819 sc' = ai (n:env) sc in
821 ai env (PPi p n ty sc) = let ty' = ai env ty
822 sc' = ai (n:env) sc in
824 ai env (PHidden tm) = PHidden (ai env tm)
825 ai env (PProof ts) = PProof (map (fmap (ai env)) ts)
826 ai env (PTactics ts) = PTactics (map (fmap (ai env)) ts)
829aiFn :: IState -> FC -> Name -> [PArg] -> PTerm
831 | f `elem` primNames = PApp fc (PRef fc f) as
833 = case lookupCtxt f (idris_implicits ist) of
834 Just ns -> mkPApp fc (length ns) (PRef fc f) (insertImpl ns as)
835 Nothing -> mkPApp fc 1 (PRef fc f) as
837 insertImpl :: [PArg] -> [PArg] -> [PArg]
838 insertImpl (PExp p l ty : ps) (PExp _ _ tm : given) =
839 PExp p l tm : insertImpl ps given
840 insertImpl (PConstraint p l ty : ps) (PConstraint _ _ tm : given) =
841 PConstraint p l tm : insertImpl ps given
842 insertImpl (PConstraint p l ty : ps) given =
843 PConstraint p l (PResolveTC fc) : insertImpl ps given
844 insertImpl (PImp p l n ty : ps) given =
845 case find n given [] of
846 Just (tm, given') -> PImp p l n tm : insertImpl ps given'
847 Nothing -> PImp p l n Placeholder : insertImpl ps given
848 insertImpl expected [] = []
849 insertImpl _ given = given
851 find n [] acc = Nothing
852 find n (PImp _ _ n' t : gs) acc
853 | n == n' = Just (t, reverse acc ++ gs)
854 find n (g : gs) acc = find n gs (g : acc)
857mkPApp fc a f as = let rest = drop a as in
858 appRest fc (PApp fc f (take a as)) rest
861 appRest fc f (a : as) = appRest fc (PApp fc f [a]) as
863-- Find 'static' argument positions
864-- (the declared ones, plus any names in argument position in the declared
866-- FIXME: It's possible that this really has to happen after elaboration
868findStatics :: IState -> PTerm -> (PTerm, [Bool])
869findStatics ist tm = let (ns, ss) = fs tm in
870 runState (pos ns ss tm) []
871 where fs (PPi p n t sc)
872 | Static <- pstatic p
873 = let (ns, ss) = fs sc in
874 (namesIn ist t : ns, namesIn ist t ++ n : ss)
875 | otherwise = let (ns, ss) = fs sc in
876 (namesIn ist t : ns, ss)
879 inOne n ns = length (filter id (map (elem n) ns)) == 1
881 pos ns ss (PPi p n t sc)
882 | n `inOne` ns && elem n ss
883 = do sc' <- pos ns ss sc
886 return (PPi (p { pstatic = Static }) n t sc')
887 | otherwise = do sc' <- pos ns ss sc
890 return (PPi p n t sc')
891 pos ns ss t = return t
893-- Debugging/logging stuff
895dumpDecls :: [PDecl] -> String
897dumpDecls (d:ds) = dumpDecl d ++ "\n" ++ dumpDecls ds
899dumpDecl (PFix _ f ops) = show f ++ " " ++ showSep ", " ops
900dumpDecl (PTy _ _ n t) = "tydecl " ++ show n ++ " : " ++ showImp True t
901dumpDecl (PClauses _ _ n cs) = "pat " ++ show n ++ "\t" ++ showSep "\n\t" (map (showCImp True) cs)
902dumpDecl (PData _ _ d) = showDImp True d
903dumpDecl (PParams _ ns ps) = "params {" ++ show ns ++ "\n" ++ dumpDecls ps ++ "}\n"
904dumpDecl (PSyntax _ syn) = "syntax " ++ show syn
905dumpDecl (PClass _ _ cs n ps ds)
906 = "class " ++ show cs ++ " " ++ show n ++ " " ++ show ps ++ "\n" ++ dumpDecls ds
907dumpDecl (PInstance _ _ cs n _ t ds)
908 = "instance " ++ show cs ++ " " ++ show n ++ " " ++ show t ++ "\n" ++ dumpDecls ds
910-- dumpDecl (PImport i) = "import " ++ i
912-- syntactic match of a against b, returning pair of variables in a
913-- and what they match. Returns 'Nothing' if not a match.
915matchClause :: PTerm -> PTerm -> Maybe [(Name, PTerm)]
916matchClause x y = match x y where
917 matchArg x y = match (getTm x) (getTm y)
919 match (PApp _ f args) (PApp _ f' args')
920 | length args == length args'
921 = do mf <- match f f'
922 ms <- zipWithM matchArg args args'
923 return (mf ++ concat ms)
924-- match (PRef _ n) (PRef _ n') | n == n' = return []
925-- | otherwise = Nothing
926 match (PRef _ n) tm = return [(n, tm)]
927 match (PEq _ l r) (PEq _ l' r') = do ml <- match l l'
930 match (PPair _ l r) (PPair _ l' r') = do ml <- match l l'
933 match (PDPair _ l t r) (PDPair _ l' t' r') = do ml <- match l l'
936 return (ml ++ mt ++ mr)
937 match (PRefl _) (PRefl _) = return []
938 match (PResolveTC _) (PResolveTC _) = return []
939 match (PTrue _) (PTrue _) = return []
940 match (PFalse _) (PFalse _) = return []
941 match (PReturn _) (PReturn _) = return []
942 match (PPi _ _ t s) (PPi _ _ t' s') = do mt <- match t t'
945 match (PLam _ t s) (PLam _ t' s') = do mt <- match t t'
948 match (PHidden x) (PHidden y) = match x y
949 match a b | a == b = return []
950 | otherwise = Nothing
952substMatches :: [(Name, PTerm)] -> PTerm -> PTerm
954substMatches ((n,tm):ns) t = substMatch n tm (substMatches ns t)
956substMatch :: Name -> PTerm -> PTerm -> PTerm
957substMatch n tm t = sm t where
958 sm (PRef _ n') | n == n' = tm
959 sm (PLam x t sc) = PLam x (sm t) (sm sc)
960 sm (PPi p x t sc) = PPi p x (sm t) (sm sc)
961 sm (PApp f x as) = PApp f (sm x) (map (fmap sm) as)
962 sm (PEq f x y) = PEq f (sm x) (sm y)
963 sm (PPair f x y) = PPair f (sm x) (sm y)
964 sm (PDPair f x t y) = PDPair f (sm x) (sm t) (sm y)
965 sm (PHidden x) = PHidden (sm x)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list