1{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, DeriveFunctor #-}
3{-| TT is the core language of Idris. The language has:
7 * A hierarchy of universes, with cumulativity: Type : Type1, Type1 : Type2, ...
9 * Pattern matching letrec binding
11 * (primitive types defined externally)
15 * Typechecker is kept as simple as possible - no unification, just a checker for incomplete terms.
17 * We have a simple collection of tactics which we use to elaborate source
18 programs with implicit syntax into fully explicit terms.
23import Control.Monad.State
25import qualified Data.Map as Map
28import Data.Vector.Unboxed (Vector)
29import qualified Data.Vector.Unboxed as V
30import qualified Data.Binary as B
31import Data.Binary hiding (get, put)
32import Foreign.Storable (sizeOf)
34import Util.Pretty hiding (Str)
36data Option = TTypeInTType
40-- | Source location. These are typically produced by the parser 'Idris.Parser.pfc'
41data FC = FC { fc_fname :: String, -- ^ Filename
42 fc_line :: Int -- ^ Line number
46deriving instance Binary FC
49instance Sized FC where
50 size (FC f l) = 1 + length f
53 show (FC f l) = f ++ ":" ++ show l
57 | CantUnify Bool Term Term Err [(Name, Type)] Int
58 -- Int is 'score' - how much we did unify
59 -- Bool indicates recoverability, True indicates more info may make
60 -- unification succeed
61 | InfiniteUnify Name Term [(Name, Type)]
62 | CantConvert Term Term [(Name, Type)]
63 | CantInferType String
64 | NonFunctionType Term Term
68 | NotInjective Term Term Term
70 | CantResolveAlts [String]
75 | NonCollapsiblePostulate Name
80 | ProviderError String
83instance Sized Err where
84 size (Msg msg) = length msg
85 size (InternalMsg msg) = length msg
86 size (CantUnify _ left right err _ score) = size left + size right + size err
87 size (InfiniteUnify _ right _) = size right
88 size (CantConvert left right _) = size left + size right
89 size (NoSuchVariable name) = size name
90 size (NoTypeDecl name) = size name
91 size (NotInjective l c r) = size l + size c + size r
92 size (CantResolve trm) = size trm
93 size (NoRewriting trm) = size trm
94 size (CantResolveAlts _) = 1
95 size (IncompleteTerm trm) = size trm
96 size UniverseError = 1
97 size ProgramLineComment = 1
98 size (At fc err) = size fc + size err
99 size (ProviderError msg) = length msg
103score (CantUnify _ _ _ m _ s) = s + score m
104score (CantResolve _) = 20
105score (NoSuchVariable _) = 1000
106score (ProofSearchFail _) = 10000
107score (InternalMsg _) = -1
110instance Show Err where
112 show (InternalMsg s) = "Internal error: " ++ show s
113 show (CantUnify _ l r e sc i) = "CantUnify " ++ show l ++ " " ++ show r ++ " "
114 ++ show e ++ " in " ++ show sc ++ " " ++ show i
115 show (Inaccessible n) = show n ++ " is not an accessible pattern variable"
116 show (ProviderError msg) = "Type provider error: " ++ msg
119instance Pretty Err where
120 pretty (Msg m) = text m
121 pretty (CantUnify _ l r e _ i) =
122 if size l + size r > breakingSize then
123 text "Cannot unify" <+> colon $$
124 nest nestingSize (pretty l <+> text "and" <+> pretty r) $$
125 nest nestingSize (text "where" <+> pretty e <+> text "with" <+> (text . show $ i))
127 text "Cannot unify" <+> colon <+> pretty l <+> text "and" <+> pretty r $$
128 nest nestingSize (text "where" <+> pretty e <+> text "with" <+> (text . show $ i))
129 pretty (ProviderError msg) = text msg
130 pretty _ = text "Error"
134 deriving (Eq, Functor)
136instance Pretty a => Pretty (TC a) where
137 pretty (OK ok) = pretty ok
139 if size err > breakingSize then
140 text "Error" <+> colon $$ (nest nestingSize $ pretty err)
142 text "Error" <+> colon <+> pretty err
144instance Show a => Show (TC a) where
146 show (Error str) = "Error: " ++ show str
148-- at some point, this instance should also carry type checking options
151instance Monad TC where
156 fail e = Error (InternalMsg e)
161trun :: FC -> TC a -> TC a
163trun fc (Error e) = Error (At fc e)
165instance MonadPlus TC where
166 mzero = fail "Unknown error"
167 (OK x) `mplus` _ = OK x
168 _ `mplus` (OK y) = OK y
171discard :: Monad m => m a -> m ()
172discard f = f >> return ()
174showSep :: String -> [String] -> String
177showSep sep (x:xs) = x ++ sep ++ showSep sep xs
179pmap f (x, y) = (f x, f y)
181traceWhen True msg a = trace msg a
182traceWhen False _ a = a
184-- RAW TERMS ----------------------------------------------------------------
186-- | Names are hierarchies of strings, describing scope (so no danger of
187-- duplicate names, but need to be careful on lookup).
188data Name = UN String -- ^ User-provided name
189 | NS Name [String] -- ^ Root, namespaces
190 | MN Int String -- ^ Machine chosen names
191 | NErased -- ^ Name of somethng which is never used in scope
194deriving instance Binary Name
197instance Sized Name where
199 size (NS n els) = 1 + length els
203instance Pretty Name where
204 pretty (UN n) = text n
205 pretty (NS n s) = pretty n
206 pretty (MN i s) = lbrace <+> text s <+> (text . show $ i) <+> rbrace
208instance Show Name where
210 show (NS n s) = showSep "." (reverse s) ++ "." ++ show n
211 show (MN i s) = "{" ++ s ++ show i ++ "}"
214-- |Contexts allow us to map names to things. A root name maps to a collection
215-- of things in different namespaces with that name.
216type Ctxt a = Map.Map Name (Map.Map Name a)
217emptyContext = Map.empty
219tcname (UN ('@':_)) = True
220tcname (NS n _) = tcname n
223implicitable (NS n _) = implicitable n
224implicitable (UN (x:xs)) = isLower x
225implicitable _ = False
230addDef :: Name -> a -> Ctxt a -> Ctxt a
231addDef n v ctxt = case Map.lookup (nsroot n) ctxt of
232 Nothing -> Map.insert (nsroot n)
233 (Map.insert n v Map.empty) ctxt
234 Just xs -> Map.insert (nsroot n)
235 (Map.insert n v xs) ctxt
237{-| Look up a name in the context, given an optional namespace.
238 The name (n) may itself have a (partial) namespace given.
240 Rules for resolution:
242 - if an explicit namespace is given, return the names which match it. If none
243 match, return all names.
245 - if the name has has explicit namespace given, return the names which match it
246 and ignore the given namespace.
248 - otherwise, return all names.
252lookupCtxtName :: Name -> Ctxt a -> [(Name, a)]
253lookupCtxtName n ctxt = case Map.lookup (nsroot n) ctxt of
254 Just xs -> filterNS (Map.toList xs)
258 filterNS ((found, v) : xs)
259 | nsmatch n found = (found, v) : filterNS xs
260 | otherwise = filterNS xs
262 nsmatch (NS n ns) (NS p ps) = ns `isPrefixOf` ps
263 nsmatch (NS _ _) _ = False
264 nsmatch looking found = True
266lookupCtxt :: Name -> Ctxt a -> [a]
267lookupCtxt n ctxt = map snd (lookupCtxtName n ctxt)
269updateDef :: Name -> (a -> a) -> Ctxt a -> Ctxt a
271 = let ds = lookupCtxtName n ctxt in
272 foldr (\ (n, t) c -> addDef n (f t) c) ctxt ds
274toAlist :: Ctxt a -> [(Name, a)]
275toAlist ctxt = let allns = map snd (Map.toList ctxt) in
276 concat (map (Map.toList) allns)
278addAlist :: Show a => [(Name, a)] -> Ctxt a -> Ctxt a
279addAlist [] ctxt = ctxt
280addAlist ((n, tm) : ds) ctxt = addDef n tm (addAlist ds ctxt)
282data NativeTy = IT8 | IT16 | IT32 | IT64
283 deriving (Show, Eq, Ord, Enum)
285instance Pretty NativeTy where
286 pretty IT8 = text "Bits8"
287 pretty IT16 = text "Bits16"
288 pretty IT32 = text "Bits32"
289 pretty IT64 = text "Bits64"
291data IntTy = ITFixed NativeTy | ITNative | ITBig | ITChar
293 deriving (Show, Eq, Ord)
295data ArithTy = ATInt IntTy | ATFloat -- TODO: Float vectors
296 deriving (Show, Eq, Ord)
298instance Pretty ArithTy where
299 pretty (ATInt ITNative) = text "Int"
300 pretty (ATInt ITBig) = text "BigInt"
301 pretty (ATInt ITChar) = text "Char"
302 pretty (ATInt (ITFixed n)) = pretty n
303 pretty (ATInt (ITVec e c)) = pretty e <> text "x" <> (text . show $ c)
304 pretty ATFloat = text "Float"
306nativeTyWidth :: NativeTy -> Int
308nativeTyWidth IT16 = 16
309nativeTyWidth IT32 = 32
310nativeTyWidth IT64 = 64
312{-# DEPRECATED intTyWidth "Non-total function, use nativeTyWidth and appropriate casing" #-}
313intTyWidth :: IntTy -> Int
314intTyWidth (ITFixed n) = nativeTyWidth n
315intTyWidth ITNative = 8 * sizeOf (0 :: Int)
316intTyWidth ITChar = error "IRTS.Lang.intTyWidth: Characters have platform and backend dependent width"
317intTyWidth ITBig = error "IRTS.Lang.intTyWidth: Big integers have variable width"
319data Const = I Int | BI Integer | Fl Double | Ch Char | Str String
320 | B8 Word8 | B16 Word16 | B32 Word32 | B64 Word64
321 | B8V (Vector Word8) | B16V (Vector Word16)
322 | B32V (Vector Word32) | B64V (Vector Word64)
323 | AType ArithTy | StrType
324 | PtrType | VoidType | Forgot
327deriving instance Binary Const
330instance Sized Const where
333instance Pretty Const where
334 pretty (I i) = text . show $ i
335 pretty (BI i) = text . show $ i
336 pretty (Fl f) = text . show $ f
337 pretty (Ch c) = text . show $ c
338 pretty (Str s) = text s
339 pretty (AType a) = pretty a
340 pretty StrType = text "String"
341 pretty PtrType = text "Ptr"
342 pretty VoidType = text "Void"
343 pretty Forgot = text "Forgot"
344 pretty (B8 w) = text . show $ w
345 pretty (B16 w) = text . show $ w
346 pretty (B32 w) = text . show $ w
347 pretty (B64 w) = text . show $ w
350 | RBind Name (Binder Raw) Raw
357instance Sized Raw where
359 size (RBind name bind right) = 1 + size bind + size right
360 size (RApp left right) = 1 + size left + size right
362 size (RForce raw) = 1 + size raw
363 size (RConstant const) = size const
365instance Pretty Raw where
369deriving instance Binary Raw
372-- | All binding forms are represented in a unform fashion.
373data Binder b = Lam { binderTy :: b {-^ type annotation for bound variable-}}
374 | Pi { binderTy :: b }
375 | Let { binderTy :: b,
376 binderVal :: b {-^ value for bound variable-}}
377 | NLet { binderTy :: b,
379 | Hole { binderTy :: b}
380 | GHole { binderTy :: b}
381 | Guess { binderTy :: b,
383 | PVar { binderTy :: b }
384 | PVTy { binderTy :: b }
385 deriving (Show, Eq, Ord, Functor)
387deriving instance Binary Binder
390instance Sized a => Sized (Binder a) where
391 size (Lam ty) = 1 + size ty
392 size (Pi ty) = 1 + size ty
393 size (Let ty val) = 1 + size ty + size val
394 size (NLet ty val) = 1 + size ty + size val
395 size (Hole ty) = 1 + size ty
396 size (GHole ty) = 1 + size ty
397 size (Guess ty val) = 1 + size ty + size val
398 size (PVar ty) = 1 + size ty
399 size (PVTy ty) = 1 + size ty
401fmapMB :: Monad m => (a -> m b) -> Binder a -> m (Binder b)
402fmapMB f (Let t v) = liftM2 Let (f t) (f v)
403fmapMB f (NLet t v) = liftM2 NLet (f t) (f v)
404fmapMB f (Guess t v) = liftM2 Guess (f t) (f v)
405fmapMB f (Lam t) = liftM Lam (f t)
406fmapMB f (Pi t) = liftM Pi (f t)
407fmapMB f (Hole t) = liftM Hole (f t)
408fmapMB f (GHole t) = liftM GHole (f t)
409fmapMB f (PVar t) = liftM PVar (f t)
410fmapMB f (PVTy t) = liftM PVTy (f t)
412raw_apply :: Raw -> [Raw] -> Raw
414raw_apply f (a : as) = raw_apply (RApp f a) as
416raw_unapply :: Raw -> (Raw, [Raw])
417raw_unapply t = ua [] t where
418 ua args (RApp f a) = ua (a:args) f
419 ua args t = (t, args)
421data RawFun = RawFun { rtype :: Raw,
426data RawDatatype = RDatatype Name Raw [(Name, Raw)]
429data RDef = RFunction RawFun
434type RProgram = [(Name, RDef)]
436-- WELL TYPED TERMS ---------------------------------------------------------
438-- | Universe expressions for universe checking
439data UExp = UVar Int -- ^ universe variable
440 | UVal Int -- ^ explicit universe level
443instance Sized UExp where
446-- We assume that universe levels have been checked, so anything external
447-- can just have the same universe variable and we won't get any new
450instance Binary UExp where
452 get = return (UVar (-1))
454instance Show UExp where
455 show (UVar x) | x < 26 = [toEnum (x + fromEnum 'a')]
456 | otherwise = toEnum ((x `mod` 26) + fromEnum 'a') : show (x `div` 26)
457 show (UVal x) = show x
458-- show (UMax l r) = "max(" ++ show l ++ ", " ++ show r ++")"
460-- | Universe constraints
461data UConstraint = ULT UExp UExp -- ^ Strictly less than
462 | ULE UExp UExp -- ^ Less than or equal to
465instance Show UConstraint where
466 show (ULT x y) = show x ++ " < " ++ show y
467 show (ULE x y) = show x ++ " <= " ++ show y
469type UCs = (Int, [UConstraint])
473 | DCon Int Int -- ^ Data constructor; Ints are tag and arity
474 | TCon Int Int -- ^ Type constructor; Ints are tag and arity
477deriving instance Binary NameType
480instance Sized NameType where
483instance Pretty NameType where
486instance Eq NameType where
487 Bound == Bound = True
489 DCon _ a == DCon _ b = (a == b) -- ignore tag
490 TCon _ a == TCon _ b = (a == b) -- ignore tag
493-- | Terms in the core language
494data TT n = P NameType n (TT n) -- ^ named references
495 | V Int -- ^ a resolved de Bruijn-indexed variable
496 | Bind n (Binder (TT n)) (TT n) -- ^ a binding
497 | App (TT n) (TT n) -- ^ function, function type, arg
498 | Constant Const -- ^ constant
499 | Proj (TT n) Int -- ^ argument projection; runtime only
500 | Erased -- ^ an erased term
501 | Impossible -- ^ special case for totality checking
502 | TType UExp -- ^ the type of types at some level
503 deriving (Ord, Functor)
505deriving instance Binary TT
508class TermSize a where
509 termsize :: Name -> a -> Int
511instance TermSize a => TermSize [a] where
513 termsize n (x : xs) = termsize n x + termsize n xs
515instance TermSize (TT Name) where
517 | x == n = 1000000 -- recursive => really big
520 termsize n (Bind n' (Let t v) sc)
521 = let rn = if n == n' then MN 0 "noname" else n in
522 termsize rn v + termsize rn sc
523 termsize n (Bind n' b sc)
524 = let rn = if n == n' then MN 0 "noname" else n in
526 termsize n (App f a) = termsize n f + termsize n a
527 termsize n (Proj t i) = termsize n t
530instance Sized a => Sized (TT a) where
531 size (P name n trm) = 1 + size name + size n + size trm
533 size (Bind nm binder bdy) = 1 + size nm + size binder + size bdy
534 size (App l r) = 1 + size l + size r
535 size (Constant c) = size c
537 size (TType u) = 1 + size u
539instance Pretty a => Pretty (TT a) where
540 pretty _ = text "test"
542type EnvTT n = [(n, Binder (TT n))]
544data Datatype n = Data { d_typename :: n,
547 d_cons :: [(n, TT n)] }
548 deriving (Show, Functor, Eq)
550instance Eq n => Eq (TT n) where
551 (==) (P xt x _) (P yt y _) = x == y
552 (==) (V x) (V y) = x == y
553 (==) (Bind _ xb xs) (Bind _ yb ys) = xb == yb && xs == ys
554 (==) (App fx ax) (App fy ay) = fx == fy && ax == ay
555 (==) (TType _) (TType _) = True -- deal with constraints later
556 (==) (Constant x) (Constant y) = x == y
557 (==) (Proj x i) (Proj y j) = x == y && i == j
562-- * A few handy operations on well typed terms:
564-- | A term is injective iff it is a data constructor, type constructor,
565-- constant, the type Type, pi-binding, or an application of an injective
567isInjective :: TT n -> Bool
568isInjective (P (DCon _ _) _ _) = True
569isInjective (P (TCon _ _) _ _) = True
570isInjective (Constant _) = True
571isInjective (TType x) = True
572isInjective (Bind _ (Pi _) sc) = True
573isInjective (App f a) = isInjective f
576-- | Count the number of instances of a de Bruijn index in a term
577vinstances :: Int -> TT n -> Int
578vinstances i (V x) | i == x = 1
579vinstances i (App f a) = vinstances i f + vinstances i a
580vinstances i (Bind x b sc) = instancesB b + vinstances (i + 1) sc
581 where instancesB (Let t v) = vinstances i v
585instantiate :: TT n -> TT n -> TT n
586instantiate e = subst 0 where
587 subst i (V x) | i == x = e
588 subst i (Bind x b sc) = Bind x (fmap (subst i) b) (subst (i+1) sc)
589 subst i (App f a) = App (subst i f) (subst i a)
590 subst i (Proj x idx) = Proj (subst i x) idx
593explicitNames :: TT n -> TT n
594explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
596 (explicitNames (instantiate
597 (P Bound x (binderTy b')) sc))
598explicitNames (App f a) = App (explicitNames f) (explicitNames a)
599explicitNames (Proj x idx) = Proj (explicitNames x) idx
602pToV :: Eq n => n -> TT n -> TT n
604pToV' n i (P _ x _) | n == x = V i
605pToV' n i (Bind x b sc)
606-- We can assume the inner scope has been pToVed already, so continue to
607-- resolve names from the *outer* scope which may happen to have the same id.
608-- | n == x = Bind x (fmap (pToV' n i) b) sc
609 | otherwise = Bind x (fmap (pToV' n i) b) (pToV' n (i+1) sc)
610pToV' n i (App f a) = App (pToV' n i f) (pToV' n i a)
611pToV' n i (Proj t idx) = Proj (pToV' n i t) idx
614-- increase de Bruijn indices, as if a binder has been added
615addBinder :: TT n -> TT n
618 ab top (V i) | i >= top = V (i + 1)
620 ab top (Bind x b sc) = Bind x (fmap (ab top) b) (ab (top + 1) sc)
621 ab top (App f a) = App (ab top f) (ab top a)
622 ab top (Proj t idx) = Proj (ab top t) idx
625-- | Convert several names. First in the list comes out as V 0
626pToVs :: Eq n => [n] -> TT n -> TT n
627pToVs ns tm = pToVs' ns tm 0 where
629 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
633 vToP' env (V i) = let (n, b) = (env !! i) in
634 P Bound n (binderTy b)
635 vToP' env (Bind n b sc) = let b' = fmap (vToP' env) b in
636 Bind n b' (vToP' ((n, b'):env) sc)
637 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
640finalise :: Eq n => TT n -> TT n
641finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
642finalise (App f a) = App (finalise f) (finalise a)
645subst :: Eq n => n -> TT n -> TT n -> TT n
646subst n v tm = instantiate v (pToV n tm)
648substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
650substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
652substTerm :: Eq n => TT n -> TT n -> TT n -> TT n
653substTerm old new = st where
654 st t | t == old = new
655 st (App f a) = App (st f) (st a)
656 st (Bind x b sc) = Bind x (fmap st b) (st sc)
659-- Returns true if V 0 and bound name n do not occur in the term
661noOccurrence :: Eq n => n -> TT n -> Bool
662noOccurrence n t = no' 0 t
664 no' i (V x) = not (i == x)
665 no' i (P Bound x _) = not (n == x)
666 no' i (Bind n b sc) = noB' i b && no' (i+1) sc
667 where noB' i (Let t v) = no' i t && no' i v
668 noB' i (Guess t v) = no' i t && no' i v
669 noB' i b = no' i (binderTy b)
670 no' i (App f a) = no' i f && no' i a
671 no' i (Proj x _) = no' i x
674-- | Returns all names used free in the term
675freeNames :: Eq n => TT n -> [n]
676freeNames (P _ n _) = [n]
677freeNames (Bind n (Let t v) sc) = nub $ freeNames v ++ (freeNames sc \\ [n])
679freeNames (Bind n b sc) = nub $ freeNames (binderTy b) ++ (freeNames sc \\ [n])
680freeNames (App f a) = nub $ freeNames f ++ freeNames a
681freeNames (Proj x i) = nub $ freeNames x
684-- | Return the arity of a (normalised) type
686arity (Bind n (Pi t) sc) = 1 + arity sc
689-- | Deconstruct an application; returns the function and a list of arguments
690unApply :: TT n -> (TT n, [TT n])
691unApply t = ua [] t where
692 ua args (App f a) = ua (a:args) f
693 ua args t = (t, args)
695mkApp :: TT n -> [TT n] -> TT n
697mkApp f (a:as) = mkApp (App f a) as
699forget :: TT Name -> Raw
702 fe env (P _ n _) = Var n
703 fe env (V i) = Var (env !! i)
704 fe env (Bind n b sc) = RBind n (fmap (fe env) b)
706 fe env (App f a) = RApp (fe env f) (fe env a)
709 fe env (TType i) = RType
710 fe env Erased = RConstant Forgot
712bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
714bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
716bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
717bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
719getArgTys :: TT n -> [(n, TT n)]
720getArgTys (Bind n (Pi t) sc) = (n, t) : getArgTys sc
723getRetTy :: TT n -> TT n
724getRetTy (Bind n (PVar _) sc) = getRetTy sc
725getRetTy (Bind n (PVTy _) sc) = getRetTy sc
726getRetTy (Bind n (Pi _) sc) = getRetTy sc
729uniqueName :: Name -> [Name] -> Name
730uniqueName n hs | n `elem` hs = uniqueName (nextName n) hs
733uniqueBinders :: [Name] -> TT Name -> TT Name
734uniqueBinders ns (Bind n b sc)
735 = let n' = uniqueName n ns in
736 Bind n' (fmap (uniqueBinders (n':ns)) b) (uniqueBinders ns sc)
737uniqueBinders ns (App f a) = App (uniqueBinders ns f) (uniqueBinders ns a)
738uniqueBinders ns t = t
741nextName (NS x s) = NS (nextName x) s
742nextName (MN i n) = MN (i+1) n
743nextName (UN x) = let (num', nm') = span isDigit (reverse x)
745 num = readN (reverse num') in
746 UN (nm ++ show (num+1))
756-- an environment with de Bruijn indices 'normalised' so that they all refer to
759newtype WkEnvTT n = Wk (EnvTT n)
760type WkEnv = WkEnvTT Name
762instance (Eq n, Show n) => Show (TT n) where
763 show t = showEnv [] t
765itBitsName IT8 = "Bits8"
766itBitsName IT16 = "Bits16"
767itBitsName IT32 = "Bits32"
768itBitsName IT64 = "Bits64"
770instance Show Const where
772 show (BI i) = show i ++ "L"
775 show (Str s) = show s
777 show (B16 x) = show x
778 show (B32 x) = show x
779 show (B64 x) = show x
780 show (B8V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
781 show (B16V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
782 show (B32V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
783 show (B64V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
784 show (AType ATFloat) = "Float"
785 show (AType (ATInt ITBig)) = "Integer"
786 show (AType (ATInt ITNative)) = "Int"
787 show (AType (ATInt ITChar)) = "Char"
788 show (AType (ATInt (ITFixed it))) = itBitsName it
789 show (AType (ATInt (ITVec it c))) = itBitsName it ++ "x" ++ show c
790 show StrType = "String"
792 show VoidType = "Void"
794showEnv env t = showEnv' env t False
795showEnvDbg env t = showEnv' env t True
797prettyEnv env t = prettyEnv' env t False
799 prettyEnv' env t dbg = prettySe 10 env t dbg
801 bracket outer inner p
802 | inner > outer = lparen <> p <> rparen
805 prettySe p env (P nt n t) debug =
808 lbrack <+> pretty nt <+> colon <+> prettySe 10 env t debug <+> rbrack
811 prettySe p env (V i) debug
814 text . show . fst $ env!!i
816 lbrack <+> text (show i) <+> rbrack
817 | otherwise = text "unbound" <+> text (show i) <+> text "!"
818 prettySe p env (Bind n b@(Pi t) sc) debug
819 | noOccurrence n sc && not debug =
820 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
821 prettySe p env (Bind n b sc) debug =
822 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
823 prettySe p env (App f a) debug =
824 bracket p 1 $ prettySe 1 env f debug <+> prettySe 0 env a debug
825 prettySe p env (Proj x i) debug =
826 prettySe 1 env x debug <+> text ("!" ++ show i)
827 prettySe p env (Constant c) debug = pretty c
828 prettySe p env Erased debug = text "[_]"
829 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
831 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
832 prettySb env n (Hole t) = prettyB env "?defer" "." n t
833 prettySb env n (Pi t) = prettyB env "(" ") ->" n t
834 prettySb env n (PVar t) = prettyB env "pat" "." n t
835 prettySb env n (PVTy t) = prettyB env "pty" "." n t
836 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
837 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
839 prettyB env op sc n t debug =
840 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
842 prettyBv env op sc n t v debug =
843 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
844 prettySe 10 env v debug <> text sc
847showEnv' env t dbg = se 10 env t where
848 se p env (P nt n t) = show n
849 ++ if dbg then "{" ++ show nt ++ " : " ++ se 10 env t ++ "}" else ""
850 se p env (V i) | i < length env && i >= 0
851 = (show $ fst $ env!!i) ++
852 if dbg then "{" ++ show i ++ "}" else ""
853 | otherwise = "!!V " ++ show i ++ "!!"
854 se p env (Bind n b@(Pi t) sc)
855 | noOccurrence n sc && not dbg = bracket p 2 $ se 1 env t ++ " -> " ++ se 10 ((n,b):env) sc
856 se p env (Bind n b sc) = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
857 se p env (App f a) = bracket p 1 $ se 1 env f ++ " " ++ se 0 env a
858 se p env (Proj x i) = se 1 env x ++ "!" ++ show i
859 se p env (Constant c) = show c
860 se p env Erased = "[__]"
861 se p env Impossible = "[impossible]"
862 se p env (TType i) = "Type " ++ show i
864 sb env n (Lam t) = showb env "\\ " " => " n t
865 sb env n (Hole t) = showb env "? " ". " n t
866 sb env n (GHole t) = showb env "?defer " ". " n t
867 sb env n (Pi t) = showb env "(" ") -> " n t
868 sb env n (PVar t) = showb env "pat " ". " n t
869 sb env n (PVTy t) = showb env "pty " ". " n t
870 sb env n (Let t v) = showbv env "let " " in " n t v
871 sb env n (Guess t v) = showbv env "?? " " in " n t v
873 showb env op sc n t = op ++ show n ++ " : " ++ se 10 env t ++ sc
874 showbv env op sc n t v = op ++ show n ++ " : " ++ se 10 env t ++ " = " ++
877 bracket outer inner str | inner > outer = "(" ++ str ++ ")"
880-- | Check whether a term has any holes in it - impure if so
881pureTerm :: TT Name -> Bool
882pureTerm (App f a) = pureTerm f && pureTerm a
883pureTerm (Bind n b sc) = notClassName n && pureBinder b && pureTerm sc where
884 pureBinder (Hole _) = False
885 pureBinder (Guess _ _) = False
886 pureBinder (Let t v) = pureTerm t && pureTerm v
887 pureBinder t = pureTerm (binderTy t)
889 notClassName (MN _ "class") = False
890 notClassName _ = True
894-- | Weaken a term by adding i to each de Bruijn index (i.e. lift it over i bindings)
895weakenTm :: Int -> TT n -> TT n
896weakenTm i t = wk i 0 t
897 where wk i min (V x) | x >= min = V (i + x)
898 wk i m (App f a) = App (wk i m f) (wk i m a)
899 wk i m (Bind x b sc) = Bind x (wkb i m b) (wk i (m + 1) sc)
901 wkb i m t = fmap (wk i m) t
903-- | Weaken an environment so that all the de Bruijn indices are correct according
904-- to the latest bound variable
906weakenEnv :: EnvTT n -> EnvTT n
907weakenEnv env = wk (length env - 1) env
909 wk i ((n, b) : bs) = (n, weakenTmB i b) : wk (i - 1) bs
910 weakenTmB i (Let t v) = Let (weakenTm i t) (weakenTm i v)
911 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
912 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
914weakenTmEnv :: Int -> EnvTT n -> EnvTT n
915weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
917orderPats :: Term -> Term
918orderPats tm = op [] tm
920 op ps (Bind n (PVar t) sc) = op ((n, PVar t) : ps) sc
921 op ps (Bind n (Hole t) sc) = op ((n, Hole t) : ps) sc
922 op ps sc = bindAll (map (\ (n, t) -> (n, t)) (sortP ps)) sc
924 sortP ps = pick [] (reverse ps)
926 namesIn (P _ n _) = [n]
927 namesIn (Bind n b t) = nub $ nb b ++ (namesIn t \\ [n])
928 where nb (Let t v) = nub (namesIn t) ++ nub (namesIn v)
929 nb (Guess t v) = nub (namesIn t) ++ nub (namesIn v)
930 nb t = namesIn (binderTy t)
931 namesIn (App f a) = nub (namesIn f ++ namesIn a)
934 pick acc [] = reverse acc
935 pick acc ((n, t) : ps) = pick (insert n t acc) ps
937 insert n t [] = [(n, t)]
938 insert n t ((n',t') : ps)
939 | n `elem` (namesIn (binderTy t') ++
940 concatMap namesIn (map (binderTy . snd) ps))
941 = (n', t') : insert n t ps
942 | 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