1{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, DeriveFunctor #-}
3{-| TT is the core language of Idris. The language has:
7 * A hierarchy of universes, with cumulativity: Type : Type1, Type1 : Type2, ...
9 * Pattern matching letrec binding
11 * (primitive types defined externally)
15 * Typechecker is kept as simple as possible - no unification, just a checker for incomplete terms.
17 * We have a simple collection of tactics which we use to elaborate source
18 programs with implicit syntax into fully explicit terms.
23import Control.Monad.State
24import Control.Monad.Trans.Error (Error(..))
26import qualified Data.Map as Map
29import Data.Vector.Unboxed (Vector)
30import qualified Data.Vector.Unboxed as V
31import qualified Data.Binary as B
32import Data.Binary hiding (get, put)
33import Foreign.Storable (sizeOf)
35import Util.Pretty hiding (Str)
37data Option = TTypeInTType
41-- | Source location. These are typically produced by the parser 'Idris.Parser.pfc'
42data FC = FC { fc_fname :: String, -- ^ Filename
43 fc_line :: Int -- ^ Line number
47deriving instance Binary FC
50instance Sized FC where
51 size (FC f l) = 1 + length f
54 show (FC f l) = f ++ ":" ++ show l
58 | CantUnify Bool Term Term Err [(Name, Type)] Int
59 -- Int is 'score' - how much we did unify
60 -- Bool indicates recoverability, True indicates more info may make
61 -- unification succeed
62 | InfiniteUnify Name Term [(Name, Type)]
63 | CantConvert Term Term [(Name, Type)]
64 | UnifyScope Name Name Term [(Name, Type)]
65 | CantInferType String
66 | NonFunctionType Term Term
70 | NotInjective Term Term Term
72 | CantResolveAlts [String]
77 | NonCollapsiblePostulate Name
82 | Elaborating String Name Err
83 | ProviderError String
86instance Sized Err where
87 size (Msg msg) = length msg
88 size (InternalMsg msg) = length msg
89 size (CantUnify _ left right err _ score) = size left + size right + size err
90 size (InfiniteUnify _ right _) = size right
91 size (CantConvert left right _) = size left + size right
92 size (UnifyScope _ _ right _) = size right
93 size (NoSuchVariable name) = size name
94 size (NoTypeDecl name) = size name
95 size (NotInjective l c r) = size l + size c + size r
96 size (CantResolve trm) = size trm
97 size (NoRewriting trm) = size trm
98 size (CantResolveAlts _) = 1
99 size (IncompleteTerm trm) = size trm
100 size UniverseError = 1
101 size ProgramLineComment = 1
102 size (At fc err) = size fc + size err
103 size (Elaborating _ n err) = size err
104 size (ProviderError msg) = length msg
108score (CantUnify _ _ _ m _ s) = s + score m
109score (CantResolve _) = 20
110score (NoSuchVariable _) = 1000
111score (ProofSearchFail _) = 10000
112score (InternalMsg _) = -1
115instance Show Err where
117 show (InternalMsg s) = "Internal error: " ++ show s
118 show (CantUnify _ l r e sc i) = "CantUnify " ++ show l ++ " " ++ show r ++ " "
119 ++ show e ++ " in " ++ show sc ++ " " ++ show i
120 show (Inaccessible n) = show n ++ " is not an accessible pattern variable"
121 show (ProviderError msg) = "Type provider error: " ++ msg
124instance Pretty Err where
125 pretty (Msg m) = text m
126 pretty (CantUnify _ l r e _ i) =
127 if size l + size r > breakingSize then
128 text "Cannot unify" <+> colon $$
129 nest nestingSize (pretty l <+> text "and" <+> pretty r) $$
130 nest nestingSize (text "where" <+> pretty e <+> text "with" <+> (text . show $ i))
132 text "Cannot unify" <+> colon <+> pretty l <+> text "and" <+> pretty r $$
133 nest nestingSize (text "where" <+> pretty e <+> text "with" <+> (text . show $ i))
134 pretty (ProviderError msg) = text msg
135 pretty _ = text "Error"
137instance Error Err where
142 deriving (Eq, Functor)
144instance Pretty a => Pretty (TC a) where
145 pretty (OK ok) = pretty ok
147 if size err > breakingSize then
148 text "Error" <+> colon $$ (nest nestingSize $ pretty err)
150 text "Error" <+> colon <+> pretty err
152instance Show a => Show (TC a) where
154 show (Error str) = "Error: " ++ show str
156-- at some point, this instance should also carry type checking options
159instance Monad TC where
164 fail e = Error (InternalMsg e)
169trun :: FC -> TC a -> TC a
171trun fc (Error e) = Error (At fc e)
173instance MonadPlus TC where
174 mzero = fail "Unknown error"
175 (OK x) `mplus` _ = OK x
176 _ `mplus` (OK y) = OK y
179discard :: Monad m => m a -> m ()
180discard f = f >> return ()
182showSep :: String -> [String] -> String
185showSep sep (x:xs) = x ++ sep ++ showSep sep xs
187pmap f (x, y) = (f x, f y)
189traceWhen True msg a = trace msg a
190traceWhen False _ a = a
192-- RAW TERMS ----------------------------------------------------------------
194-- | Names are hierarchies of strings, describing scope (so no danger of
195-- duplicate names, but need to be careful on lookup).
196data Name = UN String -- ^ User-provided name
197 | NS Name [String] -- ^ Root, namespaces
198 | MN Int String -- ^ Machine chosen names
199 | NErased -- ^ Name of somethng which is never used in scope
200 | SN SpecialName -- ^ Decorated function names
203deriving instance Binary Name
206data SpecialName = WhereN Int Name Name
207 | InstanceN Name [String]
208 | ParentN Name String
213deriving instance Binary SpecialName
216instance Sized Name where
218 size (NS n els) = 1 + length els
222instance Pretty Name where
223 pretty (UN n) = text n
224 pretty (NS n s) = pretty n
225 pretty (MN i s) = lbrace <+> text s <+> (text . show $ i) <+> rbrace
226 pretty (SN s) = text (show s)
228instance Show Name where
230 show (NS n s) = showSep "." (reverse s) ++ "." ++ show n
231 show (MN _ "underscore") = "_"
232 show (MN i s) = "{" ++ s ++ show i ++ "}"
236instance Show SpecialName where
237 show (WhereN i p c) = show p ++ ", " ++ show c
238 show (InstanceN cl inst) = showSep ", " inst ++ " instance of " ++ show cl
239 show (MethodN m) = "method " ++ show m
240 show (ParentN p c) = show p ++ "#" ++ c
241 show (CaseN n) = "case block in " ++ show n
243-- Show a name in a way decorated for code generation, not human reading
244showCG :: Name -> String
246showCG (NS n s) = showSep "." (reverse s) ++ "." ++ show n
247showCG (MN _ "underscore") = "_"
248showCG (MN i s) = "{" ++ s ++ show i ++ "}"
249showCG (SN s) = showCG' s
250 where showCG' (WhereN i p c) = show p ++ ":" ++ show c ++ ":" ++ show i
251 showCG' (InstanceN cl inst) = '@':show cl ++ '$':showSep ":" inst
252 showCG' (MethodN m) = '!':show m
253 showCG' (ParentN p c) = show p ++ "#" ++ show c
254 showCG' (CaseN c) = show c ++ "_case"
258-- |Contexts allow us to map names to things. A root name maps to a collection
259-- of things in different namespaces with that name.
260type Ctxt a = Map.Map Name (Map.Map Name a)
261emptyContext = Map.empty
263tcname (UN ('@':_)) = True
264tcname (NS n _) = tcname n
265tcname (SN (InstanceN _ _)) = True
266tcname (SN (MethodN _)) = True
267tcname (SN (ParentN _ _)) = True
270implicitable (NS n _) = implicitable n
271implicitable (UN (x:xs)) = isLower x
272implicitable _ = False
277addDef :: Name -> a -> Ctxt a -> Ctxt a
278addDef n v ctxt = case Map.lookup (nsroot n) ctxt of
279 Nothing -> Map.insert (nsroot n)
280 (Map.insert n v Map.empty) ctxt
281 Just xs -> Map.insert (nsroot n)
282 (Map.insert n v xs) ctxt
284{-| Look up a name in the context, given an optional namespace.
285 The name (n) may itself have a (partial) namespace given.
287 Rules for resolution:
289 - if an explicit namespace is given, return the names which match it. If none
290 match, return all names.
292 - if the name has has explicit namespace given, return the names which match it
293 and ignore the given namespace.
295 - otherwise, return all names.
299lookupCtxtName :: Name -> Ctxt a -> [(Name, a)]
300lookupCtxtName n ctxt = case Map.lookup (nsroot n) ctxt of
301 Just xs -> filterNS (Map.toList xs)
305 filterNS ((found, v) : xs)
306 | nsmatch n found = (found, v) : filterNS xs
307 | otherwise = filterNS xs
309 nsmatch (NS n ns) (NS p ps) = ns `isPrefixOf` ps
310 nsmatch (NS _ _) _ = False
311 nsmatch looking found = True
313lookupCtxt :: Name -> Ctxt a -> [a]
314lookupCtxt n ctxt = map snd (lookupCtxtName n ctxt)
316lookupCtxtExact :: Name -> Ctxt a -> [a]
317lookupCtxtExact n ctxt = [ v | (nm, v) <- lookupCtxtName n ctxt, nm == n]
319updateDef :: Name -> (a -> a) -> Ctxt a -> Ctxt a
321 = let ds = lookupCtxtName n ctxt in
322 foldr (\ (n, t) c -> addDef n (f t) c) ctxt ds
324toAlist :: Ctxt a -> [(Name, a)]
325toAlist ctxt = let allns = map snd (Map.toList ctxt) in
326 concat (map (Map.toList) allns)
328addAlist :: Show a => [(Name, a)] -> Ctxt a -> Ctxt a
329addAlist [] ctxt = ctxt
330addAlist ((n, tm) : ds) ctxt = addDef n tm (addAlist ds ctxt)
332data NativeTy = IT8 | IT16 | IT32 | IT64
333 deriving (Show, Eq, Ord, Enum)
335instance Pretty NativeTy where
336 pretty IT8 = text "Bits8"
337 pretty IT16 = text "Bits16"
338 pretty IT32 = text "Bits32"
339 pretty IT64 = text "Bits64"
341data IntTy = ITFixed NativeTy | ITNative | ITBig | ITChar
343 deriving (Show, Eq, Ord)
345data ArithTy = ATInt IntTy | ATFloat -- TODO: Float vectors
346 deriving (Show, Eq, Ord)
348instance Pretty ArithTy where
349 pretty (ATInt ITNative) = text "Int"
350 pretty (ATInt ITBig) = text "BigInt"
351 pretty (ATInt ITChar) = text "Char"
352 pretty (ATInt (ITFixed n)) = pretty n
353 pretty (ATInt (ITVec e c)) = pretty e <> text "x" <> (text . show $ c)
354 pretty ATFloat = text "Float"
356nativeTyWidth :: NativeTy -> Int
358nativeTyWidth IT16 = 16
359nativeTyWidth IT32 = 32
360nativeTyWidth IT64 = 64
362{-# DEPRECATED intTyWidth "Non-total function, use nativeTyWidth and appropriate casing" #-}
363intTyWidth :: IntTy -> Int
364intTyWidth (ITFixed n) = nativeTyWidth n
365intTyWidth ITNative = 8 * sizeOf (0 :: Int)
366intTyWidth ITChar = error "IRTS.Lang.intTyWidth: Characters have platform and backend dependent width"
367intTyWidth ITBig = error "IRTS.Lang.intTyWidth: Big integers have variable width"
369data Const = I Int | BI Integer | Fl Double | Ch Char | Str String
370 | B8 Word8 | B16 Word16 | B32 Word32 | B64 Word64
371 | B8V (Vector Word8) | B16V (Vector Word16)
372 | B32V (Vector Word32) | B64V (Vector Word64)
373 | AType ArithTy | StrType
374 | PtrType | VoidType | Forgot
377deriving instance Binary Const
380instance Sized Const where
383instance Pretty Const where
384 pretty (I i) = text . show $ i
385 pretty (BI i) = text . show $ i
386 pretty (Fl f) = text . show $ f
387 pretty (Ch c) = text . show $ c
388 pretty (Str s) = text s
389 pretty (AType a) = pretty a
390 pretty StrType = text "String"
391 pretty PtrType = text "Ptr"
392 pretty VoidType = text "Void"
393 pretty Forgot = text "Forgot"
394 pretty (B8 w) = text . show $ w
395 pretty (B16 w) = text . show $ w
396 pretty (B32 w) = text . show $ w
397 pretty (B64 w) = text . show $ w
400 | RBind Name (Binder Raw) Raw
407instance Sized Raw where
409 size (RBind name bind right) = 1 + size bind + size right
410 size (RApp left right) = 1 + size left + size right
412 size (RForce raw) = 1 + size raw
413 size (RConstant const) = size const
415instance Pretty Raw where
419deriving instance Binary Raw
422-- | All binding forms are represented in a unform fashion.
423data Binder b = Lam { binderTy :: b {-^ type annotation for bound variable-}}
424 | Pi { binderTy :: b }
425 | Let { binderTy :: b,
426 binderVal :: b {-^ value for bound variable-}}
427 | NLet { binderTy :: b,
429 | Hole { binderTy :: b}
430 | GHole { binderTy :: b}
431 | Guess { binderTy :: b,
433 | PVar { binderTy :: b }
434 | PVTy { binderTy :: b }
435 deriving (Show, Eq, Ord, Functor)
437deriving instance Binary Binder
440instance Sized a => Sized (Binder a) where
441 size (Lam ty) = 1 + size ty
442 size (Pi ty) = 1 + size ty
443 size (Let ty val) = 1 + size ty + size val
444 size (NLet ty val) = 1 + size ty + size val
445 size (Hole ty) = 1 + size ty
446 size (GHole ty) = 1 + size ty
447 size (Guess ty val) = 1 + size ty + size val
448 size (PVar ty) = 1 + size ty
449 size (PVTy ty) = 1 + size ty
451fmapMB :: Monad m => (a -> m b) -> Binder a -> m (Binder b)
452fmapMB f (Let t v) = liftM2 Let (f t) (f v)
453fmapMB f (NLet t v) = liftM2 NLet (f t) (f v)
454fmapMB f (Guess t v) = liftM2 Guess (f t) (f v)
455fmapMB f (Lam t) = liftM Lam (f t)
456fmapMB f (Pi t) = liftM Pi (f t)
457fmapMB f (Hole t) = liftM Hole (f t)
458fmapMB f (GHole t) = liftM GHole (f t)
459fmapMB f (PVar t) = liftM PVar (f t)
460fmapMB f (PVTy t) = liftM PVTy (f t)
462raw_apply :: Raw -> [Raw] -> Raw
464raw_apply f (a : as) = raw_apply (RApp f a) as
466raw_unapply :: Raw -> (Raw, [Raw])
467raw_unapply t = ua [] t where
468 ua args (RApp f a) = ua (a:args) f
469 ua args t = (t, args)
471data RawFun = RawFun { rtype :: Raw,
476data RawDatatype = RDatatype Name Raw [(Name, Raw)]
479data RDef = RFunction RawFun
484type RProgram = [(Name, RDef)]
486-- WELL TYPED TERMS ---------------------------------------------------------
488-- | Universe expressions for universe checking
489data UExp = UVar Int -- ^ universe variable
490 | UVal Int -- ^ explicit universe level
493instance Sized UExp where
496-- We assume that universe levels have been checked, so anything external
497-- can just have the same universe variable and we won't get any new
500instance Binary UExp where
502 get = return (UVar (-1))
504instance Show UExp where
505 show (UVar x) | x < 26 = [toEnum (x + fromEnum 'a')]
506 | otherwise = toEnum ((x `mod` 26) + fromEnum 'a') : show (x `div` 26)
507 show (UVal x) = show x
508-- show (UMax l r) = "max(" ++ show l ++ ", " ++ show r ++")"
510-- | Universe constraints
511data UConstraint = ULT UExp UExp -- ^ Strictly less than
512 | ULE UExp UExp -- ^ Less than or equal to
515instance Show UConstraint where
516 show (ULT x y) = show x ++ " < " ++ show y
517 show (ULE x y) = show x ++ " <= " ++ show y
519type UCs = (Int, [UConstraint])
523 | DCon Int Int -- ^ Data constructor; Ints are tag and arity
524 | TCon Int Int -- ^ Type constructor; Ints are tag and arity
527deriving instance Binary NameType
530instance Sized NameType where
533instance Pretty NameType where
536instance Eq NameType where
537 Bound == Bound = True
539 DCon _ a == DCon _ b = (a == b) -- ignore tag
540 TCon _ a == TCon _ b = (a == b) -- ignore tag
543-- | Terms in the core language
544data TT n = P NameType n (TT n) -- ^ named references
545 | V Int -- ^ a resolved de Bruijn-indexed variable
546 | Bind n (Binder (TT n)) (TT n) -- ^ a binding
547 | App (TT n) (TT n) -- ^ function, function type, arg
548 | Constant Const -- ^ constant
549 | Proj (TT n) Int -- ^ argument projection; runtime only
550 | Erased -- ^ an erased term
551 | Impossible -- ^ special case for totality checking
552 | TType UExp -- ^ the type of types at some level
553 deriving (Ord, Functor)
555deriving instance Binary TT
558class TermSize a where
559 termsize :: Name -> a -> Int
561instance TermSize a => TermSize [a] where
563 termsize n (x : xs) = termsize n x + termsize n xs
565instance TermSize (TT Name) where
567 | x == n = 1000000 -- recursive => really big
570 termsize n (Bind n' (Let t v) sc)
571 = let rn = if n == n' then MN 0 "noname" else n in
572 termsize rn v + termsize rn sc
573 termsize n (Bind n' b sc)
574 = let rn = if n == n' then MN 0 "noname" else n in
576 termsize n (App f a) = termsize n f + termsize n a
577 termsize n (Proj t i) = termsize n t
580instance Sized a => Sized (TT a) where
581 size (P name n trm) = 1 + size name + size n + size trm
583 size (Bind nm binder bdy) = 1 + size nm + size binder + size bdy
584 size (App l r) = 1 + size l + size r
585 size (Constant c) = size c
587 size (TType u) = 1 + size u
589instance Pretty a => Pretty (TT a) where
590 pretty _ = text "test"
592type EnvTT n = [(n, Binder (TT n))]
594data Datatype n = Data { d_typename :: n,
597 d_cons :: [(n, TT n)] }
598 deriving (Show, Functor, Eq)
600instance Eq n => Eq (TT n) where
601 (==) (P xt x _) (P yt y _) = x == y
602 (==) (V x) (V y) = x == y
603 (==) (Bind _ xb xs) (Bind _ yb ys) = xb == yb && xs == ys
604 (==) (App fx ax) (App fy ay) = fx == fy && ax == ay
605 (==) (TType _) (TType _) = True -- deal with constraints later
606 (==) (Constant x) (Constant y) = x == y
607 (==) (Proj x i) (Proj y j) = x == y && i == j
612-- * A few handy operations on well typed terms:
614-- | A term is injective iff it is a data constructor, type constructor,
615-- constant, the type Type, pi-binding, or an application of an injective
617isInjective :: TT n -> Bool
618isInjective (P (DCon _ _) _ _) = True
619isInjective (P (TCon _ _) _ _) = True
620isInjective (Constant _) = True
621isInjective (TType x) = True
622isInjective (Bind _ (Pi _) sc) = True
623isInjective (App f a) = isInjective f
626-- | Count the number of instances of a de Bruijn index in a term
627vinstances :: Int -> TT n -> Int
628vinstances i (V x) | i == x = 1
629vinstances i (App f a) = vinstances i f + vinstances i a
630vinstances i (Bind x b sc) = instancesB b + vinstances (i + 1) sc
631 where instancesB (Let t v) = vinstances i v
635instantiate :: TT n -> TT n -> TT n
636instantiate e = subst 0 where
637 subst i (V x) | i == x = e
638 subst i (Bind x b sc) = Bind x (fmap (subst i) b) (subst (i+1) sc)
639 subst i (App f a) = App (subst i f) (subst i a)
640 subst i (Proj x idx) = Proj (subst i x) idx
643substV :: TT n -> TT n -> TT n
644substV x tm = dropV 0 (instantiate x tm) where
645 dropV i (V x) | x > i = V (x - 1)
647 dropV i (Bind x b sc) = Bind x (fmap (dropV i) b) (dropV (i+1) sc)
648 dropV i (App f a) = App (dropV i f) (dropV i a)
649 dropV i (Proj x idx) = Proj (dropV i x) idx
652explicitNames :: TT n -> TT n
653explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
655 (explicitNames (instantiate
656 (P Bound x (binderTy b')) sc))
657explicitNames (App f a) = App (explicitNames f) (explicitNames a)
658explicitNames (Proj x idx) = Proj (explicitNames x) idx
661pToV :: Eq n => n -> TT n -> TT n
663pToV' n i (P _ x _) | n == x = V i
664pToV' n i (Bind x b sc)
665-- We can assume the inner scope has been pToVed already, so continue to
666-- resolve names from the *outer* scope which may happen to have the same id.
667 | n == x = Bind x (fmap (pToV' n i) b) sc
668 | otherwise = Bind x (fmap (pToV' n i) b) (pToV' n (i+1) sc)
669pToV' n i (App f a) = App (pToV' n i f) (pToV' n i a)
670pToV' n i (Proj t idx) = Proj (pToV' n i t) idx
673-- increase de Bruijn indices, as if a binder has been added
674addBinder :: TT n -> TT n
677 ab top (V i) | i >= top = V (i + 1)
679 ab top (Bind x b sc) = Bind x (fmap (ab top) b) (ab (top + 1) sc)
680 ab top (App f a) = App (ab top f) (ab top a)
681 ab top (Proj t idx) = Proj (ab top t) idx
684-- | Convert several names. First in the list comes out as V 0
685pToVs :: Eq n => [n] -> TT n -> TT n
686pToVs ns tm = pToVs' ns tm 0 where
688 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
692 vToP' env (V i) = let (n, b) = (env !! i) in
693 P Bound n (binderTy b)
694 vToP' env (Bind n b sc) = let b' = fmap (vToP' env) b in
695 Bind n b' (vToP' ((n, b'):env) sc)
696 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
699finalise :: Eq n => TT n -> TT n
700finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
701finalise (App f a) = App (finalise f) (finalise a)
704subst :: Eq n => n -> TT n -> TT n -> TT n
705subst n v tm = instantiate v (pToV n tm)
707substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
709substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
711substTerm :: Eq n => TT n -> TT n -> TT n -> TT n
712substTerm old new = st where
713 st t | t == old = new
714 st (App f a) = App (st f) (st a)
715 st (Bind x b sc) = Bind x (fmap st b) (st sc)
718-- Returns true if V 0 and bound name n do not occur in the term
720noOccurrence :: Eq n => n -> TT n -> Bool
721noOccurrence n t = no' 0 t
723 no' i (V x) = not (i == x)
724 no' i (P Bound x _) = not (n == x)
725 no' i (Bind n b sc) = noB' i b && no' (i+1) sc
726 where noB' i (Let t v) = no' i t && no' i v
727 noB' i (Guess t v) = no' i t && no' i v
728 noB' i b = no' i (binderTy b)
729 no' i (App f a) = no' i f && no' i a
730 no' i (Proj x _) = no' i x
733-- | Returns all names used free in the term
734freeNames :: Eq n => TT n -> [n]
735freeNames (P _ n _) = [n]
736freeNames (Bind n (Let t v) sc) = nub $ freeNames v ++ (freeNames sc \\ [n])
738freeNames (Bind n b sc) = nub $ freeNames (binderTy b) ++ (freeNames sc \\ [n])
739freeNames (App f a) = nub $ freeNames f ++ freeNames a
740freeNames (Proj x i) = nub $ freeNames x
743-- | Return the arity of a (normalised) type
745arity (Bind n (Pi t) sc) = 1 + arity sc
748-- | Deconstruct an application; returns the function and a list of arguments
749unApply :: TT n -> (TT n, [TT n])
750unApply t = ua [] t where
751 ua args (App f a) = ua (a:args) f
752 ua args t = (t, args)
754mkApp :: TT n -> [TT n] -> TT n
756mkApp f (a:as) = mkApp (App f a) as
758forget :: TT Name -> Raw
761 fe env (P _ n _) = Var n
762 fe env (V i) = Var (env !! i)
763 fe env (Bind n b sc) = RBind n (fmap (fe env) b)
765 fe env (App f a) = RApp (fe env f) (fe env a)
768 fe env (TType i) = RType
769 fe env Erased = RConstant Forgot
771bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
773bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
775bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
776bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
778getArgTys :: TT n -> [(n, TT n)]
779getArgTys (Bind n (Pi t) sc) = (n, t) : getArgTys sc
782getRetTy :: TT n -> TT n
783getRetTy (Bind n (PVar _) sc) = getRetTy sc
784getRetTy (Bind n (PVTy _) sc) = getRetTy sc
785getRetTy (Bind n (Pi _) sc) = getRetTy sc
788uniqueName :: Name -> [Name] -> Name
789uniqueName n hs | n `elem` hs = uniqueName (nextName n) hs
792uniqueBinders :: [Name] -> TT Name -> TT Name
793uniqueBinders ns (Bind n b sc)
794 = let n' = uniqueName n ns in
795 Bind n' (fmap (uniqueBinders (n':ns)) b) (uniqueBinders ns sc)
796uniqueBinders ns (App f a) = App (uniqueBinders ns f) (uniqueBinders ns a)
797uniqueBinders ns t = t
800nextName (NS x s) = NS (nextName x) s
801nextName (MN i n) = MN (i+1) n
802nextName (UN x) = let (num', nm') = span isDigit (reverse x)
804 num = readN (reverse num') in
805 UN (nm ++ show (num+1))
809nextName (SN x) = SN (nextName' x)
811 nextName' (WhereN i f x) = WhereN i f (nextName x)
812 nextName' (CaseN n) = CaseN (nextName n)
813 nextName' (MethodN n) = MethodN (nextName n)
820-- an environment with de Bruijn indices 'normalised' so that they all refer to
823newtype WkEnvTT n = Wk (EnvTT n)
824type WkEnv = WkEnvTT Name
826instance (Eq n, Show n) => Show (TT n) where
827 show t = showEnv [] t
829itBitsName IT8 = "Bits8"
830itBitsName IT16 = "Bits16"
831itBitsName IT32 = "Bits32"
832itBitsName IT64 = "Bits64"
834instance Show Const where
839 show (Str s) = show s
841 show (B16 x) = show x
842 show (B32 x) = show x
843 show (B64 x) = show x
844 show (B8V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
845 show (B16V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
846 show (B32V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
847 show (B64V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
848 show (AType ATFloat) = "Float"
849 show (AType (ATInt ITBig)) = "Integer"
850 show (AType (ATInt ITNative)) = "Int"
851 show (AType (ATInt ITChar)) = "Char"
852 show (AType (ATInt (ITFixed it))) = itBitsName it
853 show (AType (ATInt (ITVec it c))) = itBitsName it ++ "x" ++ show c
854 show StrType = "String"
856 show VoidType = "Void"
858showEnv env t = showEnv' env t False
859showEnvDbg env t = showEnv' env t True
861prettyEnv env t = prettyEnv' env t False
863 prettyEnv' env t dbg = prettySe 10 env t dbg
865 bracket outer inner p
866 | inner > outer = lparen <> p <> rparen
869 prettySe p env (P nt n t) debug =
872 lbrack <+> pretty nt <+> colon <+> prettySe 10 env t debug <+> rbrack
875 prettySe p env (V i) debug
878 text . show . fst $ env!!i
880 lbrack <+> text (show i) <+> rbrack
881 | otherwise = text "unbound" <+> text (show i) <+> text "!"
882 prettySe p env (Bind n b@(Pi t) sc) debug
883 | noOccurrence n sc && not debug =
884 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
885 prettySe p env (Bind n b sc) debug =
886 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
887 prettySe p env (App f a) debug =
888 bracket p 1 $ prettySe 1 env f debug <+> prettySe 0 env a debug
889 prettySe p env (Proj x i) debug =
890 prettySe 1 env x debug <+> text ("!" ++ show i)
891 prettySe p env (Constant c) debug = pretty c
892 prettySe p env Erased debug = text "[_]"
893 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
895 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
896 prettySb env n (Hole t) = prettyB env "?defer" "." n t
897 prettySb env n (Pi t) = prettyB env "(" ") ->" n t
898 prettySb env n (PVar t) = prettyB env "pat" "." n t
899 prettySb env n (PVTy t) = prettyB env "pty" "." n t
900 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
901 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
903 prettyB env op sc n t debug =
904 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
906 prettyBv env op sc n t v debug =
907 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
908 prettySe 10 env v debug <> text sc
911showEnv' env t dbg = se 10 env t where
912 se p env (P nt n t) = show n
913 ++ if dbg then "{" ++ show nt ++ " : " ++ se 10 env t ++ "}" else ""
914 se p env (V i) | i < length env && i >= 0
915 = (show $ fst $ env!!i) ++
916 if dbg then "{" ++ show i ++ "}" else ""
917 | otherwise = "!!V " ++ show i ++ "!!"
918 se p env (Bind n b@(Pi t) sc)
919 | noOccurrence n sc && not dbg = bracket p 2 $ se 1 env t ++ " -> " ++ se 10 ((n,b):env) sc
920 se p env (Bind n b sc) = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
921 se p env (App f a) = bracket p 1 $ se 1 env f ++ " " ++ se 0 env a
922 se p env (Proj x i) = se 1 env x ++ "!" ++ show i
923 se p env (Constant c) = show c
924 se p env Erased = "[__]"
925 se p env Impossible = "[impossible]"
926 se p env (TType i) = "Type " ++ show i
928 sb env n (Lam t) = showb env "\\ " " => " n t
929 sb env n (Hole t) = showb env "? " ". " n t
930 sb env n (GHole t) = showb env "?defer " ". " n t
931 sb env n (Pi t) = showb env "(" ") -> " n t
932 sb env n (PVar t) = showb env "pat " ". " n t
933 sb env n (PVTy t) = showb env "pty " ". " n t
934 sb env n (Let t v) = showbv env "let " " in " n t v
935 sb env n (Guess t v) = showbv env "?? " " in " n t v
937 showb env op sc n t = op ++ show n ++ " : " ++ se 10 env t ++ sc
938 showbv env op sc n t v = op ++ show n ++ " : " ++ se 10 env t ++ " = " ++
941 bracket outer inner str | inner > outer = "(" ++ str ++ ")"
944-- | Check whether a term has any holes in it - impure if so
945pureTerm :: TT Name -> Bool
946pureTerm (App f a) = pureTerm f && pureTerm a
947pureTerm (Bind n b sc) = notClassName n && pureBinder b && pureTerm sc where
948 pureBinder (Hole _) = False
949 pureBinder (Guess _ _) = False
950 pureBinder (Let t v) = pureTerm t && pureTerm v
951 pureBinder t = pureTerm (binderTy t)
953 notClassName (MN _ "class") = False
954 notClassName _ = True
958-- | Weaken a term by adding i to each de Bruijn index (i.e. lift it over i bindings)
959weakenTm :: Int -> TT n -> TT n
960weakenTm i t = wk i 0 t
961 where wk i min (V x) | x >= min = V (i + x)
962 wk i m (App f a) = App (wk i m f) (wk i m a)
963 wk i m (Bind x b sc) = Bind x (wkb i m b) (wk i (m + 1) sc)
965 wkb i m t = fmap (wk i m) t
967-- | Weaken an environment so that all the de Bruijn indices are correct according
968-- to the latest bound variable
970weakenEnv :: EnvTT n -> EnvTT n
971weakenEnv env = wk (length env - 1) env
973 wk i ((n, b) : bs) = (n, weakenTmB i b) : wk (i - 1) bs
974 weakenTmB i (Let t v) = Let (weakenTm i t) (weakenTm i v)
975 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
976 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
978weakenTmEnv :: Int -> EnvTT n -> EnvTT n
979weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
981orderPats :: Term -> Term
982orderPats tm = op [] tm
984 op ps (Bind n (PVar t) sc) = op ((n, PVar t) : ps) sc
985 op ps (Bind n (Hole t) sc) = op ((n, Hole t) : ps) sc
986 op ps sc = bindAll (map (\ (n, t) -> (n, t)) (sortP ps)) sc
988 sortP ps = pick [] (reverse ps)
990 namesIn (P _ n _) = [n]
991 namesIn (Bind n b t) = nub $ nb b ++ (namesIn t \\ [n])
992 where nb (Let t v) = nub (namesIn t) ++ nub (namesIn v)
993 nb (Guess t v) = nub (namesIn t) ++ nub (namesIn v)
994 nb t = namesIn (binderTy t)
995 namesIn (App f a) = nub (namesIn f ++ namesIn a)
998 pick acc [] = reverse acc
999 pick acc ((n, t) : ps) = pick (insert n t acc) ps
1001 insert n t [] = [(n, t)]
1002 insert n t ((n',t') : ps)
1003 | n `elem` (namesIn (binderTy t') ++
1004 concatMap namesIn (map (binderTy . snd) ps))
1005 = (n', t') : insert n t ps
1006 | otherwise = (n,t):(n',t'):ps
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