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
70instance Sized FC where
71 size (FC f l c) = 1 + length f
74 show (FC f l c) = f ++ ":" ++ show l ++ ":" ++ show c
78 | CantUnify Bool Term Term Err [(Name, Type)] Int
79 -- Int is 'score' - how much we did unify
80 -- Bool indicates recoverability, True indicates more info may make
81 -- unification succeed
82 | InfiniteUnify Name Term [(Name, Type)]
83 | CantConvert Term Term [(Name, Type)]
84 | UnifyScope Name Name Term [(Name, Type)]
85 | CantInferType String
86 | NonFunctionType Term Term
90 | NotInjective Term Term Term
92 | CantResolveAlts [String]
97 | NonCollapsiblePostulate Name
102 | Elaborating String Name Err
103 | ProviderError String
104 | LoadingFailed String Err
107instance Sized Err where
108 size (Msg msg) = length msg
109 size (InternalMsg msg) = length msg
110 size (CantUnify _ left right err _ score) = size left + size right + size err
111 size (InfiniteUnify _ right _) = size right
112 size (CantConvert left right _) = size left + size right
113 size (UnifyScope _ _ right _) = size right
114 size (NoSuchVariable name) = size name
115 size (NoTypeDecl name) = size name
116 size (NotInjective l c r) = size l + size c + size r
117 size (CantResolve trm) = size trm
118 size (NoRewriting trm) = size trm
119 size (CantResolveAlts _) = 1
120 size (IncompleteTerm trm) = size trm
121 size UniverseError = 1
122 size ProgramLineComment = 1
123 size (At fc err) = size fc + size err
124 size (Elaborating _ n err) = size err
125 size (ProviderError msg) = length msg
126 size (LoadingFailed fn e) = 1 + length fn + size e
130score (CantUnify _ _ _ m _ s) = s + score m
131score (CantResolve _) = 20
132score (NoSuchVariable _) = 1000
133score (ProofSearchFail _) = 10000
134score (InternalMsg _) = -1
137instance Show Err where
139 show (InternalMsg s) = "Internal error: " ++ show s
140 show (CantUnify _ l r e sc i) = "CantUnify " ++ show l ++ " " ++ show r ++ " "
141 ++ show e ++ " in " ++ show sc ++ " " ++ show i
142 show (Inaccessible n) = show n ++ " is not an accessible pattern variable"
143 show (ProviderError msg) = "Type provider error: " ++ msg
144 show (LoadingFailed fn e) = "Loading " ++ fn ++ " failed: " ++ show e
147instance Pretty Err where
148 pretty (Msg m) = text m
149 pretty (CantUnify _ l r e _ i) =
150 if size l + size r > breakingSize then
151 text "Cannot unify" <+> colon $$
152 nest nestingSize (pretty l <+> text "and" <+> pretty r) $$
153 nest nestingSize (text "where" <+> pretty e <+> text "with" <+> (text . show $ i))
155 text "Cannot unify" <+> colon <+> pretty l <+> text "and" <+> pretty r $$
156 nest nestingSize (text "where" <+> pretty e <+> text "with" <+> (text . show $ i))
157 pretty (ProviderError msg) = text msg
158 pretty err@(LoadingFailed _ _) = text (show err)
159 pretty _ = text "Error"
161instance Error Err where
166 deriving (Eq, Functor)
168instance Pretty a => Pretty (TC a) where
169 pretty (OK ok) = pretty ok
171 if size err > breakingSize then
172 text "Error" <+> colon $$ (nest nestingSize $ pretty err)
174 text "Error" <+> colon <+> pretty err
176instance Show a => Show (TC a) where
178 show (Error str) = "Error: " ++ show str
180-- at some point, this instance should also carry type checking options
183instance Monad TC where
188 fail e = Error (InternalMsg e)
193trun :: FC -> TC a -> TC a
195trun fc (Error e) = Error (At fc e)
197instance MonadPlus TC where
198 mzero = fail "Unknown error"
199 (OK x) `mplus` _ = OK x
200 _ `mplus` (OK y) = OK y
203discard :: Monad m => m a -> m ()
204discard f = f >> return ()
206showSep :: String -> [String] -> String
209showSep sep (x:xs) = x ++ sep ++ showSep sep xs
211pmap f (x, y) = (f x, f y)
213traceWhen True msg a = trace msg a
214traceWhen False _ a = a
216-- RAW TERMS ----------------------------------------------------------------
218-- | Names are hierarchies of strings, describing scope (so no danger of
219-- duplicate names, but need to be careful on lookup).
220data Name = UN String -- ^ User-provided name
221 | NS Name [String] -- ^ Root, namespaces
222 | MN Int String -- ^ Machine chosen names
223 | NErased -- ^ Name of somethng which is never used in scope
224 | SN SpecialName -- ^ Decorated function names
227deriving instance Binary Name
230data SpecialName = WhereN Int Name Name
231 | InstanceN Name [String]
232 | ParentN Name String
237deriving instance Binary SpecialName
240instance Sized Name where
242 size (NS n els) = 1 + length els
246instance Pretty Name where
247 pretty (UN n) = text n
248 pretty (NS n s) = pretty n
249 pretty (MN i s) = lbrace <+> text s <+> (text . show $ i) <+> rbrace
250 pretty (SN s) = text (show s)
252instance Show Name where
254 show (NS n s) = showSep "." (reverse s) ++ "." ++ show n
255 show (MN _ "underscore") = "_"
256 show (MN i s) = "{" ++ s ++ show i ++ "}"
260instance Show SpecialName where
261 show (WhereN i p c) = show p ++ ", " ++ show c
262 show (InstanceN cl inst) = showSep ", " inst ++ " instance of " ++ show cl
263 show (MethodN m) = "method " ++ show m
264 show (ParentN p c) = show p ++ "#" ++ c
265 show (CaseN n) = "case block in " ++ show n
267-- Show a name in a way decorated for code generation, not human reading
268showCG :: Name -> String
270showCG (NS n s) = showSep "." (reverse s) ++ "." ++ show n
271showCG (MN _ "underscore") = "_"
272showCG (MN i s) = "{" ++ s ++ show i ++ "}"
273showCG (SN s) = showCG' s
274 where showCG' (WhereN i p c) = show p ++ ":" ++ show c ++ ":" ++ show i
275 showCG' (InstanceN cl inst) = '@':show cl ++ '$':showSep ":" inst
276 showCG' (MethodN m) = '!':show m
277 showCG' (ParentN p c) = show p ++ "#" ++ show c
278 showCG' (CaseN c) = show c ++ "_case"
282-- |Contexts allow us to map names to things. A root name maps to a collection
283-- of things in different namespaces with that name.
284type Ctxt a = Map.Map Name (Map.Map Name a)
285emptyContext = Map.empty
287tcname (UN ('@':_)) = True
288tcname (NS n _) = tcname n
289tcname (SN (InstanceN _ _)) = True
290tcname (SN (MethodN _)) = True
291tcname (SN (ParentN _ _)) = True
294implicitable (NS n _) = implicitable n
295implicitable (UN (x:xs)) = isLower x
296implicitable _ = False
301addDef :: Name -> a -> Ctxt a -> Ctxt a
302addDef n v ctxt = case Map.lookup (nsroot n) ctxt of
303 Nothing -> Map.insert (nsroot n)
304 (Map.insert n v Map.empty) ctxt
305 Just xs -> Map.insert (nsroot n)
306 (Map.insert n v xs) ctxt
308{-| Look up a name in the context, given an optional namespace.
309 The name (n) may itself have a (partial) namespace given.
311 Rules for resolution:
313 - if an explicit namespace is given, return the names which match it. If none
314 match, return all names.
316 - if the name has has explicit namespace given, return the names which match it
317 and ignore the given namespace.
319 - otherwise, return all names.
323lookupCtxtName :: Name -> Ctxt a -> [(Name, a)]
324lookupCtxtName n ctxt = case Map.lookup (nsroot n) ctxt of
325 Just xs -> filterNS (Map.toList xs)
329 filterNS ((found, v) : xs)
330 | nsmatch n found = (found, v) : filterNS xs
331 | otherwise = filterNS xs
333 nsmatch (NS n ns) (NS p ps) = ns `isPrefixOf` ps
334 nsmatch (NS _ _) _ = False
335 nsmatch looking found = True
337lookupCtxt :: Name -> Ctxt a -> [a]
338lookupCtxt n ctxt = map snd (lookupCtxtName n ctxt)
340lookupCtxtExact :: Name -> Ctxt a -> [a]
341lookupCtxtExact n ctxt = [ v | (nm, v) <- lookupCtxtName n ctxt, nm == n]
343updateDef :: Name -> (a -> a) -> Ctxt a -> Ctxt a
345 = let ds = lookupCtxtName n ctxt in
346 foldr (\ (n, t) c -> addDef n (f t) c) ctxt ds
348toAlist :: Ctxt a -> [(Name, a)]
349toAlist ctxt = let allns = map snd (Map.toList ctxt) in
350 concat (map (Map.toList) allns)
352addAlist :: Show a => [(Name, a)] -> Ctxt a -> Ctxt a
353addAlist [] ctxt = ctxt
354addAlist ((n, tm) : ds) ctxt = addDef n tm (addAlist ds ctxt)
356data NativeTy = IT8 | IT16 | IT32 | IT64
357 deriving (Show, Eq, Ord, Enum)
359instance Pretty NativeTy where
360 pretty IT8 = text "Bits8"
361 pretty IT16 = text "Bits16"
362 pretty IT32 = text "Bits32"
363 pretty IT64 = text "Bits64"
365data IntTy = ITFixed NativeTy | ITNative | ITBig | ITChar
367 deriving (Show, Eq, Ord)
369data ArithTy = ATInt IntTy | ATFloat -- TODO: Float vectors
370 deriving (Show, Eq, Ord)
372instance Pretty ArithTy where
373 pretty (ATInt ITNative) = text "Int"
374 pretty (ATInt ITBig) = text "BigInt"
375 pretty (ATInt ITChar) = text "Char"
376 pretty (ATInt (ITFixed n)) = pretty n
377 pretty (ATInt (ITVec e c)) = pretty e <> text "x" <> (text . show $ c)
378 pretty ATFloat = text "Float"
380nativeTyWidth :: NativeTy -> Int
382nativeTyWidth IT16 = 16
383nativeTyWidth IT32 = 32
384nativeTyWidth IT64 = 64
386{-# DEPRECATED intTyWidth "Non-total function, use nativeTyWidth and appropriate casing" #-}
387intTyWidth :: IntTy -> Int
388intTyWidth (ITFixed n) = nativeTyWidth n
389intTyWidth ITNative = 8 * sizeOf (0 :: Int)
390intTyWidth ITChar = error "IRTS.Lang.intTyWidth: Characters have platform and backend dependent width"
391intTyWidth ITBig = error "IRTS.Lang.intTyWidth: Big integers have variable width"
393data Const = I Int | BI Integer | Fl Double | Ch Char | Str String
394 | B8 Word8 | B16 Word16 | B32 Word32 | B64 Word64
395 | B8V (Vector Word8) | B16V (Vector Word16)
396 | B32V (Vector Word32) | B64V (Vector Word64)
397 | AType ArithTy | StrType
398 | PtrType | VoidType | Forgot
401deriving instance Binary Const
404instance Sized Const where
407instance Pretty Const where
408 pretty (I i) = text . show $ i
409 pretty (BI i) = text . show $ i
410 pretty (Fl f) = text . show $ f
411 pretty (Ch c) = text . show $ c
412 pretty (Str s) = text s
413 pretty (AType a) = pretty a
414 pretty StrType = text "String"
415 pretty PtrType = text "Ptr"
416 pretty VoidType = text "Void"
417 pretty Forgot = text "Forgot"
418 pretty (B8 w) = text . show $ w
419 pretty (B16 w) = text . show $ w
420 pretty (B32 w) = text . show $ w
421 pretty (B64 w) = text . show $ w
424 | RBind Name (Binder Raw) Raw
431instance Sized Raw where
433 size (RBind name bind right) = 1 + size bind + size right
434 size (RApp left right) = 1 + size left + size right
436 size (RForce raw) = 1 + size raw
437 size (RConstant const) = size const
439instance Pretty Raw where
443deriving instance Binary Raw
446-- | All binding forms are represented in a unform fashion.
447data Binder b = Lam { binderTy :: b {-^ type annotation for bound variable-}}
448 | Pi { binderTy :: b }
449 | Let { binderTy :: b,
450 binderVal :: b {-^ value for bound variable-}}
451 | NLet { binderTy :: b,
453 | Hole { binderTy :: b}
454 | GHole { binderTy :: b}
455 | Guess { binderTy :: b,
457 | PVar { binderTy :: b }
458 | PVTy { binderTy :: b }
459 deriving (Show, Eq, Ord, Functor)
461deriving instance Binary Binder
464instance Sized a => Sized (Binder a) where
465 size (Lam ty) = 1 + size ty
466 size (Pi ty) = 1 + size ty
467 size (Let ty val) = 1 + size ty + size val
468 size (NLet ty val) = 1 + size ty + size val
469 size (Hole ty) = 1 + size ty
470 size (GHole ty) = 1 + size ty
471 size (Guess ty val) = 1 + size ty + size val
472 size (PVar ty) = 1 + size ty
473 size (PVTy ty) = 1 + size ty
475fmapMB :: Monad m => (a -> m b) -> Binder a -> m (Binder b)
476fmapMB f (Let t v) = liftM2 Let (f t) (f v)
477fmapMB f (NLet t v) = liftM2 NLet (f t) (f v)
478fmapMB f (Guess t v) = liftM2 Guess (f t) (f v)
479fmapMB f (Lam t) = liftM Lam (f t)
480fmapMB f (Pi t) = liftM Pi (f t)
481fmapMB f (Hole t) = liftM Hole (f t)
482fmapMB f (GHole t) = liftM GHole (f t)
483fmapMB f (PVar t) = liftM PVar (f t)
484fmapMB f (PVTy t) = liftM PVTy (f t)
486raw_apply :: Raw -> [Raw] -> Raw
488raw_apply f (a : as) = raw_apply (RApp f a) as
490raw_unapply :: Raw -> (Raw, [Raw])
491raw_unapply t = ua [] t where
492 ua args (RApp f a) = ua (a:args) f
493 ua args t = (t, args)
495data RawFun = RawFun { rtype :: Raw,
500data RawDatatype = RDatatype Name Raw [(Name, Raw)]
503data RDef = RFunction RawFun
508type RProgram = [(Name, RDef)]
510-- WELL TYPED TERMS ---------------------------------------------------------
512-- | Universe expressions for universe checking
513data UExp = UVar Int -- ^ universe variable
514 | UVal Int -- ^ explicit universe level
517instance Sized UExp where
520-- We assume that universe levels have been checked, so anything external
521-- can just have the same universe variable and we won't get any new
524instance Binary UExp where
526 get = return (UVar (-1))
528instance Show UExp where
529 show (UVar x) | x < 26 = [toEnum (x + fromEnum 'a')]
530 | otherwise = toEnum ((x `mod` 26) + fromEnum 'a') : show (x `div` 26)
531 show (UVal x) = show x
532-- show (UMax l r) = "max(" ++ show l ++ ", " ++ show r ++")"
534-- | Universe constraints
535data UConstraint = ULT UExp UExp -- ^ Strictly less than
536 | ULE UExp UExp -- ^ Less than or equal to
539instance Show UConstraint where
540 show (ULT x y) = show x ++ " < " ++ show y
541 show (ULE x y) = show x ++ " <= " ++ show y
543type UCs = (Int, [UConstraint])
547 | DCon Int Int -- ^ Data constructor; Ints are tag and arity
548 | TCon Int Int -- ^ Type constructor; Ints are tag and arity
551deriving instance Binary NameType
554instance Sized NameType where
557instance Pretty NameType where
560instance Eq NameType where
561 Bound == Bound = True
563 DCon _ a == DCon _ b = (a == b) -- ignore tag
564 TCon _ a == TCon _ b = (a == b) -- ignore tag
567-- | Terms in the core language
568data TT n = P NameType n (TT n) -- ^ named references
569 | V Int -- ^ a resolved de Bruijn-indexed variable
570 | Bind n (Binder (TT n)) (TT n) -- ^ a binding
571 | App (TT n) (TT n) -- ^ function, function type, arg
572 | Constant Const -- ^ constant
573 | Proj (TT n) Int -- ^ argument projection; runtime only
574 | Erased -- ^ an erased term
575 | Impossible -- ^ special case for totality checking
576 | TType UExp -- ^ the type of types at some level
577 deriving (Ord, Functor)
579deriving instance Binary TT
582class TermSize a where
583 termsize :: Name -> a -> Int
585instance TermSize a => TermSize [a] where
587 termsize n (x : xs) = termsize n x + termsize n xs
589instance TermSize (TT Name) where
591 | x == n = 1000000 -- recursive => really big
594 termsize n (Bind n' (Let t v) sc)
595 = let rn = if n == n' then MN 0 "noname" else n in
596 termsize rn v + termsize rn sc
597 termsize n (Bind n' b sc)
598 = let rn = if n == n' then MN 0 "noname" else n in
600 termsize n (App f a) = termsize n f + termsize n a
601 termsize n (Proj t i) = termsize n t
604instance Sized a => Sized (TT a) where
605 size (P name n trm) = 1 + size name + size n + size trm
607 size (Bind nm binder bdy) = 1 + size nm + size binder + size bdy
608 size (App l r) = 1 + size l + size r
609 size (Constant c) = size c
611 size (TType u) = 1 + size u
613instance Pretty a => Pretty (TT a) where
614 pretty _ = text "test"
616type EnvTT n = [(n, Binder (TT n))]
618data Datatype n = Data { d_typename :: n,
621 d_cons :: [(n, TT n)] }
622 deriving (Show, Functor, Eq)
624instance Eq n => Eq (TT n) where
625 (==) (P xt x _) (P yt y _) = x == y
626 (==) (V x) (V y) = x == y
627 (==) (Bind _ xb xs) (Bind _ yb ys) = xb == yb && xs == ys
628 (==) (App fx ax) (App fy ay) = fx == fy && ax == ay
629 (==) (TType _) (TType _) = True -- deal with constraints later
630 (==) (Constant x) (Constant y) = x == y
631 (==) (Proj x i) (Proj y j) = x == y && i == j
636-- * A few handy operations on well typed terms:
638-- | A term is injective iff it is a data constructor, type constructor,
639-- constant, the type Type, pi-binding, or an application of an injective
641isInjective :: TT n -> Bool
642isInjective (P (DCon _ _) _ _) = True
643isInjective (P (TCon _ _) _ _) = True
644isInjective (Constant _) = True
645isInjective (TType x) = True
646isInjective (Bind _ (Pi _) sc) = True
647isInjective (App f a) = isInjective f
650-- | Count the number of instances of a de Bruijn index in a term
651vinstances :: Int -> TT n -> Int
652vinstances i (V x) | i == x = 1
653vinstances i (App f a) = vinstances i f + vinstances i a
654vinstances i (Bind x b sc) = instancesB b + vinstances (i + 1) sc
655 where instancesB (Let t v) = vinstances i v
659instantiate :: TT n -> TT n -> TT n
660instantiate e = subst 0 where
661 subst i (V x) | i == x = e
662 subst i (Bind x b sc) = Bind x (fmap (subst i) b) (subst (i+1) sc)
663 subst i (App f a) = App (subst i f) (subst i a)
664 subst i (Proj x idx) = Proj (subst i x) idx
667substV :: TT n -> TT n -> TT n
668substV x tm = dropV 0 (instantiate x tm) where
669 dropV i (V x) | x > i = V (x - 1)
671 dropV i (Bind x b sc) = Bind x (fmap (dropV i) b) (dropV (i+1) sc)
672 dropV i (App f a) = App (dropV i f) (dropV i a)
673 dropV i (Proj x idx) = Proj (dropV i x) idx
676explicitNames :: TT n -> TT n
677explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
679 (explicitNames (instantiate
680 (P Bound x (binderTy b')) sc))
681explicitNames (App f a) = App (explicitNames f) (explicitNames a)
682explicitNames (Proj x idx) = Proj (explicitNames x) idx
685pToV :: Eq n => n -> TT n -> TT n
687pToV' n i (P _ x _) | n == x = V i
688pToV' n i (Bind x b sc)
689-- We can assume the inner scope has been pToVed already, so continue to
690-- resolve names from the *outer* scope which may happen to have the same id.
691 | n == x = Bind x (fmap (pToV' n i) b) sc
692 | otherwise = Bind x (fmap (pToV' n i) b) (pToV' n (i+1) sc)
693pToV' n i (App f a) = App (pToV' n i f) (pToV' n i a)
694pToV' n i (Proj t idx) = Proj (pToV' n i t) idx
697-- increase de Bruijn indices, as if a binder has been added
698addBinder :: TT n -> TT n
701 ab top (V i) | i >= top = V (i + 1)
703 ab top (Bind x b sc) = Bind x (fmap (ab top) b) (ab (top + 1) sc)
704 ab top (App f a) = App (ab top f) (ab top a)
705 ab top (Proj t idx) = Proj (ab top t) idx
708-- | Convert several names. First in the list comes out as V 0
709pToVs :: Eq n => [n] -> TT n -> TT n
710pToVs ns tm = pToVs' ns tm 0 where
712 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
716 vToP' env (V i) = let (n, b) = (env !! i) in
717 P Bound n (binderTy b)
718 vToP' env (Bind n b sc) = let b' = fmap (vToP' env) b in
719 Bind n b' (vToP' ((n, b'):env) sc)
720 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
723finalise :: Eq n => TT n -> TT n
724finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
725finalise (App f a) = App (finalise f) (finalise a)
728subst :: Eq n => n -> TT n -> TT n -> TT n
729subst n v tm = instantiate v (pToV n tm)
731substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
733substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
735substTerm :: Eq n => TT n -> TT n -> TT n -> TT n
736substTerm old new = st where
737 st t | t == old = new
738 st (App f a) = App (st f) (st a)
739 st (Bind x b sc) = Bind x (fmap st b) (st sc)
742-- Returns true if V 0 and bound name n do not occur in the term
744noOccurrence :: Eq n => n -> TT n -> Bool
745noOccurrence n t = no' 0 t
747 no' i (V x) = not (i == x)
748 no' i (P Bound x _) = not (n == x)
749 no' i (Bind n b sc) = noB' i b && no' (i+1) sc
750 where noB' i (Let t v) = no' i t && no' i v
751 noB' i (Guess t v) = no' i t && no' i v
752 noB' i b = no' i (binderTy b)
753 no' i (App f a) = no' i f && no' i a
754 no' i (Proj x _) = no' i x
757-- | Returns all names used free in the term
758freeNames :: Eq n => TT n -> [n]
759freeNames (P _ n _) = [n]
760freeNames (Bind n (Let t v) sc) = nub $ freeNames v ++ (freeNames sc \\ [n])
762freeNames (Bind n b sc) = nub $ freeNames (binderTy b) ++ (freeNames sc \\ [n])
763freeNames (App f a) = nub $ freeNames f ++ freeNames a
764freeNames (Proj x i) = nub $ freeNames x
767-- | Return the arity of a (normalised) type
769arity (Bind n (Pi t) sc) = 1 + arity sc
772-- | Deconstruct an application; returns the function and a list of arguments
773unApply :: TT n -> (TT n, [TT n])
774unApply t = ua [] t where
775 ua args (App f a) = ua (a:args) f
776 ua args t = (t, args)
778mkApp :: TT n -> [TT n] -> TT n
780mkApp f (a:as) = mkApp (App f a) as
782forget :: TT Name -> Raw
785 fe env (P _ n _) = Var n
786 fe env (V i) = Var (env !! i)
787 fe env (Bind n b sc) = RBind n (fmap (fe env) b)
789 fe env (App f a) = RApp (fe env f) (fe env a)
792 fe env (TType i) = RType
793 fe env Erased = RConstant Forgot
795bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
797bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
799bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
800bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
802getArgTys :: TT n -> [(n, TT n)]
803getArgTys (Bind n (Pi t) sc) = (n, t) : getArgTys sc
806getRetTy :: TT n -> TT n
807getRetTy (Bind n (PVar _) sc) = getRetTy sc
808getRetTy (Bind n (PVTy _) sc) = getRetTy sc
809getRetTy (Bind n (Pi _) sc) = getRetTy sc
812uniqueName :: Name -> [Name] -> Name
813uniqueName n hs | n `elem` hs = uniqueName (nextName n) hs
816uniqueBinders :: [Name] -> TT Name -> TT Name
817uniqueBinders ns (Bind n b sc)
818 = let n' = uniqueName n ns in
819 Bind n' (fmap (uniqueBinders (n':ns)) b) (uniqueBinders ns sc)
820uniqueBinders ns (App f a) = App (uniqueBinders ns f) (uniqueBinders ns a)
821uniqueBinders ns t = t
824nextName (NS x s) = NS (nextName x) s
825nextName (MN i n) = MN (i+1) n
826nextName (UN x) = let (num', nm') = span isDigit (reverse x)
828 num = readN (reverse num') in
829 UN (nm ++ show (num+1))
833nextName (SN x) = SN (nextName' x)
835 nextName' (WhereN i f x) = WhereN i f (nextName x)
836 nextName' (CaseN n) = CaseN (nextName n)
837 nextName' (MethodN n) = MethodN (nextName n)
844-- an environment with de Bruijn indices 'normalised' so that they all refer to
847newtype WkEnvTT n = Wk (EnvTT n)
848type WkEnv = WkEnvTT Name
850instance (Eq n, Show n) => Show (TT n) where
851 show t = showEnv [] t
853itBitsName IT8 = "Bits8"
854itBitsName IT16 = "Bits16"
855itBitsName IT32 = "Bits32"
856itBitsName IT64 = "Bits64"
858instance Show Const where
863 show (Str s) = show s
865 show (B16 x) = show x
866 show (B32 x) = show x
867 show (B64 x) = show x
868 show (B8V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
869 show (B16V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
870 show (B32V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
871 show (B64V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
872 show (AType ATFloat) = "Float"
873 show (AType (ATInt ITBig)) = "Integer"
874 show (AType (ATInt ITNative)) = "Int"
875 show (AType (ATInt ITChar)) = "Char"
876 show (AType (ATInt (ITFixed it))) = itBitsName it
877 show (AType (ATInt (ITVec it c))) = itBitsName it ++ "x" ++ show c
878 show StrType = "String"
880 show VoidType = "Void"
882showEnv env t = showEnv' env t False
883showEnvDbg env t = showEnv' env t True
885prettyEnv env t = prettyEnv' env t False
887 prettyEnv' env t dbg = prettySe 10 env t dbg
889 bracket outer inner p
890 | inner > outer = lparen <> p <> rparen
893 prettySe p env (P nt n t) debug =
896 lbrack <+> pretty nt <+> colon <+> prettySe 10 env t debug <+> rbrack
899 prettySe p env (V i) debug
902 text . show . fst $ env!!i
904 lbrack <+> text (show i) <+> rbrack
905 | otherwise = text "unbound" <+> text (show i) <+> text "!"
906 prettySe p env (Bind n b@(Pi t) sc) debug
907 | noOccurrence n sc && not debug =
908 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
909 prettySe p env (Bind n b sc) debug =
910 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
911 prettySe p env (App f a) debug =
912 bracket p 1 $ prettySe 1 env f debug <+> prettySe 0 env a debug
913 prettySe p env (Proj x i) debug =
914 prettySe 1 env x debug <+> text ("!" ++ show i)
915 prettySe p env (Constant c) debug = pretty c
916 prettySe p env Erased debug = text "[_]"
917 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
919 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
920 prettySb env n (Hole t) = prettyB env "?defer" "." n t
921 prettySb env n (Pi t) = prettyB env "(" ") ->" n t
922 prettySb env n (PVar t) = prettyB env "pat" "." n t
923 prettySb env n (PVTy t) = prettyB env "pty" "." n t
924 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
925 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
927 prettyB env op sc n t debug =
928 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
930 prettyBv env op sc n t v debug =
931 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
932 prettySe 10 env v debug <> text sc
935showEnv' env t dbg = se 10 env t where
936 se p env (P nt n t) = show n
937 ++ if dbg then "{" ++ show nt ++ " : " ++ se 10 env t ++ "}" else ""
938 se p env (V i) | i < length env && i >= 0
939 = (show $ fst $ env!!i) ++
940 if dbg then "{" ++ show i ++ "}" else ""
941 | otherwise = "!!V " ++ show i ++ "!!"
942 se p env (Bind n b@(Pi t) sc)
943 | noOccurrence n sc && not dbg = bracket p 2 $ se 1 env t ++ " -> " ++ se 10 ((n,b):env) sc
944 se p env (Bind n b sc) = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
945 se p env (App f a) = bracket p 1 $ se 1 env f ++ " " ++ se 0 env a
946 se p env (Proj x i) = se 1 env x ++ "!" ++ show i
947 se p env (Constant c) = show c
948 se p env Erased = "[__]"
949 se p env Impossible = "[impossible]"
950 se p env (TType i) = "Type " ++ show i
952 sb env n (Lam t) = showb env "\\ " " => " n t
953 sb env n (Hole t) = showb env "? " ". " n t
954 sb env n (GHole t) = showb env "?defer " ". " n t
955 sb env n (Pi t) = showb env "(" ") -> " n t
956 sb env n (PVar t) = showb env "pat " ". " n t
957 sb env n (PVTy t) = showb env "pty " ". " n t
958 sb env n (Let t v) = showbv env "let " " in " n t v
959 sb env n (Guess t v) = showbv env "?? " " in " n t v
961 showb env op sc n t = op ++ show n ++ " : " ++ se 10 env t ++ sc
962 showbv env op sc n t v = op ++ show n ++ " : " ++ se 10 env t ++ " = " ++
965 bracket outer inner str | inner > outer = "(" ++ str ++ ")"
968-- | Check whether a term has any holes in it - impure if so
969pureTerm :: TT Name -> Bool
970pureTerm (App f a) = pureTerm f && pureTerm a
971pureTerm (Bind n b sc) = notClassName n && pureBinder b && pureTerm sc where
972 pureBinder (Hole _) = False
973 pureBinder (Guess _ _) = False
974 pureBinder (Let t v) = pureTerm t && pureTerm v
975 pureBinder t = pureTerm (binderTy t)
977 notClassName (MN _ "class") = False
978 notClassName _ = True
982-- | Weaken a term by adding i to each de Bruijn index (i.e. lift it over i bindings)
983weakenTm :: Int -> TT n -> TT n
984weakenTm i t = wk i 0 t
985 where wk i min (V x) | x >= min = V (i + x)
986 wk i m (App f a) = App (wk i m f) (wk i m a)
987 wk i m (Bind x b sc) = Bind x (wkb i m b) (wk i (m + 1) sc)
989 wkb i m t = fmap (wk i m) t
991-- | Weaken an environment so that all the de Bruijn indices are correct according
992-- to the latest bound variable
994weakenEnv :: EnvTT n -> EnvTT n
995weakenEnv env = wk (length env - 1) env
997 wk i ((n, b) : bs) = (n, weakenTmB i b) : wk (i - 1) bs
998 weakenTmB i (Let t v) = Let (weakenTm i t) (weakenTm i v)
999 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
1000 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
1002weakenTmEnv :: Int -> EnvTT n -> EnvTT n
1003weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
1005orderPats :: Term -> Term
1006orderPats tm = op [] tm
1008 op ps (Bind n (PVar t) sc) = op ((n, PVar t) : ps) sc
1009 op ps (Bind n (Hole t) sc) = op ((n, Hole t) : ps) sc
1010 op ps sc = bindAll (map (\ (n, t) -> (n, t)) (sortP ps)) sc
1012 sortP ps = pick [] (reverse ps)
1014 namesIn (P _ n _) = [n]
1015 namesIn (Bind n b t) = nub $ nb b ++ (namesIn t \\ [n])
1016 where nb (Let t v) = nub (namesIn t) ++ nub (namesIn v)
1017 nb (Guess t v) = nub (namesIn t) ++ nub (namesIn v)
1018 nb t = namesIn (binderTy t)
1019 namesIn (App f a) = nub (namesIn f ++ namesIn a)
1022 pick acc [] = reverse acc
1023 pick acc ((n, t) : ps) = pick (insert n t acc) ps
1025 insert n t [] = [(n, t)]
1026 insert n t ((n',t') : ps)
1027 | n `elem` (namesIn (binderTy t') ++
1028 concatMap namesIn (map (binderTy . snd) ps))
1029 = (n', t') : insert n t ps
1030 | 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