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
243deriving instance Binary SpecialName
244deriving instance NFData SpecialName
247instance Sized Name where
249 size (NS n els) = 1 + length els
253instance Pretty Name where
254 pretty (UN n) = text n
255 pretty (NS n s) = pretty n
256 pretty (MN i s) = lbrace <+> text s <+> (text . show $ i) <+> rbrace
257 pretty (SN s) = text (show s)
259instance Show Name where
261 show (NS n s) = showSep "." (reverse s) ++ "." ++ show n
262 show (MN _ "underscore") = "_"
263 show (MN i s) = "{" ++ s ++ show i ++ "}"
267instance Show SpecialName where
268 show (WhereN i p c) = show p ++ ", " ++ show c
269 show (InstanceN cl inst) = showSep ", " inst ++ " instance of " ++ show cl
270 show (MethodN m) = "method " ++ show m
271 show (ParentN p c) = show p ++ "#" ++ c
272 show (CaseN n) = "case block in " ++ show n
273 show (ElimN n) = "<<" ++ show n ++ " eliminator>>"
275-- Show a name in a way decorated for code generation, not human reading
276showCG :: Name -> String
278showCG (NS n s) = showSep "." (reverse s) ++ "." ++ showCG n
279showCG (MN _ "underscore") = "_"
280showCG (MN i s) = "{" ++ s ++ show i ++ "}"
281showCG (SN s) = showCG' s
282 where showCG' (WhereN i p c) = showCG p ++ ":" ++ showCG c ++ ":" ++ show i
283 showCG' (InstanceN cl inst) = '@':showCG cl ++ '$':showSep ":" inst
284 showCG' (MethodN m) = '!':showCG m
285 showCG' (ParentN p c) = showCG p ++ "#" ++ show c
286 showCG' (CaseN c) = showCG c ++ "_case"
290-- |Contexts allow us to map names to things. A root name maps to a collection
291-- of things in different namespaces with that name.
292type Ctxt a = Map.Map Name (Map.Map Name a)
293emptyContext = Map.empty
295tcname (UN ('@':_)) = True
296tcname (NS n _) = tcname n
297tcname (SN (InstanceN _ _)) = True
298tcname (SN (MethodN _)) = True
299tcname (SN (ParentN _ _)) = True
302implicitable (NS n _) = implicitable n
303implicitable (UN (x:xs)) = isLower x
304implicitable (MN _ _) = True
305implicitable _ = False
310addDef :: Name -> a -> Ctxt a -> Ctxt a
311addDef n v ctxt = case Map.lookup (nsroot n) ctxt of
312 Nothing -> Map.insert (nsroot n)
313 (Map.insert n v Map.empty) ctxt
314 Just xs -> Map.insert (nsroot n)
315 (Map.insert n v xs) ctxt
317{-| Look up a name in the context, given an optional namespace.
318 The name (n) may itself have a (partial) namespace given.
320 Rules for resolution:
322 - if an explicit namespace is given, return the names which match it. If none
323 match, return all names.
325 - if the name has has explicit namespace given, return the names which match it
326 and ignore the given namespace.
328 - otherwise, return all names.
332lookupCtxtName :: Name -> Ctxt a -> [(Name, a)]
333lookupCtxtName n ctxt = case Map.lookup (nsroot n) ctxt of
334 Just xs -> filterNS (Map.toList xs)
338 filterNS ((found, v) : xs)
339 | nsmatch n found = (found, v) : filterNS xs
340 | otherwise = filterNS xs
342 nsmatch (NS n ns) (NS p ps) = ns `isPrefixOf` ps
343 nsmatch (NS _ _) _ = False
344 nsmatch looking found = True
346lookupCtxt :: Name -> Ctxt a -> [a]
347lookupCtxt n ctxt = map snd (lookupCtxtName n ctxt)
349lookupCtxtExact :: Name -> Ctxt a -> [a]
350lookupCtxtExact n ctxt = [ v | (nm, v) <- lookupCtxtName n ctxt, nm == n]
352updateDef :: Name -> (a -> a) -> Ctxt a -> Ctxt a
354 = let ds = lookupCtxtName n ctxt in
355 foldr (\ (n, t) c -> addDef n (f t) c) ctxt ds
357toAlist :: Ctxt a -> [(Name, a)]
358toAlist ctxt = let allns = map snd (Map.toList ctxt) in
359 concat (map (Map.toList) allns)
361addAlist :: Show a => [(Name, a)] -> Ctxt a -> Ctxt a
362addAlist [] ctxt = ctxt
363addAlist ((n, tm) : ds) ctxt = addDef n tm (addAlist ds ctxt)
365data NativeTy = IT8 | IT16 | IT32 | IT64
366 deriving (Show, Eq, Ord, Enum)
368instance Pretty NativeTy where
369 pretty IT8 = text "Bits8"
370 pretty IT16 = text "Bits16"
371 pretty IT32 = text "Bits32"
372 pretty IT64 = text "Bits64"
374data IntTy = ITFixed NativeTy | ITNative | ITBig | ITChar
376 deriving (Show, Eq, Ord)
378data ArithTy = ATInt IntTy | ATFloat -- TODO: Float vectors
379 deriving (Show, Eq, Ord)
381deriving instance NFData IntTy
382deriving instance NFData NativeTy
383deriving instance NFData ArithTy
386instance Pretty ArithTy where
387 pretty (ATInt ITNative) = text "Int"
388 pretty (ATInt ITBig) = text "BigInt"
389 pretty (ATInt ITChar) = text "Char"
390 pretty (ATInt (ITFixed n)) = pretty n
391 pretty (ATInt (ITVec e c)) = pretty e <> text "x" <> (text . show $ c)
392 pretty ATFloat = text "Float"
394nativeTyWidth :: NativeTy -> Int
396nativeTyWidth IT16 = 16
397nativeTyWidth IT32 = 32
398nativeTyWidth IT64 = 64
400{-# DEPRECATED intTyWidth "Non-total function, use nativeTyWidth and appropriate casing" #-}
401intTyWidth :: IntTy -> Int
402intTyWidth (ITFixed n) = nativeTyWidth n
403intTyWidth ITNative = 8 * sizeOf (0 :: Int)
404intTyWidth ITChar = error "IRTS.Lang.intTyWidth: Characters have platform and backend dependent width"
405intTyWidth ITBig = error "IRTS.Lang.intTyWidth: Big integers have variable width"
407data Const = I Int | BI Integer | Fl Double | Ch Char | Str String
408 | B8 Word8 | B16 Word16 | B32 Word32 | B64 Word64
409 | B8V (Vector Word8) | B16V (Vector Word16)
410 | B32V (Vector Word32) | B64V (Vector Word64)
411 | AType ArithTy | StrType
412 | PtrType | VoidType | Forgot
415deriving instance Binary Const
416deriving instance NFData Const
419instance Sized Const where
422instance Pretty Const where
423 pretty (I i) = text . show $ i
424 pretty (BI i) = text . show $ i
425 pretty (Fl f) = text . show $ f
426 pretty (Ch c) = text . show $ c
427 pretty (Str s) = text s
428 pretty (AType a) = pretty a
429 pretty StrType = text "String"
430 pretty PtrType = text "Ptr"
431 pretty VoidType = text "Void"
432 pretty Forgot = text "Forgot"
433 pretty (B8 w) = text . show $ w
434 pretty (B16 w) = text . show $ w
435 pretty (B32 w) = text . show $ w
436 pretty (B64 w) = text . show $ w
439 | RBind Name (Binder Raw) Raw
446instance Sized Raw where
448 size (RBind name bind right) = 1 + size bind + size right
449 size (RApp left right) = 1 + size left + size right
451 size (RForce raw) = 1 + size raw
452 size (RConstant const) = size const
454instance Pretty Raw where
458deriving instance Binary Raw
459deriving instance NFData Raw
462-- | All binding forms are represented in a unform fashion.
463data Binder b = Lam { binderTy :: b {-^ type annotation for bound variable-}}
464 | Pi { binderTy :: b }
465 | Let { binderTy :: b,
466 binderVal :: b {-^ value for bound variable-}}
467 | NLet { binderTy :: b,
469 | Hole { binderTy :: b}
470 | GHole { envlen :: Int,
472 | Guess { binderTy :: b,
474 | PVar { binderTy :: b }
475 | PVTy { binderTy :: b }
476 deriving (Show, Eq, Ord, Functor)
478deriving instance Binary Binder
479deriving instance NFData Binder
482instance Sized a => Sized (Binder a) where
483 size (Lam ty) = 1 + size ty
484 size (Pi ty) = 1 + size ty
485 size (Let ty val) = 1 + size ty + size val
486 size (NLet ty val) = 1 + size ty + size val
487 size (Hole ty) = 1 + size ty
488 size (GHole _ ty) = 1 + size ty
489 size (Guess ty val) = 1 + size ty + size val
490 size (PVar ty) = 1 + size ty
491 size (PVTy ty) = 1 + size ty
493fmapMB :: Monad m => (a -> m b) -> Binder a -> m (Binder b)
494fmapMB f (Let t v) = liftM2 Let (f t) (f v)
495fmapMB f (NLet t v) = liftM2 NLet (f t) (f v)
496fmapMB f (Guess t v) = liftM2 Guess (f t) (f v)
497fmapMB f (Lam t) = liftM Lam (f t)
498fmapMB f (Pi t) = liftM Pi (f t)
499fmapMB f (Hole t) = liftM Hole (f t)
500fmapMB f (GHole i t) = liftM (GHole i) (f t)
501fmapMB f (PVar t) = liftM PVar (f t)
502fmapMB f (PVTy t) = liftM PVTy (f t)
504raw_apply :: Raw -> [Raw] -> Raw
506raw_apply f (a : as) = raw_apply (RApp f a) as
508raw_unapply :: Raw -> (Raw, [Raw])
509raw_unapply t = ua [] t where
510 ua args (RApp f a) = ua (a:args) f
511 ua args t = (t, args)
513data RawFun = RawFun { rtype :: Raw,
518data RawDatatype = RDatatype Name Raw [(Name, Raw)]
521data RDef = RFunction RawFun
526type RProgram = [(Name, RDef)]
528-- WELL TYPED TERMS ---------------------------------------------------------
530-- | Universe expressions for universe checking
531data UExp = UVar Int -- ^ universe variable
532 | UVal Int -- ^ explicit universe level
535deriving instance NFData UExp
538instance Sized UExp where
541-- We assume that universe levels have been checked, so anything external
542-- can just have the same universe variable and we won't get any new
545instance Binary UExp where
547 get = return (UVar (-1))
549instance Show UExp where
550 show (UVar x) | x < 26 = [toEnum (x + fromEnum 'a')]
551 | otherwise = toEnum ((x `mod` 26) + fromEnum 'a') : show (x `div` 26)
552 show (UVal x) = show x
553-- show (UMax l r) = "max(" ++ show l ++ ", " ++ show r ++")"
555-- | Universe constraints
556data UConstraint = ULT UExp UExp -- ^ Strictly less than
557 | ULE UExp UExp -- ^ Less than or equal to
560instance Show UConstraint where
561 show (ULT x y) = show x ++ " < " ++ show y
562 show (ULE x y) = show x ++ " <= " ++ show y
564type UCs = (Int, [UConstraint])
568 | DCon Int Int -- ^ Data constructor; Ints are tag and arity
569 | TCon Int Int -- ^ Type constructor; Ints are tag and arity
572deriving instance Binary NameType
573deriving instance NFData NameType
576instance Sized NameType where
579instance Pretty NameType where
582instance Eq NameType where
583 Bound == Bound = True
585 DCon _ a == DCon _ b = (a == b) -- ignore tag
586 TCon _ a == TCon _ b = (a == b) -- ignore tag
589-- | Terms in the core language
590data TT n = P NameType n (TT n) -- ^ named references
591 | V Int -- ^ a resolved de Bruijn-indexed variable
592 | Bind n (Binder (TT n)) (TT n) -- ^ a binding
593 | App (TT n) (TT n) -- ^ function, function type, arg
594 | Constant Const -- ^ constant
595 | Proj (TT n) Int -- ^ argument projection; runtime only
596 -- (-1) is a special case for 'subtract one from BI'
597 | Erased -- ^ an erased term
598 | Impossible -- ^ special case for totality checking
599 | TType UExp -- ^ the type of types at some level
600 deriving (Ord, Functor)
602deriving instance Binary TT
603deriving instance NFData TT
606class TermSize a where
607 termsize :: Name -> a -> Int
609instance TermSize a => TermSize [a] where
611 termsize n (x : xs) = termsize n x + termsize n xs
613instance TermSize (TT Name) where
615 | x == n = 1000000 -- recursive => really big
618 termsize n (Bind n' (Let t v) sc)
619 = let rn = if n == n' then MN 0 "noname" else n in
620 termsize rn v + termsize rn sc
621 termsize n (Bind n' b sc)
622 = let rn = if n == n' then MN 0 "noname" else n in
624 termsize n (App f a) = termsize n f + termsize n a
625 termsize n (Proj t i) = termsize n t
628instance Sized a => Sized (TT a) where
629 size (P name n trm) = 1 + size name + size n + size trm
631 size (Bind nm binder bdy) = 1 + size nm + size binder + size bdy
632 size (App l r) = 1 + size l + size r
633 size (Constant c) = size c
635 size (TType u) = 1 + size u
637instance Pretty a => Pretty (TT a) where
638 pretty _ = text "test"
640type EnvTT n = [(n, Binder (TT n))]
642data Datatype n = Data { d_typename :: n,
645 d_cons :: [(n, TT n)] }
646 deriving (Show, Functor, Eq)
648instance Eq n => Eq (TT n) where
649 (==) (P xt x _) (P yt y _) = x == y
650 (==) (V x) (V y) = x == y
651 (==) (Bind _ xb xs) (Bind _ yb ys) = xb == yb && xs == ys
652 (==) (App fx ax) (App fy ay) = fx == fy && ax == ay
653 (==) (TType _) (TType _) = True -- deal with constraints later
654 (==) (Constant x) (Constant y) = x == y
655 (==) (Proj x i) (Proj y j) = x == y && i == j
660-- * A few handy operations on well typed terms:
662-- | A term is injective iff it is a data constructor, type constructor,
663-- constant, the type Type, pi-binding, or an application of an injective
665isInjective :: TT n -> Bool
666isInjective (P (DCon _ _) _ _) = True
667isInjective (P (TCon _ _) _ _) = True
668isInjective (Constant _) = True
669isInjective (TType x) = True
670isInjective (Bind _ (Pi _) sc) = True
671isInjective (App f a) = isInjective f
674-- | Count the number of instances of a de Bruijn index in a term
675vinstances :: Int -> TT n -> Int
676vinstances i (V x) | i == x = 1
677vinstances i (App f a) = vinstances i f + vinstances i a
678vinstances i (Bind x b sc) = instancesB b + vinstances (i + 1) sc
679 where instancesB (Let t v) = vinstances i v
683instantiate :: TT n -> TT n -> TT n
684instantiate e = subst 0 where
685 subst i (V x) | i == x = e
686 subst i (Bind x b sc) = Bind x (fmap (subst i) b) (subst (i+1) sc)
687 subst i (App f a) = App (subst i f) (subst i a)
688 subst i (Proj x idx) = Proj (subst i x) idx
691substV :: TT n -> TT n -> TT n
692substV x tm = dropV 0 (instantiate x tm) where
693 dropV i (V x) | x > i = V (x - 1)
695 dropV i (Bind x b sc) = Bind x (fmap (dropV i) b) (dropV (i+1) sc)
696 dropV i (App f a) = App (dropV i f) (dropV i a)
697 dropV i (Proj x idx) = Proj (dropV i x) idx
700explicitNames :: TT n -> TT n
701explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
703 (explicitNames (instantiate
704 (P Bound x (binderTy b')) sc))
705explicitNames (App f a) = App (explicitNames f) (explicitNames a)
706explicitNames (Proj x idx) = Proj (explicitNames x) idx
709pToV :: Eq n => n -> TT n -> TT n
711pToV' n i (P _ x _) | n == x = V i
712pToV' n i (Bind x b sc)
713-- We can assume the inner scope has been pToVed already, so continue to
714-- resolve names from the *outer* scope which may happen to have the same id.
715 | n == x = Bind x (fmap (pToV' n i) b) sc
716 | otherwise = Bind x (fmap (pToV' n i) b) (pToV' n (i+1) sc)
717pToV' n i (App f a) = App (pToV' n i f) (pToV' n i a)
718pToV' n i (Proj t idx) = Proj (pToV' n i t) idx
721-- increase de Bruijn indices, as if a binder has been added
722addBinder :: TT n -> TT n
725 ab top (V i) | i >= top = V (i + 1)
727 ab top (Bind x b sc) = Bind x (fmap (ab top) b) (ab (top + 1) sc)
728 ab top (App f a) = App (ab top f) (ab top a)
729 ab top (Proj t idx) = Proj (ab top t) idx
732-- | Convert several names. First in the list comes out as V 0
733pToVs :: Eq n => [n] -> TT n -> TT n
734pToVs ns tm = pToVs' ns tm 0 where
736 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
740 vToP' env (V i) = let (n, b) = (env !! i) in
741 P Bound n (binderTy b)
742 vToP' env (Bind n b sc) = let b' = fmap (vToP' env) b in
743 Bind n b' (vToP' ((n, b'):env) sc)
744 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
747finalise :: Eq n => TT n -> TT n
748finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
749finalise (App f a) = App (finalise f) (finalise a)
752subst :: Eq n => n -> TT n -> TT n -> TT n
753subst n v tm = instantiate v (pToV n tm)
755substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
757substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
759substTerm :: Eq n => TT n -> TT n -> TT n -> TT n
760substTerm old new = st where
761 st t | t == old = new
762 st (App f a) = App (st f) (st a)
763 st (Bind x b sc) = Bind x (fmap st b) (st sc)
766-- Returns true if V 0 and bound name n do not occur in the term
768noOccurrence :: Eq n => n -> TT n -> Bool
769noOccurrence n t = no' 0 t
771 no' i (V x) = not (i == x)
772 no' i (P Bound x _) = not (n == x)
773 no' i (Bind n b sc) = noB' i b && no' (i+1) sc
774 where noB' i (Let t v) = no' i t && no' i v
775 noB' i (Guess t v) = no' i t && no' i v
776 noB' i b = no' i (binderTy b)
777 no' i (App f a) = no' i f && no' i a
778 no' i (Proj x _) = no' i x
781-- | Returns all names used free in the term
782freeNames :: Eq n => TT n -> [n]
783freeNames (P _ n _) = [n]
784freeNames (Bind n (Let t v) sc) = nub $ freeNames v ++ (freeNames sc \\ [n])
786freeNames (Bind n b sc) = nub $ freeNames (binderTy b) ++ (freeNames sc \\ [n])
787freeNames (App f a) = nub $ freeNames f ++ freeNames a
788freeNames (Proj x i) = nub $ freeNames x
791-- | Return the arity of a (normalised) type
793arity (Bind n (Pi t) sc) = 1 + arity sc
796-- | Deconstruct an application; returns the function and a list of arguments
797unApply :: TT n -> (TT n, [TT n])
798unApply t = ua [] t where
799 ua args (App f a) = ua (a:args) f
800 ua args t = (t, args)
802mkApp :: TT n -> [TT n] -> TT n
804mkApp f (a:as) = mkApp (App f a) as
806forget :: TT Name -> Raw
809 fe env (P _ n _) = Var n
810 fe env (V i) = Var (env !! i)
811 fe env (Bind n b sc) = RBind n (fmap (fe env) b)
813 fe env (App f a) = RApp (fe env f) (fe env a)
816 fe env (TType i) = RType
817 fe env Erased = RConstant Forgot
819bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
821bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
823bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
824bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
826getArgTys :: TT n -> [(n, TT n)]
827getArgTys (Bind n (Pi t) sc) = (n, t) : getArgTys sc
830getRetTy :: TT n -> TT n
831getRetTy (Bind n (PVar _) sc) = getRetTy sc
832getRetTy (Bind n (PVTy _) sc) = getRetTy sc
833getRetTy (Bind n (Pi _) sc) = getRetTy sc
836uniqueName :: Name -> [Name] -> Name
837uniqueName n hs | n `elem` hs = uniqueName (nextName n) hs
840uniqueBinders :: [Name] -> TT Name -> TT Name
841uniqueBinders ns (Bind n b sc)
842 = let n' = uniqueName n ns in
843 Bind n' (fmap (uniqueBinders (n':ns)) b) (uniqueBinders ns sc)
844uniqueBinders ns (App f a) = App (uniqueBinders ns f) (uniqueBinders ns a)
845uniqueBinders ns t = t
848nextName (NS x s) = NS (nextName x) s
849nextName (MN i n) = MN (i+1) n
850nextName (UN x) = let (num', nm') = span isDigit (reverse x)
852 num = readN (reverse num') in
853 UN (nm ++ show (num+1))
857nextName (SN x) = SN (nextName' x)
859 nextName' (WhereN i f x) = WhereN i f (nextName x)
860 nextName' (CaseN n) = CaseN (nextName n)
861 nextName' (MethodN n) = MethodN (nextName n)
868-- an environment with de Bruijn indices 'normalised' so that they all refer to
871newtype WkEnvTT n = Wk (EnvTT n)
872type WkEnv = WkEnvTT Name
874instance (Eq n, Show n) => Show (TT n) where
875 show t = showEnv [] t
877itBitsName IT8 = "Bits8"
878itBitsName IT16 = "Bits16"
879itBitsName IT32 = "Bits32"
880itBitsName IT64 = "Bits64"
882instance Show Const where
887 show (Str s) = show s
889 show (B16 x) = show x
890 show (B32 x) = show x
891 show (B64 x) = show x
892 show (B8V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
893 show (B16V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
894 show (B32V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
895 show (B64V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
896 show (AType ATFloat) = "Float"
897 show (AType (ATInt ITBig)) = "Integer"
898 show (AType (ATInt ITNative)) = "Int"
899 show (AType (ATInt ITChar)) = "Char"
900 show (AType (ATInt (ITFixed it))) = itBitsName it
901 show (AType (ATInt (ITVec it c))) = itBitsName it ++ "x" ++ show c
902 show StrType = "String"
904 show VoidType = "Void"
906showEnv env t = showEnv' env t False
907showEnvDbg env t = showEnv' env t True
909prettyEnv env t = prettyEnv' env t False
911 prettyEnv' env t dbg = prettySe 10 env t dbg
913 bracket outer inner p
914 | inner > outer = lparen <> p <> rparen
917 prettySe p env (P nt n t) debug =
920 lbrack <+> pretty nt <+> colon <+> prettySe 10 env t debug <+> rbrack
923 prettySe p env (V i) debug
926 text . show . fst $ env!!i
928 lbrack <+> text (show i) <+> rbrack
929 | otherwise = text "unbound" <+> text (show i) <+> text "!"
930 prettySe p env (Bind n b@(Pi t) sc) debug
931 | noOccurrence n sc && not debug =
932 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
933 prettySe p env (Bind n b sc) debug =
934 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
935 prettySe p env (App f a) debug =
936 bracket p 1 $ prettySe 1 env f debug <+> prettySe 0 env a debug
937 prettySe p env (Proj x i) debug =
938 prettySe 1 env x debug <+> text ("!" ++ show i)
939 prettySe p env (Constant c) debug = pretty c
940 prettySe p env Erased debug = text "[_]"
941 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
943 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
944 prettySb env n (Hole t) = prettyB env "?defer" "." n t
945 prettySb env n (Pi t) = prettyB env "(" ") ->" n t
946 prettySb env n (PVar t) = prettyB env "pat" "." n t
947 prettySb env n (PVTy t) = prettyB env "pty" "." n t
948 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
949 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
951 prettyB env op sc n t debug =
952 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
954 prettyBv env op sc n t v debug =
955 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
956 prettySe 10 env v debug <> text sc
959showEnv' env t dbg = se 10 env t where
960 se p env (P nt n t) = show n
961 ++ if dbg then "{" ++ show nt ++ " : " ++ se 10 env t ++ "}" else ""
962 se p env (V i) | i < length env && i >= 0
963 = (show $ fst $ env!!i) ++
964 if dbg then "{" ++ show i ++ "}" else ""
965 | otherwise = "!!V " ++ show i ++ "!!"
966 se p env (Bind n b@(Pi t) sc)
967 | noOccurrence n sc && not dbg = bracket p 2 $ se 1 env t ++ " -> " ++ se 10 ((n,b):env) sc
968 se p env (Bind n b sc) = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
969 se p env (App f a) = bracket p 1 $ se 1 env f ++ " " ++ se 0 env a
970 se p env (Proj x i) = se 1 env x ++ "!" ++ show i
971 se p env (Constant c) = show c
972 se p env Erased = "[__]"
973 se p env Impossible = "[impossible]"
974 se p env (TType i) = "Type " ++ show i
976 sb env n (Lam t) = showb env "\\ " " => " n t
977 sb env n (Hole t) = showb env "? " ". " n t
978 sb env n (GHole i t) = showb env "?defer " ". " n t
979 sb env n (Pi t) = showb env "(" ") -> " n t
980 sb env n (PVar t) = showb env "pat " ". " n t
981 sb env n (PVTy t) = showb env "pty " ". " n t
982 sb env n (Let t v) = showbv env "let " " in " n t v
983 sb env n (Guess t v) = showbv env "?? " " in " n t v
985 showb env op sc n t = op ++ show n ++ " : " ++ se 10 env t ++ sc
986 showbv env op sc n t v = op ++ show n ++ " : " ++ se 10 env t ++ " = " ++
989 bracket outer inner str | inner > outer = "(" ++ str ++ ")"
992-- | Check whether a term has any holes in it - impure if so
993pureTerm :: TT Name -> Bool
994pureTerm (App f a) = pureTerm f && pureTerm a
995pureTerm (Bind n b sc) = notClassName n && pureBinder b && pureTerm sc where
996 pureBinder (Hole _) = False
997 pureBinder (Guess _ _) = False
998 pureBinder (Let t v) = pureTerm t && pureTerm v
999 pureBinder t = pureTerm (binderTy t)
1001 notClassName (MN _ "class") = False
1002 notClassName _ = True
1006-- | Weaken a term by adding i to each de Bruijn index (i.e. lift it over i bindings)
1007weakenTm :: Int -> TT n -> TT n
1008weakenTm i t = wk i 0 t
1009 where wk i min (V x) | x >= min = V (i + x)
1010 wk i m (App f a) = App (wk i m f) (wk i m a)
1011 wk i m (Bind x b sc) = Bind x (wkb i m b) (wk i (m + 1) sc)
1013 wkb i m t = fmap (wk i m) t
1015-- | Weaken an environment so that all the de Bruijn indices are correct according
1016-- to the latest bound variable
1018weakenEnv :: EnvTT n -> EnvTT n
1019weakenEnv env = wk (length env - 1) env
1021 wk i ((n, b) : bs) = (n, weakenTmB i b) : wk (i - 1) bs
1022 weakenTmB i (Let t v) = Let (weakenTm i t) (weakenTm i v)
1023 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
1024 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
1026weakenTmEnv :: Int -> EnvTT n -> EnvTT n
1027weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
1029orderPats :: Term -> Term
1030orderPats tm = op [] tm
1032 op ps (Bind n (PVar t) sc) = op ((n, PVar t) : ps) sc
1033 op ps (Bind n (Hole t) sc) = op ((n, Hole t) : ps) sc
1034 op ps sc = bindAll (sortP ps) sc
1036 sortP ps = pick [] (reverse ps)
1038 namesIn (P _ n _) = [n]
1039 namesIn (Bind n b t) = nub $ nb b ++ (namesIn t \\ [n])
1040 where nb (Let t v) = nub (namesIn t) ++ nub (namesIn v)
1041 nb (Guess t v) = nub (namesIn t) ++ nub (namesIn v)
1042 nb t = namesIn (binderTy t)
1043 namesIn (App f a) = nub (namesIn f ++ namesIn a)
1046 pick acc [] = reverse acc
1047 pick acc ((n, t) : ps) = pick (insert n t acc) ps
1049 insert n t [] = [(n, t)]
1050 insert n t ((n',t') : ps)
1051 | n `elem` (namesIn (binderTy t') ++
1052 concatMap namesIn (map (binderTy . snd) ps))
1053 = (n', t') : insert n t ps
1054 | 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