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.getFC'
42data FC = FC { fc_fname :: String, -- ^ Filename
43 fc_line :: Int, -- ^ Line number
44 fc_column :: Int -- ^ Column number
47-- | Ignore source location equality (so deriving classes do not compare FCs)
52newtype FC' = FC' { unwrapFC :: FC }
55 FC' fc == FC' fc' = fcEq fc fc'
56 where fcEq (FC n l c) (FC n' l' c') = n == n' && l == l' && c == c'
58-- | Empty source location
62-- | Source location with file only
67deriving instance Binary FC
68deriving instance NFData FC
71instance Sized FC where
72 size (FC f l c) = 1 + length f
75 show (FC f l c) = f ++ ":" ++ show l ++ ":" ++ show c
79 | CantUnify Bool Term Term Err [(Name, Type)] Int
80 -- Int is 'score' - how much we did unify
81 -- Bool indicates recoverability, True indicates more info may make
82 -- unification succeed
83 | InfiniteUnify Name Term [(Name, Type)]
84 | CantConvert Term Term [(Name, Type)]
85 | UnifyScope Name Name Term [(Name, Type)]
86 | CantInferType String
87 | NonFunctionType Term Term
91 | NotInjective Term Term Term
93 | CantResolveAlts [String]
98 | NonCollapsiblePostulate Name
100 | ProofSearchFail Err
103 | Elaborating String Name Err
104 | ProviderError String
105 | LoadingFailed String Err
108deriving instance NFData Err
111instance Sized Err where
112 size (Msg msg) = length msg
113 size (InternalMsg msg) = length msg
114 size (CantUnify _ left right err _ score) = size left + size right + size err
115 size (InfiniteUnify _ right _) = size right
116 size (CantConvert left right _) = size left + size right
117 size (UnifyScope _ _ right _) = size right
118 size (NoSuchVariable name) = size name
119 size (NoTypeDecl name) = size name
120 size (NotInjective l c r) = size l + size c + size r
121 size (CantResolve trm) = size trm
122 size (NoRewriting trm) = size trm
123 size (CantResolveAlts _) = 1
124 size (IncompleteTerm trm) = size trm
125 size UniverseError = 1
126 size ProgramLineComment = 1
127 size (At fc err) = size fc + size err
128 size (Elaborating _ n err) = size err
129 size (ProviderError msg) = length msg
130 size (LoadingFailed fn e) = 1 + length fn + size e
134score (CantUnify _ _ _ m _ s) = s + score m
135score (CantResolve _) = 20
136score (NoSuchVariable _) = 1000
137score (ProofSearchFail _) = 10000
138score (InternalMsg _) = -1
141instance Show Err where
143 show (InternalMsg s) = "Internal error: " ++ show s
144 show (CantUnify _ l r e sc i) = "CantUnify " ++ show l ++ " " ++ show r ++ " "
145 ++ show e ++ " in " ++ show sc ++ " " ++ show i
146 show (Inaccessible n) = show n ++ " is not an accessible pattern variable"
147 show (ProviderError msg) = "Type provider error: " ++ msg
148 show (LoadingFailed fn e) = "Loading " ++ fn ++ " failed: " ++ show e
151instance Pretty Err where
152 pretty (Msg m) = text m
153 pretty (CantUnify _ l r e _ i) =
154 if size l + size r > breakingSize then
155 text "Cannot unify" <+> colon $$
156 nest nestingSize (pretty l <+> text "and" <+> pretty r) $$
157 nest nestingSize (text "where" <+> pretty e <+> text "with" <+> (text . show $ i))
159 text "Cannot unify" <+> colon <+> pretty l <+> text "and" <+> pretty r $$
160 nest nestingSize (text "where" <+> pretty e <+> text "with" <+> (text . show $ i))
161 pretty (ProviderError msg) = text msg
162 pretty err@(LoadingFailed _ _) = text (show err)
163 pretty _ = text "Error"
165instance Error Err where
170 deriving (Eq, Functor)
172instance Pretty a => Pretty (TC a) where
173 pretty (OK ok) = pretty ok
175 if size err > breakingSize then
176 text "Error" <+> colon $$ (nest nestingSize $ pretty err)
178 text "Error" <+> colon <+> pretty err
180instance Show a => Show (TC a) where
182 show (Error str) = "Error: " ++ show str
184-- at some point, this instance should also carry type checking options
187instance Monad TC where
192 fail e = Error (InternalMsg e)
197trun :: FC -> TC a -> TC a
199trun fc (Error e) = Error (At fc e)
201instance MonadPlus TC where
202 mzero = fail "Unknown error"
203 (OK x) `mplus` _ = OK x
204 _ `mplus` (OK y) = OK y
207discard :: Monad m => m a -> m ()
208discard f = f >> return ()
210showSep :: String -> [String] -> String
213showSep sep (x:xs) = x ++ sep ++ showSep sep xs
215pmap f (x, y) = (f x, f y)
217traceWhen True msg a = trace msg a
218traceWhen False _ a = a
220-- RAW TERMS ----------------------------------------------------------------
222-- | Names are hierarchies of strings, describing scope (so no danger of
223-- duplicate names, but need to be careful on lookup).
224data Name = UN String -- ^ User-provided name
225 | NS Name [String] -- ^ Root, namespaces
226 | MN Int String -- ^ Machine chosen names
227 | NErased -- ^ Name of somethng which is never used in scope
228 | SN SpecialName -- ^ Decorated function names
231deriving instance Binary Name
232deriving instance NFData Name
235data SpecialName = WhereN Int Name Name
236 | InstanceN Name [String]
237 | ParentN Name String
242deriving instance Binary SpecialName
243deriving instance NFData SpecialName
246instance Sized Name where
248 size (NS n els) = 1 + length els
252instance Pretty Name where
253 pretty (UN n) = text n
254 pretty (NS n s) = pretty n
255 pretty (MN i s) = lbrace <+> text s <+> (text . show $ i) <+> rbrace
256 pretty (SN s) = text (show s)
258instance Show Name where
260 show (NS n s) = showSep "." (reverse s) ++ "." ++ show n
261 show (MN _ "underscore") = "_"
262 show (MN i s) = "{" ++ s ++ show i ++ "}"
266instance Show SpecialName where
267 show (WhereN i p c) = show p ++ ", " ++ show c
268 show (InstanceN cl inst) = showSep ", " inst ++ " instance of " ++ show cl
269 show (MethodN m) = "method " ++ show m
270 show (ParentN p c) = show p ++ "#" ++ c
271 show (CaseN n) = "case block in " ++ show n
273-- Show a name in a way decorated for code generation, not human reading
274showCG :: Name -> String
276showCG (NS n s) = showSep "." (reverse s) ++ "." ++ show n
277showCG (MN _ "underscore") = "_"
278showCG (MN i s) = "{" ++ s ++ show i ++ "}"
279showCG (SN s) = showCG' s
280 where showCG' (WhereN i p c) = show p ++ ":" ++ show c ++ ":" ++ show i
281 showCG' (InstanceN cl inst) = '@':show cl ++ '$':showSep ":" inst
282 showCG' (MethodN m) = '!':show m
283 showCG' (ParentN p c) = show p ++ "#" ++ show c
284 showCG' (CaseN c) = show c ++ "_case"
288-- |Contexts allow us to map names to things. A root name maps to a collection
289-- of things in different namespaces with that name.
290type Ctxt a = Map.Map Name (Map.Map Name a)
291emptyContext = Map.empty
293tcname (UN ('@':_)) = True
294tcname (NS n _) = tcname n
295tcname (SN (InstanceN _ _)) = True
296tcname (SN (MethodN _)) = True
297tcname (SN (ParentN _ _)) = True
300implicitable (NS n _) = implicitable n
301implicitable (UN (x:xs)) = isLower x
302implicitable (MN _ _) = True
303implicitable _ = False
308addDef :: Name -> a -> Ctxt a -> Ctxt a
309addDef n v ctxt = case Map.lookup (nsroot n) ctxt of
310 Nothing -> Map.insert (nsroot n)
311 (Map.insert n v Map.empty) ctxt
312 Just xs -> Map.insert (nsroot n)
313 (Map.insert n v xs) ctxt
315{-| Look up a name in the context, given an optional namespace.
316 The name (n) may itself have a (partial) namespace given.
318 Rules for resolution:
320 - if an explicit namespace is given, return the names which match it. If none
321 match, return all names.
323 - if the name has has explicit namespace given, return the names which match it
324 and ignore the given namespace.
326 - otherwise, return all names.
330lookupCtxtName :: Name -> Ctxt a -> [(Name, a)]
331lookupCtxtName n ctxt = case Map.lookup (nsroot n) ctxt of
332 Just xs -> filterNS (Map.toList xs)
336 filterNS ((found, v) : xs)
337 | nsmatch n found = (found, v) : filterNS xs
338 | otherwise = filterNS xs
340 nsmatch (NS n ns) (NS p ps) = ns `isPrefixOf` ps
341 nsmatch (NS _ _) _ = False
342 nsmatch looking found = True
344lookupCtxt :: Name -> Ctxt a -> [a]
345lookupCtxt n ctxt = map snd (lookupCtxtName n ctxt)
347lookupCtxtExact :: Name -> Ctxt a -> [a]
348lookupCtxtExact n ctxt = [ v | (nm, v) <- lookupCtxtName n ctxt, nm == n]
350updateDef :: Name -> (a -> a) -> Ctxt a -> Ctxt a
352 = let ds = lookupCtxtName n ctxt in
353 foldr (\ (n, t) c -> addDef n (f t) c) ctxt ds
355toAlist :: Ctxt a -> [(Name, a)]
356toAlist ctxt = let allns = map snd (Map.toList ctxt) in
357 concat (map (Map.toList) allns)
359addAlist :: Show a => [(Name, a)] -> Ctxt a -> Ctxt a
360addAlist [] ctxt = ctxt
361addAlist ((n, tm) : ds) ctxt = addDef n tm (addAlist ds ctxt)
363data NativeTy = IT8 | IT16 | IT32 | IT64
364 deriving (Show, Eq, Ord, Enum)
366instance Pretty NativeTy where
367 pretty IT8 = text "Bits8"
368 pretty IT16 = text "Bits16"
369 pretty IT32 = text "Bits32"
370 pretty IT64 = text "Bits64"
372data IntTy = ITFixed NativeTy | ITNative | ITBig | ITChar
374 deriving (Show, Eq, Ord)
376data ArithTy = ATInt IntTy | ATFloat -- TODO: Float vectors
377 deriving (Show, Eq, Ord)
379deriving instance NFData IntTy
380deriving instance NFData NativeTy
381deriving instance NFData ArithTy
384instance Pretty ArithTy where
385 pretty (ATInt ITNative) = text "Int"
386 pretty (ATInt ITBig) = text "BigInt"
387 pretty (ATInt ITChar) = text "Char"
388 pretty (ATInt (ITFixed n)) = pretty n
389 pretty (ATInt (ITVec e c)) = pretty e <> text "x" <> (text . show $ c)
390 pretty ATFloat = text "Float"
392nativeTyWidth :: NativeTy -> Int
394nativeTyWidth IT16 = 16
395nativeTyWidth IT32 = 32
396nativeTyWidth IT64 = 64
398{-# DEPRECATED intTyWidth "Non-total function, use nativeTyWidth and appropriate casing" #-}
399intTyWidth :: IntTy -> Int
400intTyWidth (ITFixed n) = nativeTyWidth n
401intTyWidth ITNative = 8 * sizeOf (0 :: Int)
402intTyWidth ITChar = error "IRTS.Lang.intTyWidth: Characters have platform and backend dependent width"
403intTyWidth ITBig = error "IRTS.Lang.intTyWidth: Big integers have variable width"
405data Const = I Int | BI Integer | Fl Double | Ch Char | Str String
406 | B8 Word8 | B16 Word16 | B32 Word32 | B64 Word64
407 | B8V (Vector Word8) | B16V (Vector Word16)
408 | B32V (Vector Word32) | B64V (Vector Word64)
409 | AType ArithTy | StrType
410 | PtrType | VoidType | Forgot
413deriving instance Binary Const
414deriving instance NFData Const
417instance Sized Const where
420instance Pretty Const where
421 pretty (I i) = text . show $ i
422 pretty (BI i) = text . show $ i
423 pretty (Fl f) = text . show $ f
424 pretty (Ch c) = text . show $ c
425 pretty (Str s) = text s
426 pretty (AType a) = pretty a
427 pretty StrType = text "String"
428 pretty PtrType = text "Ptr"
429 pretty VoidType = text "Void"
430 pretty Forgot = text "Forgot"
431 pretty (B8 w) = text . show $ w
432 pretty (B16 w) = text . show $ w
433 pretty (B32 w) = text . show $ w
434 pretty (B64 w) = text . show $ w
437 | RBind Name (Binder Raw) Raw
444instance Sized Raw where
446 size (RBind name bind right) = 1 + size bind + size right
447 size (RApp left right) = 1 + size left + size right
449 size (RForce raw) = 1 + size raw
450 size (RConstant const) = size const
452instance Pretty Raw where
456deriving instance Binary Raw
457deriving instance NFData Raw
460-- | All binding forms are represented in a unform fashion.
461data Binder b = Lam { binderTy :: b {-^ type annotation for bound variable-}}
462 | Pi { binderTy :: b }
463 | Let { binderTy :: b,
464 binderVal :: b {-^ value for bound variable-}}
465 | NLet { binderTy :: b,
467 | Hole { binderTy :: b}
468 | GHole { envlen :: Int,
470 | Guess { binderTy :: b,
472 | PVar { binderTy :: b }
473 | PVTy { binderTy :: b }
474 deriving (Show, Eq, Ord, Functor)
476deriving instance Binary Binder
477deriving instance NFData Binder
480instance Sized a => Sized (Binder a) where
481 size (Lam ty) = 1 + size ty
482 size (Pi ty) = 1 + size ty
483 size (Let ty val) = 1 + size ty + size val
484 size (NLet ty val) = 1 + size ty + size val
485 size (Hole ty) = 1 + size ty
486 size (GHole _ ty) = 1 + size ty
487 size (Guess ty val) = 1 + size ty + size val
488 size (PVar ty) = 1 + size ty
489 size (PVTy ty) = 1 + size ty
491fmapMB :: Monad m => (a -> m b) -> Binder a -> m (Binder b)
492fmapMB f (Let t v) = liftM2 Let (f t) (f v)
493fmapMB f (NLet t v) = liftM2 NLet (f t) (f v)
494fmapMB f (Guess t v) = liftM2 Guess (f t) (f v)
495fmapMB f (Lam t) = liftM Lam (f t)
496fmapMB f (Pi t) = liftM Pi (f t)
497fmapMB f (Hole t) = liftM Hole (f t)
498fmapMB f (GHole i t) = liftM (GHole i) (f t)
499fmapMB f (PVar t) = liftM PVar (f t)
500fmapMB f (PVTy t) = liftM PVTy (f t)
502raw_apply :: Raw -> [Raw] -> Raw
504raw_apply f (a : as) = raw_apply (RApp f a) as
506raw_unapply :: Raw -> (Raw, [Raw])
507raw_unapply t = ua [] t where
508 ua args (RApp f a) = ua (a:args) f
509 ua args t = (t, args)
511data RawFun = RawFun { rtype :: Raw,
516data RawDatatype = RDatatype Name Raw [(Name, Raw)]
519data RDef = RFunction RawFun
524type RProgram = [(Name, RDef)]
526-- WELL TYPED TERMS ---------------------------------------------------------
528-- | Universe expressions for universe checking
529data UExp = UVar Int -- ^ universe variable
530 | UVal Int -- ^ explicit universe level
533deriving instance NFData UExp
536instance Sized UExp where
539-- We assume that universe levels have been checked, so anything external
540-- can just have the same universe variable and we won't get any new
543instance Binary UExp where
545 get = return (UVar (-1))
547instance Show UExp where
548 show (UVar x) | x < 26 = [toEnum (x + fromEnum 'a')]
549 | otherwise = toEnum ((x `mod` 26) + fromEnum 'a') : show (x `div` 26)
550 show (UVal x) = show x
551-- show (UMax l r) = "max(" ++ show l ++ ", " ++ show r ++")"
553-- | Universe constraints
554data UConstraint = ULT UExp UExp -- ^ Strictly less than
555 | ULE UExp UExp -- ^ Less than or equal to
558instance Show UConstraint where
559 show (ULT x y) = show x ++ " < " ++ show y
560 show (ULE x y) = show x ++ " <= " ++ show y
562type UCs = (Int, [UConstraint])
566 | DCon Int Int -- ^ Data constructor; Ints are tag and arity
567 | TCon Int Int -- ^ Type constructor; Ints are tag and arity
570deriving instance Binary NameType
571deriving instance NFData NameType
574instance Sized NameType where
577instance Pretty NameType where
580instance Eq NameType where
581 Bound == Bound = True
583 DCon _ a == DCon _ b = (a == b) -- ignore tag
584 TCon _ a == TCon _ b = (a == b) -- ignore tag
587-- | Terms in the core language
588data TT n = P NameType n (TT n) -- ^ named references
589 | V Int -- ^ a resolved de Bruijn-indexed variable
590 | Bind n (Binder (TT n)) (TT n) -- ^ a binding
591 | App (TT n) (TT n) -- ^ function, function type, arg
592 | Constant Const -- ^ constant
593 | Proj (TT n) Int -- ^ argument projection; runtime only
594 -- (-1) is a special case for 'subtract one from BI'
595 | Erased -- ^ an erased term
596 | Impossible -- ^ special case for totality checking
597 | TType UExp -- ^ the type of types at some level
598 deriving (Ord, Functor)
600deriving instance Binary TT
601deriving instance NFData TT
604class TermSize a where
605 termsize :: Name -> a -> Int
607instance TermSize a => TermSize [a] where
609 termsize n (x : xs) = termsize n x + termsize n xs
611instance TermSize (TT Name) where
613 | x == n = 1000000 -- recursive => really big
616 termsize n (Bind n' (Let t v) sc)
617 = let rn = if n == n' then MN 0 "noname" else n in
618 termsize rn v + termsize rn sc
619 termsize n (Bind n' b sc)
620 = let rn = if n == n' then MN 0 "noname" else n in
622 termsize n (App f a) = termsize n f + termsize n a
623 termsize n (Proj t i) = termsize n t
626instance Sized a => Sized (TT a) where
627 size (P name n trm) = 1 + size name + size n + size trm
629 size (Bind nm binder bdy) = 1 + size nm + size binder + size bdy
630 size (App l r) = 1 + size l + size r
631 size (Constant c) = size c
633 size (TType u) = 1 + size u
635instance Pretty a => Pretty (TT a) where
636 pretty _ = text "test"
638type EnvTT n = [(n, Binder (TT n))]
640data Datatype n = Data { d_typename :: n,
643 d_cons :: [(n, TT n)] }
644 deriving (Show, Functor, Eq)
646instance Eq n => Eq (TT n) where
647 (==) (P xt x _) (P yt y _) = x == y
648 (==) (V x) (V y) = x == y
649 (==) (Bind _ xb xs) (Bind _ yb ys) = xb == yb && xs == ys
650 (==) (App fx ax) (App fy ay) = fx == fy && ax == ay
651 (==) (TType _) (TType _) = True -- deal with constraints later
652 (==) (Constant x) (Constant y) = x == y
653 (==) (Proj x i) (Proj y j) = x == y && i == j
658-- * A few handy operations on well typed terms:
660-- | A term is injective iff it is a data constructor, type constructor,
661-- constant, the type Type, pi-binding, or an application of an injective
663isInjective :: TT n -> Bool
664isInjective (P (DCon _ _) _ _) = True
665isInjective (P (TCon _ _) _ _) = True
666isInjective (Constant _) = True
667isInjective (TType x) = True
668isInjective (Bind _ (Pi _) sc) = True
669isInjective (App f a) = isInjective f
672-- | Count the number of instances of a de Bruijn index in a term
673vinstances :: Int -> TT n -> Int
674vinstances i (V x) | i == x = 1
675vinstances i (App f a) = vinstances i f + vinstances i a
676vinstances i (Bind x b sc) = instancesB b + vinstances (i + 1) sc
677 where instancesB (Let t v) = vinstances i v
681instantiate :: TT n -> TT n -> TT n
682instantiate e = subst 0 where
683 subst i (V x) | i == x = e
684 subst i (Bind x b sc) = Bind x (fmap (subst i) b) (subst (i+1) sc)
685 subst i (App f a) = App (subst i f) (subst i a)
686 subst i (Proj x idx) = Proj (subst i x) idx
689substV :: TT n -> TT n -> TT n
690substV x tm = dropV 0 (instantiate x tm) where
691 dropV i (V x) | x > i = V (x - 1)
693 dropV i (Bind x b sc) = Bind x (fmap (dropV i) b) (dropV (i+1) sc)
694 dropV i (App f a) = App (dropV i f) (dropV i a)
695 dropV i (Proj x idx) = Proj (dropV i x) idx
698explicitNames :: TT n -> TT n
699explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
701 (explicitNames (instantiate
702 (P Bound x (binderTy b')) sc))
703explicitNames (App f a) = App (explicitNames f) (explicitNames a)
704explicitNames (Proj x idx) = Proj (explicitNames x) idx
707pToV :: Eq n => n -> TT n -> TT n
709pToV' n i (P _ x _) | n == x = V i
710pToV' n i (Bind x b sc)
711-- We can assume the inner scope has been pToVed already, so continue to
712-- resolve names from the *outer* scope which may happen to have the same id.
713 | n == x = Bind x (fmap (pToV' n i) b) sc
714 | otherwise = Bind x (fmap (pToV' n i) b) (pToV' n (i+1) sc)
715pToV' n i (App f a) = App (pToV' n i f) (pToV' n i a)
716pToV' n i (Proj t idx) = Proj (pToV' n i t) idx
719-- increase de Bruijn indices, as if a binder has been added
720addBinder :: TT n -> TT n
723 ab top (V i) | i >= top = V (i + 1)
725 ab top (Bind x b sc) = Bind x (fmap (ab top) b) (ab (top + 1) sc)
726 ab top (App f a) = App (ab top f) (ab top a)
727 ab top (Proj t idx) = Proj (ab top t) idx
730-- | Convert several names. First in the list comes out as V 0
731pToVs :: Eq n => [n] -> TT n -> TT n
732pToVs ns tm = pToVs' ns tm 0 where
734 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
738 vToP' env (V i) = let (n, b) = (env !! i) in
739 P Bound n (binderTy b)
740 vToP' env (Bind n b sc) = let b' = fmap (vToP' env) b in
741 Bind n b' (vToP' ((n, b'):env) sc)
742 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
745finalise :: Eq n => TT n -> TT n
746finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
747finalise (App f a) = App (finalise f) (finalise a)
750subst :: Eq n => n -> TT n -> TT n -> TT n
751subst n v tm = instantiate v (pToV n tm)
753substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
755substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
757substTerm :: Eq n => TT n -> TT n -> TT n -> TT n
758substTerm old new = st where
759 st t | t == old = new
760 st (App f a) = App (st f) (st a)
761 st (Bind x b sc) = Bind x (fmap st b) (st sc)
764-- Returns true if V 0 and bound name n do not occur in the term
766noOccurrence :: Eq n => n -> TT n -> Bool
767noOccurrence n t = no' 0 t
769 no' i (V x) = not (i == x)
770 no' i (P Bound x _) = not (n == x)
771 no' i (Bind n b sc) = noB' i b && no' (i+1) sc
772 where noB' i (Let t v) = no' i t && no' i v
773 noB' i (Guess t v) = no' i t && no' i v
774 noB' i b = no' i (binderTy b)
775 no' i (App f a) = no' i f && no' i a
776 no' i (Proj x _) = no' i x
779-- | Returns all names used free in the term
780freeNames :: Eq n => TT n -> [n]
781freeNames (P _ n _) = [n]
782freeNames (Bind n (Let t v) sc) = nub $ freeNames v ++ (freeNames sc \\ [n])
784freeNames (Bind n b sc) = nub $ freeNames (binderTy b) ++ (freeNames sc \\ [n])
785freeNames (App f a) = nub $ freeNames f ++ freeNames a
786freeNames (Proj x i) = nub $ freeNames x
789-- | Return the arity of a (normalised) type
791arity (Bind n (Pi t) sc) = 1 + arity sc
794-- | Deconstruct an application; returns the function and a list of arguments
795unApply :: TT n -> (TT n, [TT n])
796unApply t = ua [] t where
797 ua args (App f a) = ua (a:args) f
798 ua args t = (t, args)
800mkApp :: TT n -> [TT n] -> TT n
802mkApp f (a:as) = mkApp (App f a) as
804forget :: TT Name -> Raw
807 fe env (P _ n _) = Var n
808 fe env (V i) = Var (env !! i)
809 fe env (Bind n b sc) = RBind n (fmap (fe env) b)
811 fe env (App f a) = RApp (fe env f) (fe env a)
814 fe env (TType i) = RType
815 fe env Erased = RConstant Forgot
817bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
819bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
821bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
822bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
824getArgTys :: TT n -> [(n, TT n)]
825getArgTys (Bind n (Pi t) sc) = (n, t) : getArgTys sc
828getRetTy :: TT n -> TT n
829getRetTy (Bind n (PVar _) sc) = getRetTy sc
830getRetTy (Bind n (PVTy _) sc) = getRetTy sc
831getRetTy (Bind n (Pi _) sc) = getRetTy sc
834uniqueName :: Name -> [Name] -> Name
835uniqueName n hs | n `elem` hs = uniqueName (nextName n) hs
838uniqueBinders :: [Name] -> TT Name -> TT Name
839uniqueBinders ns (Bind n b sc)
840 = let n' = uniqueName n ns in
841 Bind n' (fmap (uniqueBinders (n':ns)) b) (uniqueBinders ns sc)
842uniqueBinders ns (App f a) = App (uniqueBinders ns f) (uniqueBinders ns a)
843uniqueBinders ns t = t
846nextName (NS x s) = NS (nextName x) s
847nextName (MN i n) = MN (i+1) n
848nextName (UN x) = let (num', nm') = span isDigit (reverse x)
850 num = readN (reverse num') in
851 UN (nm ++ show (num+1))
855nextName (SN x) = SN (nextName' x)
857 nextName' (WhereN i f x) = WhereN i f (nextName x)
858 nextName' (CaseN n) = CaseN (nextName n)
859 nextName' (MethodN n) = MethodN (nextName n)
866-- an environment with de Bruijn indices 'normalised' so that they all refer to
869newtype WkEnvTT n = Wk (EnvTT n)
870type WkEnv = WkEnvTT Name
872instance (Eq n, Show n) => Show (TT n) where
873 show t = showEnv [] t
875itBitsName IT8 = "Bits8"
876itBitsName IT16 = "Bits16"
877itBitsName IT32 = "Bits32"
878itBitsName IT64 = "Bits64"
880instance Show Const where
885 show (Str s) = show s
887 show (B16 x) = show x
888 show (B32 x) = show x
889 show (B64 x) = show x
890 show (B8V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
891 show (B16V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
892 show (B32V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
893 show (B64V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
894 show (AType ATFloat) = "Float"
895 show (AType (ATInt ITBig)) = "Integer"
896 show (AType (ATInt ITNative)) = "Int"
897 show (AType (ATInt ITChar)) = "Char"
898 show (AType (ATInt (ITFixed it))) = itBitsName it
899 show (AType (ATInt (ITVec it c))) = itBitsName it ++ "x" ++ show c
900 show StrType = "String"
902 show VoidType = "Void"
904showEnv env t = showEnv' env t False
905showEnvDbg env t = showEnv' env t True
907prettyEnv env t = prettyEnv' env t False
909 prettyEnv' env t dbg = prettySe 10 env t dbg
911 bracket outer inner p
912 | inner > outer = lparen <> p <> rparen
915 prettySe p env (P nt n t) debug =
918 lbrack <+> pretty nt <+> colon <+> prettySe 10 env t debug <+> rbrack
921 prettySe p env (V i) debug
924 text . show . fst $ env!!i
926 lbrack <+> text (show i) <+> rbrack
927 | otherwise = text "unbound" <+> text (show i) <+> text "!"
928 prettySe p env (Bind n b@(Pi t) sc) debug
929 | noOccurrence n sc && not debug =
930 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
931 prettySe p env (Bind n b sc) debug =
932 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
933 prettySe p env (App f a) debug =
934 bracket p 1 $ prettySe 1 env f debug <+> prettySe 0 env a debug
935 prettySe p env (Proj x i) debug =
936 prettySe 1 env x debug <+> text ("!" ++ show i)
937 prettySe p env (Constant c) debug = pretty c
938 prettySe p env Erased debug = text "[_]"
939 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
941 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
942 prettySb env n (Hole t) = prettyB env "?defer" "." n t
943 prettySb env n (Pi t) = prettyB env "(" ") ->" n t
944 prettySb env n (PVar t) = prettyB env "pat" "." n t
945 prettySb env n (PVTy t) = prettyB env "pty" "." n t
946 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
947 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
949 prettyB env op sc n t debug =
950 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
952 prettyBv env op sc n t v debug =
953 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
954 prettySe 10 env v debug <> text sc
957showEnv' env t dbg = se 10 env t where
958 se p env (P nt n t) = show n
959 ++ if dbg then "{" ++ show nt ++ " : " ++ se 10 env t ++ "}" else ""
960 se p env (V i) | i < length env && i >= 0
961 = (show $ fst $ env!!i) ++
962 if dbg then "{" ++ show i ++ "}" else ""
963 | otherwise = "!!V " ++ show i ++ "!!"
964 se p env (Bind n b@(Pi t) sc)
965 | noOccurrence n sc && not dbg = bracket p 2 $ se 1 env t ++ " -> " ++ se 10 ((n,b):env) sc
966 se p env (Bind n b sc) = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
967 se p env (App f a) = bracket p 1 $ se 1 env f ++ " " ++ se 0 env a
968 se p env (Proj x i) = se 1 env x ++ "!" ++ show i
969 se p env (Constant c) = show c
970 se p env Erased = "[__]"
971 se p env Impossible = "[impossible]"
972 se p env (TType i) = "Type " ++ show i
974 sb env n (Lam t) = showb env "\\ " " => " n t
975 sb env n (Hole t) = showb env "? " ". " n t
976 sb env n (GHole i t) = showb env "?defer " ". " n t
977 sb env n (Pi t) = showb env "(" ") -> " n t
978 sb env n (PVar t) = showb env "pat " ". " n t
979 sb env n (PVTy t) = showb env "pty " ". " n t
980 sb env n (Let t v) = showbv env "let " " in " n t v
981 sb env n (Guess t v) = showbv env "?? " " in " n t v
983 showb env op sc n t = op ++ show n ++ " : " ++ se 10 env t ++ sc
984 showbv env op sc n t v = op ++ show n ++ " : " ++ se 10 env t ++ " = " ++
987 bracket outer inner str | inner > outer = "(" ++ str ++ ")"
990-- | Check whether a term has any holes in it - impure if so
991pureTerm :: TT Name -> Bool
992pureTerm (App f a) = pureTerm f && pureTerm a
993pureTerm (Bind n b sc) = notClassName n && pureBinder b && pureTerm sc where
994 pureBinder (Hole _) = False
995 pureBinder (Guess _ _) = False
996 pureBinder (Let t v) = pureTerm t && pureTerm v
997 pureBinder t = pureTerm (binderTy t)
999 notClassName (MN _ "class") = False
1000 notClassName _ = True
1004-- | Weaken a term by adding i to each de Bruijn index (i.e. lift it over i bindings)
1005weakenTm :: Int -> TT n -> TT n
1006weakenTm i t = wk i 0 t
1007 where wk i min (V x) | x >= min = V (i + x)
1008 wk i m (App f a) = App (wk i m f) (wk i m a)
1009 wk i m (Bind x b sc) = Bind x (wkb i m b) (wk i (m + 1) sc)
1011 wkb i m t = fmap (wk i m) t
1013-- | Weaken an environment so that all the de Bruijn indices are correct according
1014-- to the latest bound variable
1016weakenEnv :: EnvTT n -> EnvTT n
1017weakenEnv env = wk (length env - 1) env
1019 wk i ((n, b) : bs) = (n, weakenTmB i b) : wk (i - 1) bs
1020 weakenTmB i (Let t v) = Let (weakenTm i t) (weakenTm i v)
1021 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
1022 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
1024weakenTmEnv :: Int -> EnvTT n -> EnvTT n
1025weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
1027orderPats :: Term -> Term
1028orderPats tm = op [] tm
1030 op ps (Bind n (PVar t) sc) = op ((n, PVar t) : ps) sc
1031 op ps (Bind n (Hole t) sc) = op ((n, Hole t) : ps) sc
1032 op ps sc = bindAll (sortP ps) sc
1034 sortP ps = pick [] (reverse ps)
1036 namesIn (P _ n _) = [n]
1037 namesIn (Bind n b t) = nub $ nb b ++ (namesIn t \\ [n])
1038 where nb (Let t v) = nub (namesIn t) ++ nub (namesIn v)
1039 nb (Guess t v) = nub (namesIn t) ++ nub (namesIn v)
1040 nb t = namesIn (binderTy t)
1041 namesIn (App f a) = nub (namesIn f ++ namesIn a)
1044 pick acc [] = reverse acc
1045 pick acc ((n, t) : ps) = pick (insert n t acc) ps
1047 insert n t [] = [(n, t)]
1048 insert n t ((n',t') : ps)
1049 | n `elem` (namesIn (binderTy t') ++
1050 concatMap namesIn (map (binderTy . snd) ps))
1051 = (n', t') : insert n t ps
1052 | 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