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
25import qualified Data.Map as Map
28import Data.Vector.Unboxed (Vector)
29import qualified Data.Vector.Unboxed as V
30import qualified Data.Binary as B
31import Data.Binary hiding (get, put)
32import Foreign.Storable (sizeOf)
34import Util.Pretty hiding (Str)
36data Option = TTypeInTType
40-- | Source location. These are typically produced by the parser 'Idris.Parser.pfc'
41data FC = FC { fc_fname :: String, -- ^ Filename
42 fc_line :: Int -- ^ Line number
46deriving instance Binary FC
49instance Sized FC where
50 size (FC f l) = 1 + length f
53 show (FC f l) = f ++ ":" ++ show l
57 | CantUnify Bool Term Term Err [(Name, Type)] Int
58 -- Int is 'score' - how much we did unify
59 -- Bool indicates recoverability, True indicates more info may make
60 -- unification succeed
61 | InfiniteUnify Name Term [(Name, Type)]
62 | CantConvert Term Term [(Name, Type)]
63 | UnifyScope Name Name Term [(Name, Type)]
64 | CantInferType String
65 | NonFunctionType Term Term
69 | NotInjective Term Term Term
71 | CantResolveAlts [String]
76 | NonCollapsiblePostulate Name
81 | Elaborating String Name Err
82 | ProviderError String
85instance Sized Err where
86 size (Msg msg) = length msg
87 size (InternalMsg msg) = length msg
88 size (CantUnify _ left right err _ score) = size left + size right + size err
89 size (InfiniteUnify _ right _) = size right
90 size (CantConvert left right _) = size left + size right
91 size (UnifyScope _ _ right _) = size right
92 size (NoSuchVariable name) = size name
93 size (NoTypeDecl name) = size name
94 size (NotInjective l c r) = size l + size c + size r
95 size (CantResolve trm) = size trm
96 size (NoRewriting trm) = size trm
97 size (CantResolveAlts _) = 1
98 size (IncompleteTerm trm) = size trm
99 size UniverseError = 1
100 size ProgramLineComment = 1
101 size (At fc err) = size fc + size err
102 size (Elaborating _ n err) = size err
103 size (ProviderError msg) = length msg
107score (CantUnify _ _ _ m _ s) = s + score m
108score (CantResolve _) = 20
109score (NoSuchVariable _) = 1000
110score (ProofSearchFail _) = 10000
111score (InternalMsg _) = -1
114instance Show Err where
116 show (InternalMsg s) = "Internal error: " ++ show s
117 show (CantUnify _ l r e sc i) = "CantUnify " ++ show l ++ " " ++ show r ++ " "
118 ++ show e ++ " in " ++ show sc ++ " " ++ show i
119 show (Inaccessible n) = show n ++ " is not an accessible pattern variable"
120 show (ProviderError msg) = "Type provider error: " ++ msg
123instance Pretty Err where
124 pretty (Msg m) = text m
125 pretty (CantUnify _ l r e _ i) =
126 if size l + size r > breakingSize then
127 text "Cannot unify" <+> colon $$
128 nest nestingSize (pretty l <+> text "and" <+> pretty r) $$
129 nest nestingSize (text "where" <+> pretty e <+> text "with" <+> (text . show $ i))
131 text "Cannot unify" <+> colon <+> pretty l <+> text "and" <+> pretty r $$
132 nest nestingSize (text "where" <+> pretty e <+> text "with" <+> (text . show $ i))
133 pretty (ProviderError msg) = text msg
134 pretty _ = text "Error"
138 deriving (Eq, Functor)
140instance Pretty a => Pretty (TC a) where
141 pretty (OK ok) = pretty ok
143 if size err > breakingSize then
144 text "Error" <+> colon $$ (nest nestingSize $ pretty err)
146 text "Error" <+> colon <+> pretty err
148instance Show a => Show (TC a) where
150 show (Error str) = "Error: " ++ show str
152-- at some point, this instance should also carry type checking options
155instance Monad TC where
160 fail e = Error (InternalMsg e)
165trun :: FC -> TC a -> TC a
167trun fc (Error e) = Error (At fc e)
169instance MonadPlus TC where
170 mzero = fail "Unknown error"
171 (OK x) `mplus` _ = OK x
172 _ `mplus` (OK y) = OK y
175discard :: Monad m => m a -> m ()
176discard f = f >> return ()
178showSep :: String -> [String] -> String
181showSep sep (x:xs) = x ++ sep ++ showSep sep xs
183pmap f (x, y) = (f x, f y)
185traceWhen True msg a = trace msg a
186traceWhen False _ a = a
188-- RAW TERMS ----------------------------------------------------------------
190-- | Names are hierarchies of strings, describing scope (so no danger of
191-- duplicate names, but need to be careful on lookup).
192data Name = UN String -- ^ User-provided name
193 | NS Name [String] -- ^ Root, namespaces
194 | MN Int String -- ^ Machine chosen names
195 | NErased -- ^ Name of somethng which is never used in scope
196 | SN SpecialName -- ^ Decorated function names
199deriving instance Binary Name
202data SpecialName = WhereN Int Name Name
203 | InstanceN Name [String]
204 | ParentN Name String
209deriving instance Binary SpecialName
212instance Sized Name where
214 size (NS n els) = 1 + length els
218instance Pretty Name where
219 pretty (UN n) = text n
220 pretty (NS n s) = pretty n
221 pretty (MN i s) = lbrace <+> text s <+> (text . show $ i) <+> rbrace
222 pretty (SN s) = text (show s)
224instance Show Name where
226 show (NS n s) = showSep "." (reverse s) ++ "." ++ show n
227 show (MN _ "underscore") = "_"
228 show (MN i s) = "{" ++ s ++ show i ++ "}"
232instance Show SpecialName where
233 show (WhereN i p c) = show p ++ ", " ++ show c
234 show (InstanceN cl inst) = showSep ", " inst ++ " instance of " ++ show cl
235 show (MethodN m) = "method " ++ show m
236 show (ParentN p c) = show p ++ "#" ++ c
237 show (CaseN n) = "case block in " ++ show n
239-- Show a name in a way decorated for code generation, not human reading
240showCG :: Name -> String
242showCG (NS n s) = showSep "." (reverse s) ++ "." ++ show n
243showCG (MN _ "underscore") = "_"
244showCG (MN i s) = "{" ++ s ++ show i ++ "}"
245showCG (SN s) = showCG' s
246 where showCG' (WhereN i p c) = show p ++ ":" ++ show c ++ ":" ++ show i
247 showCG' (InstanceN cl inst) = '@':show cl ++ '$':showSep ":" inst
248 showCG' (MethodN m) = '!':show m
249 showCG' (ParentN p c) = show p ++ "#" ++ show c
250 showCG' (CaseN c) = show c ++ "_case"
254-- |Contexts allow us to map names to things. A root name maps to a collection
255-- of things in different namespaces with that name.
256type Ctxt a = Map.Map Name (Map.Map Name a)
257emptyContext = Map.empty
259tcname (UN ('@':_)) = True
260tcname (NS n _) = tcname n
261tcname (SN (InstanceN _ _)) = True
262tcname (SN (MethodN _)) = True
263tcname (SN (ParentN _ _)) = True
266implicitable (NS n _) = implicitable n
267implicitable (UN (x:xs)) = isLower x
268implicitable _ = False
273addDef :: Name -> a -> Ctxt a -> Ctxt a
274addDef n v ctxt = case Map.lookup (nsroot n) ctxt of
275 Nothing -> Map.insert (nsroot n)
276 (Map.insert n v Map.empty) ctxt
277 Just xs -> Map.insert (nsroot n)
278 (Map.insert n v xs) ctxt
280{-| Look up a name in the context, given an optional namespace.
281 The name (n) may itself have a (partial) namespace given.
283 Rules for resolution:
285 - if an explicit namespace is given, return the names which match it. If none
286 match, return all names.
288 - if the name has has explicit namespace given, return the names which match it
289 and ignore the given namespace.
291 - otherwise, return all names.
295lookupCtxtName :: Name -> Ctxt a -> [(Name, a)]
296lookupCtxtName n ctxt = case Map.lookup (nsroot n) ctxt of
297 Just xs -> filterNS (Map.toList xs)
301 filterNS ((found, v) : xs)
302 | nsmatch n found = (found, v) : filterNS xs
303 | otherwise = filterNS xs
305 nsmatch (NS n ns) (NS p ps) = ns `isPrefixOf` ps
306 nsmatch (NS _ _) _ = False
307 nsmatch looking found = True
309lookupCtxt :: Name -> Ctxt a -> [a]
310lookupCtxt n ctxt = map snd (lookupCtxtName n ctxt)
312updateDef :: Name -> (a -> a) -> Ctxt a -> Ctxt a
314 = let ds = lookupCtxtName n ctxt in
315 foldr (\ (n, t) c -> addDef n (f t) c) ctxt ds
317toAlist :: Ctxt a -> [(Name, a)]
318toAlist ctxt = let allns = map snd (Map.toList ctxt) in
319 concat (map (Map.toList) allns)
321addAlist :: Show a => [(Name, a)] -> Ctxt a -> Ctxt a
322addAlist [] ctxt = ctxt
323addAlist ((n, tm) : ds) ctxt = addDef n tm (addAlist ds ctxt)
325data NativeTy = IT8 | IT16 | IT32 | IT64
326 deriving (Show, Eq, Ord, Enum)
328instance Pretty NativeTy where
329 pretty IT8 = text "Bits8"
330 pretty IT16 = text "Bits16"
331 pretty IT32 = text "Bits32"
332 pretty IT64 = text "Bits64"
334data IntTy = ITFixed NativeTy | ITNative | ITBig | ITChar
336 deriving (Show, Eq, Ord)
338data ArithTy = ATInt IntTy | ATFloat -- TODO: Float vectors
339 deriving (Show, Eq, Ord)
341instance Pretty ArithTy where
342 pretty (ATInt ITNative) = text "Int"
343 pretty (ATInt ITBig) = text "BigInt"
344 pretty (ATInt ITChar) = text "Char"
345 pretty (ATInt (ITFixed n)) = pretty n
346 pretty (ATInt (ITVec e c)) = pretty e <> text "x" <> (text . show $ c)
347 pretty ATFloat = text "Float"
349nativeTyWidth :: NativeTy -> Int
351nativeTyWidth IT16 = 16
352nativeTyWidth IT32 = 32
353nativeTyWidth IT64 = 64
355{-# DEPRECATED intTyWidth "Non-total function, use nativeTyWidth and appropriate casing" #-}
356intTyWidth :: IntTy -> Int
357intTyWidth (ITFixed n) = nativeTyWidth n
358intTyWidth ITNative = 8 * sizeOf (0 :: Int)
359intTyWidth ITChar = error "IRTS.Lang.intTyWidth: Characters have platform and backend dependent width"
360intTyWidth ITBig = error "IRTS.Lang.intTyWidth: Big integers have variable width"
362data Const = I Int | BI Integer | Fl Double | Ch Char | Str String
363 | B8 Word8 | B16 Word16 | B32 Word32 | B64 Word64
364 | B8V (Vector Word8) | B16V (Vector Word16)
365 | B32V (Vector Word32) | B64V (Vector Word64)
366 | AType ArithTy | StrType
367 | PtrType | VoidType | Forgot
370deriving instance Binary Const
373instance Sized Const where
376instance Pretty Const where
377 pretty (I i) = text . show $ i
378 pretty (BI i) = text . show $ i
379 pretty (Fl f) = text . show $ f
380 pretty (Ch c) = text . show $ c
381 pretty (Str s) = text s
382 pretty (AType a) = pretty a
383 pretty StrType = text "String"
384 pretty PtrType = text "Ptr"
385 pretty VoidType = text "Void"
386 pretty Forgot = text "Forgot"
387 pretty (B8 w) = text . show $ w
388 pretty (B16 w) = text . show $ w
389 pretty (B32 w) = text . show $ w
390 pretty (B64 w) = text . show $ w
393 | RBind Name (Binder Raw) Raw
400instance Sized Raw where
402 size (RBind name bind right) = 1 + size bind + size right
403 size (RApp left right) = 1 + size left + size right
405 size (RForce raw) = 1 + size raw
406 size (RConstant const) = size const
408instance Pretty Raw where
412deriving instance Binary Raw
415-- | All binding forms are represented in a unform fashion.
416data Binder b = Lam { binderTy :: b {-^ type annotation for bound variable-}}
417 | Pi { binderTy :: b }
418 | Let { binderTy :: b,
419 binderVal :: b {-^ value for bound variable-}}
420 | NLet { binderTy :: b,
422 | Hole { binderTy :: b}
423 | GHole { binderTy :: b}
424 | Guess { binderTy :: b,
426 | PVar { binderTy :: b }
427 | PVTy { binderTy :: b }
428 deriving (Show, Eq, Ord, Functor)
430deriving instance Binary Binder
433instance Sized a => Sized (Binder a) where
434 size (Lam ty) = 1 + size ty
435 size (Pi ty) = 1 + size ty
436 size (Let ty val) = 1 + size ty + size val
437 size (NLet ty val) = 1 + size ty + size val
438 size (Hole ty) = 1 + size ty
439 size (GHole ty) = 1 + size ty
440 size (Guess ty val) = 1 + size ty + size val
441 size (PVar ty) = 1 + size ty
442 size (PVTy ty) = 1 + size ty
444fmapMB :: Monad m => (a -> m b) -> Binder a -> m (Binder b)
445fmapMB f (Let t v) = liftM2 Let (f t) (f v)
446fmapMB f (NLet t v) = liftM2 NLet (f t) (f v)
447fmapMB f (Guess t v) = liftM2 Guess (f t) (f v)
448fmapMB f (Lam t) = liftM Lam (f t)
449fmapMB f (Pi t) = liftM Pi (f t)
450fmapMB f (Hole t) = liftM Hole (f t)
451fmapMB f (GHole t) = liftM GHole (f t)
452fmapMB f (PVar t) = liftM PVar (f t)
453fmapMB f (PVTy t) = liftM PVTy (f t)
455raw_apply :: Raw -> [Raw] -> Raw
457raw_apply f (a : as) = raw_apply (RApp f a) as
459raw_unapply :: Raw -> (Raw, [Raw])
460raw_unapply t = ua [] t where
461 ua args (RApp f a) = ua (a:args) f
462 ua args t = (t, args)
464data RawFun = RawFun { rtype :: Raw,
469data RawDatatype = RDatatype Name Raw [(Name, Raw)]
472data RDef = RFunction RawFun
477type RProgram = [(Name, RDef)]
479-- WELL TYPED TERMS ---------------------------------------------------------
481-- | Universe expressions for universe checking
482data UExp = UVar Int -- ^ universe variable
483 | UVal Int -- ^ explicit universe level
486instance Sized UExp where
489-- We assume that universe levels have been checked, so anything external
490-- can just have the same universe variable and we won't get any new
493instance Binary UExp where
495 get = return (UVar (-1))
497instance Show UExp where
498 show (UVar x) | x < 26 = [toEnum (x + fromEnum 'a')]
499 | otherwise = toEnum ((x `mod` 26) + fromEnum 'a') : show (x `div` 26)
500 show (UVal x) = show x
501-- show (UMax l r) = "max(" ++ show l ++ ", " ++ show r ++")"
503-- | Universe constraints
504data UConstraint = ULT UExp UExp -- ^ Strictly less than
505 | ULE UExp UExp -- ^ Less than or equal to
508instance Show UConstraint where
509 show (ULT x y) = show x ++ " < " ++ show y
510 show (ULE x y) = show x ++ " <= " ++ show y
512type UCs = (Int, [UConstraint])
516 | DCon Int Int -- ^ Data constructor; Ints are tag and arity
517 | TCon Int Int -- ^ Type constructor; Ints are tag and arity
520deriving instance Binary NameType
523instance Sized NameType where
526instance Pretty NameType where
529instance Eq NameType where
530 Bound == Bound = True
532 DCon _ a == DCon _ b = (a == b) -- ignore tag
533 TCon _ a == TCon _ b = (a == b) -- ignore tag
536-- | Terms in the core language
537data TT n = P NameType n (TT n) -- ^ named references
538 | V Int -- ^ a resolved de Bruijn-indexed variable
539 | Bind n (Binder (TT n)) (TT n) -- ^ a binding
540 | App (TT n) (TT n) -- ^ function, function type, arg
541 | Constant Const -- ^ constant
542 | Proj (TT n) Int -- ^ argument projection; runtime only
543 | Erased -- ^ an erased term
544 | Impossible -- ^ special case for totality checking
545 | TType UExp -- ^ the type of types at some level
546 deriving (Ord, Functor)
548deriving instance Binary TT
551class TermSize a where
552 termsize :: Name -> a -> Int
554instance TermSize a => TermSize [a] where
556 termsize n (x : xs) = termsize n x + termsize n xs
558instance TermSize (TT Name) where
560 | x == n = 1000000 -- recursive => really big
563 termsize n (Bind n' (Let t v) sc)
564 = let rn = if n == n' then MN 0 "noname" else n in
565 termsize rn v + termsize rn sc
566 termsize n (Bind n' b sc)
567 = let rn = if n == n' then MN 0 "noname" else n in
569 termsize n (App f a) = termsize n f + termsize n a
570 termsize n (Proj t i) = termsize n t
573instance Sized a => Sized (TT a) where
574 size (P name n trm) = 1 + size name + size n + size trm
576 size (Bind nm binder bdy) = 1 + size nm + size binder + size bdy
577 size (App l r) = 1 + size l + size r
578 size (Constant c) = size c
580 size (TType u) = 1 + size u
582instance Pretty a => Pretty (TT a) where
583 pretty _ = text "test"
585type EnvTT n = [(n, Binder (TT n))]
587data Datatype n = Data { d_typename :: n,
590 d_cons :: [(n, TT n)] }
591 deriving (Show, Functor, Eq)
593instance Eq n => Eq (TT n) where
594 (==) (P xt x _) (P yt y _) = x == y
595 (==) (V x) (V y) = x == y
596 (==) (Bind _ xb xs) (Bind _ yb ys) = xb == yb && xs == ys
597 (==) (App fx ax) (App fy ay) = fx == fy && ax == ay
598 (==) (TType _) (TType _) = True -- deal with constraints later
599 (==) (Constant x) (Constant y) = x == y
600 (==) (Proj x i) (Proj y j) = x == y && i == j
605-- * A few handy operations on well typed terms:
607-- | A term is injective iff it is a data constructor, type constructor,
608-- constant, the type Type, pi-binding, or an application of an injective
610isInjective :: TT n -> Bool
611isInjective (P (DCon _ _) _ _) = True
612isInjective (P (TCon _ _) _ _) = True
613isInjective (Constant _) = True
614isInjective (TType x) = True
615isInjective (Bind _ (Pi _) sc) = True
616isInjective (App f a) = isInjective f
619-- | Count the number of instances of a de Bruijn index in a term
620vinstances :: Int -> TT n -> Int
621vinstances i (V x) | i == x = 1
622vinstances i (App f a) = vinstances i f + vinstances i a
623vinstances i (Bind x b sc) = instancesB b + vinstances (i + 1) sc
624 where instancesB (Let t v) = vinstances i v
628instantiate :: TT n -> TT n -> TT n
629instantiate e = subst 0 where
630 subst i (V x) | i == x = e
631 subst i (Bind x b sc) = Bind x (fmap (subst i) b) (subst (i+1) sc)
632 subst i (App f a) = App (subst i f) (subst i a)
633 subst i (Proj x idx) = Proj (subst i x) idx
636substV :: TT n -> TT n -> TT n
637substV x tm = dropV 0 (instantiate x tm) where
638 dropV i (V x) | x > i = V (x - 1)
640 dropV i (Bind x b sc) = Bind x (fmap (dropV i) b) (dropV (i+1) sc)
641 dropV i (App f a) = App (dropV i f) (dropV i a)
642 dropV i (Proj x idx) = Proj (dropV i x) idx
645explicitNames :: TT n -> TT n
646explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
648 (explicitNames (instantiate
649 (P Bound x (binderTy b')) sc))
650explicitNames (App f a) = App (explicitNames f) (explicitNames a)
651explicitNames (Proj x idx) = Proj (explicitNames x) idx
654pToV :: Eq n => n -> TT n -> TT n
656pToV' n i (P _ x _) | n == x = V i
657pToV' n i (Bind x b sc)
658-- We can assume the inner scope has been pToVed already, so continue to
659-- resolve names from the *outer* scope which may happen to have the same id.
660 | n == x = Bind x (fmap (pToV' n i) b) sc
661 | otherwise = Bind x (fmap (pToV' n i) b) (pToV' n (i+1) sc)
662pToV' n i (App f a) = App (pToV' n i f) (pToV' n i a)
663pToV' n i (Proj t idx) = Proj (pToV' n i t) idx
666-- increase de Bruijn indices, as if a binder has been added
667addBinder :: TT n -> TT n
670 ab top (V i) | i >= top = V (i + 1)
672 ab top (Bind x b sc) = Bind x (fmap (ab top) b) (ab (top + 1) sc)
673 ab top (App f a) = App (ab top f) (ab top a)
674 ab top (Proj t idx) = Proj (ab top t) idx
677-- | Convert several names. First in the list comes out as V 0
678pToVs :: Eq n => [n] -> TT n -> TT n
679pToVs ns tm = pToVs' ns tm 0 where
681 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
685 vToP' env (V i) = let (n, b) = (env !! i) in
686 P Bound n (binderTy b)
687 vToP' env (Bind n b sc) = let b' = fmap (vToP' env) b in
688 Bind n b' (vToP' ((n, b'):env) sc)
689 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
692finalise :: Eq n => TT n -> TT n
693finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
694finalise (App f a) = App (finalise f) (finalise a)
697subst :: Eq n => n -> TT n -> TT n -> TT n
698subst n v tm = instantiate v (pToV n tm)
700substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
702substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
704substTerm :: Eq n => TT n -> TT n -> TT n -> TT n
705substTerm old new = st where
706 st t | t == old = new
707 st (App f a) = App (st f) (st a)
708 st (Bind x b sc) = Bind x (fmap st b) (st sc)
711-- Returns true if V 0 and bound name n do not occur in the term
713noOccurrence :: Eq n => n -> TT n -> Bool
714noOccurrence n t = no' 0 t
716 no' i (V x) = not (i == x)
717 no' i (P Bound x _) = not (n == x)
718 no' i (Bind n b sc) = noB' i b && no' (i+1) sc
719 where noB' i (Let t v) = no' i t && no' i v
720 noB' i (Guess t v) = no' i t && no' i v
721 noB' i b = no' i (binderTy b)
722 no' i (App f a) = no' i f && no' i a
723 no' i (Proj x _) = no' i x
726-- | Returns all names used free in the term
727freeNames :: Eq n => TT n -> [n]
728freeNames (P _ n _) = [n]
729freeNames (Bind n (Let t v) sc) = nub $ freeNames v ++ (freeNames sc \\ [n])
731freeNames (Bind n b sc) = nub $ freeNames (binderTy b) ++ (freeNames sc \\ [n])
732freeNames (App f a) = nub $ freeNames f ++ freeNames a
733freeNames (Proj x i) = nub $ freeNames x
736-- | Return the arity of a (normalised) type
738arity (Bind n (Pi t) sc) = 1 + arity sc
741-- | Deconstruct an application; returns the function and a list of arguments
742unApply :: TT n -> (TT n, [TT n])
743unApply t = ua [] t where
744 ua args (App f a) = ua (a:args) f
745 ua args t = (t, args)
747mkApp :: TT n -> [TT n] -> TT n
749mkApp f (a:as) = mkApp (App f a) as
751forget :: TT Name -> Raw
754 fe env (P _ n _) = Var n
755 fe env (V i) = Var (env !! i)
756 fe env (Bind n b sc) = RBind n (fmap (fe env) b)
758 fe env (App f a) = RApp (fe env f) (fe env a)
761 fe env (TType i) = RType
762 fe env Erased = RConstant Forgot
764bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
766bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
768bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
769bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
771getArgTys :: TT n -> [(n, TT n)]
772getArgTys (Bind n (Pi t) sc) = (n, t) : getArgTys sc
775getRetTy :: TT n -> TT n
776getRetTy (Bind n (PVar _) sc) = getRetTy sc
777getRetTy (Bind n (PVTy _) sc) = getRetTy sc
778getRetTy (Bind n (Pi _) sc) = getRetTy sc
781uniqueName :: Name -> [Name] -> Name
782uniqueName n hs | n `elem` hs = uniqueName (nextName n) hs
785uniqueBinders :: [Name] -> TT Name -> TT Name
786uniqueBinders ns (Bind n b sc)
787 = let n' = uniqueName n ns in
788 Bind n' (fmap (uniqueBinders (n':ns)) b) (uniqueBinders ns sc)
789uniqueBinders ns (App f a) = App (uniqueBinders ns f) (uniqueBinders ns a)
790uniqueBinders ns t = t
793nextName (NS x s) = NS (nextName x) s
794nextName (MN i n) = MN (i+1) n
795nextName (UN x) = let (num', nm') = span isDigit (reverse x)
797 num = readN (reverse num') in
798 UN (nm ++ show (num+1))
802nextName (SN x) = SN (nextName' x)
804 nextName' (WhereN i f x) = WhereN i f (nextName x)
805 nextName' (CaseN n) = CaseN (nextName n)
806 nextName' (MethodN n) = MethodN (nextName n)
813-- an environment with de Bruijn indices 'normalised' so that they all refer to
816newtype WkEnvTT n = Wk (EnvTT n)
817type WkEnv = WkEnvTT Name
819instance (Eq n, Show n) => Show (TT n) where
820 show t = showEnv [] t
822itBitsName IT8 = "Bits8"
823itBitsName IT16 = "Bits16"
824itBitsName IT32 = "Bits32"
825itBitsName IT64 = "Bits64"
827instance Show Const where
832 show (Str s) = show s
834 show (B16 x) = show x
835 show (B32 x) = show x
836 show (B64 x) = show x
837 show (B8V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
838 show (B16V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
839 show (B32V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
840 show (B64V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
841 show (AType ATFloat) = "Float"
842 show (AType (ATInt ITBig)) = "Integer"
843 show (AType (ATInt ITNative)) = "Int"
844 show (AType (ATInt ITChar)) = "Char"
845 show (AType (ATInt (ITFixed it))) = itBitsName it
846 show (AType (ATInt (ITVec it c))) = itBitsName it ++ "x" ++ show c
847 show StrType = "String"
849 show VoidType = "Void"
851showEnv env t = showEnv' env t False
852showEnvDbg env t = showEnv' env t True
854prettyEnv env t = prettyEnv' env t False
856 prettyEnv' env t dbg = prettySe 10 env t dbg
858 bracket outer inner p
859 | inner > outer = lparen <> p <> rparen
862 prettySe p env (P nt n t) debug =
865 lbrack <+> pretty nt <+> colon <+> prettySe 10 env t debug <+> rbrack
868 prettySe p env (V i) debug
871 text . show . fst $ env!!i
873 lbrack <+> text (show i) <+> rbrack
874 | otherwise = text "unbound" <+> text (show i) <+> text "!"
875 prettySe p env (Bind n b@(Pi t) sc) debug
876 | noOccurrence n sc && not debug =
877 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
878 prettySe p env (Bind n b sc) debug =
879 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
880 prettySe p env (App f a) debug =
881 bracket p 1 $ prettySe 1 env f debug <+> prettySe 0 env a debug
882 prettySe p env (Proj x i) debug =
883 prettySe 1 env x debug <+> text ("!" ++ show i)
884 prettySe p env (Constant c) debug = pretty c
885 prettySe p env Erased debug = text "[_]"
886 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
888 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
889 prettySb env n (Hole t) = prettyB env "?defer" "." n t
890 prettySb env n (Pi t) = prettyB env "(" ") ->" n t
891 prettySb env n (PVar t) = prettyB env "pat" "." n t
892 prettySb env n (PVTy t) = prettyB env "pty" "." n t
893 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
894 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
896 prettyB env op sc n t debug =
897 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
899 prettyBv env op sc n t v debug =
900 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
901 prettySe 10 env v debug <> text sc
904showEnv' env t dbg = se 10 env t where
905 se p env (P nt n t) = show n
906 ++ if dbg then "{" ++ show nt ++ " : " ++ se 10 env t ++ "}" else ""
907 se p env (V i) | i < length env && i >= 0
908 = (show $ fst $ env!!i) ++
909 if dbg then "{" ++ show i ++ "}" else ""
910 | otherwise = "!!V " ++ show i ++ "!!"
911 se p env (Bind n b@(Pi t) sc)
912 | noOccurrence n sc && not dbg = bracket p 2 $ se 1 env t ++ " -> " ++ se 10 ((n,b):env) sc
913 se p env (Bind n b sc) = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
914 se p env (App f a) = bracket p 1 $ se 1 env f ++ " " ++ se 0 env a
915 se p env (Proj x i) = se 1 env x ++ "!" ++ show i
916 se p env (Constant c) = show c
917 se p env Erased = "[__]"
918 se p env Impossible = "[impossible]"
919 se p env (TType i) = "Type " ++ show i
921 sb env n (Lam t) = showb env "\\ " " => " n t
922 sb env n (Hole t) = showb env "? " ". " n t
923 sb env n (GHole t) = showb env "?defer " ". " n t
924 sb env n (Pi t) = showb env "(" ") -> " n t
925 sb env n (PVar t) = showb env "pat " ". " n t
926 sb env n (PVTy t) = showb env "pty " ". " n t
927 sb env n (Let t v) = showbv env "let " " in " n t v
928 sb env n (Guess t v) = showbv env "?? " " in " n t v
930 showb env op sc n t = op ++ show n ++ " : " ++ se 10 env t ++ sc
931 showbv env op sc n t v = op ++ show n ++ " : " ++ se 10 env t ++ " = " ++
934 bracket outer inner str | inner > outer = "(" ++ str ++ ")"
937-- | Check whether a term has any holes in it - impure if so
938pureTerm :: TT Name -> Bool
939pureTerm (App f a) = pureTerm f && pureTerm a
940pureTerm (Bind n b sc) = notClassName n && pureBinder b && pureTerm sc where
941 pureBinder (Hole _) = False
942 pureBinder (Guess _ _) = False
943 pureBinder (Let t v) = pureTerm t && pureTerm v
944 pureBinder t = pureTerm (binderTy t)
946 notClassName (MN _ "class") = False
947 notClassName _ = True
951-- | Weaken a term by adding i to each de Bruijn index (i.e. lift it over i bindings)
952weakenTm :: Int -> TT n -> TT n
953weakenTm i t = wk i 0 t
954 where wk i min (V x) | x >= min = V (i + x)
955 wk i m (App f a) = App (wk i m f) (wk i m a)
956 wk i m (Bind x b sc) = Bind x (wkb i m b) (wk i (m + 1) sc)
958 wkb i m t = fmap (wk i m) t
960-- | Weaken an environment so that all the de Bruijn indices are correct according
961-- to the latest bound variable
963weakenEnv :: EnvTT n -> EnvTT n
964weakenEnv env = wk (length env - 1) env
966 wk i ((n, b) : bs) = (n, weakenTmB i b) : wk (i - 1) bs
967 weakenTmB i (Let t v) = Let (weakenTm i t) (weakenTm i v)
968 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
969 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
971weakenTmEnv :: Int -> EnvTT n -> EnvTT n
972weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
974orderPats :: Term -> Term
975orderPats tm = op [] tm
977 op ps (Bind n (PVar t) sc) = op ((n, PVar t) : ps) sc
978 op ps (Bind n (Hole t) sc) = op ((n, Hole t) : ps) sc
979 op ps sc = bindAll (map (\ (n, t) -> (n, t)) (sortP ps)) sc
981 sortP ps = pick [] (reverse ps)
983 namesIn (P _ n _) = [n]
984 namesIn (Bind n b t) = nub $ nb b ++ (namesIn t \\ [n])
985 where nb (Let t v) = nub (namesIn t) ++ nub (namesIn v)
986 nb (Guess t v) = nub (namesIn t) ++ nub (namesIn v)
987 nb t = namesIn (binderTy t)
988 namesIn (App f a) = nub (namesIn f ++ namesIn a)
991 pick acc [] = reverse acc
992 pick acc ((n, t) : ps) = pick (insert n t acc) ps
994 insert n t [] = [(n, t)]
995 insert n t ((n',t') : ps)
996 | n `elem` (namesIn (binderTy t') ++
997 concatMap namesIn (map (binderTy . snd) ps))
998 = (n', t') : insert n t ps
999 | 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