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)
312lookupCtxtExact :: Name -> Ctxt a -> [a]
313lookupCtxtExact n ctxt = [ v | (nm, v) <- lookupCtxtName n ctxt, nm == n]
315updateDef :: Name -> (a -> a) -> Ctxt a -> Ctxt a
317 = let ds = lookupCtxtName n ctxt in
318 foldr (\ (n, t) c -> addDef n (f t) c) ctxt ds
320toAlist :: Ctxt a -> [(Name, a)]
321toAlist ctxt = let allns = map snd (Map.toList ctxt) in
322 concat (map (Map.toList) allns)
324addAlist :: Show a => [(Name, a)] -> Ctxt a -> Ctxt a
325addAlist [] ctxt = ctxt
326addAlist ((n, tm) : ds) ctxt = addDef n tm (addAlist ds ctxt)
328data NativeTy = IT8 | IT16 | IT32 | IT64
329 deriving (Show, Eq, Ord, Enum)
331instance Pretty NativeTy where
332 pretty IT8 = text "Bits8"
333 pretty IT16 = text "Bits16"
334 pretty IT32 = text "Bits32"
335 pretty IT64 = text "Bits64"
337data IntTy = ITFixed NativeTy | ITNative | ITBig | ITChar
339 deriving (Show, Eq, Ord)
341data ArithTy = ATInt IntTy | ATFloat -- TODO: Float vectors
342 deriving (Show, Eq, Ord)
344instance Pretty ArithTy where
345 pretty (ATInt ITNative) = text "Int"
346 pretty (ATInt ITBig) = text "BigInt"
347 pretty (ATInt ITChar) = text "Char"
348 pretty (ATInt (ITFixed n)) = pretty n
349 pretty (ATInt (ITVec e c)) = pretty e <> text "x" <> (text . show $ c)
350 pretty ATFloat = text "Float"
352nativeTyWidth :: NativeTy -> Int
354nativeTyWidth IT16 = 16
355nativeTyWidth IT32 = 32
356nativeTyWidth IT64 = 64
358{-# DEPRECATED intTyWidth "Non-total function, use nativeTyWidth and appropriate casing" #-}
359intTyWidth :: IntTy -> Int
360intTyWidth (ITFixed n) = nativeTyWidth n
361intTyWidth ITNative = 8 * sizeOf (0 :: Int)
362intTyWidth ITChar = error "IRTS.Lang.intTyWidth: Characters have platform and backend dependent width"
363intTyWidth ITBig = error "IRTS.Lang.intTyWidth: Big integers have variable width"
365data Const = I Int | BI Integer | Fl Double | Ch Char | Str String
366 | B8 Word8 | B16 Word16 | B32 Word32 | B64 Word64
367 | B8V (Vector Word8) | B16V (Vector Word16)
368 | B32V (Vector Word32) | B64V (Vector Word64)
369 | AType ArithTy | StrType
370 | PtrType | VoidType | Forgot
373deriving instance Binary Const
376instance Sized Const where
379instance Pretty Const where
380 pretty (I i) = text . show $ i
381 pretty (BI i) = text . show $ i
382 pretty (Fl f) = text . show $ f
383 pretty (Ch c) = text . show $ c
384 pretty (Str s) = text s
385 pretty (AType a) = pretty a
386 pretty StrType = text "String"
387 pretty PtrType = text "Ptr"
388 pretty VoidType = text "Void"
389 pretty Forgot = text "Forgot"
390 pretty (B8 w) = text . show $ w
391 pretty (B16 w) = text . show $ w
392 pretty (B32 w) = text . show $ w
393 pretty (B64 w) = text . show $ w
396 | RBind Name (Binder Raw) Raw
403instance Sized Raw where
405 size (RBind name bind right) = 1 + size bind + size right
406 size (RApp left right) = 1 + size left + size right
408 size (RForce raw) = 1 + size raw
409 size (RConstant const) = size const
411instance Pretty Raw where
415deriving instance Binary Raw
418-- | All binding forms are represented in a unform fashion.
419data Binder b = Lam { binderTy :: b {-^ type annotation for bound variable-}}
420 | Pi { binderTy :: b }
421 | Let { binderTy :: b,
422 binderVal :: b {-^ value for bound variable-}}
423 | NLet { binderTy :: b,
425 | Hole { binderTy :: b}
426 | GHole { binderTy :: b}
427 | Guess { binderTy :: b,
429 | PVar { binderTy :: b }
430 | PVTy { binderTy :: b }
431 deriving (Show, Eq, Ord, Functor)
433deriving instance Binary Binder
436instance Sized a => Sized (Binder a) where
437 size (Lam ty) = 1 + size ty
438 size (Pi ty) = 1 + size ty
439 size (Let ty val) = 1 + size ty + size val
440 size (NLet ty val) = 1 + size ty + size val
441 size (Hole ty) = 1 + size ty
442 size (GHole ty) = 1 + size ty
443 size (Guess ty val) = 1 + size ty + size val
444 size (PVar ty) = 1 + size ty
445 size (PVTy ty) = 1 + size ty
447fmapMB :: Monad m => (a -> m b) -> Binder a -> m (Binder b)
448fmapMB f (Let t v) = liftM2 Let (f t) (f v)
449fmapMB f (NLet t v) = liftM2 NLet (f t) (f v)
450fmapMB f (Guess t v) = liftM2 Guess (f t) (f v)
451fmapMB f (Lam t) = liftM Lam (f t)
452fmapMB f (Pi t) = liftM Pi (f t)
453fmapMB f (Hole t) = liftM Hole (f t)
454fmapMB f (GHole t) = liftM GHole (f t)
455fmapMB f (PVar t) = liftM PVar (f t)
456fmapMB f (PVTy t) = liftM PVTy (f t)
458raw_apply :: Raw -> [Raw] -> Raw
460raw_apply f (a : as) = raw_apply (RApp f a) as
462raw_unapply :: Raw -> (Raw, [Raw])
463raw_unapply t = ua [] t where
464 ua args (RApp f a) = ua (a:args) f
465 ua args t = (t, args)
467data RawFun = RawFun { rtype :: Raw,
472data RawDatatype = RDatatype Name Raw [(Name, Raw)]
475data RDef = RFunction RawFun
480type RProgram = [(Name, RDef)]
482-- WELL TYPED TERMS ---------------------------------------------------------
484-- | Universe expressions for universe checking
485data UExp = UVar Int -- ^ universe variable
486 | UVal Int -- ^ explicit universe level
489instance Sized UExp where
492-- We assume that universe levels have been checked, so anything external
493-- can just have the same universe variable and we won't get any new
496instance Binary UExp where
498 get = return (UVar (-1))
500instance Show UExp where
501 show (UVar x) | x < 26 = [toEnum (x + fromEnum 'a')]
502 | otherwise = toEnum ((x `mod` 26) + fromEnum 'a') : show (x `div` 26)
503 show (UVal x) = show x
504-- show (UMax l r) = "max(" ++ show l ++ ", " ++ show r ++")"
506-- | Universe constraints
507data UConstraint = ULT UExp UExp -- ^ Strictly less than
508 | ULE UExp UExp -- ^ Less than or equal to
511instance Show UConstraint where
512 show (ULT x y) = show x ++ " < " ++ show y
513 show (ULE x y) = show x ++ " <= " ++ show y
515type UCs = (Int, [UConstraint])
519 | DCon Int Int -- ^ Data constructor; Ints are tag and arity
520 | TCon Int Int -- ^ Type constructor; Ints are tag and arity
523deriving instance Binary NameType
526instance Sized NameType where
529instance Pretty NameType where
532instance Eq NameType where
533 Bound == Bound = True
535 DCon _ a == DCon _ b = (a == b) -- ignore tag
536 TCon _ a == TCon _ b = (a == b) -- ignore tag
539-- | Terms in the core language
540data TT n = P NameType n (TT n) -- ^ named references
541 | V Int -- ^ a resolved de Bruijn-indexed variable
542 | Bind n (Binder (TT n)) (TT n) -- ^ a binding
543 | App (TT n) (TT n) -- ^ function, function type, arg
544 | Constant Const -- ^ constant
545 | Proj (TT n) Int -- ^ argument projection; runtime only
546 | Erased -- ^ an erased term
547 | Impossible -- ^ special case for totality checking
548 | TType UExp -- ^ the type of types at some level
549 deriving (Ord, Functor)
551deriving instance Binary TT
554class TermSize a where
555 termsize :: Name -> a -> Int
557instance TermSize a => TermSize [a] where
559 termsize n (x : xs) = termsize n x + termsize n xs
561instance TermSize (TT Name) where
563 | x == n = 1000000 -- recursive => really big
566 termsize n (Bind n' (Let t v) sc)
567 = let rn = if n == n' then MN 0 "noname" else n in
568 termsize rn v + termsize rn sc
569 termsize n (Bind n' b sc)
570 = let rn = if n == n' then MN 0 "noname" else n in
572 termsize n (App f a) = termsize n f + termsize n a
573 termsize n (Proj t i) = termsize n t
576instance Sized a => Sized (TT a) where
577 size (P name n trm) = 1 + size name + size n + size trm
579 size (Bind nm binder bdy) = 1 + size nm + size binder + size bdy
580 size (App l r) = 1 + size l + size r
581 size (Constant c) = size c
583 size (TType u) = 1 + size u
585instance Pretty a => Pretty (TT a) where
586 pretty _ = text "test"
588type EnvTT n = [(n, Binder (TT n))]
590data Datatype n = Data { d_typename :: n,
593 d_cons :: [(n, TT n)] }
594 deriving (Show, Functor, Eq)
596instance Eq n => Eq (TT n) where
597 (==) (P xt x _) (P yt y _) = x == y
598 (==) (V x) (V y) = x == y
599 (==) (Bind _ xb xs) (Bind _ yb ys) = xb == yb && xs == ys
600 (==) (App fx ax) (App fy ay) = fx == fy && ax == ay
601 (==) (TType _) (TType _) = True -- deal with constraints later
602 (==) (Constant x) (Constant y) = x == y
603 (==) (Proj x i) (Proj y j) = x == y && i == j
608-- * A few handy operations on well typed terms:
610-- | A term is injective iff it is a data constructor, type constructor,
611-- constant, the type Type, pi-binding, or an application of an injective
613isInjective :: TT n -> Bool
614isInjective (P (DCon _ _) _ _) = True
615isInjective (P (TCon _ _) _ _) = True
616isInjective (Constant _) = True
617isInjective (TType x) = True
618isInjective (Bind _ (Pi _) sc) = True
619isInjective (App f a) = isInjective f
622-- | Count the number of instances of a de Bruijn index in a term
623vinstances :: Int -> TT n -> Int
624vinstances i (V x) | i == x = 1
625vinstances i (App f a) = vinstances i f + vinstances i a
626vinstances i (Bind x b sc) = instancesB b + vinstances (i + 1) sc
627 where instancesB (Let t v) = vinstances i v
631instantiate :: TT n -> TT n -> TT n
632instantiate e = subst 0 where
633 subst i (V x) | i == x = e
634 subst i (Bind x b sc) = Bind x (fmap (subst i) b) (subst (i+1) sc)
635 subst i (App f a) = App (subst i f) (subst i a)
636 subst i (Proj x idx) = Proj (subst i x) idx
639substV :: TT n -> TT n -> TT n
640substV x tm = dropV 0 (instantiate x tm) where
641 dropV i (V x) | x > i = V (x - 1)
643 dropV i (Bind x b sc) = Bind x (fmap (dropV i) b) (dropV (i+1) sc)
644 dropV i (App f a) = App (dropV i f) (dropV i a)
645 dropV i (Proj x idx) = Proj (dropV i x) idx
648explicitNames :: TT n -> TT n
649explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
651 (explicitNames (instantiate
652 (P Bound x (binderTy b')) sc))
653explicitNames (App f a) = App (explicitNames f) (explicitNames a)
654explicitNames (Proj x idx) = Proj (explicitNames x) idx
657pToV :: Eq n => n -> TT n -> TT n
659pToV' n i (P _ x _) | n == x = V i
660pToV' n i (Bind x b sc)
661-- We can assume the inner scope has been pToVed already, so continue to
662-- resolve names from the *outer* scope which may happen to have the same id.
663 | n == x = Bind x (fmap (pToV' n i) b) sc
664 | otherwise = Bind x (fmap (pToV' n i) b) (pToV' n (i+1) sc)
665pToV' n i (App f a) = App (pToV' n i f) (pToV' n i a)
666pToV' n i (Proj t idx) = Proj (pToV' n i t) idx
669-- increase de Bruijn indices, as if a binder has been added
670addBinder :: TT n -> TT n
673 ab top (V i) | i >= top = V (i + 1)
675 ab top (Bind x b sc) = Bind x (fmap (ab top) b) (ab (top + 1) sc)
676 ab top (App f a) = App (ab top f) (ab top a)
677 ab top (Proj t idx) = Proj (ab top t) idx
680-- | Convert several names. First in the list comes out as V 0
681pToVs :: Eq n => [n] -> TT n -> TT n
682pToVs ns tm = pToVs' ns tm 0 where
684 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
688 vToP' env (V i) = let (n, b) = (env !! i) in
689 P Bound n (binderTy b)
690 vToP' env (Bind n b sc) = let b' = fmap (vToP' env) b in
691 Bind n b' (vToP' ((n, b'):env) sc)
692 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
695finalise :: Eq n => TT n -> TT n
696finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
697finalise (App f a) = App (finalise f) (finalise a)
700subst :: Eq n => n -> TT n -> TT n -> TT n
701subst n v tm = instantiate v (pToV n tm)
703substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
705substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
707substTerm :: Eq n => TT n -> TT n -> TT n -> TT n
708substTerm old new = st where
709 st t | t == old = new
710 st (App f a) = App (st f) (st a)
711 st (Bind x b sc) = Bind x (fmap st b) (st sc)
714-- Returns true if V 0 and bound name n do not occur in the term
716noOccurrence :: Eq n => n -> TT n -> Bool
717noOccurrence n t = no' 0 t
719 no' i (V x) = not (i == x)
720 no' i (P Bound x _) = not (n == x)
721 no' i (Bind n b sc) = noB' i b && no' (i+1) sc
722 where noB' i (Let t v) = no' i t && no' i v
723 noB' i (Guess t v) = no' i t && no' i v
724 noB' i b = no' i (binderTy b)
725 no' i (App f a) = no' i f && no' i a
726 no' i (Proj x _) = no' i x
729-- | Returns all names used free in the term
730freeNames :: Eq n => TT n -> [n]
731freeNames (P _ n _) = [n]
732freeNames (Bind n (Let t v) sc) = nub $ freeNames v ++ (freeNames sc \\ [n])
734freeNames (Bind n b sc) = nub $ freeNames (binderTy b) ++ (freeNames sc \\ [n])
735freeNames (App f a) = nub $ freeNames f ++ freeNames a
736freeNames (Proj x i) = nub $ freeNames x
739-- | Return the arity of a (normalised) type
741arity (Bind n (Pi t) sc) = 1 + arity sc
744-- | Deconstruct an application; returns the function and a list of arguments
745unApply :: TT n -> (TT n, [TT n])
746unApply t = ua [] t where
747 ua args (App f a) = ua (a:args) f
748 ua args t = (t, args)
750mkApp :: TT n -> [TT n] -> TT n
752mkApp f (a:as) = mkApp (App f a) as
754forget :: TT Name -> Raw
757 fe env (P _ n _) = Var n
758 fe env (V i) = Var (env !! i)
759 fe env (Bind n b sc) = RBind n (fmap (fe env) b)
761 fe env (App f a) = RApp (fe env f) (fe env a)
764 fe env (TType i) = RType
765 fe env Erased = RConstant Forgot
767bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
769bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
771bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
772bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
774getArgTys :: TT n -> [(n, TT n)]
775getArgTys (Bind n (Pi t) sc) = (n, t) : getArgTys sc
778getRetTy :: TT n -> TT n
779getRetTy (Bind n (PVar _) sc) = getRetTy sc
780getRetTy (Bind n (PVTy _) sc) = getRetTy sc
781getRetTy (Bind n (Pi _) sc) = getRetTy sc
784uniqueName :: Name -> [Name] -> Name
785uniqueName n hs | n `elem` hs = uniqueName (nextName n) hs
788uniqueBinders :: [Name] -> TT Name -> TT Name
789uniqueBinders ns (Bind n b sc)
790 = let n' = uniqueName n ns in
791 Bind n' (fmap (uniqueBinders (n':ns)) b) (uniqueBinders ns sc)
792uniqueBinders ns (App f a) = App (uniqueBinders ns f) (uniqueBinders ns a)
793uniqueBinders ns t = t
796nextName (NS x s) = NS (nextName x) s
797nextName (MN i n) = MN (i+1) n
798nextName (UN x) = let (num', nm') = span isDigit (reverse x)
800 num = readN (reverse num') in
801 UN (nm ++ show (num+1))
805nextName (SN x) = SN (nextName' x)
807 nextName' (WhereN i f x) = WhereN i f (nextName x)
808 nextName' (CaseN n) = CaseN (nextName n)
809 nextName' (MethodN n) = MethodN (nextName n)
816-- an environment with de Bruijn indices 'normalised' so that they all refer to
819newtype WkEnvTT n = Wk (EnvTT n)
820type WkEnv = WkEnvTT Name
822instance (Eq n, Show n) => Show (TT n) where
823 show t = showEnv [] t
825itBitsName IT8 = "Bits8"
826itBitsName IT16 = "Bits16"
827itBitsName IT32 = "Bits32"
828itBitsName IT64 = "Bits64"
830instance Show Const where
835 show (Str s) = show s
837 show (B16 x) = show x
838 show (B32 x) = show x
839 show (B64 x) = show x
840 show (B8V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
841 show (B16V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
842 show (B32V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
843 show (B64V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
844 show (AType ATFloat) = "Float"
845 show (AType (ATInt ITBig)) = "Integer"
846 show (AType (ATInt ITNative)) = "Int"
847 show (AType (ATInt ITChar)) = "Char"
848 show (AType (ATInt (ITFixed it))) = itBitsName it
849 show (AType (ATInt (ITVec it c))) = itBitsName it ++ "x" ++ show c
850 show StrType = "String"
852 show VoidType = "Void"
854showEnv env t = showEnv' env t False
855showEnvDbg env t = showEnv' env t True
857prettyEnv env t = prettyEnv' env t False
859 prettyEnv' env t dbg = prettySe 10 env t dbg
861 bracket outer inner p
862 | inner > outer = lparen <> p <> rparen
865 prettySe p env (P nt n t) debug =
868 lbrack <+> pretty nt <+> colon <+> prettySe 10 env t debug <+> rbrack
871 prettySe p env (V i) debug
874 text . show . fst $ env!!i
876 lbrack <+> text (show i) <+> rbrack
877 | otherwise = text "unbound" <+> text (show i) <+> text "!"
878 prettySe p env (Bind n b@(Pi t) sc) debug
879 | noOccurrence n sc && not debug =
880 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
881 prettySe p env (Bind n b sc) debug =
882 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
883 prettySe p env (App f a) debug =
884 bracket p 1 $ prettySe 1 env f debug <+> prettySe 0 env a debug
885 prettySe p env (Proj x i) debug =
886 prettySe 1 env x debug <+> text ("!" ++ show i)
887 prettySe p env (Constant c) debug = pretty c
888 prettySe p env Erased debug = text "[_]"
889 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
891 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
892 prettySb env n (Hole t) = prettyB env "?defer" "." n t
893 prettySb env n (Pi t) = prettyB env "(" ") ->" n t
894 prettySb env n (PVar t) = prettyB env "pat" "." n t
895 prettySb env n (PVTy t) = prettyB env "pty" "." n t
896 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
897 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
899 prettyB env op sc n t debug =
900 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
902 prettyBv env op sc n t v debug =
903 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
904 prettySe 10 env v debug <> text sc
907showEnv' env t dbg = se 10 env t where
908 se p env (P nt n t) = show n
909 ++ if dbg then "{" ++ show nt ++ " : " ++ se 10 env t ++ "}" else ""
910 se p env (V i) | i < length env && i >= 0
911 = (show $ fst $ env!!i) ++
912 if dbg then "{" ++ show i ++ "}" else ""
913 | otherwise = "!!V " ++ show i ++ "!!"
914 se p env (Bind n b@(Pi t) sc)
915 | noOccurrence n sc && not dbg = bracket p 2 $ se 1 env t ++ " -> " ++ se 10 ((n,b):env) sc
916 se p env (Bind n b sc) = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
917 se p env (App f a) = bracket p 1 $ se 1 env f ++ " " ++ se 0 env a
918 se p env (Proj x i) = se 1 env x ++ "!" ++ show i
919 se p env (Constant c) = show c
920 se p env Erased = "[__]"
921 se p env Impossible = "[impossible]"
922 se p env (TType i) = "Type " ++ show i
924 sb env n (Lam t) = showb env "\\ " " => " n t
925 sb env n (Hole t) = showb env "? " ". " n t
926 sb env n (GHole t) = showb env "?defer " ". " n t
927 sb env n (Pi t) = showb env "(" ") -> " n t
928 sb env n (PVar t) = showb env "pat " ". " n t
929 sb env n (PVTy t) = showb env "pty " ". " n t
930 sb env n (Let t v) = showbv env "let " " in " n t v
931 sb env n (Guess t v) = showbv env "?? " " in " n t v
933 showb env op sc n t = op ++ show n ++ " : " ++ se 10 env t ++ sc
934 showbv env op sc n t v = op ++ show n ++ " : " ++ se 10 env t ++ " = " ++
937 bracket outer inner str | inner > outer = "(" ++ str ++ ")"
940-- | Check whether a term has any holes in it - impure if so
941pureTerm :: TT Name -> Bool
942pureTerm (App f a) = pureTerm f && pureTerm a
943pureTerm (Bind n b sc) = notClassName n && pureBinder b && pureTerm sc where
944 pureBinder (Hole _) = False
945 pureBinder (Guess _ _) = False
946 pureBinder (Let t v) = pureTerm t && pureTerm v
947 pureBinder t = pureTerm (binderTy t)
949 notClassName (MN _ "class") = False
950 notClassName _ = True
954-- | Weaken a term by adding i to each de Bruijn index (i.e. lift it over i bindings)
955weakenTm :: Int -> TT n -> TT n
956weakenTm i t = wk i 0 t
957 where wk i min (V x) | x >= min = V (i + x)
958 wk i m (App f a) = App (wk i m f) (wk i m a)
959 wk i m (Bind x b sc) = Bind x (wkb i m b) (wk i (m + 1) sc)
961 wkb i m t = fmap (wk i m) t
963-- | Weaken an environment so that all the de Bruijn indices are correct according
964-- to the latest bound variable
966weakenEnv :: EnvTT n -> EnvTT n
967weakenEnv env = wk (length env - 1) env
969 wk i ((n, b) : bs) = (n, weakenTmB i b) : wk (i - 1) bs
970 weakenTmB i (Let t v) = Let (weakenTm i t) (weakenTm i v)
971 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
972 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
974weakenTmEnv :: Int -> EnvTT n -> EnvTT n
975weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
977orderPats :: Term -> Term
978orderPats tm = op [] tm
980 op ps (Bind n (PVar t) sc) = op ((n, PVar t) : ps) sc
981 op ps (Bind n (Hole t) sc) = op ((n, Hole t) : ps) sc
982 op ps sc = bindAll (map (\ (n, t) -> (n, t)) (sortP ps)) sc
984 sortP ps = pick [] (reverse ps)
986 namesIn (P _ n _) = [n]
987 namesIn (Bind n b t) = nub $ nb b ++ (namesIn t \\ [n])
988 where nb (Let t v) = nub (namesIn t) ++ nub (namesIn v)
989 nb (Guess t v) = nub (namesIn t) ++ nub (namesIn v)
990 nb t = namesIn (binderTy t)
991 namesIn (App f a) = nub (namesIn f ++ namesIn a)
994 pick acc [] = reverse acc
995 pick acc ((n, t) : ps) = pick (insert n t acc) ps
997 insert n t [] = [(n, t)]
998 insert n t ((n',t') : ps)
999 | n `elem` (namesIn (binderTy t') ++
1000 concatMap namesIn (map (binderTy . snd) ps))
1001 = (n', t') : insert n t ps
1002 | 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