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"
291-- |Contexts allow us to map names to things. A root name maps to a collection
292-- of things in different namespaces with that name.
293type Ctxt a = Map.Map Name (Map.Map Name a)
294emptyContext = Map.empty
296tcname (UN ('@':_)) = True
297tcname (NS n _) = tcname n
298tcname (SN (InstanceN _ _)) = True
299tcname (SN (MethodN _)) = True
300tcname (SN (ParentN _ _)) = True
303implicitable (NS n _) = implicitable n
304implicitable (UN (x:xs)) = isLower x
305implicitable (MN _ _) = True
306implicitable _ = False
311addDef :: Name -> a -> Ctxt a -> Ctxt a
312addDef n v ctxt = case Map.lookup (nsroot n) ctxt of
313 Nothing -> Map.insert (nsroot n)
314 (Map.insert n v Map.empty) ctxt
315 Just xs -> Map.insert (nsroot n)
316 (Map.insert n v xs) ctxt
318{-| Look up a name in the context, given an optional namespace.
319 The name (n) may itself have a (partial) namespace given.
321 Rules for resolution:
323 - if an explicit namespace is given, return the names which match it. If none
324 match, return all names.
326 - if the name has has explicit namespace given, return the names which match it
327 and ignore the given namespace.
329 - otherwise, return all names.
333lookupCtxtName :: Name -> Ctxt a -> [(Name, a)]
334lookupCtxtName n ctxt = case Map.lookup (nsroot n) ctxt of
335 Just xs -> filterNS (Map.toList xs)
339 filterNS ((found, v) : xs)
340 | nsmatch n found = (found, v) : filterNS xs
341 | otherwise = filterNS xs
343 nsmatch (NS n ns) (NS p ps) = ns `isPrefixOf` ps
344 nsmatch (NS _ _) _ = False
345 nsmatch looking found = True
347lookupCtxt :: Name -> Ctxt a -> [a]
348lookupCtxt n ctxt = map snd (lookupCtxtName n ctxt)
350lookupCtxtExact :: Name -> Ctxt a -> [a]
351lookupCtxtExact n ctxt = [ v | (nm, v) <- lookupCtxtName n ctxt, nm == n]
353updateDef :: Name -> (a -> a) -> Ctxt a -> Ctxt a
355 = let ds = lookupCtxtName n ctxt in
356 foldr (\ (n, t) c -> addDef n (f t) c) ctxt ds
358toAlist :: Ctxt a -> [(Name, a)]
359toAlist ctxt = let allns = map snd (Map.toList ctxt) in
360 concat (map (Map.toList) allns)
362addAlist :: Show a => [(Name, a)] -> Ctxt a -> Ctxt a
363addAlist [] ctxt = ctxt
364addAlist ((n, tm) : ds) ctxt = addDef n tm (addAlist ds ctxt)
366data NativeTy = IT8 | IT16 | IT32 | IT64
367 deriving (Show, Eq, Ord, Enum)
369instance Pretty NativeTy where
370 pretty IT8 = text "Bits8"
371 pretty IT16 = text "Bits16"
372 pretty IT32 = text "Bits32"
373 pretty IT64 = text "Bits64"
375data IntTy = ITFixed NativeTy | ITNative | ITBig | ITChar
377 deriving (Show, Eq, Ord)
379data ArithTy = ATInt IntTy | ATFloat -- TODO: Float vectors
380 deriving (Show, Eq, Ord)
382deriving instance NFData IntTy
383deriving instance NFData NativeTy
384deriving instance NFData ArithTy
387instance Pretty ArithTy where
388 pretty (ATInt ITNative) = text "Int"
389 pretty (ATInt ITBig) = text "BigInt"
390 pretty (ATInt ITChar) = text "Char"
391 pretty (ATInt (ITFixed n)) = pretty n
392 pretty (ATInt (ITVec e c)) = pretty e <> text "x" <> (text . show $ c)
393 pretty ATFloat = text "Float"
395nativeTyWidth :: NativeTy -> Int
397nativeTyWidth IT16 = 16
398nativeTyWidth IT32 = 32
399nativeTyWidth IT64 = 64
401{-# DEPRECATED intTyWidth "Non-total function, use nativeTyWidth and appropriate casing" #-}
402intTyWidth :: IntTy -> Int
403intTyWidth (ITFixed n) = nativeTyWidth n
404intTyWidth ITNative = 8 * sizeOf (0 :: Int)
405intTyWidth ITChar = error "IRTS.Lang.intTyWidth: Characters have platform and backend dependent width"
406intTyWidth ITBig = error "IRTS.Lang.intTyWidth: Big integers have variable width"
408data Const = I Int | BI Integer | Fl Double | Ch Char | Str String
409 | B8 Word8 | B16 Word16 | B32 Word32 | B64 Word64
410 | B8V (Vector Word8) | B16V (Vector Word16)
411 | B32V (Vector Word32) | B64V (Vector Word64)
412 | AType ArithTy | StrType
413 | PtrType | VoidType | Forgot
416deriving instance Binary Const
417deriving instance NFData Const
420instance Sized Const where
423instance Pretty Const where
424 pretty (I i) = text . show $ i
425 pretty (BI i) = text . show $ i
426 pretty (Fl f) = text . show $ f
427 pretty (Ch c) = text . show $ c
428 pretty (Str s) = text s
429 pretty (AType a) = pretty a
430 pretty StrType = text "String"
431 pretty PtrType = text "Ptr"
432 pretty VoidType = text "Void"
433 pretty Forgot = text "Forgot"
434 pretty (B8 w) = text . show $ w
435 pretty (B16 w) = text . show $ w
436 pretty (B32 w) = text . show $ w
437 pretty (B64 w) = text . show $ w
440 | RBind Name (Binder Raw) Raw
447instance Sized Raw where
449 size (RBind name bind right) = 1 + size bind + size right
450 size (RApp left right) = 1 + size left + size right
452 size (RForce raw) = 1 + size raw
453 size (RConstant const) = size const
455instance Pretty Raw where
459deriving instance Binary Raw
460deriving instance NFData Raw
463-- | All binding forms are represented in a unform fashion.
464data Binder b = Lam { binderTy :: b {-^ type annotation for bound variable-}}
465 | Pi { binderTy :: b }
466 | Let { binderTy :: b,
467 binderVal :: b {-^ value for bound variable-}}
468 | NLet { binderTy :: b,
470 | Hole { binderTy :: b}
471 | GHole { envlen :: Int,
473 | Guess { binderTy :: b,
475 | PVar { binderTy :: b }
476 | PVTy { binderTy :: b }
477 deriving (Show, Eq, Ord, Functor)
479deriving instance Binary Binder
480deriving instance NFData Binder
483instance Sized a => Sized (Binder a) where
484 size (Lam ty) = 1 + size ty
485 size (Pi ty) = 1 + size ty
486 size (Let ty val) = 1 + size ty + size val
487 size (NLet ty val) = 1 + size ty + size val
488 size (Hole ty) = 1 + size ty
489 size (GHole _ ty) = 1 + size ty
490 size (Guess ty val) = 1 + size ty + size val
491 size (PVar ty) = 1 + size ty
492 size (PVTy ty) = 1 + size ty
494fmapMB :: Monad m => (a -> m b) -> Binder a -> m (Binder b)
495fmapMB f (Let t v) = liftM2 Let (f t) (f v)
496fmapMB f (NLet t v) = liftM2 NLet (f t) (f v)
497fmapMB f (Guess t v) = liftM2 Guess (f t) (f v)
498fmapMB f (Lam t) = liftM Lam (f t)
499fmapMB f (Pi t) = liftM Pi (f t)
500fmapMB f (Hole t) = liftM Hole (f t)
501fmapMB f (GHole i t) = liftM (GHole i) (f t)
502fmapMB f (PVar t) = liftM PVar (f t)
503fmapMB f (PVTy t) = liftM PVTy (f t)
505raw_apply :: Raw -> [Raw] -> Raw
507raw_apply f (a : as) = raw_apply (RApp f a) as
509raw_unapply :: Raw -> (Raw, [Raw])
510raw_unapply t = ua [] t where
511 ua args (RApp f a) = ua (a:args) f
512 ua args t = (t, args)
514data RawFun = RawFun { rtype :: Raw,
519data RawDatatype = RDatatype Name Raw [(Name, Raw)]
522data RDef = RFunction RawFun
527type RProgram = [(Name, RDef)]
529-- WELL TYPED TERMS ---------------------------------------------------------
531-- | Universe expressions for universe checking
532data UExp = UVar Int -- ^ universe variable
533 | UVal Int -- ^ explicit universe level
536deriving instance NFData UExp
539instance Sized UExp where
542-- We assume that universe levels have been checked, so anything external
543-- can just have the same universe variable and we won't get any new
546instance Binary UExp where
548 get = return (UVar (-1))
550instance Show UExp where
551 show (UVar x) | x < 26 = [toEnum (x + fromEnum 'a')]
552 | otherwise = toEnum ((x `mod` 26) + fromEnum 'a') : show (x `div` 26)
553 show (UVal x) = show x
554-- show (UMax l r) = "max(" ++ show l ++ ", " ++ show r ++")"
556-- | Universe constraints
557data UConstraint = ULT UExp UExp -- ^ Strictly less than
558 | ULE UExp UExp -- ^ Less than or equal to
561instance Show UConstraint where
562 show (ULT x y) = show x ++ " < " ++ show y
563 show (ULE x y) = show x ++ " <= " ++ show y
565type UCs = (Int, [UConstraint])
569 | DCon Int Int -- ^ Data constructor; Ints are tag and arity
570 | TCon Int Int -- ^ Type constructor; Ints are tag and arity
573deriving instance Binary NameType
574deriving instance NFData NameType
577instance Sized NameType where
580instance Pretty NameType where
583instance Eq NameType where
584 Bound == Bound = True
586 DCon _ a == DCon _ b = (a == b) -- ignore tag
587 TCon _ a == TCon _ b = (a == b) -- ignore tag
590-- | Terms in the core language
591data TT n = P NameType n (TT n) -- ^ named references
592 | V Int -- ^ a resolved de Bruijn-indexed variable
593 | Bind n (Binder (TT n)) (TT n) -- ^ a binding
594 | App (TT n) (TT n) -- ^ function, function type, arg
595 | Constant Const -- ^ constant
596 | Proj (TT n) Int -- ^ argument projection; runtime only
597 -- (-1) is a special case for 'subtract one from BI'
598 | Erased -- ^ an erased term
599 | Impossible -- ^ special case for totality checking
600 | TType UExp -- ^ the type of types at some level
601 deriving (Ord, Functor)
603deriving instance Binary TT
604deriving instance NFData TT
607class TermSize a where
608 termsize :: Name -> a -> Int
610instance TermSize a => TermSize [a] where
612 termsize n (x : xs) = termsize n x + termsize n xs
614instance TermSize (TT Name) where
616 | x == n = 1000000 -- recursive => really big
619 termsize n (Bind n' (Let t v) sc)
620 = let rn = if n == n' then MN 0 "noname" else n in
621 termsize rn v + termsize rn sc
622 termsize n (Bind n' b sc)
623 = let rn = if n == n' then MN 0 "noname" else n in
625 termsize n (App f a) = termsize n f + termsize n a
626 termsize n (Proj t i) = termsize n t
629instance Sized a => Sized (TT a) where
630 size (P name n trm) = 1 + size name + size n + size trm
632 size (Bind nm binder bdy) = 1 + size nm + size binder + size bdy
633 size (App l r) = 1 + size l + size r
634 size (Constant c) = size c
636 size (TType u) = 1 + size u
638instance Pretty a => Pretty (TT a) where
639 pretty _ = text "test"
641type EnvTT n = [(n, Binder (TT n))]
643data Datatype n = Data { d_typename :: n,
646 d_cons :: [(n, TT n)] }
647 deriving (Show, Functor, Eq)
649instance Eq n => Eq (TT n) where
650 (==) (P xt x _) (P yt y _) = x == y
651 (==) (V x) (V y) = x == y
652 (==) (Bind _ xb xs) (Bind _ yb ys) = xb == yb && xs == ys
653 (==) (App fx ax) (App fy ay) = fx == fy && ax == ay
654 (==) (TType _) (TType _) = True -- deal with constraints later
655 (==) (Constant x) (Constant y) = x == y
656 (==) (Proj x i) (Proj y j) = x == y && i == j
661-- * A few handy operations on well typed terms:
663-- | A term is injective iff it is a data constructor, type constructor,
664-- constant, the type Type, pi-binding, or an application of an injective
666isInjective :: TT n -> Bool
667isInjective (P (DCon _ _) _ _) = True
668isInjective (P (TCon _ _) _ _) = True
669isInjective (Constant _) = True
670isInjective (TType x) = True
671isInjective (Bind _ (Pi _) sc) = True
672isInjective (App f a) = isInjective f
675-- | Count the number of instances of a de Bruijn index in a term
676vinstances :: Int -> TT n -> Int
677vinstances i (V x) | i == x = 1
678vinstances i (App f a) = vinstances i f + vinstances i a
679vinstances i (Bind x b sc) = instancesB b + vinstances (i + 1) sc
680 where instancesB (Let t v) = vinstances i v
684instantiate :: TT n -> TT n -> TT n
685instantiate e = subst 0 where
686 subst i (V x) | i == x = e
687 subst i (Bind x b sc) = Bind x (fmap (subst i) b) (subst (i+1) sc)
688 subst i (App f a) = App (subst i f) (subst i a)
689 subst i (Proj x idx) = Proj (subst i x) idx
692substV :: TT n -> TT n -> TT n
693substV x tm = dropV 0 (instantiate x tm) where
694 dropV i (V x) | x > i = V (x - 1)
696 dropV i (Bind x b sc) = Bind x (fmap (dropV i) b) (dropV (i+1) sc)
697 dropV i (App f a) = App (dropV i f) (dropV i a)
698 dropV i (Proj x idx) = Proj (dropV i x) idx
701explicitNames :: TT n -> TT n
702explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
704 (explicitNames (instantiate
705 (P Bound x (binderTy b')) sc))
706explicitNames (App f a) = App (explicitNames f) (explicitNames a)
707explicitNames (Proj x idx) = Proj (explicitNames x) idx
710pToV :: Eq n => n -> TT n -> TT n
712pToV' n i (P _ x _) | n == x = V i
713pToV' n i (Bind x b sc)
714-- We can assume the inner scope has been pToVed already, so continue to
715-- resolve names from the *outer* scope which may happen to have the same id.
716 | n == x = Bind x (fmap (pToV' n i) b) sc
717 | otherwise = Bind x (fmap (pToV' n i) b) (pToV' n (i+1) sc)
718pToV' n i (App f a) = App (pToV' n i f) (pToV' n i a)
719pToV' n i (Proj t idx) = Proj (pToV' n i t) idx
722-- increase de Bruijn indices, as if a binder has been added
723addBinder :: TT n -> TT n
726 ab top (V i) | i >= top = V (i + 1)
728 ab top (Bind x b sc) = Bind x (fmap (ab top) b) (ab (top + 1) sc)
729 ab top (App f a) = App (ab top f) (ab top a)
730 ab top (Proj t idx) = Proj (ab top t) idx
733-- | Convert several names. First in the list comes out as V 0
734pToVs :: Eq n => [n] -> TT n -> TT n
735pToVs ns tm = pToVs' ns tm 0 where
737 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
741 vToP' env (V i) = let (n, b) = (env !! i) in
742 P Bound n (binderTy b)
743 vToP' env (Bind n b sc) = let b' = fmap (vToP' env) b in
744 Bind n b' (vToP' ((n, b'):env) sc)
745 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
748finalise :: Eq n => TT n -> TT n
749finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
750finalise (App f a) = App (finalise f) (finalise a)
753subst :: Eq n => n -> TT n -> TT n -> TT n
754subst n v tm = instantiate v (pToV n tm)
756substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
758substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
760substTerm :: Eq n => TT n -> TT n -> TT n -> TT n
761substTerm old new = st where
762 st t | t == old = new
763 st (App f a) = App (st f) (st a)
764 st (Bind x b sc) = Bind x (fmap st b) (st sc)
767-- Returns true if V 0 and bound name n do not occur in the term
769noOccurrence :: Eq n => n -> TT n -> Bool
770noOccurrence n t = no' 0 t
772 no' i (V x) = not (i == x)
773 no' i (P Bound x _) = not (n == x)
774 no' i (Bind n b sc) = noB' i b && no' (i+1) sc
775 where noB' i (Let t v) = no' i t && no' i v
776 noB' i (Guess t v) = no' i t && no' i v
777 noB' i b = no' i (binderTy b)
778 no' i (App f a) = no' i f && no' i a
779 no' i (Proj x _) = no' i x
782-- | Returns all names used free in the term
783freeNames :: Eq n => TT n -> [n]
784freeNames (P _ n _) = [n]
785freeNames (Bind n (Let t v) sc) = nub $ freeNames v ++ (freeNames sc \\ [n])
787freeNames (Bind n b sc) = nub $ freeNames (binderTy b) ++ (freeNames sc \\ [n])
788freeNames (App f a) = nub $ freeNames f ++ freeNames a
789freeNames (Proj x i) = nub $ freeNames x
792-- | Return the arity of a (normalised) type
794arity (Bind n (Pi t) sc) = 1 + arity sc
797-- | Deconstruct an application; returns the function and a list of arguments
798unApply :: TT n -> (TT n, [TT n])
799unApply t = ua [] t where
800 ua args (App f a) = ua (a:args) f
801 ua args t = (t, args)
803mkApp :: TT n -> [TT n] -> TT n
805mkApp f (a:as) = mkApp (App f a) as
807forget :: TT Name -> Raw
810 fe env (P _ n _) = Var n
811 fe env (V i) = Var (env !! i)
812 fe env (Bind n b sc) = RBind n (fmap (fe env) b)
814 fe env (App f a) = RApp (fe env f) (fe env a)
817 fe env (TType i) = RType
818 fe env Erased = RConstant Forgot
820bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
822bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
824bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
825bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
827getArgTys :: TT n -> [(n, TT n)]
828getArgTys (Bind n (Pi t) sc) = (n, t) : getArgTys sc
831getRetTy :: TT n -> TT n
832getRetTy (Bind n (PVar _) sc) = getRetTy sc
833getRetTy (Bind n (PVTy _) sc) = getRetTy sc
834getRetTy (Bind n (Pi _) sc) = getRetTy sc
837uniqueName :: Name -> [Name] -> Name
838uniqueName n hs | n `elem` hs = uniqueName (nextName n) hs
841uniqueBinders :: [Name] -> TT Name -> TT Name
842uniqueBinders ns (Bind n b sc)
843 = let n' = uniqueName n ns in
844 Bind n' (fmap (uniqueBinders (n':ns)) b) (uniqueBinders ns sc)
845uniqueBinders ns (App f a) = App (uniqueBinders ns f) (uniqueBinders ns a)
846uniqueBinders ns t = t
849nextName (NS x s) = NS (nextName x) s
850nextName (MN i n) = MN (i+1) n
851nextName (UN x) = let (num', nm') = span isDigit (reverse x)
853 num = readN (reverse num') in
854 UN (nm ++ show (num+1))
858nextName (SN x) = SN (nextName' x)
860 nextName' (WhereN i f x) = WhereN i f (nextName x)
861 nextName' (CaseN n) = CaseN (nextName n)
862 nextName' (MethodN n) = MethodN (nextName n)
869-- an environment with de Bruijn indices 'normalised' so that they all refer to
872newtype WkEnvTT n = Wk (EnvTT n)
873type WkEnv = WkEnvTT Name
875instance (Eq n, Show n) => Show (TT n) where
876 show t = showEnv [] t
878itBitsName IT8 = "Bits8"
879itBitsName IT16 = "Bits16"
880itBitsName IT32 = "Bits32"
881itBitsName IT64 = "Bits64"
883instance Show Const where
888 show (Str s) = show s
890 show (B16 x) = show x
891 show (B32 x) = show x
892 show (B64 x) = show x
893 show (B8V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
894 show (B16V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
895 show (B32V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
896 show (B64V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
897 show (AType ATFloat) = "Float"
898 show (AType (ATInt ITBig)) = "Integer"
899 show (AType (ATInt ITNative)) = "Int"
900 show (AType (ATInt ITChar)) = "Char"
901 show (AType (ATInt (ITFixed it))) = itBitsName it
902 show (AType (ATInt (ITVec it c))) = itBitsName it ++ "x" ++ show c
903 show StrType = "String"
905 show VoidType = "Void"
907showEnv env t = showEnv' env t False
908showEnvDbg env t = showEnv' env t True
910prettyEnv env t = prettyEnv' env t False
912 prettyEnv' env t dbg = prettySe 10 env t dbg
914 bracket outer inner p
915 | inner > outer = lparen <> p <> rparen
918 prettySe p env (P nt n t) debug =
921 lbrack <+> pretty nt <+> colon <+> prettySe 10 env t debug <+> rbrack
924 prettySe p env (V i) debug
927 text . show . fst $ env!!i
929 lbrack <+> text (show i) <+> rbrack
930 | otherwise = text "unbound" <+> text (show i) <+> text "!"
931 prettySe p env (Bind n b@(Pi t) sc) debug
932 | noOccurrence n sc && not debug =
933 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
934 prettySe p env (Bind n b sc) debug =
935 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
936 prettySe p env (App f a) debug =
937 bracket p 1 $ prettySe 1 env f debug <+> prettySe 0 env a debug
938 prettySe p env (Proj x i) debug =
939 prettySe 1 env x debug <+> text ("!" ++ show i)
940 prettySe p env (Constant c) debug = pretty c
941 prettySe p env Erased debug = text "[_]"
942 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
944 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
945 prettySb env n (Hole t) = prettyB env "?defer" "." n t
946 prettySb env n (Pi t) = prettyB env "(" ") ->" n t
947 prettySb env n (PVar t) = prettyB env "pat" "." n t
948 prettySb env n (PVTy t) = prettyB env "pty" "." n t
949 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
950 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
952 prettyB env op sc n t debug =
953 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
955 prettyBv env op sc n t v debug =
956 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
957 prettySe 10 env v debug <> text sc
960showEnv' env t dbg = se 10 env t where
961 se p env (P nt n t) = show n
962 ++ if dbg then "{" ++ show nt ++ " : " ++ se 10 env t ++ "}" else ""
963 se p env (V i) | i < length env && i >= 0
964 = (show $ fst $ env!!i) ++
965 if dbg then "{" ++ show i ++ "}" else ""
966 | otherwise = "!!V " ++ show i ++ "!!"
967 se p env (Bind n b@(Pi t) sc)
968 | noOccurrence n sc && not dbg = bracket p 2 $ se 1 env t ++ " -> " ++ se 10 ((n,b):env) sc
969 se p env (Bind n b sc) = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
970 se p env (App f a) = bracket p 1 $ se 1 env f ++ " " ++ se 0 env a
971 se p env (Proj x i) = se 1 env x ++ "!" ++ show i
972 se p env (Constant c) = show c
973 se p env Erased = "[__]"
974 se p env Impossible = "[impossible]"
975 se p env (TType i) = "Type " ++ show i
977 sb env n (Lam t) = showb env "\\ " " => " n t
978 sb env n (Hole t) = showb env "? " ". " n t
979 sb env n (GHole i t) = showb env "?defer " ". " n t
980 sb env n (Pi t) = showb env "(" ") -> " n t
981 sb env n (PVar t) = showb env "pat " ". " n t
982 sb env n (PVTy t) = showb env "pty " ". " n t
983 sb env n (Let t v) = showbv env "let " " in " n t v
984 sb env n (Guess t v) = showbv env "?? " " in " n t v
986 showb env op sc n t = op ++ show n ++ " : " ++ se 10 env t ++ sc
987 showbv env op sc n t v = op ++ show n ++ " : " ++ se 10 env t ++ " = " ++
990 bracket outer inner str | inner > outer = "(" ++ str ++ ")"
993-- | Check whether a term has any holes in it - impure if so
994pureTerm :: TT Name -> Bool
995pureTerm (App f a) = pureTerm f && pureTerm a
996pureTerm (Bind n b sc) = notClassName n && pureBinder b && pureTerm sc where
997 pureBinder (Hole _) = False
998 pureBinder (Guess _ _) = False
999 pureBinder (Let t v) = pureTerm t && pureTerm v
1000 pureBinder t = pureTerm (binderTy t)
1002 notClassName (MN _ "class") = False
1003 notClassName _ = True
1007-- | Weaken a term by adding i to each de Bruijn index (i.e. lift it over i bindings)
1008weakenTm :: Int -> TT n -> TT n
1009weakenTm i t = wk i 0 t
1010 where wk i min (V x) | x >= min = V (i + x)
1011 wk i m (App f a) = App (wk i m f) (wk i m a)
1012 wk i m (Bind x b sc) = Bind x (wkb i m b) (wk i (m + 1) sc)
1014 wkb i m t = fmap (wk i m) t
1016-- | Weaken an environment so that all the de Bruijn indices are correct according
1017-- to the latest bound variable
1019weakenEnv :: EnvTT n -> EnvTT n
1020weakenEnv env = wk (length env - 1) env
1022 wk i ((n, b) : bs) = (n, weakenTmB i b) : wk (i - 1) bs
1023 weakenTmB i (Let t v) = Let (weakenTm i t) (weakenTm i v)
1024 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
1025 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
1027weakenTmEnv :: Int -> EnvTT n -> EnvTT n
1028weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
1030orderPats :: Term -> Term
1031orderPats tm = op [] tm
1033 op ps (Bind n (PVar t) sc) = op ((n, PVar t) : ps) sc
1034 op ps (Bind n (Hole t) sc) = op ((n, Hole t) : ps) sc
1035 op ps sc = bindAll (sortP ps) sc
1037 sortP ps = pick [] (reverse ps)
1039 namesIn (P _ n _) = [n]
1040 namesIn (Bind n b t) = nub $ nb b ++ (namesIn t \\ [n])
1041 where nb (Let t v) = nub (namesIn t) ++ nub (namesIn v)
1042 nb (Guess t v) = nub (namesIn t) ++ nub (namesIn v)
1043 nb t = namesIn (binderTy t)
1044 namesIn (App f a) = nub (namesIn f ++ namesIn a)
1047 pick acc [] = reverse acc
1048 pick acc ((n, t) : ps) = pick (insert n t acc) ps
1050 insert n t [] = [(n, t)]
1051 insert n t ((n',t') : ps)
1052 | n `elem` (namesIn (binderTy t') ++
1053 concatMap namesIn (map (binderTy . snd) ps))
1054 = (n', t') : insert n t ps
1055 | 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