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,
20 opt_typeintype :: Bool,
26defaultOpts = IOption 0 False False False True
28-- TODO: Add 'module data' to IState, which can be saved out and reloaded quickly (i.e
29-- without typechecking).
30-- This will include all the functions and data declarations, plus fixity declarations
33data IState = IState { tt_ctxt :: Context,
34 idris_constraints :: [(UConstraint, FC)],
35 idris_infixes :: [FixDecl],
36 idris_implicits :: Ctxt [PArg],
37 idris_statics :: Ctxt [Bool],
38 idris_classes :: Ctxt ClassInfo,
40 idris_options :: IOption,
42 idris_metavars :: [Name],
43 syntax_rules :: [Syntax],
44 syntax_keywords :: [String],
45 imported :: [FilePath],
46 idris_prims :: [(Name, ([E.Name], E.Term))],
47 idris_objs :: [FilePath],
48 idris_libs :: [String],
49 idris_hdrs :: [String],
50 last_proof :: Maybe (Name, [String]),
52 ibc_write :: [IBCWrite]
55-- information that needs writing for the current module's .ibc file
56data IBCWrite = IBCFix FixDecl
66 | IBCDef Name -- i.e. main context
69idrisInit = IState initContext [] [] emptyContext emptyContext emptyContext
70 "" defaultOpts 6 [] [] [] [] [] [] [] [] Nothing Nothing []
72-- The monad for the main REPL - reading and processing files and updating
73-- global state (hence the IO inner monad).
74type Idris a = StateT IState IO a
76getContext :: Idris Context
77getContext = do i <- get; return (tt_ctxt i)
79getObjectFiles :: Idris [FilePath]
80getObjectFiles = do i <- get; return (idris_objs i)
82addObjectFile :: FilePath -> Idris ()
83addObjectFile f = do i <- get; put (i { idris_objs = f : idris_objs i })
85getLibs :: Idris [String]
86getLibs = do i <- get; return (idris_libs i)
88addLib :: String -> Idris ()
89addLib f = do i <- get; put (i { idris_libs = f : idris_libs i })
91addHdr :: String -> Idris ()
92addHdr f = do i <- get; put (i { idris_hdrs = f : idris_hdrs i })
94addIBC :: IBCWrite -> Idris ()
95addIBC ibc = do i <- get; put (i { ibc_write = ibc : ibc_write i })
98clearIBC = do i <- get; put (i { ibc_write = [] })
100getHdrs :: Idris [String]
101getHdrs = do i <- get; return (idris_hdrs i)
103setErrLine :: Int -> Idris ()
104setErrLine x = do i <- get;
106 Nothing -> put (i { errLine = Just x })
110clearErr = do i <- get
111 put (i { errLine = Nothing })
113getIState :: Idris IState
116putIState :: IState -> Idris ()
120getName = do i <- get;
121 let idx = idris_name i;
122 put (i { idris_name = idx + 1 })
125checkUndefined :: FC -> Name -> Idris ()
128 case lookupTy Nothing n i of
129 (_:_) -> fail $ show fc ++ ":" ++
130 show n ++ " already defined"
133setContext :: Context -> Idris ()
134setContext ctxt = do i <- get; put (i { tt_ctxt = ctxt } )
136updateContext :: (Context -> Context) -> Idris ()
137updateContext f = do i <- get; put (i { tt_ctxt = f (tt_ctxt i) } )
139addConstraints :: FC -> (Int, [UConstraint]) -> Idris ()
140addConstraints fc (v, cs)
143 let ctxt' = ctxt { uconstraints = cs ++ uconstraints ctxt,
145 let ics = zip cs (repeat fc) ++ idris_constraints i
146 put (i { tt_ctxt = ctxt', idris_constraints = ics })
148addDeferred :: [(Name, Type)] -> Idris ()
149addDeferred ns = do mapM_ (\(n, t) -> updateContext (addTyDecl n (tidyNames [] t))) ns
151 put (i { idris_metavars = map fst ns ++ idris_metavars i })
152 where tidyNames used (Bind (MN i x) b sc)
153 = let n' = uniqueName (UN x) used in
154 Bind n' b $ tidyNames (n':used) sc
155 tidyNames used (Bind n b sc)
156 = let n' = uniqueName n used in
157 Bind n' b $ tidyNames (n':used) sc
160solveDeferred :: Name -> Idris ()
161solveDeferred n = do i <- get
162 put (i { idris_metavars = idris_metavars i \\ [n] })
164iputStrLn :: String -> Idris ()
165iputStrLn = lift.putStrLn
167iWarn :: FC -> String -> Idris ()
168iWarn fc err = do lift $ putStrLn (show fc ++ ":" ++ err)
170setLogLevel :: Int -> Idris ()
171setLogLevel l = do i <- get
172 let opts = idris_options i
173 let opt' = opts { opt_logLevel = l }
174 put (i { idris_options = opt' } )
177logLevel = do i <- get
178 return (opt_logLevel (idris_options i))
182 return (opt_repl (idris_options i))
184setREPL :: Bool -> Idris ()
185setREPL t = do i <- get
186 let opts = idris_options i
187 let opt' = opts { opt_repl = t }
188 put (i { idris_options = opt' })
190typeInType :: Idris Bool
191typeInType = do i <- get
192 return (opt_typeintype (idris_options i))
194setTypeInType :: Bool -> Idris ()
195setTypeInType t = do i <- get
196 let opts = idris_options i
197 let opt' = opts { opt_typeintype = t }
198 put (i { idris_options = opt' })
202 return (opt_showimp (idris_options i))
204setImpShow :: Bool -> Idris ()
205setImpShow t = do i <- get
206 let opts = idris_options i
207 let opt' = opts { opt_showimp = t }
208 put (i { idris_options = opt' })
210logLvl :: Int -> String -> Idris ()
211logLvl l str = do i <- get
212 let lvl = opt_logLevel (idris_options i)
214 $ do lift (putStrLn str)
215 put (i { idris_log = idris_log i ++ str ++ "\n" } )
217iLOG :: String -> Idris ()
220noErrors :: Idris Bool
221noErrors = do i <- get
223 Nothing -> return True
226setTypeCase :: Bool -> Idris ()
227setTypeCase t = do i <- get
228 let opts = idris_options i
229 let opt' = opts { opt_typecase = t }
230 put (i { idris_options = opt' })
232-- Commands in the REPL
234data Command = Quit | Help | Eval PTerm | Check PTerm | Reload | Edit
235 | Compile String | Execute String
236 | Metavars | Prove Name | AddProof | Universes
238 | LogLvl Int | Spec PTerm | HNF PTerm | Defn Name
241-- Parsed declarations
243data Fixity = Infixl { prec :: Int }
244 | Infixr { prec :: Int }
245 | InfixN { prec :: Int }
246 | PrefixN { prec :: Int }
249deriving instance Binary Fixity
252instance Show Fixity where
253 show (Infixl i) = "infixl " ++ show i
254 show (Infixr i) = "infixr " ++ show i
255 show (InfixN i) = "infix " ++ show i
256 show (PrefixN i) = "prefix " ++ show i
258data FixDecl = Fix Fixity String
261deriving instance Binary FixDecl
264instance Ord FixDecl where
265 compare (Fix x _) (Fix y _) = compare (prec x) (prec y)
268data Static = Static | Dynamic
271deriving instance Binary Static
274-- Mark bindings with their explicitness, and laziness
275data Plicity = Imp { plazy :: Bool,
277 | Exp { plazy :: Bool,
279 | Constraint { plazy :: Bool,
284deriving instance Binary Plicity
287impl = Imp False Dynamic
288expl = Exp False Dynamic
289constraint = Constraint False Static
291data FnOpt = Inlinable | Partial | Abstract | Private
296inlinable :: FnOpts -> Bool
297inlinable = elem Inlinable
299data PDecl' t = PFix FC Fixity [String] -- fixity declaration
300 | PTy SyntaxInfo FC Name t -- type declaration
301 | PClauses FC FnOpts Name [PClause' t] -- pattern clause
302 | PData SyntaxInfo FC (PData' t) -- data declaration
303 | PParams FC [(Name, t)] [PDecl' t] -- params block
304 | PNamespace String [PDecl' t] -- new namespace
305 | PClass SyntaxInfo FC
308 [(Name, t)] -- parameters
309 [PDecl' t] -- declarations
310 | PInstance SyntaxInfo FC [t] -- constraints
313 t -- full instance type
316 | PDirective (Idris ())
319data PClause' t = PClause Name t [t] t [PDecl' t]
320 | PWith Name t [t] t [PDecl' t]
323data PData' t = PDatadecl { d_name :: Name,
325 d_cons :: [(Name, t, FC)] }
328-- Handy to get a free function for applying PTerm -> PTerm functions
329-- across a program, by deriving Functor
331type PDecl = PDecl' PTerm
332type PData = PData' PTerm
333type PClause = PClause' PTerm
335-- get all the names declared in a decl
337declared :: PDecl -> [Name]
338declared (PFix _ _ _) = []
339declared (PTy _ _ n t) = [n]
340declared (PClauses _ _ n _) = [] -- not a declaration
341declared (PData _ _ (PDatadecl n _ ts)) = n : map fstt ts
342 where fstt (a, _, _) = a
343declared (PParams _ _ ds) = concatMap declared ds
344declared (PNamespace _ ds) = concatMap declared ds
345-- declared (PImport _) = []
347updateN :: [(Name, Name)] -> Name -> Name
348updateN ns n | Just n' <- lookup n ns = n'
351updateNs :: [(Name, Name)] -> PTerm -> PTerm
353updateNs ns t = mapPT updateRef t
354 where updateRef (PRef fc f) = PRef fc (updateN ns f)
357-- updateDNs :: [(Name, Name)] -> PDecl -> PDecl
359-- updateDNs ns (PTy s f n t) | Just n' <- lookup n ns = PTy s f n' t
360-- updateDNs ns (PClauses f n c) | Just n' <- lookup n ns = PClauses f n' (map updateCNs c)
361-- where updateCNs ns (PClause n l ts r ds)
362-- = PClause (updateN ns n) (fmap (updateNs ns) l)
363-- (map (fmap (updateNs ns)) ts)
364-- (fmap (updateNs ns) r)
365-- (map (updateDNs ns) ds)
368-- High level language terms
370data PTerm = PQuote Raw
372 | PLam Name PTerm PTerm
373 | PPi Plicity Name PTerm PTerm
374 | PLet Name PTerm PTerm PTerm
375 | PApp FC PTerm [PArg]
381 | PPair FC PTerm PTerm
382 | PDPair FC PTerm PTerm PTerm
383 | PAlternative [PTerm]
384 | PHidden PTerm -- irrelevant or hidden pattern
392 | PTactics [PTactic] -- as PProof, but no auto solving
393 | PElabError String -- error to report on elaboration
394 | PImpossible -- special case for declaring when an LHS can't typecheck
397deriving instance Binary PTerm
400mapPT :: (PTerm -> PTerm) -> PTerm -> PTerm
401mapPT f t = f (mpt t) where
402 mpt (PLam n t s) = PLam n (mapPT f t) (mapPT f s)
403 mpt (PPi p n t s) = PPi p n (mapPT f t) (mapPT f s)
404 mpt (PLet n ty v s) = PLet n (mapPT f ty) (mapPT f v) (mapPT f s)
405 mpt (PApp fc t as) = PApp fc (mapPT f t) (map (fmap (mapPT f)) as)
406 mpt (PEq fc l r) = PEq fc (mapPT f l) (mapPT f r)
407 mpt (PPair fc l r) = PPair fc (mapPT f l) (mapPT f r)
408 mpt (PDPair fc l t r) = PDPair fc (mapPT f l) (mapPT f t) (mapPT f r)
409 mpt (PAlternative as) = PAlternative (map (mapPT f) as)
410 mpt (PHidden t) = PHidden (mapPT f t)
411 mpt (PDoBlock ds) = PDoBlock (map (fmap (mapPT f)) ds)
412 mpt (PProof ts) = PProof (map (fmap (mapPT f)) ts)
413 mpt (PTactics ts) = PTactics (map (fmap (mapPT f)) ts)
417data PTactic' t = Intro [Name] | Focus Name
418 | Refine Name [Bool] | Rewrite t | LetTac Name t
419 | Exact t | Compute | Trivial
422 | ProofState | ProofTerm | Undo
423 | Try (PTactic' t) (PTactic' t)
424 | TSeq (PTactic' t) (PTactic' t)
426 deriving (Show, Eq, Functor)
428deriving instance Binary PTactic'
431type PTactic = PTactic' PTerm
433data PDo' t = DoExp FC t
436 deriving (Eq, Functor)
438deriving instance Binary PDo'
443-- The priority gives a hint as to elaboration order. Best to elaborate
444-- things early which will help give a more concrete type to other
445-- variables, e.g. a before (interpTy a).
447data PArg' t = PImp { priority :: Int,
448 lazyarg :: Bool, pname :: Name, getTm :: t }
449 | PExp { priority :: Int,
450 lazyarg :: Bool, getTm :: t }
451 | PConstraint { priority :: Int,
452 lazyarg :: Bool, getTm :: t }
453 deriving (Show, Eq, Functor)
455deriving instance Binary PArg'
460pconst = PConstraint 0 False
462type PArg = PArg' PTerm
466data ClassInfo = CI { instanceName :: Name,
467 class_methods :: [(Name, PTerm)],
468 class_defaults :: [(Name, Name)], -- method name -> default impl
469 class_params :: [Name] }
472deriving instance Binary ClassInfo
475-- Syntactic sugar info
477data DSL = DSL { dsl_bind :: Name,
481data SynContext = PatternSyntax | TermSyntax | AnySyntax
484deriving instance Binary SynContext
487data Syntax = Rule [SSymbol] PTerm SynContext
490deriving instance Binary Syntax
493data SSymbol = Keyword Name
498deriving instance Binary SSymbol
501initDSL = DSL (UN ">>=") (UN "return")
503data SyntaxInfo = Syn { using :: [(Name, PTerm)],
504 syn_params :: [(Name, PTerm)],
505 syn_namespace :: [String],
507 decoration :: Name -> Name,
512defaultSyntax = Syn [] [] [] [] id False initDSL
514--- Pretty printing declarations and terms
516instance Show PTerm where
517 show tm = showImp False tm
519instance Show PDecl where
520 show (PFix _ f ops) = show f ++ " " ++ showSep ", " ops
521 show (PTy _ _ n ty) = show n ++ " : " ++ show ty
522 show (PClauses _ _ n c) = showSep "\n" (map show c)
523 show (PData _ _ d) = show d
525instance Show PClause where
526 show c = showCImp True c
528instance Show PData where
529 show d = showDImp False d
531showCImp :: Bool -> PClause -> String
532showCImp impl (PClause n l ws r w)
533 = showImp impl l ++ showWs ws ++ " = " ++ showImp impl r
534 ++ " where " ++ show w
537 showWs (x : xs) = " | " ++ showImp impl x ++ showWs xs
538showCImp impl (PWith n l ws r w)
539 = showImp impl l ++ showWs ws ++ " with " ++ showImp impl r
540 ++ " { " ++ show w ++ " } "
543 showWs (x : xs) = " | " ++ showImp impl x ++ showWs xs
546showDImp :: Bool -> PData -> String
547showDImp impl (PDatadecl n ty cons)
548 = "data " ++ show n ++ " : " ++ showImp impl ty ++ " where\n\t"
550 (map (\ (n, t, _) -> show n ++ " : " ++ showImp impl t) cons)
552getImps :: [PArg] -> [(Name, PTerm)]
554getImps (PImp _ _ n tm : xs) = (n, tm) : getImps xs
555getImps (_ : xs) = getImps xs
557getExps :: [PArg] -> [PTerm]
559getExps (PExp _ _ tm : xs) = tm : getExps xs
560getExps (_ : xs) = getExps xs
562getConsts :: [PArg] -> [PTerm]
564getConsts (PConstraint _ _ tm : xs) = tm : getConsts xs
565getConsts (_ : xs) = getConsts xs
567getAll :: [PArg] -> [PTerm]
570showImp :: Bool -> PTerm -> String
571showImp impl tm = se 10 tm where
572 se p (PQuote r) = "![" ++ show r ++ "]"
573 se p (PRef _ n) = if impl then show n
575 where showbasic n@(UN _) = show n
576 showbasic (MN _ s) = s
577 showbasic (NS n s) = showSep "." (reverse s) ++ "." ++ showbasic n
578 se p (PLam n ty sc) = bracket p 2 $ "\\ " ++ show n ++ " => " ++ show sc
579 se p (PLet n ty v sc) = bracket p 2 $ "let " ++ show n ++ " = " ++ se 10 v ++
581 se p (PPi (Exp l s) n ty sc)
582 | n `elem` allNamesIn sc = bracket p 2 $
583 if l then "|(" else "(" ++
584 show n ++ " : " ++ se 10 ty ++
587 | otherwise = bracket p 2 $ se 0 ty ++ " " ++ st ++ "-> " ++ se 10 sc
589 Static -> "[static] "
591 se p (PPi (Imp l s) n ty sc)
592 | impl = bracket p 2 $ if l then "|{" else "{" ++
593 show n ++ " : " ++ se 10 ty ++
594 "} " ++ st ++ "-> " ++ se 10 sc
595 | otherwise = se 10 sc
597 Static -> "[static] "
599 se p (PPi (Constraint _ _) n ty sc)
600 = bracket p 2 $ se 10 ty ++ " => " ++ se 10 sc
601 se p (PApp _ (PRef _ f) [])
603 se p (PApp _ (PRef _ op@(UN (f:_))) args)
604 | length (getExps args) == 2 && not impl && not (isAlpha f)
605 = let [l, r] = getExps args in
606 bracket p 1 $ se 1 l ++ " " ++ show op ++ " " ++ se 0 r
608 = let args = getExps as in
609 bracket p 1 $ se 1 f ++ if impl then concatMap sArg as
610 else concatMap seArg args
611 se p (PHidden tm) = "." ++ se 0 tm
612 se p (PRefl _) = "refl"
613 se p (PResolveTC _) = "resolvetc"
614 se p (PTrue _) = "()"
615 se p (PFalse _) = "_|_"
616 se p (PEq _ l r) = bracket p 2 $ se 10 l ++ " = " ++ se 10 r
617 se p (PPair _ l r) = "(" ++ se 10 l ++ ", " ++ se 10 r ++ ")"
618 se p (PDPair _ l t r) = "(" ++ se 10 l ++ " ** " ++ se 10 r ++ ")"
619 se p (PAlternative as) = "(|" ++ showSep " , " (map (se 10) as) ++ "|)"
621 se p (PConstant c) = show c
622 se p (PProof ts) = "proof { " ++ show ts ++ "}"
623 se p (PTactics ts) = "tactics { " ++ show ts ++ "}"
624 se p (PMetavar n) = "?" ++ show n
625 se p Placeholder = "_"
627 sArg (PImp _ _ n tm) = siArg (n, tm)
628 sArg (PExp _ _ tm) = seArg tm
629 sArg (PConstraint _ _ tm) = scArg tm
631 seArg arg = " " ++ se 0 arg
632 siArg (n, val) = " {" ++ show n ++ " = " ++ se 10 val ++ "}"
633 scArg val = " {{" ++ se 10 val ++ "}}"
635 bracket outer inner str | inner > outer = "(" ++ str ++ ")"
638allNamesIn :: PTerm -> [Name]
639allNamesIn tm = nub $ ni [] tm
642 | not (n `elem` env) = [n]
643 ni env (PApp _ f as) = ni env f ++ concatMap (ni env) (map getTm as)
644 ni env (PLam n ty sc) = ni env ty ++ ni (n:env) sc
645 ni env (PPi _ n ty sc) = ni env ty ++ ni (n:env) sc
646 ni env (PHidden tm) = ni env tm
647 ni env (PEq _ l r) = ni env l ++ ni env r
648 ni env (PPair _ l r) = ni env l ++ ni env r
649 ni env (PDPair _ (PRef _ n) t r) = ni env t ++ ni (n:env) r
650 ni env (PDPair _ l t r) = ni env l ++ ni env t ++ ni env r
651 ni env (PAlternative ls) = concatMap (ni env) ls
654namesIn :: IState -> PTerm -> [Name]
655namesIn ist tm = nub $ ni [] tm
659 = case lookupTy Nothing n (tt_ctxt ist) of
662 ni env (PApp _ f as) = ni env f ++ concatMap (ni env) (map getTm as)
663 ni env (PLam n ty sc) = ni env ty ++ ni (n:env) sc
664 ni env (PPi _ n ty sc) = ni env ty ++ ni (n:env) sc
665 ni env (PEq _ l r) = ni env l ++ ni env r
666 ni env (PPair _ l r) = ni env l ++ ni env r
667 ni env (PDPair _ (PRef _ n) t r) = ni env t ++ ni (n:env) r
668 ni env (PDPair _ l t r) = ni env l ++ ni env t ++ ni env r
669 ni env (PAlternative as) = concatMap (ni env) as
670 ni env (PHidden tm) = ni env tm
673-- For inferring types of things
677inferTy = MN 0 "__Infer"
678inferCon = MN 0 "__infer"
679inferDecl = PDatadecl inferTy
681 [(inferCon, PPi impl (MN 0 "A") PSet (
682 PPi expl (MN 0 "a") (PRef bi (MN 0 "A"))
683 (PRef bi inferTy)), bi)]
685infTerm t = PApp bi (PRef bi inferCon) [pimp (MN 0 "A") Placeholder, pexp t]
686infP = P (TCon 6 0) inferTy (Set (UVal 0))
688getInferTerm, getInferType :: Term -> Term
689getInferTerm (Bind n b sc) = Bind n b $ getInferTerm sc
690getInferTerm (App (App _ _) tm) = tm
691getInferTerm tm = error ("getInferTerm " ++ show tm)
693getInferType (Bind n b sc) = Bind n b $ getInferType sc
694getInferType (App (App _ ty) _) = ty
696-- Handy primitives: Unit, False, Pair, MkPair, =, mkForeign
698primNames = [unitTy, unitCon,
699 falseTy, pairTy, pairCon,
700 eqTy, eqCon, inferTy, inferCon]
702unitTy = MN 0 "__Unit"
704unitDecl = PDatadecl unitTy PSet
705 [(unitCon, PRef bi unitTy, bi)]
707falseTy = MN 0 "__False"
708falseDecl = PDatadecl falseTy PSet []
710pairTy = MN 0 "__Pair"
711pairCon = MN 0 "__MkPair"
712pairDecl = PDatadecl pairTy (piBind [(n "A", PSet), (n "B", PSet)] PSet)
713 [(pairCon, PPi impl (n "A") PSet (
714 PPi impl (n "B") PSet (
715 PPi expl (n "a") (PRef bi (n "A")) (
716 PPi expl (n "b") (PRef bi (n "B"))
717 (PApp bi (PRef bi pairTy) [pexp (PRef bi (n "A")),
718 pexp (PRef bi (n "B"))])))), bi)]
723eqDecl = PDatadecl eqTy (piBind [(n "a", PSet), (n "b", PSet),
724 (n "x", PRef bi (n "a")), (n "y", PRef bi (n "b"))]
726 [(eqCon, PPi impl (n "a") PSet (
727 PPi impl (n "x") (PRef bi (n "a"))
728 (PApp bi (PRef bi eqTy) [pimp (n "a") Placeholder,
729 pimp (n "b") Placeholder,
730 pexp (PRef bi (n "x")),
731 pexp (PRef bi (n "x"))])), bi)]
734-- Defined in builtins.idr
736existsCon = UN "Ex_intro"
738piBind :: [(Name, PTerm)] -> PTerm -> PTerm
740piBind ((n, ty):ns) t = PPi expl n ty (piBind ns t)
742-- Dealing with parameters
744expandParams :: (Name -> Name) -> [(Name, PTerm)] -> [Name] -> PTerm -> PTerm
745expandParams dec ps ns tm = en tm
747 en (PLam n t s) = PLam n (en t) (en s)
748 en (PPi p n t s) = PPi p n (en t) (en s)
749 en (PLet n ty v s) = PLet n (en ty) (en v) (en s)
750 en (PEq f l r) = PEq f (en l) (en r)
751 en (PPair f l r) = PPair f (en l) (en r)
752 en (PDPair f l t r) = PDPair f (en l) (en t) (en r)
753 en (PAlternative as) = PAlternative (map en as)
754 en (PHidden t) = PHidden (en t)
755 en (PDoBlock ds) = PDoBlock (map (fmap en) ds)
756 en (PProof ts) = PProof (map (fmap en) ts)
757 en (PTactics ts) = PTactics (map (fmap en) ts)
760 | n `elem` ns = PQuote (Var (dec n))
761 en (PApp fc (PRef fc' n) as)
762 | n `elem` ns = PApp fc (PRef fc' (dec n))
763 (map (pexp . (PRef fc)) (map fst ps) ++ (map (fmap en) as))
765 | n `elem` ns = PApp fc (PRef fc (dec n))
766 (map (pexp . (PRef fc)) (map fst ps))
767 en (PApp fc f as) = PApp fc (en f) (map (fmap en) as)
770expandParamsD :: IState ->
771 (Name -> Name) -> [(Name, PTerm)] -> [Name] -> PDecl -> PDecl
772expandParamsD ist dec ps ns (PTy syn fc n ty)
774 then PTy syn fc (dec n) (piBind ps (expandParams dec ps ns ty))
775 else PTy syn fc n (expandParams dec ps ns ty)
776expandParamsD ist dec ps ns (PClauses fc opts n cs)
777 = let n' = if n `elem` ns then dec n else n in
778 PClauses fc opts n' (map expandParamsC cs)
780 expandParamsC (PClause n lhs ws rhs ds)
781 = let -- ps' = updateps True (namesIn ist rhs) (zip ps [0..])
782 ps'' = updateps False (namesIn ist lhs) (zip ps [0..])
783 n' = if n `elem` ns then dec n else n in
784 PClause n' (expandParams dec ps'' ns lhs)
785 (map (expandParams dec ps'' ns) ws)
786 (expandParams dec ps'' ns rhs)
787 (map (expandParamsD ist dec ps'' ns) ds)
788 expandParamsC (PWith n lhs ws wval ds)
789 = let -- ps' = updateps True (namesIn ist wval) (zip ps [0..])
790 ps'' = updateps False (namesIn ist lhs) (zip ps [0..])
791 n' = if n `elem` ns then dec n else n in
792 PWith n' (expandParams dec ps'' ns lhs)
793 (map (expandParams dec ps'' ns) ws)
794 (expandParams dec ps'' ns wval)
795 (map (expandParamsD ist dec ps'' ns) ds)
796 updateps yn nm [] = []
797 updateps yn nm (((a, t), i):as)
798 | (a `elem` nm) == yn = (a, t) : updateps yn nm as
799 | otherwise = (MN i (show n ++ "_u"), t) : updateps yn nm as
801expandParamsD ist dec ps ns d = d
803-- Calculate a priority for a type, for deciding elaboration order
804-- * if it's just a type variable or concrete type, do it early (0)
805-- * if there's only type variables and injective constructors, do it next (1)
806-- * if there's a function type, next (2)
807-- * finally, everything else (3)
809getPriority :: IState -> PTerm -> Int
810getPriority i tm = pri tm
813 case lookupP Nothing n (tt_ctxt i) of
814 ((P (DCon _ _) _ _):_) -> 1
815 ((P (TCon _ _) _ _):_) -> 1
817 [] -> 0 -- must be locally bound, if it's not an error...
818 pri (PPi _ _ x y) = max 4 (max (pri x) (pri y))
822 pri (PEq _ l r) = max 1 (max (pri l) (pri r))
823 pri (PApp _ f as) = max 1 (max (pri f) (foldr max 0 (map (pri.getTm) as)))
824 pri (PPair _ l r) = max 1 (max (pri l) (pri r))
825 pri (PDPair _ l t r) = max 1 (max (pri l) (max (pri t) (pri r)))
826 pri (PAlternative as) = maximum (map pri as)
827 pri (PConstant _) = 0
831-- Dealing with implicit arguments
833-- Add implicit Pi bindings for any names in the term which appear in an
836-- This has become a right mess already. Better redo it some time...
838implicit :: SyntaxInfo -> Name -> PTerm -> Idris PTerm
841 let (tm', impdata) = implicitise syn i ptm
842 let (tm'', spos) = findStatics i tm'
843 put (i { idris_implicits = addDef n impdata (idris_implicits i) })
845 logLvl 5 ("Implicit " ++ show n ++ " " ++ show impdata)
847 put (i { idris_statics = addDef n spos (idris_statics i) })
851implicitise :: SyntaxInfo -> IState -> PTerm -> (PTerm, [PArg])
852implicitise syn ist tm
853 = let uvars = using syn
854 pvars = syn_params syn
855 (declimps, ns') = execState (imps True [] tm) ([], [])
856 ns = ns' \\ (map fst pvars ++ no_imp syn) in
858 then (tm, reverse declimps)
859 else implicitise syn ist (pibind uvars ns tm)
861 dropAll (x:xs) ys | x `elem` ys = dropAll xs ys
862 | otherwise = x : dropAll xs ys
865 imps top env (PApp _ f as)
866 = do (decls, ns) <- get
867 let isn = concatMap (namesIn ist) (map getTm as)
868 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
869 imps top env (PPi (Imp l _) n ty sc)
870 = do let isn = nub (namesIn ist ty) `dropAll` [n]
872 put (PImp (getPriority ist ty) l n ty : decls,
873 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
875 imps top env (PPi (Exp l _) n ty sc)
876 = do let isn = nub (namesIn ist ty ++ case sc of
877 (PRef _ x) -> namesIn ist sc `dropAll` [n]
879 (decls, ns) <- get -- ignore decls in HO types
880 put (PExp (getPriority ist ty) l ty : decls,
881 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
883 imps top env (PPi (Constraint l _) n ty sc)
884 = do let isn = nub (namesIn ist ty ++ case sc of
885 (PRef _ x) -> namesIn ist sc `dropAll` [n]
887 (decls, ns) <- get -- ignore decls in HO types
888 put (PConstraint 10 l ty : decls,
889 nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
891 imps top env (PEq _ l r)
892 = do (decls, ns) <- get
893 let isn = namesIn ist l ++ namesIn ist r
894 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
895 imps top env (PPair _ l r)
896 = do (decls, ns) <- get
897 let isn = namesIn ist l ++ namesIn ist r
898 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
899 imps top env (PDPair _ (PRef _ n) t r)
900 = do (decls, ns) <- get
901 let isn = nub (namesIn ist t ++ namesIn ist r) \\ [n]
902 put (decls, nub (ns ++ (isn \\ (env ++ map fst (getImps decls)))))
903 imps top env (PDPair _ l t r)
904 = do (decls, ns) <- get
905 let isn = namesIn ist l ++ namesIn ist t ++ namesIn ist r
906 put (decls, nub (ns ++ (isn \\ (env ++ map fst (getImps decls)))))
907 imps top env (PAlternative as)
908 = do (decls, ns) <- get
909 let isn = concatMap (namesIn ist) as
910 put (decls, nub (ns ++ (isn `dropAll` (env ++ map fst (getImps decls)))))
911 imps top env (PLam n ty sc)
912 = do imps False env ty
913 imps False (n:env) sc
914 imps top env (PHidden tm) = imps False env tm
915 imps top env _ = return ()
917 pibind using [] sc = sc
918 pibind using (n:ns) sc
919 = case lookup n using of
920 Just ty -> PPi (Imp False Dynamic) n ty (pibind using ns sc)
921 Nothing -> PPi (Imp False Dynamic) n Placeholder (pibind using ns sc)
923-- Add implicit arguments in function calls
925addImpl :: IState -> PTerm -> PTerm
926addImpl ist ptm = ai [] ptm
928 ai env (PRef fc f) = aiFn ist fc f []
929 ai env (PEq fc l r) = let l' = ai env l
932 ai env (PPair fc l r) = let l' = ai env l
935 ai env (PDPair fc l t r) = let l' = ai env l
939 ai env (PAlternative as) = let as' = map (ai env) as in
941 ai env (PApp fc (PRef _ f) as)
942 = let as' = map (fmap (ai env)) as in
944 ai env (PApp fc f as) = let f' = ai env f
945 as' = map (fmap (ai env)) as in
947 ai env (PLam n ty sc) = let ty' = ai env ty
948 sc' = ai (n:env) sc in
950 ai env (PLet n ty val sc)
951 = let ty' = ai env ty
953 sc' = ai (n:env) sc in
955 ai env (PPi p n ty sc) = let ty' = ai env ty
956 sc' = ai (n:env) sc in
958 ai env (PHidden tm) = PHidden (ai env tm)
959 ai env (PProof ts) = PProof (map (fmap (ai env)) ts)
960 ai env (PTactics ts) = PTactics (map (fmap (ai env)) ts)
963aiFn :: IState -> FC -> Name -> [PArg] -> PTerm
965 | f `elem` primNames = PApp fc (PRef fc f) as
967 -- This is where namespaces get resolved by adding PAlternative
968 = case lookupCtxtName Nothing f (idris_implicits ist) of
969 [(f',ns)] -> mkPApp fc (length ns) (PRef fc f') (insertImpl ns as)
970 [] -> mkPApp fc 1 (PRef fc f) as
971 alts -> PAlternative $
972 map (\(f', ns) -> mkPApp fc (length ns) (PRef fc f')
973 (insertImpl ns as)) alts
975 insertImpl :: [PArg] -> [PArg] -> [PArg]
976 insertImpl (PExp p l ty : ps) (PExp _ _ tm : given) =
977 PExp p l tm : insertImpl ps given
978 insertImpl (PConstraint p l ty : ps) (PConstraint _ _ tm : given) =
979 PConstraint p l tm : insertImpl ps given
980 insertImpl (PConstraint p l ty : ps) given =
981 PConstraint p l (PResolveTC fc) : insertImpl ps given
982 insertImpl (PImp p l n ty : ps) given =
983 case find n given [] of
984 Just (tm, given') -> PImp p l n tm : insertImpl ps given'
985 Nothing -> PImp p l n Placeholder : insertImpl ps given
986 insertImpl expected [] = []
987 insertImpl _ given = given
989 find n [] acc = Nothing
990 find n (PImp _ _ n' t : gs) acc
991 | n == n' = Just (t, reverse acc ++ gs)
992 find n (g : gs) acc = find n gs (g : acc)
995mkPApp fc a f as = let rest = drop a as in
996 appRest fc (PApp fc f (take a as)) rest
999 appRest fc f (a : as) = appRest fc (PApp fc f [a]) as
1001-- Find 'static' argument positions
1002-- (the declared ones, plus any names in argument position in the declared
1004-- FIXME: It's possible that this really has to happen after elaboration
1006findStatics :: IState -> PTerm -> (PTerm, [Bool])
1007findStatics ist tm = let (ns, ss) = fs tm in
1008 runState (pos ns ss tm) []
1009 where fs (PPi p n t sc)
1010 | Static <- pstatic p
1011 = let (ns, ss) = fs sc in
1012 (namesIn ist t : ns, namesIn ist t ++ n : ss)
1013 | otherwise = let (ns, ss) = fs sc in
1014 (namesIn ist t : ns, ss)
1017 inOne n ns = length (filter id (map (elem n) ns)) == 1
1019 pos ns ss (PPi p n t sc)
1020 | n `inOne` ns && elem n ss
1021 = do sc' <- pos ns ss sc
1024 return (PPi (p { pstatic = Static }) n t sc')
1025 | otherwise = do sc' <- pos ns ss sc
1028 return (PPi p n t sc')
1029 pos ns ss t = return t
1031-- Debugging/logging stuff
1033dumpDecls :: [PDecl] -> String
1035dumpDecls (d:ds) = dumpDecl d ++ "\n" ++ dumpDecls ds
1037dumpDecl (PFix _ f ops) = show f ++ " " ++ showSep ", " ops
1038dumpDecl (PTy _ _ n t) = "tydecl " ++ show n ++ " : " ++ showImp True t
1039dumpDecl (PClauses _ _ n cs) = "pat " ++ show n ++ "\t" ++ showSep "\n\t" (map (showCImp True) cs)
1040dumpDecl (PData _ _ d) = showDImp True d
1041dumpDecl (PParams _ ns ps) = "params {" ++ show ns ++ "\n" ++ dumpDecls ps ++ "}\n"
1042dumpDecl (PNamespace n ps) = "namespace {" ++ n ++ "\n" ++ dumpDecls ps ++ "}\n"
1043dumpDecl (PSyntax _ syn) = "syntax " ++ show syn
1044dumpDecl (PClass _ _ cs n ps ds)
1045 = "class " ++ show cs ++ " " ++ show n ++ " " ++ show ps ++ "\n" ++ dumpDecls ds
1046dumpDecl (PInstance _ _ cs n _ t ds)
1047 = "instance " ++ show cs ++ " " ++ show n ++ " " ++ show t ++ "\n" ++ dumpDecls ds
1049-- dumpDecl (PImport i) = "import " ++ i
1051-- syntactic match of a against b, returning pair of variables in a
1052-- and what they match. Returns 'Nothing' if not a match.
1054matchClause :: PTerm -> PTerm -> Maybe [(Name, PTerm)]
1055matchClause x y = match x y where
1056 matchArg x y = match (getTm x) (getTm y)
1058 match (PApp _ f args) (PApp _ f' args')
1059 | length args == length args'
1060 = do mf <- match f f'
1061 ms <- zipWithM matchArg args args'
1062 return (mf ++ concat ms)
1063-- match (PRef _ n) (PRef _ n') | n == n' = return []
1064-- | otherwise = Nothing
1065 match (PRef _ n) tm = return [(n, tm)]
1066 match (PEq _ l r) (PEq _ l' r') = do ml <- match l l'
1069 match (PPair _ l r) (PPair _ l' r') = do ml <- match l l'
1072 match (PDPair _ l t r) (PDPair _ l' t' r') = do ml <- match l l'
1075 return (ml ++ mt ++ mr)
1076 match (PAlternative as) (PAlternative as')
1077 = do ms <- zipWithM match as as'
1079 match (PRefl _) (PRefl _) = return []
1080 match (PResolveTC _) (PResolveTC _) = return []
1081 match (PTrue _) (PTrue _) = return []
1082 match (PFalse _) (PFalse _) = return []
1083 match (PReturn _) (PReturn _) = return []
1084 match (PPi _ _ t s) (PPi _ _ t' s') = do mt <- match t t'
1087 match (PLam _ t s) (PLam _ t' s') = do mt <- match t t'
1090 match (PHidden x) (PHidden y) = match x y
1091 match a b | a == b = return []
1092 | otherwise = Nothing
1094substMatches :: [(Name, PTerm)] -> PTerm -> PTerm
1095substMatches [] t = t
1096substMatches ((n,tm):ns) t = substMatch n tm (substMatches ns t)
1098substMatch :: Name -> PTerm -> PTerm -> PTerm
1099substMatch n tm t = sm t where
1100 sm (PRef _ n') | n == n' = tm
1101 sm (PLam x t sc) = PLam x (sm t) (sm sc)
1102 sm (PPi p x t sc) = PPi p x (sm t) (sm sc)
1103 sm (PApp f x as) = PApp f (sm x) (map (fmap sm) as)
1104 sm (PEq f x y) = PEq f (sm x) (sm y)
1105 sm (PPair f x y) = PPair f (sm x) (sm y)
1106 sm (PDPair f x t y) = PDPair f (sm x) (sm t) (sm y)
1107 sm (PAlternative as) = PAlternative (map sm as)
1108 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