1{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, DeriveFunctor, DeriveDataTypeable #-}
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.
21module Idris.Core.TT where
23import Control.Applicative (Applicative (..), Alternative)
24import qualified Control.Applicative as A (Alternative (..))
25import Control.Monad.State.Strict
26import Control.Monad.Trans.Except (Except (..))
28import qualified Data.Map.Strict as Map
30import Data.Data (Data)
31import Numeric (showIntAtBase)
32import qualified Data.Text as T
33import Data.List hiding (group, insert)
34import Data.Set(Set, member, fromList, insert)
35import Data.Maybe (listToMaybe)
36import Data.Foldable (Foldable)
37import Data.Traversable (Traversable)
38import Data.Typeable (Typeable)
39import Data.Vector.Unboxed (Vector)
40import qualified Data.Vector.Unboxed as V
41import qualified Data.Binary as B
42import Data.Binary hiding (get, put)
43import Foreign.Storable (sizeOf)
45import Util.Pretty hiding (Str)
47data Option = TTypeInTType
51-- | Source location. These are typically produced by the parser 'Idris.Parser.getFC'
52data FC = FC { fc_fname :: String, -- ^ Filename
53 fc_start :: (Int, Int), -- ^ Line and column numbers for the start of the location span
54 fc_end :: (Int, Int) -- ^ Line and column numbers for the end of the location span
56 deriving (Data, Typeable, Ord)
58-- | Ignore source location equality (so deriving classes do not compare FCs)
63newtype FC' = FC' { unwrapFC :: FC }
66 FC' fc == FC' fc' = fcEq fc fc'
67 where fcEq (FC n s e) (FC n' s' e') = n == n' && s == s' && e == e'
69-- | Empty source location
73-- | Source location with file only
75fileFC s = FC s (0, 0) (0, 0)
78deriving instance Binary FC
79deriving instance NFData FC
82instance Sized FC where
83 size (FC f s e) = 4 + length f
86 show (FC f s e) = f ++ ":" ++ showLC s e
87 where showLC (sl, sc) (el, ec) | sl == el && sc == ec = show sl ++ ":" ++ show sc
88 | sl == el = show sl ++ ":" ++ show sc ++ "-" ++ show ec
89 | otherwise = show sl ++ ":" ++ show sc ++ "-" ++ show el ++ ":" ++ show ec
91-- | Output annotation for pretty-printed name - decides colour
92data NameOutput = TypeOutput | FunOutput | DataOutput | MetavarOutput | PostulateOutput
94-- | Text formatting output
95data TextFormatting = BoldText | ItalicText | UnderlineText
97-- | Output annotations for pretty-printing
98data OutputAnnotation = AnnName Name (Maybe NameOutput) (Maybe String) (Maybe String)
99 -- ^^ The name, classification, docs overview, and pretty-printed type
100 | AnnBoundName Name Bool
101 -- ^^ The name and whether it is implicit
103 | AnnData String String -- ^ type, doc overview
104 | AnnType String String -- ^ name, doc overview
107 | AnnTextFmt TextFormatting
108 | AnnTerm [(Name, Bool)] (TT Name) -- ^ pprint bound vars, original term
109 | AnnSearchResult Ordering -- ^ more general, isomorphic, or more specific
112-- | Used for error reflection
113data ErrorReportPart = TextPart String
116 | SubReport [ErrorReportPart]
117 deriving (Show, Eq, Data, Typeable)
120-- Please remember to keep Err synchronised with
121-- Language.Reflection.Errors.Err in the stdlib!
123data Provenance = ExpectedType
128 deriving (Show, Eq, Data, Typeable)
130deriving instance NFData Err
131deriving instance Binary Err
134-- | Idris errors. Used as exceptions in the compiler, but reported to users
135-- if they reach the top level.
139 | CantUnify Bool (t, Maybe Provenance) -- Expected type, provenance
140 (t, Maybe Provenance) -- Actual type, provenance
141 (Err' t) [(Name, t)] Int
142 -- Int is 'score' - how much we did unify
143 -- Bool indicates recoverability, True indicates more info may make
144 -- unification succeed
145 | InfiniteUnify Name t [(Name, t)]
146 | CantConvert t t [(Name, t)]
147 | CantSolveGoal t [(Name, t)]
148 | UnifyScope Name Name t [(Name, t)]
149 | CantInferType String
150 | NonFunctionType t t
152 | TooManyArguments Name
154 | NoSuchVariable Name
158 | CantResolve Bool -- True if postponed, False if fatal
160 | InvalidTCArg Name t
161 | CantResolveAlts [Name]
163 | NoEliminator String t
165 | UniqueError Universe Name
166 | UniqueKindError Universe Name
170 | NonCollapsiblePostulate Name
171 | AlreadyDefined Name
172 | ProofSearchFail (Err' t)
175 | Elaborating String Name (Err' t)
176 | ElaboratingArg Name Name [(Name, Name)] (Err' t)
177 | ProviderError String
178 | LoadingFailed String (Err' t)
179 | ReflectionError [[ErrorReportPart]] (Err' t)
180 | ReflectionFailed String (Err' t)
181 | ElabDebug (Maybe String) t [(Name, t, [(Name, Binder t)])]
182 -- ^ User-specified message, proof term, goals with context (first goal is focused)
183 deriving (Eq, Functor, Data, Typeable)
189 deriving (Eq, Functor)
191bindTC :: TC a -> (a -> TC b) -> TC b
192bindTC x k = case x of
197instance Monad TC where
200 fail e = Error (InternalMsg e)
202instance MonadPlus TC where
203 mzero = fail "Unknown error"
204 (OK x) `mplus` _ = OK x
205 _ `mplus` (OK y) = OK y
209instance Applicative TC where
213instance Alternative TC where
218deriving instance NFData Err
221instance Sized ErrorReportPart where
222 size (TextPart msg) = 1 + length msg
223 size (TermPart t) = 1 + size t
224 size (NamePart n) = 1 + size n
225 size (SubReport rs) = 1 + size rs
227instance Sized Err where
228 size (Msg msg) = length msg
229 size (InternalMsg msg) = length msg
230 size (CantUnify _ left right err _ score) = size (fst left) + size (fst right) + size err
231 size (InfiniteUnify _ right _) = size right
232 size (CantConvert left right _) = size left + size right
233 size (UnifyScope _ _ right _) = size right
234 size (NoSuchVariable name) = size name
235 size (NoTypeDecl name) = size name
236 size (NotInjective l c r) = size l + size c + size r
237 size (CantResolve _ trm) = size trm
238 size (NoRewriting trm) = size trm
239 size (CantResolveAlts _) = 1
240 size (IncompleteTerm trm) = size trm
241 size UniverseError = 1
242 size ProgramLineComment = 1
243 size (At fc err) = size fc + size err
244 size (Elaborating _ n err) = size err
245 size (ElaboratingArg _ _ _ err) = size err
246 size (ProviderError msg) = length msg
247 size (LoadingFailed fn e) = 1 + length fn + size e
251score (CantUnify _ _ _ m _ s) = s + score m
252score (CantResolve _ _) = 20
253score (NoSuchVariable _) = 1000
254score (ProofSearchFail e) = score e
255score (CantSolveGoal _ _) = 100000
256score (InternalMsg _) = -1
257score (At _ e) = score e
258score (ElaboratingArg _ _ _ e) = score e
259score (Elaborating _ _ e) = score e
262instance Show Err where
264 show (InternalMsg s) = "Internal error: " ++ show s
265 show (CantUnify rcv l r e sc i) = "CantUnify " ++ show rcv ++ " " ++
266 show l ++ " " ++ show r ++ " " ++
267 show e ++ " in " ++ show sc ++ " " ++ show i
268 show (CantSolveGoal g _) = "CantSolve " ++ show g
269 show (Inaccessible n) = show n ++ " is not an accessible pattern variable"
270 show (ProviderError msg) = "Type provider error: " ++ msg
271 show (LoadingFailed fn e) = "Loading " ++ fn ++ " failed: (TT) " ++ show e
272 show ProgramLineComment = "Program line next to comment"
273 show (At f e) = show f ++ ":" ++ show e
274 show (ElaboratingArg f x prev e) = "Elaborating " ++ show f ++ " arg " ++
275 show x ++ ": " ++ show e
276 show (Elaborating what n e) = "Elaborating " ++ what ++ show n ++ ":" ++ show e
277 show (ProofSearchFail e) = "Proof search fail: " ++ show e
280instance Pretty Err OutputAnnotation where
281 pretty (Msg m) = text m
282 pretty (CantUnify _ (l, _) (r, _) e _ i) =
283 text "Cannot unify" <+> colon <+> pretty l <+> text "and" <+> pretty r <+>
284 nest nestingSize (text "where" <+> pretty e <+> text "with" <+> (text . show $ i))
285 pretty (ProviderError msg) = text msg
286 pretty err@(LoadingFailed _ _) = text (show err)
287 pretty _ = text "Error"
289instance (Pretty a OutputAnnotation) => Pretty (TC a) OutputAnnotation where
290 pretty (OK ok) = pretty ok
292 text "Error" <+> colon <+> pretty err
294instance Show a => Show (TC a) where
296 show (Error str) = "Error: " ++ show str
301failMsg :: String -> TC a
302failMsg str = Error (Msg str)
304trun :: FC -> TC a -> TC a
306trun fc (Error e) = Error (At fc e)
308discard :: Monad m => m a -> m ()
309discard f = f >> return ()
311showSep :: String -> [String] -> String
314showSep sep (x:xs) = x ++ sep ++ showSep sep xs
316pmap f (x, y) = (f x, f y)
318traceWhen True msg a = trace msg a
319traceWhen False _ a = a
321-- RAW TERMS ----------------------------------------------------------------
323-- | Names are hierarchies of strings, describing scope (so no danger of
324-- duplicate names, but need to be careful on lookup).
325data Name = UN T.Text -- ^ User-provided name
326 | NS Name [T.Text] -- ^ Root, namespaces
327 | MN Int T.Text -- ^ Machine chosen names
328 | NErased -- ^ Name of something which is never used in scope
329 | SN SpecialName -- ^ Decorated function names
330 | SymRef Int -- ^ Reference to IBC file symbol table (used during serialisation)
331 deriving (Eq, Ord, Data, Typeable)
333txt :: String -> T.Text
336str :: T.Text -> String
339tnull :: T.Text -> Bool
342thead :: T.Text -> Char
345-- Smart constructors for names, using old String style
349sNS :: Name -> [String] -> Name
350sNS n ss = NS n (map txt ss)
352sMN :: Int -> String -> Name
353sMN i s = MN i (txt s)
356deriving instance Binary Name
357deriving instance NFData Name
360data SpecialName = WhereN Int Name Name
362 | InstanceN Name [T.Text]
363 | ParentN Name T.Text
368 deriving (Eq, Ord, Data, Typeable)
370deriving instance Binary SpecialName
371deriving instance NFData SpecialName
374sInstanceN :: Name -> [String] -> SpecialName
375sInstanceN n ss = InstanceN n (map T.pack ss)
377sParentN :: Name -> String -> SpecialName
378sParentN n s = ParentN n (T.pack s)
380instance Sized Name where
382 size (NS n els) = 1 + length els
386instance Pretty Name OutputAnnotation where
387 pretty n@(UN n') = annotate (AnnName n Nothing Nothing Nothing) $ text (T.unpack n')
388 pretty n@(NS un s) = annotate (AnnName n Nothing Nothing Nothing) . noAnnotate $ pretty un
389 pretty n@(MN i s) = annotate (AnnName n Nothing Nothing Nothing) $
390 lbrace <+> text (T.unpack s) <+> (text . show $ i) <+> rbrace
391 pretty n@(SN s) = annotate (AnnName n Nothing Nothing Nothing) $ text (show s)
393instance Pretty [Name] OutputAnnotation where
394 pretty = encloseSep empty empty comma . map pretty
396instance Show Name where
398 show (NS n s) = showSep "." (map T.unpack (reverse s)) ++ "." ++ show n
399 show (MN _ u) | u == txt "underscore" = "_"
400 show (MN i s) = "{" ++ str s ++ show i ++ "}"
404instance Show SpecialName where
405 show (WhereN i p c) = show p ++ ", " ++ show c
406 show (WithN i n) = "with block in " ++ show n
407 show (InstanceN cl inst) = showSep ", " (map T.unpack inst) ++ " instance of " ++ show cl
408 show (MethodN m) = "method " ++ show m
409 show (ParentN p c) = show p ++ "#" ++ T.unpack c
410 show (CaseN n) = "case block in " ++ show n
411 show (ElimN n) = "<<" ++ show n ++ " eliminator>>"
412 show (InstanceCtorN n) = "constructor of " ++ show n
414-- Show a name in a way decorated for code generation, not human reading
415showCG :: Name -> String
416showCG (UN n) = T.unpack n
417showCG (NS n s) = showSep "." (map T.unpack (reverse s)) ++ "." ++ showCG n
418showCG (MN _ u) | u == txt "underscore" = "_"
419showCG (MN i s) = "{" ++ T.unpack s ++ show i ++ "}"
420showCG (SN s) = showCG' s
421 where showCG' (WhereN i p c) = showCG p ++ ":" ++ showCG c ++ ":" ++ show i
422 showCG' (WithN i n) = "_" ++ showCG n ++ "_with_" ++ show i
423 showCG' (InstanceN cl inst) = '@':showCG cl ++ '$':showSep ":" (map T.unpack inst)
424 showCG' (MethodN m) = '!':showCG m
425 showCG' (ParentN p c) = showCG p ++ "#" ++ show c
426 showCG' (CaseN c) = showCG c ++ "_case"
427 showCG' (ElimN sn) = showCG sn ++ "_elim"
428 showCG' (InstanceCtorN n) = showCG n ++ "_ictor"
432-- |Contexts allow us to map names to things. A root name maps to a collection
433-- of things in different namespaces with that name.
434type Ctxt a = Map.Map Name (Map.Map Name a)
435emptyContext = Map.empty
437mapCtxt :: (a -> b) -> Ctxt a -> Ctxt b
440-- |Return True if the argument 'Name' should be interpreted as the name of a
442tcname (UN xs) | T.null xs = False
443 | otherwise = T.head xs == '@'
444tcname (NS n _) = tcname n
445tcname (SN (InstanceN _ _)) = True
446tcname (SN (MethodN _)) = True
447tcname (SN (ParentN _ _)) = True
450implicitable (NS n _) = implicitable n
451implicitable (UN xs) | T.null xs = False
452 | otherwise = isLower (T.head xs) || T.head xs == '_'
453implicitable (MN _ x) = not (tnull x) && thead x /= '_'
454implicitable _ = False
459-- this will overwrite already existing definitions
460addDef :: Name -> a -> Ctxt a -> Ctxt a
461addDef n v ctxt = case Map.lookup (nsroot n) ctxt of
462 Nothing -> Map.insert (nsroot n)
463 (Map.insert n v Map.empty) ctxt
464 Just xs -> Map.insert (nsroot n)
465 (Map.insert n v xs) ctxt
467{-| Look up a name in the context, given an optional namespace.
468 The name (n) may itself have a (partial) namespace given.
470 Rules for resolution:
472 - if an explicit namespace is given, return the names which match it. If none
473 match, return all names.
475 - if the name has has explicit namespace given, return the names which match it
476 and ignore the given namespace.
478 - otherwise, return all names.
482lookupCtxtName :: Name -> Ctxt a -> [(Name, a)]
483lookupCtxtName n ctxt = case Map.lookup (nsroot n) ctxt of
484 Just xs -> filterNS (Map.toList xs)
488 filterNS ((found, v) : xs)
489 | nsmatch n found = (found, v) : filterNS xs
490 | otherwise = filterNS xs
492 nsmatch (NS n ns) (NS p ps) = ns `isPrefixOf` ps
493 nsmatch (NS _ _) _ = False
494 nsmatch looking found = True
496lookupCtxt :: Name -> Ctxt a -> [a]
497lookupCtxt n ctxt = map snd (lookupCtxtName n ctxt)
499lookupCtxtExact :: Name -> Ctxt a -> Maybe a
500lookupCtxtExact n ctxt = listToMaybe [ v | (nm, v) <- lookupCtxtName n ctxt, nm == n]
502deleteDefExact :: Name -> Ctxt a -> Ctxt a
503deleteDefExact n = Map.adjust (Map.delete n) (nsroot n)
505updateDef :: Name -> (a -> a) -> Ctxt a -> Ctxt a
507 = let ds = lookupCtxtName n ctxt in
508 foldr (\ (n, t) c -> addDef n (f t) c) ctxt ds
510toAlist :: Ctxt a -> [(Name, a)]
511toAlist ctxt = let allns = map snd (Map.toList ctxt) in
512 concatMap (Map.toList) allns
514addAlist :: [(Name, a)] -> Ctxt a -> Ctxt a
515addAlist [] ctxt = ctxt
516addAlist ((n, tm) : ds) ctxt = addDef n tm (addAlist ds ctxt)
518data NativeTy = IT8 | IT16 | IT32 | IT64
519 deriving (Show, Eq, Ord, Enum, Data, Typeable)
521instance Pretty NativeTy OutputAnnotation where
522 pretty IT8 = text "Bits8"
523 pretty IT16 = text "Bits16"
524 pretty IT32 = text "Bits32"
525 pretty IT64 = text "Bits64"
527data IntTy = ITFixed NativeTy | ITNative | ITBig | ITChar
528 deriving (Show, Eq, Ord, Data, Typeable)
530intTyName :: IntTy -> String
531intTyName ITNative = "Int"
532intTyName ITBig = "BigInt"
533intTyName (ITFixed sized) = "B" ++ show (nativeTyWidth sized)
534intTyName (ITChar) = "Char"
536data ArithTy = ATInt IntTy | ATFloat -- TODO: Float vectors https://github.com/idris-lang/Idris-dev/issues/1723
537 deriving (Show, Eq, Ord, Data, Typeable)
539deriving instance NFData IntTy
540deriving instance NFData NativeTy
541deriving instance NFData ArithTy
544instance Pretty ArithTy OutputAnnotation where
545 pretty (ATInt ITNative) = text "Int"
546 pretty (ATInt ITBig) = text "BigInt"
547 pretty (ATInt ITChar) = text "Char"
548 pretty (ATInt (ITFixed n)) = pretty n
549 pretty ATFloat = text "Float"
551nativeTyWidth :: NativeTy -> Int
553nativeTyWidth IT16 = 16
554nativeTyWidth IT32 = 32
555nativeTyWidth IT64 = 64
557{-# DEPRECATED intTyWidth "Non-total function, use nativeTyWidth and appropriate casing" #-}
558intTyWidth :: IntTy -> Int
559intTyWidth (ITFixed n) = nativeTyWidth n
560intTyWidth ITNative = 8 * sizeOf (0 :: Int)
561intTyWidth ITChar = error "IRTS.Lang.intTyWidth: Characters have platform and backend dependent width"
562intTyWidth ITBig = error "IRTS.Lang.intTyWidth: Big integers have variable width"
564data Const = I Int | BI Integer | Fl Double | Ch Char | Str String
565 | B8 Word8 | B16 Word16 | B32 Word32 | B64 Word64
566 | AType ArithTy | StrType
567 | WorldType | TheWorld
569 deriving (Eq, Ord, Data, Typeable)
571deriving instance Binary Const
572deriving instance NFData Const
575isTypeConst :: Const -> Bool
576isTypeConst (AType _) = True
577isTypeConst StrType = True
578isTypeConst WorldType = True
579isTypeConst VoidType = True
582instance Sized Const where
585instance Pretty Const OutputAnnotation where
586 pretty (I i) = text . show $ i
587 pretty (BI i) = text . show $ i
588 pretty (Fl f) = text . show $ f
589 pretty (Ch c) = text . show $ c
590 pretty (Str s) = text s
591 pretty (AType a) = pretty a
592 pretty StrType = text "String"
593 pretty TheWorld = text "%theWorld"
594 pretty WorldType = text "prim__World"
595 pretty VoidType = text "Void"
596 pretty Forgot = text "Forgot"
597 pretty (B8 w) = text . show $ w
598 pretty (B16 w) = text . show $ w
599 pretty (B32 w) = text . show $ w
600 pretty (B64 w) = text . show $ w
602-- | Determines whether the input constant represents a type
603constIsType :: Const -> Bool
604constIsType (I _) = False
605constIsType (BI _) = False
606constIsType (Fl _) = False
607constIsType (Ch _) = False
608constIsType (Str _) = False
609constIsType (B8 _) = False
610constIsType (B16 _) = False
611constIsType (B32 _) = False
612constIsType (B64 _) = False
615-- | Get the docstring for a Const
616constDocs :: Const -> String
617constDocs c@(AType (ATInt ITBig)) = "Arbitrary-precision integers"
618constDocs c@(AType (ATInt ITNative)) = "Fixed-precision integers of undefined size"
619constDocs c@(AType (ATInt ITChar)) = "Characters in some unspecified encoding"
620constDocs c@(AType ATFloat) = "Double-precision floating-point numbers"
621constDocs StrType = "Strings in some unspecified encoding"
622constDocs c@(AType (ATInt (ITFixed IT8))) = "Eight bits (unsigned)"
623constDocs c@(AType (ATInt (ITFixed IT16))) = "Sixteen bits (unsigned)"
624constDocs c@(AType (ATInt (ITFixed IT32))) = "Thirty-two bits (unsigned)"
625constDocs c@(AType (ATInt (ITFixed IT64))) = "Sixty-four bits (unsigned)"
626constDocs (Fl f) = "A float"
627constDocs (I i) = "A fixed-precision integer"
628constDocs (BI i) = "An arbitrary-precision integer"
629constDocs (Str s) = "A string of length " ++ show (length s)
630constDocs (Ch c) = "A character"
631constDocs (B8 w) = "The eight-bit value 0x" ++
632 showIntAtBase 16 intToDigit w ""
633constDocs (B16 w) = "The sixteen-bit value 0x" ++
634 showIntAtBase 16 intToDigit w ""
635constDocs (B32 w) = "The thirty-two-bit value 0x" ++
636 showIntAtBase 16 intToDigit w ""
637constDocs (B64 w) = "The sixty-four-bit value 0x" ++
638 showIntAtBase 16 intToDigit w ""
639constDocs prim = "Undocumented"
641data Universe = NullType | UniqueType | AllTypes
642 deriving (Eq, Ord, Data, Typeable)
644instance Show Universe where
645 show UniqueType = "UniqueType"
646 show NullType = "NullType"
647 show AllTypes = "Type*"
650 | RBind Name (Binder Raw) Raw
656 deriving (Show, Eq, Data, Typeable)
658instance Sized Raw where
660 size (RBind name bind right) = 1 + size bind + size right
661 size (RApp left right) = 1 + size left + size right
664 size (RForce raw) = 1 + size raw
665 size (RConstant const) = size const
667instance Pretty Raw OutputAnnotation where
671deriving instance Binary Raw
672deriving instance NFData Raw
675data ImplicitInfo = Impl { tcinstance :: Bool }
676 deriving (Show, Eq, Ord, Data, Typeable)
679deriving instance Binary ImplicitInfo
680deriving instance NFData ImplicitInfo
683-- The type parameter `b` will normally be something like `TT Name` or just
684-- `Raw`. We do not make a type-level distinction between TT terms that happen
685-- to be TT types and TT terms that are not TT types.
686-- | All binding forms are represented in a uniform fashion. This type only represents
687-- the types of bindings (and their values, if any); the attached identifiers are part
688-- of the 'Bind' constructor for the 'TT' type.
689data Binder b = Lam { binderTy :: !b {-^ type annotation for bound variable-}}
690 | Pi { binderImpl :: Maybe ImplicitInfo,
693 {-^ A binding that occurs in a function type expression, e.g. @(x:Int) -> ...@
694 The 'binderImpl' flag says whether it was a scoped implicit
695 (i.e. forall bound) in the high level Idris, but otherwise
696 has no relevance in TT. -}
697 | Let { binderTy :: !b,
698 binderVal :: b {-^ value for bound variable-}}
699 -- ^ A binding that occurs in a @let@ expression
700 | NLet { binderTy :: !b,
702 | Hole { binderTy :: !b}
703 | GHole { envlen :: Int,
705 | Guess { binderTy :: !b,
707 | PVar { binderTy :: !b }
708 -- ^ A pattern variable
709 | PVTy { binderTy :: !b }
710 deriving (Show, Eq, Ord, Functor, Foldable, Traversable, Data, Typeable)
712deriving instance Binary Binder
713deriving instance NFData Binder
716instance Sized a => Sized (Binder a) where
717 size (Lam ty) = 1 + size ty
718 size (Pi _ ty _) = 1 + size ty
719 size (Let ty val) = 1 + size ty + size val
720 size (NLet ty val) = 1 + size ty + size val
721 size (Hole ty) = 1 + size ty
722 size (GHole _ ty) = 1 + size ty
723 size (Guess ty val) = 1 + size ty + size val
724 size (PVar ty) = 1 + size ty
725 size (PVTy ty) = 1 + size ty
727fmapMB :: Monad m => (a -> m b) -> Binder a -> m (Binder b)
728fmapMB f (Let t v) = liftM2 Let (f t) (f v)
729fmapMB f (NLet t v) = liftM2 NLet (f t) (f v)
730fmapMB f (Guess t v) = liftM2 Guess (f t) (f v)
731fmapMB f (Lam t) = liftM Lam (f t)
732fmapMB f (Pi i t k) = liftM2 (Pi i) (f t) (f k)
733fmapMB f (Hole t) = liftM Hole (f t)
734fmapMB f (GHole i t) = liftM (GHole i) (f t)
735fmapMB f (PVar t) = liftM PVar (f t)
736fmapMB f (PVTy t) = liftM PVTy (f t)
738raw_apply :: Raw -> [Raw] -> Raw
740raw_apply f (a : as) = raw_apply (RApp f a) as
742raw_unapply :: Raw -> (Raw, [Raw])
743raw_unapply t = ua [] t where
744 ua args (RApp f a) = ua (a:args) f
745 ua args t = (t, args)
747-- WELL TYPED TERMS ---------------------------------------------------------
749-- | Universe expressions for universe checking
750data UExp = UVar Int -- ^ universe variable
751 | UVal Int -- ^ explicit universe level
752 deriving (Eq, Ord, Data, Typeable)
754deriving instance NFData UExp
757instance Sized UExp where
760instance Show UExp where
761 show (UVar x) | x < 26 = [toEnum (x + fromEnum 'a')]
762 | otherwise = toEnum ((x `mod` 26) + fromEnum 'a') : show (x `div` 26)
763 show (UVal x) = show x
764-- show (UMax l r) = "max(" ++ show l ++ ", " ++ show r ++")"
766-- | Universe constraints
767data UConstraint = ULT UExp UExp -- ^ Strictly less than
768 | ULE UExp UExp -- ^ Less than or equal to
771data ConstraintFC = ConstraintFC { uconstraint :: UConstraint,
775instance Eq ConstraintFC where
776 x == y = uconstraint x == uconstraint y
778instance Ord ConstraintFC where
779 compare x y = compare (uconstraint x) (uconstraint y)
781instance Show UConstraint where
782 show (ULT x y) = show x ++ " < " ++ show y
783 show (ULE x y) = show x ++ " <= " ++ show y
785type UCs = (Int, [UConstraint])
789 | DCon {nt_tag :: Int, nt_arity :: Int, nt_unique :: Bool} -- ^ Data constructor
790 | TCon {nt_tag :: Int, nt_arity :: Int} -- ^ Type constructor
791 deriving (Show, Ord, Data, Typeable)
793deriving instance Binary NameType
794deriving instance NFData NameType
797instance Sized NameType where
800instance Pretty NameType OutputAnnotation where
803instance Eq NameType where
804 Bound == Bound = True
806 DCon _ a _ == DCon _ b _ = (a == b) -- ignore tag
807 TCon _ a == TCon _ b = (a == b) -- ignore tag
810-- | Terms in the core language. The type parameter is the type of
811-- identifiers used for bindings and explicit named references;
812-- usually we use @TT 'Name'@.
813data TT n = P NameType n (TT n) -- ^ named references with type
814 -- (P for "Parameter", motivated by McKinna and Pollack's
815 -- Pure Type Systems Formalized)
816 | V !Int -- ^ a resolved de Bruijn-indexed variable
817 | Bind n !(Binder (TT n)) (TT n) -- ^ a binding
818 | App !(TT n) (TT n) -- ^ function, function type, arg
819 | Constant Const -- ^ constant
820 | Proj (TT n) !Int -- ^ argument projection; runtime only
821 -- (-1) is a special case for 'subtract one from BI'
822 | Erased -- ^ an erased term
823 | Impossible -- ^ special case for totality checking
824 | TType UExp -- ^ the type of types at some level
825 | UType Universe -- ^ Uniqueness type universe (disjoint from TType)
826 deriving (Ord, Functor, Data, Typeable)
828deriving instance Binary TT
829deriving instance NFData TT
832class TermSize a where
833 termsize :: Name -> a -> Int
835instance TermSize a => TermSize [a] where
837 termsize n (x : xs) = termsize n x + termsize n xs
839instance TermSize (TT Name) where
840 termsize n (P _ n' _)
841 | n' == n = 1000000 -- recursive => really big
844 -- for `Bind` terms, we can erroneously declare a term
845 -- "recursive => really big" if the name of the bound
846 -- variable is the same as the name we're using
847 -- So generate a different name in that case.
848 termsize n (Bind n' (Let t v) sc)
849 = let rn = if n == n' then sMN 0 "noname" else n in
850 termsize rn v + termsize rn sc
851 termsize n (Bind n' b sc)
852 = let rn = if n == n' then sMN 0 "noname" else n in
854 termsize n (App f a) = termsize n f + termsize n a
855 termsize n (Proj t i) = termsize n t
858instance Sized a => Sized (TT a) where
859 size (P name n trm) = 1 + size name + size n + size trm
861 size (Bind nm binder bdy) = 1 + size nm + size binder + size bdy
862 size (App l r) = 1 + size l + size r
863 size (Constant c) = size c
865 size (TType u) = 1 + size u
867instance Pretty a o => Pretty (TT a) o where
868 pretty _ = text "test"
870type EnvTT n = [(n, Binder (TT n))]
872data Datatype n = Data { d_typename :: n,
876 d_cons :: [(n, TT n)] }
877 deriving (Show, Functor, Eq)
879instance Eq n => Eq (TT n) where
880 (==) (P xt x _) (P yt y _) = x == y
881 (==) (V x) (V y) = x == y
882 (==) (Bind _ xb xs) (Bind _ yb ys) = xs == ys && xb == yb
883 (==) (App fx ax) (App fy ay) = ax == ay && fx == fy
884 (==) (TType _) (TType _) = True -- deal with constraints later
885 (==) (Constant x) (Constant y) = x == y
886 (==) (Proj x i) (Proj y j) = x == y && i == j
891-- * A few handy operations on well typed terms:
893-- | A term is injective iff it is a data constructor, type constructor,
894-- constant, the type Type, pi-binding, or an application of an injective
896isInjective :: TT n -> Bool
897isInjective (P (DCon _ _ _) _ _) = True
898isInjective (P (TCon _ _) _ _) = True
899isInjective (Constant _) = True
900isInjective (TType x) = True
901isInjective (Bind _ (Pi _ _ _) sc) = True
902isInjective (App f a) = isInjective f
905-- | Count the number of instances of a de Bruijn index in a term
906vinstances :: Int -> TT n -> Int
907vinstances i (V x) | i == x = 1
908vinstances i (App f a) = vinstances i f + vinstances i a
909vinstances i (Bind x b sc) = instancesB b + vinstances (i + 1) sc
910 where instancesB (Let t v) = vinstances i v
914-- | Replace the outermost (index 0) de Bruijn variable with the given term
915instantiate :: TT n -> TT n -> TT n
916instantiate e = subst 0 where
917 subst i (P nt x ty) = P nt x (subst i ty)
918 subst i (V x) | i == x = e
919 subst i (Bind x b sc) = Bind x (fmap (subst i) b) (subst (i+1) sc)
920 subst i (App f a) = App (subst i f) (subst i a)
921 subst i (Proj x idx) = Proj (subst i x) idx
924-- | As 'instantiate', but also decrement the indices of all de Bruijn variables
925-- remaining in the term, so that there are no more references to the variable
926-- that has been substituted.
927substV :: TT n -> TT n -> TT n
928substV x tm = dropV 0 (instantiate x tm) where
929 subst i (P nt x ty) = P nt x (subst i ty)
930 dropV i (V x) | x > i = V (x - 1)
932 dropV i (Bind x b sc) = Bind x (fmap (dropV i) b) (dropV (i+1) sc)
933 dropV i (App f a) = App (dropV i f) (dropV i a)
934 dropV i (Proj x idx) = Proj (dropV i x) idx
937-- | Replace all non-free de Bruijn references in the given term with references
938-- to the name of their binding.
939explicitNames :: TT n -> TT n
940explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
942 (explicitNames (instantiate
943 (P Bound x (binderTy b')) sc))
944explicitNames (App f a) = App (explicitNames f) (explicitNames a)
945explicitNames (Proj x idx) = Proj (explicitNames x) idx
948-- | Replace references to the given 'Name'-like id with references to
950pToV :: Eq n => n -> TT n -> TT n
952pToV' n i (P _ x _) | n == x = V i
953pToV' n i (Bind x b sc)
954-- We can assume the inner scope has been pToVed already, so continue to
955-- resolve names from the *outer* scope which may happen to have the same id.
956 | n == x = Bind x (fmap (pToV' n i) b) sc
957 | otherwise = Bind x (fmap (pToV' n i) b) (pToV' n (i+1) sc)
958pToV' n i (App f a) = App (pToV' n i f) (pToV' n i a)
959pToV' n i (Proj t idx) = Proj (pToV' n i t) idx
962-- increase de Bruijn indices, as if a binder has been added
963addBinder :: TT n -> TT n
966 ab top (V i) | i >= top = V (i + 1)
968 ab top (Bind x b sc) = Bind x (fmap (ab top) b) (ab (top + 1) sc)
969 ab top (App f a) = App (ab top f) (ab top a)
970 ab top (Proj t idx) = Proj (ab top t) idx
973-- | Convert several names. First in the list comes out as V 0
974pToVs :: Eq n => [n] -> TT n -> TT n
975pToVs ns tm = pToVs' ns tm 0 where
977 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
979-- | Replace de Bruijn indices in the given term with explicit references to
980-- the names of the bindings they refer to. It is an error if the given term
981-- contains free de Bruijn indices.
984 vToP' env (V i) = let (n, b) = (env !! i) in
985 P Bound n (binderTy b)
986 vToP' env (Bind n b sc) = let b' = fmap (vToP' env) b in
987 Bind n b' (vToP' ((n, b'):env) sc)
988 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
991-- | Replace every non-free reference to the name of a binding in
992-- the given term with a de Bruijn index.
993finalise :: Eq n => TT n -> TT n
994finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
995finalise (App f a) = App (finalise f) (finalise a)
998-- Once we've finished checking everything about a term we no longer need
999-- the type on the 'P' so erase it so save memory
1001pEraseType :: TT n -> TT n
1002pEraseType (P nt t _) = P nt t Erased
1003pEraseType (App f a) = App (pEraseType f) (pEraseType a)
1004pEraseType (Bind n b sc) = Bind n (fmap pEraseType b) (pEraseType sc)
1007-- | As 'instantiate', but in addition to replacing @'V' 0@,
1008-- replace references to the given 'Name'-like id.
1009subst :: Eq n => n {-^ The id to replace -} ->
1010 TT n {-^ The replacement term -} ->
1011 TT n {-^ The term to replace in -} ->
1013-- subst n v tm = instantiate v (pToV n tm)
1014subst n v tm = fst $ subst' 0 tm
1016 -- keep track of updates to save allocations - this is a big win on
1017 -- large terms in particular
1018 -- ('Maybe' would be neater here, but >>= is not the right combinator.
1019 -- Feel free to tidy up, as long as it still saves allocating when no
1020 -- substitution happens...)
1021 subst' i (V x) | i == x = (v, True)
1022 subst' i (P _ x _) | n == x = (v, True)
1023 subst' i t@(P nt x ty)
1024 = let (ty', ut) = subst' i ty in
1025 if ut then (P nt x ty', True) else (t, False)
1026 subst' i t@(Bind x b sc) | x /= n
1027 = let (b', ub) = substB' i b
1028 (sc', usc) = subst' (i+1) sc in
1029 if ub || usc then (Bind x b' sc', True) else (t, False)
1030 subst' i t@(App f a) = let (f', uf) = subst' i f
1031 (a', ua) = subst' i a in
1032 if uf || ua then (App f' a', True) else (t, False)
1033 subst' i t@(Proj x idx) = let (x', u) = subst' i x in
1034 if u then (Proj x' idx, u) else (t, False)
1035 subst' i t = (t, False)
1037 substB' i b@(Let t v) = let (t', ut) = subst' i t
1038 (v', uv) = subst' i v in
1039 if ut || uv then (Let t' v', True)
1041 substB' i b@(Guess t v) = let (t', ut) = subst' i t
1042 (v', uv) = subst' i v in
1043 if ut || uv then (Guess t' v', True)
1045 substB' i b = let (ty', u) = subst' i (binderTy b) in
1046 if u then (b { binderTy = ty' }, u) else (b, False)
1048-- If there are no Vs in the term (i.e. in proof state)
1049psubst :: Eq n => n -> TT n -> TT n -> TT n
1050psubst n v tm = s' 0 tm where
1051 s' i (V x) | x > i = V (x - 1)
1054 s' i (P _ x _) | n == x = v
1055 s' i (Bind x b sc) | n == x = Bind x (fmap (s' i) b) sc
1056 | otherwise = Bind x (fmap (s' i) b) (s' (i+1) sc)
1057 s' i (App f a) = App (s' i f) (s' i a)
1058 s' i (Proj t idx) = Proj (s' i t) idx
1061-- | As 'subst', but takes a list of (name, substitution) pairs instead
1062-- of a single name and substitution
1063substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
1065substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
1067-- | Replaces all terms equal (in the sense of @(==)@) to
1068-- the old term with the new term.
1069substTerm :: Eq n => TT n {-^ Old term -} ->
1070 TT n {-^ New term -} ->
1071 TT n {-^ template term -}
1073substTerm old new = st where
1074 st t | t == old = new
1075 st (App f a) = App (st f) (st a)
1076 st (Bind x b sc) = Bind x (fmap st b) (st sc)
1079-- | Return number of occurrences of V 0 or bound name i the term
1080occurrences :: Eq n => n -> TT n -> Int
1081occurrences n t = execState (no' 0 t) 0
1083 no' i (V x) | i == x = do num <- get; put (num + 1)
1084 no' i (P Bound x _) | n == x = do num <- get; put (num + 1)
1085 no' i (Bind n b sc) = do noB' i b; no' (i+1) sc
1086 where noB' i (Let t v) = do no' i t; no' i v
1087 noB' i (Guess t v) = do no' i t; no' i v
1088 noB' i b = no' i (binderTy b)
1089 no' i (App f a) = do no' i f; no' i a
1090 no' i (Proj x _) = no' i x
1093-- | Returns true if V 0 and bound name n do not occur in the term
1094noOccurrence :: Eq n => n -> TT n -> Bool
1095noOccurrence n t = no' 0 t
1097 no' i (V x) = not (i == x)
1098 no' i (P Bound x _) = not (n == x)
1099 no' i (Bind n b sc) = noB' i b && no' (i+1) sc
1100 where noB' i (Let t v) = no' i t && no' i v
1101 noB' i (Guess t v) = no' i t && no' i v
1102 noB' i b = no' i (binderTy b)
1103 no' i (App f a) = no' i f && no' i a
1104 no' i (Proj x _) = no' i x
1107-- | Returns all names used free in the term
1108freeNames :: Eq n => TT n -> [n]
1109freeNames t = nub $ freeNames' t
1111 freeNames' (P _ n _) = [n]
1112 freeNames' (Bind n (Let t v) sc) = freeNames' v ++ (freeNames' sc \\ [n])
1114 freeNames' (Bind n b sc) = freeNames' (binderTy b) ++ (freeNames' sc \\ [n])
1115 freeNames' (App f a) = freeNames' f ++ freeNames' a
1116 freeNames' (Proj x i) = freeNames' x
1119-- | Return the arity of a (normalised) type
1121arity (Bind n (Pi _ t _) sc) = 1 + arity sc
1124-- | Deconstruct an application; returns the function and a list of arguments
1125unApply :: TT n -> (TT n, [TT n])
1126unApply t = ua [] t where
1127 ua args (App f a) = ua (a:args) f
1128 ua args t = (t, args)
1130-- | Returns a term representing the application of the first argument
1131-- (a function) to every element of the second argument.
1132mkApp :: TT n -> [TT n] -> TT n
1134mkApp f (a:as) = mkApp (App f a) as
1136unList :: Term -> Maybe [Term]
1137unList tm = case unApply tm of
1138 (nil, [_]) -> Just []
1139 (cons, ([_, x, xs])) ->
1140 do rest <- unList xs
1142 (f, args) -> Nothing
1144-- | Cast a 'TT' term to a 'Raw' value, discarding universe information and
1145-- the types of named references and replacing all de Bruijn indices
1146-- with the corresponding name. It is an error if there are free de
1148forget :: TT Name -> Raw
1149forget tm = forgetEnv [] tm
1151safeForget :: TT Name -> Maybe Raw
1152safeForget tm = safeForgetEnv [] tm
1154forgetEnv :: [Name] -> TT Name -> Raw
1155forgetEnv env tm = case safeForgetEnv env tm of
1157 Nothing -> error $ "Scope error in " ++ show tm
1160safeForgetEnv :: [Name] -> TT Name -> Maybe Raw
1161safeForgetEnv env (P _ n _) = Just $ Var n
1162safeForgetEnv env (V i) | i < length env = Just $ Var (env !! i)
1163 | otherwise = Nothing
1164safeForgetEnv env (Bind n b sc)
1165 = do let n' = uniqueName n env
1166 b' <- safeForgetEnvB env b
1167 sc' <- safeForgetEnv (n':env) sc
1168 Just $ RBind n' b' sc'
1169 where safeForgetEnvB env (Let t v) = liftM2 Let (safeForgetEnv env t)
1170 (safeForgetEnv env v)
1171 safeForgetEnvB env (Guess t v) = liftM2 Guess (safeForgetEnv env t)
1172 (safeForgetEnv env v)
1173 safeForgetEnvB env b = do ty' <- safeForgetEnv env (binderTy b)
1174 Just $ fmap (\_ -> ty') b
1175safeForgetEnv env (App f a) = liftM2 RApp (safeForgetEnv env f) (safeForgetEnv env a)
1176safeForgetEnv env (Constant c) = Just $ RConstant c
1177safeForgetEnv env (TType i) = Just RType
1178safeForgetEnv env (UType u) = Just $ RUType u
1179safeForgetEnv env Erased = Just $ RConstant Forgot
1181-- | Introduce a 'Bind' into the given term for each element of the
1182-- given list of (name, binder) pairs.
1183bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
1185bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
1187-- | Like 'bindAll', but the 'Binder's are 'TT' terms instead.
1188-- The first argument is a function to map @TT@ terms to @Binder@s.
1189-- This function might often be something like 'Lam', which directly
1190-- constructs a @Binder@ from a @TT@ term.
1191bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
1192bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
1194-- | Return a list of pairs of the names of the outermost 'Pi'-bound
1195-- variables in the given term, together with their types.
1196getArgTys :: TT n -> [(n, TT n)]
1197getArgTys (Bind n (PVar _) sc) = getArgTys sc
1198getArgTys (Bind n (PVTy _) sc) = getArgTys sc
1199getArgTys (Bind n (Pi _ t _) sc) = (n, t) : getArgTys sc
1202getRetTy :: TT n -> TT n
1203getRetTy (Bind n (PVar _) sc) = getRetTy sc
1204getRetTy (Bind n (PVTy _) sc) = getRetTy sc
1205getRetTy (Bind n (Pi _ _ _) sc) = getRetTy sc
1208uniqueNameFrom :: [Name] -> [Name] -> Name
1209uniqueNameFrom [] hs = uniqueName (nextName (sUN "x")) hs
1210uniqueNameFrom (s : supply) hs
1211 | s `elem` hs = uniqueNameFrom supply hs
1214uniqueName :: Name -> [Name] -> Name
1215uniqueName n hs | n `elem` hs = uniqueName (nextName n) hs
1218uniqueNameSet :: Name -> Set Name -> Name
1219uniqueNameSet n hs | n `member` hs = uniqueNameSet (nextName n) hs
1222uniqueBinders :: [Name] -> TT Name -> TT Name
1223uniqueBinders ns = ubSet (fromList ns) where
1224 ubSet ns (Bind n b sc)
1225 = let n' = uniqueNameSet n ns
1226 ns' = insert n' ns in
1227 Bind n' (fmap (ubSet ns') b) (ubSet ns' sc)
1228 ubSet ns (App f a) = App (ubSet ns f) (ubSet ns a)
1232nextName (NS x s) = NS (nextName x) s
1233nextName (MN i n) = MN (i+1) n
1234nextName (UN x) = let (num', nm') = T.span isDigit (T.reverse x)
1236 num = readN (T.reverse num') in
1237 UN (nm `T.append` txt (show (num+1)))
1239 readN x | not (T.null x) = read (T.unpack x)
1241nextName (SN x) = SN (nextName' x)
1243 nextName' (WhereN i f x) = WhereN i f (nextName x)
1244 nextName' (WithN i n) = WithN i (nextName n)
1245 nextName' (InstanceN n ns) = InstanceN (nextName n) ns
1246 nextName' (ParentN n ns) = ParentN (nextName n) ns
1247 nextName' (CaseN n) = CaseN (nextName n)
1248 nextName' (ElimN n) = ElimN (nextName n)
1249 nextName' (MethodN n) = MethodN (nextName n)
1250 nextName' (InstanceCtorN n) = InstanceCtorN (nextName n)
1255type Env = EnvTT Name
1257-- | an environment with de Bruijn indices 'normalised' so that they all refer to
1260newtype WkEnvTT n = Wk (EnvTT n)
1261type WkEnv = WkEnvTT Name
1263instance (Eq n, Show n) => Show (TT n) where
1264 show t = showEnv [] t
1266itBitsName IT8 = "Bits8"
1267itBitsName IT16 = "Bits16"
1268itBitsName IT32 = "Bits32"
1269itBitsName IT64 = "Bits64"
1271instance Show Const where
1273 show (BI i) = show i
1274 show (Fl f) = show f
1275 show (Ch c) = show c
1276 show (Str s) = show s
1277 show (B8 x) = show x
1278 show (B16 x) = show x
1279 show (B32 x) = show x
1280 show (B64 x) = show x
1281 show (AType ATFloat) = "Float"
1282 show (AType (ATInt ITBig)) = "Integer"
1283 show (AType (ATInt ITNative)) = "Int"
1284 show (AType (ATInt ITChar)) = "Char"
1285 show (AType (ATInt (ITFixed it))) = itBitsName it
1286 show TheWorld = "prim__TheWorld"
1287 show WorldType = "prim__WorldType"
1288 show StrType = "String"
1289 show VoidType = "Void"
1291showEnv :: (Eq n, Show n) => EnvTT n -> TT n -> String
1292showEnv env t = showEnv' env t False
1293showEnvDbg env t = showEnv' env t True
1295prettyEnv env t = prettyEnv' env t False
1297 prettyEnv' env t dbg = prettySe 10 env t dbg
1299 bracket outer inner p
1300 | inner > outer = lparen <> p <> rparen
1303 prettySe p env (P nt n t) debug =
1306 lbracket <+> pretty nt <+> colon <+> prettySe 10 env t debug <+> rbracket
1309 prettySe p env (V i) debug
1312 text . show . fst $ env!!i
1314 lbracket <+> text (show i) <+> rbracket
1315 | otherwise = text "unbound" <+> text (show i) <+> text "!"
1316 prettySe p env (Bind n b@(Pi _ t _) sc) debug
1317 | noOccurrence n sc && not debug =
1318 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
1319 prettySe p env (Bind n b sc) debug =
1320 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
1321 prettySe p env (App f a) debug =
1322 bracket p 1 $ prettySe 1 env f debug <+> prettySe 0 env a debug
1323 prettySe p env (Proj x i) debug =
1324 prettySe 1 env x debug <+> text ("!" ++ show i)
1325 prettySe p env (Constant c) debug = pretty c
1326 prettySe p env Erased debug = text "[_]"
1327 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
1329 -- Render a `Binder` and its name
1330 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
1331 prettySb env n (Hole t) = prettyB env "?defer" "." n t
1332 prettySb env n (Pi _ t _) = prettyB env "(" ") ->" n t
1333 prettySb env n (PVar t) = prettyB env "pat" "." n t
1334 prettySb env n (PVTy t) = prettyB env "pty" "." n t
1335 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
1336 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
1338 -- Use `op` and `sc` to delimit `n` (a binding name) and its type
1340 -- e.g. "λx : Int =>" for the Lam case
1341 prettyB env op sc n t debug =
1342 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
1344 -- Like `prettyB`, but handle the bindings that have values in addition
1345 -- to names and types
1346 prettyBv env op sc n t v debug =
1347 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
1348 prettySe 10 env v debug <> text sc
1351showEnv' env t dbg = se 10 env t where
1352 se p env (P nt n t) = show n
1353 ++ if dbg then "{" ++ show nt ++ " : " ++ se 10 env t ++ "}" else ""
1354 se p env (V i) | i < length env && i >= 0
1355 = (show $ fst $ env!!i) ++
1356 if dbg then "{" ++ show i ++ "}" else ""
1357 | otherwise = "!!V " ++ show i ++ "!!"
1358 se p env (Bind n b@(Pi (Just _) t k) sc)
1359 = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
1360 se p env (Bind n b@(Pi _ t k) sc)
1361 | noOccurrence n sc && not dbg = bracket p 2 $ se 1 env t ++ arrow k ++ se 10 ((n,b):env) sc
1362 where arrow (TType _) = " -> "
1363 arrow u = " [" ++ show u ++ "] -> "
1364 se p env (Bind n b sc) = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
1365 se p env (App f a) = bracket p 1 $ se 1 env f ++ " " ++ se 0 env a
1366 se p env (Proj x i) = se 1 env x ++ "!" ++ show i
1367 se p env (Constant c) = show c
1368 se p env Erased = "[__]"
1369 se p env Impossible = "[impossible]"
1370 se p env (TType i) = "Type " ++ show i
1371 se p env (UType u) = show u
1373 sb env n (Lam t) = showb env "\\ " " => " n t
1374 sb env n (Hole t) = showb env "? " ". " n t
1375 sb env n (GHole i t) = showb env "?defer " ". " n t
1376 sb env n (Pi (Just _) t _) = showb env "{" "} -> " n t
1377 sb env n (Pi _ t _) = showb env "(" ") -> " n t
1378 sb env n (PVar t) = showb env "pat " ". " n t
1379 sb env n (PVTy t) = showb env "pty " ". " n t
1380 sb env n (Let t v) = showbv env "let " " in " n t v
1381 sb env n (Guess t v) = showbv env "?? " " in " n t v
1383 showb env op sc n t = op ++ show n ++ " : " ++ se 10 env t ++ sc
1384 showbv env op sc n t v = op ++ show n ++ " : " ++ se 10 env t ++ " = " ++
1387 bracket outer inner str | inner > outer = "(" ++ str ++ ")"
1390-- | Check whether a term has any holes in it - impure if so
1391pureTerm :: TT Name -> Bool
1392pureTerm (App f a) = pureTerm f && pureTerm a
1393pureTerm (Bind n b sc) = notClassName n && pureBinder b && pureTerm sc where
1394 pureBinder (Hole _) = False
1395 pureBinder (Guess _ _) = False
1396 pureBinder (Let t v) = pureTerm t && pureTerm v
1397 pureBinder t = pureTerm (binderTy t)
1399 notClassName (MN _ c) | c == txt "class" = False
1400 notClassName _ = True
1404-- | Weaken a term by adding i to each de Bruijn index (i.e. lift it over i bindings)
1405weakenTm :: Int -> TT n -> TT n
1406weakenTm i t = wk i 0 t
1407 where wk i min (V x) | x >= min = V (i + x)
1408 wk i m (App f a) = App (wk i m f) (wk i m a)
1409 wk i m (Bind x b sc) = Bind x (wkb i m b) (wk i (m + 1) sc)
1411 wkb i m t = fmap (wk i m) t
1413-- | Weaken an environment so that all the de Bruijn indices are correct according
1414-- to the latest bound variable
1416weakenEnv :: EnvTT n -> EnvTT n
1417weakenEnv env = wk (length env - 1) env
1419 wk i ((n, b) : bs) = (n, weakenTmB i b) : wk (i - 1) bs
1420 weakenTmB i (Let t v) = Let (weakenTm i t) (weakenTm i v)
1421 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
1422 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
1424-- | Weaken every term in the environment by the given amount
1425weakenTmEnv :: Int -> EnvTT n -> EnvTT n
1426weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
1428-- | Gather up all the outer 'PVar's and 'Hole's in an expression and reintroduce
1429-- them in a canonical order
1430orderPats :: Term -> Term
1431orderPats tm = op [] tm
1433 op [] (App f a) = App f (op [] a) -- for Infer terms
1435 op ps (Bind n (PVar t) sc) = op ((n, PVar t) : ps) sc
1436 op ps (Bind n (Hole t) sc) = op ((n, Hole t) : ps) sc
1437 op ps (Bind n (Pi i t k) sc) = op ((n, Pi i t k) : ps) sc
1438 op ps sc = bindAll (sortP ps) sc
1440 sortP ps = pick [] (reverse ps)
1442 pick acc [] = reverse acc
1443 pick acc ((n, t) : ps) = pick (insert n t acc) ps
1445 insert n t [] = [(n, t)]
1446 insert n t ((n',t') : ps)
1447 | n `elem` (refsIn (binderTy t') ++
1448 concatMap refsIn (map (binderTy . snd) ps))
1449 = (n', t') : insert n t ps
1450 | otherwise = (n,t):(n',t'):ps
1452refsIn :: TT Name -> [Name]
1453refsIn (P _ n _) = [n]
1454refsIn (Bind n b t) = nub $ nb b ++ refsIn t
1455 where nb (Let t v) = nub (refsIn t) ++ nub (refsIn v)
1456 nb (Guess t v) = nub (refsIn t) ++ nub (refsIn v)
1457 nb t = refsIn (binderTy t)
1458refsIn (App f a) = nub (refsIn f ++ refsIn a)
1461-- Make sure all the pattern bindings are as far out as possible
1462liftPats :: Term -> Term
1463liftPats tm = let (tm', ps) = runState (getPats tm) [] in
1464 orderPats $ bindPats (reverse ps) tm'
1467 bindPats ((n, t):ps) tm
1468 | n `notElem` map fst ps = Bind n (PVar t) (bindPats ps tm)
1469 | otherwise = bindPats ps tm
1471 getPats :: Term -> State [(Name, Type)] Term
1472 getPats (Bind n (PVar t) sc) = do ps <- get
1475 getPats (Bind n (Guess t v) sc) = do t' <- getPats t
1478 return (Bind n (Guess t' v') sc')
1479 getPats (Bind n (Let t v) sc) = do t' <- getPats t
1482 return (Bind n (Let t' v') sc')
1483 getPats (Bind n (Pi i t k) sc) = do t' <- getPats t
1486 return (Bind n (Pi i t' k') sc')
1487 getPats (Bind n (Lam t) sc) = do t' <- getPats t
1489 return (Bind n (Lam t') sc')
1490 getPats (Bind n (Hole t) sc) = do t' <- getPats t
1492 return (Bind n (Hole t') sc')
1495 getPats (App f a) = do f' <- getPats f
1498 getPats t = return t
1500allTTNames :: Eq n => TT n -> [n]
1501allTTNames = nub . allNamesIn
1502 where allNamesIn (P _ n _) = [n]
1503 allNamesIn (Bind n b t) = [n] ++ nb b ++ allNamesIn t
1504 where nb (Let t v) = allNamesIn t ++ allNamesIn v
1505 nb (Guess t v) = allNamesIn t ++ allNamesIn v
1506 nb t = allNamesIn (binderTy t)
1507 allNamesIn (App f a) = allNamesIn f ++ allNamesIn a
1511-- | Pretty-print a term
1512pprintTT :: [Name] -- ^ The bound names (for highlighting and de Bruijn indices)
1513 -> TT Name -- ^ The term to be printed
1514 -> Doc OutputAnnotation
1515pprintTT bound tm = pp startPrec bound tm
1521 pp p bound (P Bound n ty) = annotate (AnnBoundName n False) (text $ show n)
1522 pp p bound (P nt n ty) = annotate (AnnName n Nothing Nothing Nothing)
1525 | i < length bound = let n = bound !! i
1526 in annotate (AnnBoundName n False) (text $ show n)
1527 | otherwise = text ("{{{V" ++ show i ++ "}}}")
1528 pp p bound (Bind n b sc) = ppb p bound n b $
1529 pp startPrec (n:bound) sc
1530 pp p bound (App tm1 tm2) =
1531 bracket p appPrec . group . hang 2 $
1532 pp appPrec bound tm1 <> line <>
1533 pp (appPrec + 1) bound tm2
1534 pp p bound (Constant c) = annotate (AnnConst c) (text (show c))
1535 pp p bound (Proj tm i) =
1536 lparen <> pp startPrec bound tm <> rparen <>
1537 text "!" <> text (show i)
1538 pp p bound Erased = text "<<<erased>>>"
1539 pp p bound Impossible = text "<<<impossible>>>"
1540 pp p bound (TType ue) = annotate (AnnType "Type" "The type of types") $
1542 pp p bound (UType u) = text (show u)
1544 ppb p bound n (Lam ty) sc =
1545 bracket p startPrec . group . align . hang 2 $
1546 text "λ" <+> bindingOf n False <+> text "." <> line <> sc
1547 ppb p bound n (Pi _ ty k) sc =
1548 bracket p startPrec . group . align $
1549 lparen <> (bindingOf n False) <+> colon <+>
1550 (group . align) (pp startPrec bound ty) <>
1551 rparen <+> mkArrow k <> line <> sc
1552 where mkArrow (UType UniqueType) = text "⇴"
1553 mkArrow (UType NullType) = text "⥛"
1554 mkArrow _ = text "→"
1555 ppb p bound n (Let ty val) sc =
1556 bracket p startPrec . group . align $
1557 (group . hang 2) (annotate AnnKeyword (text "let") <+>
1558 bindingOf n False <+> colon <+>
1559 pp startPrec bound ty <+>
1561 pp startPrec bound val) <> line <>
1562 (group . hang 2) (annotate AnnKeyword (text "in") <+> sc)
1563 ppb p bound n (NLet ty val) sc =
1564 bracket p startPrec . group . align $
1565 (group . hang 2) (annotate AnnKeyword (text "nlet") <+>
1566 bindingOf n False <+> colon <+>
1567 pp startPrec bound ty <+>
1569 pp startPrec bound val) <> line <>
1570 (group . hang 2) (annotate AnnKeyword (text "in") <+> sc)
1571 ppb p bound n (Hole ty) sc =
1572 bracket p startPrec . group . align . hang 2 $
1573 text "?" <+> bindingOf n False <+> text "." <> line <> sc
1574 ppb p bound n (GHole _ ty) sc =
1575 bracket p startPrec . group . align . hang 2 $
1576 text "¿" <+> bindingOf n False <+> text "." <> line <> sc
1577 ppb p bound n (Guess ty val) sc =
1578 bracket p startPrec . group . align . hang 2 $
1579 text "?" <> bindingOf n False <+>
1580 text "≈" <+> pp startPrec bound val <+>
1581 text "." <> line <> sc
1582 ppb p bound n (PVar ty) sc =
1583 bracket p startPrec . group . align . hang 2 $
1584 annotate AnnKeyword (text "pat") <+>
1585 bindingOf n False <+> colon <+> pp startPrec bound ty <+>
1588 ppb p bound n (PVTy ty) sc =
1589 bracket p startPrec . group . align . hang 2 $
1590 annotate AnnKeyword (text "patTy") <+>
1591 bindingOf n False <+> colon <+> pp startPrec bound ty <+>
1595 bracket outer inner doc
1596 | outer > inner = lparen <> doc <> rparen
1600-- | Pretty-printer helper for the binding site of a name
1601bindingOf :: Name -- ^^ the bound name
1602 -> Bool -- ^^ whether the name is implicit
1603 -> Doc OutputAnnotation
1604bindingOf n imp = annotate (AnnBoundName n imp) (text (show n))
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