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
88 | TooManyArguments Name
92 | NotInjective Term Term Term
94 | CantResolveAlts [String]
99 | NonCollapsiblePostulate Name
100 | AlreadyDefined Name
101 | ProofSearchFail Err
104 | Elaborating String Name Err
105 | ProviderError String
106 | LoadingFailed String Err
109deriving instance NFData Err
112instance Sized Err where
113 size (Msg msg) = length msg
114 size (InternalMsg msg) = length msg
115 size (CantUnify _ left right err _ score) = size left + size right + size err
116 size (InfiniteUnify _ right _) = size right
117 size (CantConvert left right _) = size left + size right
118 size (UnifyScope _ _ right _) = size right
119 size (NoSuchVariable name) = size name
120 size (NoTypeDecl name) = size name
121 size (NotInjective l c r) = size l + size c + size r
122 size (CantResolve trm) = size trm
123 size (NoRewriting trm) = size trm
124 size (CantResolveAlts _) = 1
125 size (IncompleteTerm trm) = size trm
126 size UniverseError = 1
127 size ProgramLineComment = 1
128 size (At fc err) = size fc + size err
129 size (Elaborating _ n err) = size err
130 size (ProviderError msg) = length msg
131 size (LoadingFailed fn e) = 1 + length fn + size e
135score (CantUnify _ _ _ m _ s) = s + score m
136score (CantResolve _) = 20
137score (NoSuchVariable _) = 1000
138score (ProofSearchFail _) = 10000
139score (InternalMsg _) = -1
142instance Show Err where
144 show (InternalMsg s) = "Internal error: " ++ show s
145 show (CantUnify _ l r e sc i) = "CantUnify " ++ show l ++ " " ++ show r ++ " "
146 ++ show e ++ " in " ++ show sc ++ " " ++ show i
147 show (Inaccessible n) = show n ++ " is not an accessible pattern variable"
148 show (ProviderError msg) = "Type provider error: " ++ msg
149 show (LoadingFailed fn e) = "Loading " ++ fn ++ " failed: " ++ show e
152instance Pretty Err where
153 pretty (Msg m) = text m
154 pretty (CantUnify _ l r e _ i) =
155 if size l + size r > breakingSize then
156 text "Cannot unify" <+> colon $$
157 nest nestingSize (pretty l <+> text "and" <+> pretty r) $$
158 nest nestingSize (text "where" <+> pretty e <+> text "with" <+> (text . show $ i))
160 text "Cannot unify" <+> colon <+> pretty l <+> text "and" <+> pretty r $$
161 nest nestingSize (text "where" <+> pretty e <+> text "with" <+> (text . show $ i))
162 pretty (ProviderError msg) = text msg
163 pretty err@(LoadingFailed _ _) = text (show err)
164 pretty _ = text "Error"
166instance Error Err where
171 deriving (Eq, Functor)
173instance Pretty a => Pretty (TC a) where
174 pretty (OK ok) = pretty ok
176 if size err > breakingSize then
177 text "Error" <+> colon $$ (nest nestingSize $ pretty err)
179 text "Error" <+> colon <+> pretty err
181instance Show a => Show (TC a) where
183 show (Error str) = "Error: " ++ show str
185-- at some point, this instance should also carry type checking options
188instance Monad TC where
193 fail e = Error (InternalMsg e)
198trun :: FC -> TC a -> TC a
200trun fc (Error e) = Error (At fc e)
202instance MonadPlus TC where
203 mzero = fail "Unknown error"
204 (OK x) `mplus` _ = OK x
205 _ `mplus` (OK y) = OK y
208discard :: Monad m => m a -> m ()
209discard f = f >> return ()
211showSep :: String -> [String] -> String
214showSep sep (x:xs) = x ++ sep ++ showSep sep xs
216pmap f (x, y) = (f x, f y)
218traceWhen True msg a = trace msg a
219traceWhen False _ a = a
221-- RAW TERMS ----------------------------------------------------------------
223-- | Names are hierarchies of strings, describing scope (so no danger of
224-- duplicate names, but need to be careful on lookup).
225data Name = UN String -- ^ User-provided name
226 | NS Name [String] -- ^ Root, namespaces
227 | MN Int String -- ^ Machine chosen names
228 | NErased -- ^ Name of somethng which is never used in scope
229 | SN SpecialName -- ^ Decorated function names
232deriving instance Binary Name
233deriving instance NFData Name
236data SpecialName = WhereN Int Name Name
237 | InstanceN Name [String]
238 | ParentN Name String
244deriving instance Binary SpecialName
245deriving instance NFData SpecialName
248instance Sized Name where
250 size (NS n els) = 1 + length els
254instance Pretty Name where
255 pretty (UN n) = text n
256 pretty (NS n s) = pretty n
257 pretty (MN i s) = lbrace <+> text s <+> (text . show $ i) <+> rbrace
258 pretty (SN s) = text (show s)
260instance Show Name where
262 show (NS n s) = showSep "." (reverse s) ++ "." ++ show n
263 show (MN _ "underscore") = "_"
264 show (MN i s) = "{" ++ s ++ show i ++ "}"
268instance Show SpecialName where
269 show (WhereN i p c) = show p ++ ", " ++ show c
270 show (InstanceN cl inst) = showSep ", " inst ++ " instance of " ++ show cl
271 show (MethodN m) = "method " ++ show m
272 show (ParentN p c) = show p ++ "#" ++ c
273 show (CaseN n) = "case block in " ++ show n
274 show (ElimN n) = "<<" ++ show n ++ " eliminator>>"
276-- Show a name in a way decorated for code generation, not human reading
277showCG :: Name -> String
279showCG (NS n s) = showSep "." (reverse s) ++ "." ++ showCG n
280showCG (MN _ "underscore") = "_"
281showCG (MN i s) = "{" ++ s ++ show i ++ "}"
282showCG (SN s) = showCG' s
283 where showCG' (WhereN i p c) = showCG p ++ ":" ++ showCG c ++ ":" ++ show i
284 showCG' (InstanceN cl inst) = '@':showCG cl ++ '$':showSep ":" inst
285 showCG' (MethodN m) = '!':showCG m
286 showCG' (ParentN p c) = showCG p ++ "#" ++ show c
287 showCG' (CaseN c) = showCG c ++ "_case"
288 showCG' (ElimN sn) = showCG sn ++ "_elim"
292-- |Contexts allow us to map names to things. A root name maps to a collection
293-- of things in different namespaces with that name.
294type Ctxt a = Map.Map Name (Map.Map Name a)
295emptyContext = Map.empty
297tcname (UN ('@':_)) = True
298tcname (NS n _) = tcname n
299tcname (SN (InstanceN _ _)) = True
300tcname (SN (MethodN _)) = True
301tcname (SN (ParentN _ _)) = True
304implicitable (NS n _) = implicitable n
305implicitable (UN (x:xs)) = isLower x
306implicitable (MN _ _) = True
307implicitable _ = False
312addDef :: Name -> a -> Ctxt a -> Ctxt a
313addDef n v ctxt = case Map.lookup (nsroot n) ctxt of
314 Nothing -> Map.insert (nsroot n)
315 (Map.insert n v Map.empty) ctxt
316 Just xs -> Map.insert (nsroot n)
317 (Map.insert n v xs) ctxt
319{-| Look up a name in the context, given an optional namespace.
320 The name (n) may itself have a (partial) namespace given.
322 Rules for resolution:
324 - if an explicit namespace is given, return the names which match it. If none
325 match, return all names.
327 - if the name has has explicit namespace given, return the names which match it
328 and ignore the given namespace.
330 - otherwise, return all names.
334lookupCtxtName :: Name -> Ctxt a -> [(Name, a)]
335lookupCtxtName n ctxt = case Map.lookup (nsroot n) ctxt of
336 Just xs -> filterNS (Map.toList xs)
340 filterNS ((found, v) : xs)
341 | nsmatch n found = (found, v) : filterNS xs
342 | otherwise = filterNS xs
344 nsmatch (NS n ns) (NS p ps) = ns `isPrefixOf` ps
345 nsmatch (NS _ _) _ = False
346 nsmatch looking found = True
348lookupCtxt :: Name -> Ctxt a -> [a]
349lookupCtxt n ctxt = map snd (lookupCtxtName n ctxt)
351lookupCtxtExact :: Name -> Ctxt a -> [a]
352lookupCtxtExact n ctxt = [ v | (nm, v) <- lookupCtxtName n ctxt, nm == n]
354updateDef :: Name -> (a -> a) -> Ctxt a -> Ctxt a
356 = let ds = lookupCtxtName n ctxt in
357 foldr (\ (n, t) c -> addDef n (f t) c) ctxt ds
359toAlist :: Ctxt a -> [(Name, a)]
360toAlist ctxt = let allns = map snd (Map.toList ctxt) in
361 concat (map (Map.toList) allns)
363addAlist :: Show a => [(Name, a)] -> Ctxt a -> Ctxt a
364addAlist [] ctxt = ctxt
365addAlist ((n, tm) : ds) ctxt = addDef n tm (addAlist ds ctxt)
367data NativeTy = IT8 | IT16 | IT32 | IT64
368 deriving (Show, Eq, Ord, Enum)
370instance Pretty NativeTy where
371 pretty IT8 = text "Bits8"
372 pretty IT16 = text "Bits16"
373 pretty IT32 = text "Bits32"
374 pretty IT64 = text "Bits64"
376data IntTy = ITFixed NativeTy | ITNative | ITBig | ITChar
378 deriving (Show, Eq, Ord)
380data ArithTy = ATInt IntTy | ATFloat -- TODO: Float vectors
381 deriving (Show, Eq, Ord)
383deriving instance NFData IntTy
384deriving instance NFData NativeTy
385deriving instance NFData ArithTy
388instance Pretty ArithTy where
389 pretty (ATInt ITNative) = text "Int"
390 pretty (ATInt ITBig) = text "BigInt"
391 pretty (ATInt ITChar) = text "Char"
392 pretty (ATInt (ITFixed n)) = pretty n
393 pretty (ATInt (ITVec e c)) = pretty e <> text "x" <> (text . show $ c)
394 pretty ATFloat = text "Float"
396nativeTyWidth :: NativeTy -> Int
398nativeTyWidth IT16 = 16
399nativeTyWidth IT32 = 32
400nativeTyWidth IT64 = 64
402{-# DEPRECATED intTyWidth "Non-total function, use nativeTyWidth and appropriate casing" #-}
403intTyWidth :: IntTy -> Int
404intTyWidth (ITFixed n) = nativeTyWidth n
405intTyWidth ITNative = 8 * sizeOf (0 :: Int)
406intTyWidth ITChar = error "IRTS.Lang.intTyWidth: Characters have platform and backend dependent width"
407intTyWidth ITBig = error "IRTS.Lang.intTyWidth: Big integers have variable width"
409data Const = I Int | BI Integer | Fl Double | Ch Char | Str String
410 | B8 Word8 | B16 Word16 | B32 Word32 | B64 Word64
411 | B8V (Vector Word8) | B16V (Vector Word16)
412 | B32V (Vector Word32) | B64V (Vector Word64)
413 | AType ArithTy | StrType
414 | PtrType | VoidType | Forgot
417deriving instance Binary Const
418deriving instance NFData Const
421instance Sized Const where
424instance Pretty Const where
425 pretty (I i) = text . show $ i
426 pretty (BI i) = text . show $ i
427 pretty (Fl f) = text . show $ f
428 pretty (Ch c) = text . show $ c
429 pretty (Str s) = text s
430 pretty (AType a) = pretty a
431 pretty StrType = text "String"
432 pretty PtrType = text "Ptr"
433 pretty VoidType = text "Void"
434 pretty Forgot = text "Forgot"
435 pretty (B8 w) = text . show $ w
436 pretty (B16 w) = text . show $ w
437 pretty (B32 w) = text . show $ w
438 pretty (B64 w) = text . show $ w
441 | RBind Name (Binder Raw) Raw
448instance Sized Raw where
450 size (RBind name bind right) = 1 + size bind + size right
451 size (RApp left right) = 1 + size left + size right
453 size (RForce raw) = 1 + size raw
454 size (RConstant const) = size const
456instance Pretty Raw where
460deriving instance Binary Raw
461deriving instance NFData Raw
464-- | All binding forms are represented in a unform fashion.
465data Binder b = Lam { binderTy :: b {-^ type annotation for bound variable-}}
466 | Pi { binderTy :: b }
467 | Let { binderTy :: b,
468 binderVal :: b {-^ value for bound variable-}}
469 | NLet { binderTy :: b,
471 | Hole { binderTy :: b}
472 | GHole { envlen :: Int,
474 | Guess { binderTy :: b,
476 | PVar { binderTy :: b }
477 | PVTy { binderTy :: b }
478 deriving (Show, Eq, Ord, Functor)
480deriving instance Binary Binder
481deriving instance NFData Binder
484instance Sized a => Sized (Binder a) where
485 size (Lam ty) = 1 + size ty
486 size (Pi ty) = 1 + size ty
487 size (Let ty val) = 1 + size ty + size val
488 size (NLet ty val) = 1 + size ty + size val
489 size (Hole ty) = 1 + size ty
490 size (GHole _ ty) = 1 + size ty
491 size (Guess ty val) = 1 + size ty + size val
492 size (PVar ty) = 1 + size ty
493 size (PVTy ty) = 1 + size ty
495fmapMB :: Monad m => (a -> m b) -> Binder a -> m (Binder b)
496fmapMB f (Let t v) = liftM2 Let (f t) (f v)
497fmapMB f (NLet t v) = liftM2 NLet (f t) (f v)
498fmapMB f (Guess t v) = liftM2 Guess (f t) (f v)
499fmapMB f (Lam t) = liftM Lam (f t)
500fmapMB f (Pi t) = liftM Pi (f t)
501fmapMB f (Hole t) = liftM Hole (f t)
502fmapMB f (GHole i t) = liftM (GHole i) (f t)
503fmapMB f (PVar t) = liftM PVar (f t)
504fmapMB f (PVTy t) = liftM PVTy (f t)
506raw_apply :: Raw -> [Raw] -> Raw
508raw_apply f (a : as) = raw_apply (RApp f a) as
510raw_unapply :: Raw -> (Raw, [Raw])
511raw_unapply t = ua [] t where
512 ua args (RApp f a) = ua (a:args) f
513 ua args t = (t, args)
515data RawFun = RawFun { rtype :: Raw,
520data RawDatatype = RDatatype Name Raw [(Name, Raw)]
523data RDef = RFunction RawFun
528type RProgram = [(Name, RDef)]
530-- WELL TYPED TERMS ---------------------------------------------------------
532-- | Universe expressions for universe checking
533data UExp = UVar Int -- ^ universe variable
534 | UVal Int -- ^ explicit universe level
537deriving instance NFData UExp
540instance Sized UExp where
543-- We assume that universe levels have been checked, so anything external
544-- can just have the same universe variable and we won't get any new
547instance Binary UExp where
549 get = return (UVar (-1))
551instance Show UExp where
552 show (UVar x) | x < 26 = [toEnum (x + fromEnum 'a')]
553 | otherwise = toEnum ((x `mod` 26) + fromEnum 'a') : show (x `div` 26)
554 show (UVal x) = show x
555-- show (UMax l r) = "max(" ++ show l ++ ", " ++ show r ++")"
557-- | Universe constraints
558data UConstraint = ULT UExp UExp -- ^ Strictly less than
559 | ULE UExp UExp -- ^ Less than or equal to
562instance Show UConstraint where
563 show (ULT x y) = show x ++ " < " ++ show y
564 show (ULE x y) = show x ++ " <= " ++ show y
566type UCs = (Int, [UConstraint])
570 | DCon Int Int -- ^ Data constructor; Ints are tag and arity
571 | TCon Int Int -- ^ Type constructor; Ints are tag and arity
574deriving instance Binary NameType
575deriving instance NFData NameType
578instance Sized NameType where
581instance Pretty NameType where
584instance Eq NameType where
585 Bound == Bound = True
587 DCon _ a == DCon _ b = (a == b) -- ignore tag
588 TCon _ a == TCon _ b = (a == b) -- ignore tag
591-- | Terms in the core language
592data TT n = P NameType n (TT n) -- ^ named references
593 | V Int -- ^ a resolved de Bruijn-indexed variable
594 | Bind n (Binder (TT n)) (TT n) -- ^ a binding
595 | App (TT n) (TT n) -- ^ function, function type, arg
596 | Constant Const -- ^ constant
597 | Proj (TT n) Int -- ^ argument projection; runtime only
598 -- (-1) is a special case for 'subtract one from BI'
599 | Erased -- ^ an erased term
600 | Impossible -- ^ special case for totality checking
601 | TType UExp -- ^ the type of types at some level
602 deriving (Ord, Functor)
604deriving instance Binary TT
605deriving instance NFData TT
608class TermSize a where
609 termsize :: Name -> a -> Int
611instance TermSize a => TermSize [a] where
613 termsize n (x : xs) = termsize n x + termsize n xs
615instance TermSize (TT Name) where
617 | x == n = 1000000 -- recursive => really big
620 termsize n (Bind n' (Let t v) sc)
621 = let rn = if n == n' then MN 0 "noname" else n in
622 termsize rn v + termsize rn sc
623 termsize n (Bind n' b sc)
624 = let rn = if n == n' then MN 0 "noname" else n in
626 termsize n (App f a) = termsize n f + termsize n a
627 termsize n (Proj t i) = termsize n t
630instance Sized a => Sized (TT a) where
631 size (P name n trm) = 1 + size name + size n + size trm
633 size (Bind nm binder bdy) = 1 + size nm + size binder + size bdy
634 size (App l r) = 1 + size l + size r
635 size (Constant c) = size c
637 size (TType u) = 1 + size u
639instance Pretty a => Pretty (TT a) where
640 pretty _ = text "test"
642type EnvTT n = [(n, Binder (TT n))]
644data Datatype n = Data { d_typename :: n,
647 d_cons :: [(n, TT n)] }
648 deriving (Show, Functor, Eq)
650instance Eq n => Eq (TT n) where
651 (==) (P xt x _) (P yt y _) = x == y
652 (==) (V x) (V y) = x == y
653 (==) (Bind _ xb xs) (Bind _ yb ys) = xb == yb && xs == ys
654 (==) (App fx ax) (App fy ay) = fx == fy && ax == ay
655 (==) (TType _) (TType _) = True -- deal with constraints later
656 (==) (Constant x) (Constant y) = x == y
657 (==) (Proj x i) (Proj y j) = x == y && i == j
662-- * A few handy operations on well typed terms:
664-- | A term is injective iff it is a data constructor, type constructor,
665-- constant, the type Type, pi-binding, or an application of an injective
667isInjective :: TT n -> Bool
668isInjective (P (DCon _ _) _ _) = True
669isInjective (P (TCon _ _) _ _) = True
670isInjective (Constant _) = True
671isInjective (TType x) = True
672isInjective (Bind _ (Pi _) sc) = True
673isInjective (App f a) = isInjective f
676-- | Count the number of instances of a de Bruijn index in a term
677vinstances :: Int -> TT n -> Int
678vinstances i (V x) | i == x = 1
679vinstances i (App f a) = vinstances i f + vinstances i a
680vinstances i (Bind x b sc) = instancesB b + vinstances (i + 1) sc
681 where instancesB (Let t v) = vinstances i v
685instantiate :: TT n -> TT n -> TT n
686instantiate e = subst 0 where
687 subst i (V x) | i == x = e
688 subst i (Bind x b sc) = Bind x (fmap (subst i) b) (subst (i+1) sc)
689 subst i (App f a) = App (subst i f) (subst i a)
690 subst i (Proj x idx) = Proj (subst i x) idx
693substV :: TT n -> TT n -> TT n
694substV x tm = dropV 0 (instantiate x tm) where
695 dropV i (V x) | x > i = V (x - 1)
697 dropV i (Bind x b sc) = Bind x (fmap (dropV i) b) (dropV (i+1) sc)
698 dropV i (App f a) = App (dropV i f) (dropV i a)
699 dropV i (Proj x idx) = Proj (dropV i x) idx
702explicitNames :: TT n -> TT n
703explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
705 (explicitNames (instantiate
706 (P Bound x (binderTy b')) sc))
707explicitNames (App f a) = App (explicitNames f) (explicitNames a)
708explicitNames (Proj x idx) = Proj (explicitNames x) idx
711pToV :: Eq n => n -> TT n -> TT n
713pToV' n i (P _ x _) | n == x = V i
714pToV' n i (Bind x b sc)
715-- We can assume the inner scope has been pToVed already, so continue to
716-- resolve names from the *outer* scope which may happen to have the same id.
717 | n == x = Bind x (fmap (pToV' n i) b) sc
718 | otherwise = Bind x (fmap (pToV' n i) b) (pToV' n (i+1) sc)
719pToV' n i (App f a) = App (pToV' n i f) (pToV' n i a)
720pToV' n i (Proj t idx) = Proj (pToV' n i t) idx
723-- increase de Bruijn indices, as if a binder has been added
724addBinder :: TT n -> TT n
727 ab top (V i) | i >= top = V (i + 1)
729 ab top (Bind x b sc) = Bind x (fmap (ab top) b) (ab (top + 1) sc)
730 ab top (App f a) = App (ab top f) (ab top a)
731 ab top (Proj t idx) = Proj (ab top t) idx
734-- | Convert several names. First in the list comes out as V 0
735pToVs :: Eq n => [n] -> TT n -> TT n
736pToVs ns tm = pToVs' ns tm 0 where
738 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
742 vToP' env (V i) = let (n, b) = (env !! i) in
743 P Bound n (binderTy b)
744 vToP' env (Bind n b sc) = let b' = fmap (vToP' env) b in
745 Bind n b' (vToP' ((n, b'):env) sc)
746 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
749finalise :: Eq n => TT n -> TT n
750finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
751finalise (App f a) = App (finalise f) (finalise a)
754subst :: Eq n => n -> TT n -> TT n -> TT n
755subst n v tm = instantiate v (pToV n tm)
757substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
759substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
761substTerm :: Eq n => TT n -> TT n -> TT n -> TT n
762substTerm old new = st where
763 st t | t == old = new
764 st (App f a) = App (st f) (st a)
765 st (Bind x b sc) = Bind x (fmap st b) (st sc)
768-- Returns true if V 0 and bound name n do not occur in the term
770noOccurrence :: Eq n => n -> TT n -> Bool
771noOccurrence n t = no' 0 t
773 no' i (V x) = not (i == x)
774 no' i (P Bound x _) = not (n == x)
775 no' i (Bind n b sc) = noB' i b && no' (i+1) sc
776 where noB' i (Let t v) = no' i t && no' i v
777 noB' i (Guess t v) = no' i t && no' i v
778 noB' i b = no' i (binderTy b)
779 no' i (App f a) = no' i f && no' i a
780 no' i (Proj x _) = no' i x
783-- | Returns all names used free in the term
784freeNames :: Eq n => TT n -> [n]
785freeNames (P _ n _) = [n]
786freeNames (Bind n (Let t v) sc) = nub $ freeNames v ++ (freeNames sc \\ [n])
788freeNames (Bind n b sc) = nub $ freeNames (binderTy b) ++ (freeNames sc \\ [n])
789freeNames (App f a) = nub $ freeNames f ++ freeNames a
790freeNames (Proj x i) = nub $ freeNames x
793-- | Return the arity of a (normalised) type
795arity (Bind n (Pi t) sc) = 1 + arity sc
798-- | Deconstruct an application; returns the function and a list of arguments
799unApply :: TT n -> (TT n, [TT n])
800unApply t = ua [] t where
801 ua args (App f a) = ua (a:args) f
802 ua args t = (t, args)
804mkApp :: TT n -> [TT n] -> TT n
806mkApp f (a:as) = mkApp (App f a) as
808forget :: TT Name -> Raw
811 fe env (P _ n _) = Var n
812 fe env (V i) = Var (env !! i)
813 fe env (Bind n b sc) = RBind n (fmap (fe env) b)
815 fe env (App f a) = RApp (fe env f) (fe env a)
818 fe env (TType i) = RType
819 fe env Erased = RConstant Forgot
821bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
823bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
825bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
826bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
828getArgTys :: TT n -> [(n, TT n)]
829getArgTys (Bind n (Pi t) sc) = (n, t) : getArgTys sc
832getRetTy :: TT n -> TT n
833getRetTy (Bind n (PVar _) sc) = getRetTy sc
834getRetTy (Bind n (PVTy _) sc) = getRetTy sc
835getRetTy (Bind n (Pi _) sc) = getRetTy sc
838uniqueNameFrom :: [Name] -> [Name] -> Name
839uniqueNameFrom (s : supply) hs
840 | s `elem` hs = uniqueNameFrom supply hs
843uniqueName :: Name -> [Name] -> Name
844uniqueName n hs | n `elem` hs = uniqueName (nextName n) hs
847uniqueBinders :: [Name] -> TT Name -> TT Name
848uniqueBinders ns (Bind n b sc)
849 = let n' = uniqueName n ns in
850 Bind n' (fmap (uniqueBinders (n':ns)) b) (uniqueBinders ns sc)
851uniqueBinders ns (App f a) = App (uniqueBinders ns f) (uniqueBinders ns a)
852uniqueBinders ns t = t
855nextName (NS x s) = NS (nextName x) s
856nextName (MN i n) = MN (i+1) n
857nextName (UN x) = let (num', nm') = span isDigit (reverse x)
859 num = readN (reverse num') in
860 UN (nm ++ show (num+1))
864nextName (SN x) = SN (nextName' x)
866 nextName' (WhereN i f x) = WhereN i f (nextName x)
867 nextName' (CaseN n) = CaseN (nextName n)
868 nextName' (MethodN n) = MethodN (nextName n)
875-- an environment with de Bruijn indices 'normalised' so that they all refer to
878newtype WkEnvTT n = Wk (EnvTT n)
879type WkEnv = WkEnvTT Name
881instance (Eq n, Show n) => Show (TT n) where
882 show t = showEnv [] t
884itBitsName IT8 = "Bits8"
885itBitsName IT16 = "Bits16"
886itBitsName IT32 = "Bits32"
887itBitsName IT64 = "Bits64"
889instance Show Const where
894 show (Str s) = show s
896 show (B16 x) = show x
897 show (B32 x) = show x
898 show (B64 x) = show x
899 show (B8V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
900 show (B16V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
901 show (B32V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
902 show (B64V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
903 show (AType ATFloat) = "Float"
904 show (AType (ATInt ITBig)) = "Integer"
905 show (AType (ATInt ITNative)) = "Int"
906 show (AType (ATInt ITChar)) = "Char"
907 show (AType (ATInt (ITFixed it))) = itBitsName it
908 show (AType (ATInt (ITVec it c))) = itBitsName it ++ "x" ++ show c
909 show StrType = "String"
911 show VoidType = "Void"
913showEnv env t = showEnv' env t False
914showEnvDbg env t = showEnv' env t True
916prettyEnv env t = prettyEnv' env t False
918 prettyEnv' env t dbg = prettySe 10 env t dbg
920 bracket outer inner p
921 | inner > outer = lparen <> p <> rparen
924 prettySe p env (P nt n t) debug =
927 lbrack <+> pretty nt <+> colon <+> prettySe 10 env t debug <+> rbrack
930 prettySe p env (V i) debug
933 text . show . fst $ env!!i
935 lbrack <+> text (show i) <+> rbrack
936 | otherwise = text "unbound" <+> text (show i) <+> text "!"
937 prettySe p env (Bind n b@(Pi t) sc) debug
938 | noOccurrence n sc && not debug =
939 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
940 prettySe p env (Bind n b sc) debug =
941 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
942 prettySe p env (App f a) debug =
943 bracket p 1 $ prettySe 1 env f debug <+> prettySe 0 env a debug
944 prettySe p env (Proj x i) debug =
945 prettySe 1 env x debug <+> text ("!" ++ show i)
946 prettySe p env (Constant c) debug = pretty c
947 prettySe p env Erased debug = text "[_]"
948 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
950 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
951 prettySb env n (Hole t) = prettyB env "?defer" "." n t
952 prettySb env n (Pi t) = prettyB env "(" ") ->" n t
953 prettySb env n (PVar t) = prettyB env "pat" "." n t
954 prettySb env n (PVTy t) = prettyB env "pty" "." n t
955 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
956 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
958 prettyB env op sc n t debug =
959 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
961 prettyBv env op sc n t v debug =
962 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
963 prettySe 10 env v debug <> text sc
966showEnv' env t dbg = se 10 env t where
967 se p env (P nt n t) = show n
968 ++ if dbg then "{" ++ show nt ++ " : " ++ se 10 env t ++ "}" else ""
969 se p env (V i) | i < length env && i >= 0
970 = (show $ fst $ env!!i) ++
971 if dbg then "{" ++ show i ++ "}" else ""
972 | otherwise = "!!V " ++ show i ++ "!!"
973 se p env (Bind n b@(Pi t) sc)
974 | noOccurrence n sc && not dbg = bracket p 2 $ se 1 env t ++ " -> " ++ se 10 ((n,b):env) sc
975 se p env (Bind n b sc) = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
976 se p env (App f a) = bracket p 1 $ se 1 env f ++ " " ++ se 0 env a
977 se p env (Proj x i) = se 1 env x ++ "!" ++ show i
978 se p env (Constant c) = show c
979 se p env Erased = "[__]"
980 se p env Impossible = "[impossible]"
981 se p env (TType i) = "Type " ++ show i
983 sb env n (Lam t) = showb env "\\ " " => " n t
984 sb env n (Hole t) = showb env "? " ". " n t
985 sb env n (GHole i t) = showb env "?defer " ". " n t
986 sb env n (Pi t) = showb env "(" ") -> " n t
987 sb env n (PVar t) = showb env "pat " ". " n t
988 sb env n (PVTy t) = showb env "pty " ". " n t
989 sb env n (Let t v) = showbv env "let " " in " n t v
990 sb env n (Guess t v) = showbv env "?? " " in " n t v
992 showb env op sc n t = op ++ show n ++ " : " ++ se 10 env t ++ sc
993 showbv env op sc n t v = op ++ show n ++ " : " ++ se 10 env t ++ " = " ++
996 bracket outer inner str | inner > outer = "(" ++ str ++ ")"
999-- | Check whether a term has any holes in it - impure if so
1000pureTerm :: TT Name -> Bool
1001pureTerm (App f a) = pureTerm f && pureTerm a
1002pureTerm (Bind n b sc) = notClassName n && pureBinder b && pureTerm sc where
1003 pureBinder (Hole _) = False
1004 pureBinder (Guess _ _) = False
1005 pureBinder (Let t v) = pureTerm t && pureTerm v
1006 pureBinder t = pureTerm (binderTy t)
1008 notClassName (MN _ "class") = False
1009 notClassName _ = True
1013-- | Weaken a term by adding i to each de Bruijn index (i.e. lift it over i bindings)
1014weakenTm :: Int -> TT n -> TT n
1015weakenTm i t = wk i 0 t
1016 where wk i min (V x) | x >= min = V (i + x)
1017 wk i m (App f a) = App (wk i m f) (wk i m a)
1018 wk i m (Bind x b sc) = Bind x (wkb i m b) (wk i (m + 1) sc)
1020 wkb i m t = fmap (wk i m) t
1022-- | Weaken an environment so that all the de Bruijn indices are correct according
1023-- to the latest bound variable
1025weakenEnv :: EnvTT n -> EnvTT n
1026weakenEnv env = wk (length env - 1) env
1028 wk i ((n, b) : bs) = (n, weakenTmB i b) : wk (i - 1) bs
1029 weakenTmB i (Let t v) = Let (weakenTm i t) (weakenTm i v)
1030 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
1031 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
1033weakenTmEnv :: Int -> EnvTT n -> EnvTT n
1034weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
1036orderPats :: Term -> Term
1037orderPats tm = op [] tm
1039 op ps (Bind n (PVar t) sc) = op ((n, PVar t) : ps) sc
1040 op ps (Bind n (Hole t) sc) = op ((n, Hole t) : ps) sc
1041 op ps sc = bindAll (sortP ps) sc
1043 sortP ps = pick [] (reverse ps)
1045 namesIn (P _ n _) = [n]
1046 namesIn (Bind n b t) = nub $ nb b ++ (namesIn t \\ [n])
1047 where nb (Let t v) = nub (namesIn t) ++ nub (namesIn v)
1048 nb (Guess t v) = nub (namesIn t) ++ nub (namesIn v)
1049 nb t = namesIn (binderTy t)
1050 namesIn (App f a) = nub (namesIn f ++ namesIn a)
1053 pick acc [] = reverse acc
1054 pick acc ((n, t) : ps) = pick (insert n t acc) ps
1056 insert n t [] = [(n, t)]
1057 insert n t ((n',t') : ps)
1058 | n `elem` (namesIn (binderTy t') ++
1059 concatMap namesIn (map (binderTy . snd) ps))
1060 = (n', t') : insert n t ps
1061 | 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