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
159 | CantResolveAlts [Name]
162 | UniqueError Universe Name
163 | UniqueKindError Universe Name
167 | NonCollapsiblePostulate Name
168 | AlreadyDefined Name
169 | ProofSearchFail (Err' t)
172 | Elaborating String Name (Err' t)
173 | ElaboratingArg Name Name [(Name, Name)] (Err' t)
174 | ProviderError String
175 | LoadingFailed String (Err' t)
176 | ReflectionError [[ErrorReportPart]] (Err' t)
177 | ReflectionFailed String (Err' t)
178 | ElabDebug (Maybe String) t [(Name, t, [(Name, Binder t)])]
179 -- ^ User-specified message, proof term, goals with context (first goal is focused)
180 deriving (Eq, Functor, Data, Typeable)
186 deriving (Eq, Functor)
188bindTC :: TC a -> (a -> TC b) -> TC b
189bindTC x k = case x of
194instance Monad TC where
197 fail e = Error (InternalMsg e)
199instance MonadPlus TC where
200 mzero = fail "Unknown error"
201 (OK x) `mplus` _ = OK x
202 _ `mplus` (OK y) = OK y
206instance Applicative TC where
210instance Alternative TC where
215deriving instance NFData Err
218instance Sized ErrorReportPart where
219 size (TextPart msg) = 1 + length msg
220 size (TermPart t) = 1 + size t
221 size (NamePart n) = 1 + size n
222 size (SubReport rs) = 1 + size rs
224instance Sized Err where
225 size (Msg msg) = length msg
226 size (InternalMsg msg) = length msg
227 size (CantUnify _ left right err _ score) = size (fst left) + size (fst right) + size err
228 size (InfiniteUnify _ right _) = size right
229 size (CantConvert left right _) = size left + size right
230 size (UnifyScope _ _ right _) = size right
231 size (NoSuchVariable name) = size name
232 size (NoTypeDecl name) = size name
233 size (NotInjective l c r) = size l + size c + size r
234 size (CantResolve trm) = size trm
235 size (NoRewriting trm) = size trm
236 size (CantResolveAlts _) = 1
237 size (IncompleteTerm trm) = size trm
238 size UniverseError = 1
239 size ProgramLineComment = 1
240 size (At fc err) = size fc + size err
241 size (Elaborating _ n err) = size err
242 size (ElaboratingArg _ _ _ err) = size err
243 size (ProviderError msg) = length msg
244 size (LoadingFailed fn e) = 1 + length fn + size e
248score (CantUnify _ _ _ m _ s) = s + score m
249score (CantResolve _) = 20
250score (NoSuchVariable _) = 1000
251score (ProofSearchFail e) = score e
252score (CantSolveGoal _ _) = 100000
253score (InternalMsg _) = -1
254score (At _ e) = score e
255score (ElaboratingArg _ _ _ e) = score e
256score (Elaborating _ _ e) = score e
259instance Show Err where
261 show (InternalMsg s) = "Internal error: " ++ show s
262 show (CantUnify rcv l r e sc i) = "CantUnify " ++ show rcv ++ " " ++
263 show l ++ " " ++ show r ++ " " ++
264 show e ++ " in " ++ show sc ++ " " ++ show i
265 show (CantSolveGoal g _) = "CantSolve " ++ show g
266 show (Inaccessible n) = show n ++ " is not an accessible pattern variable"
267 show (ProviderError msg) = "Type provider error: " ++ msg
268 show (LoadingFailed fn e) = "Loading " ++ fn ++ " failed: (TT) " ++ show e
269 show ProgramLineComment = "Program line next to comment"
270 show (At f e) = show f ++ ":" ++ show e
271 show (ElaboratingArg f x prev e) = "Elaborating " ++ show f ++ " arg " ++
272 show x ++ ": " ++ show e
273 show (Elaborating what n e) = "Elaborating " ++ what ++ show n ++ ":" ++ show e
274 show (ProofSearchFail e) = "Proof search fail: " ++ show e
277instance Pretty Err OutputAnnotation where
278 pretty (Msg m) = text m
279 pretty (CantUnify _ (l, _) (r, _) e _ i) =
280 text "Cannot unify" <+> colon <+> pretty l <+> text "and" <+> pretty r <+>
281 nest nestingSize (text "where" <+> pretty e <+> text "with" <+> (text . show $ i))
282 pretty (ProviderError msg) = text msg
283 pretty err@(LoadingFailed _ _) = text (show err)
284 pretty _ = text "Error"
286instance (Pretty a OutputAnnotation) => Pretty (TC a) OutputAnnotation where
287 pretty (OK ok) = pretty ok
289 text "Error" <+> colon <+> pretty err
291instance Show a => Show (TC a) where
293 show (Error str) = "Error: " ++ show str
298failMsg :: String -> TC a
299failMsg str = Error (Msg str)
301trun :: FC -> TC a -> TC a
303trun fc (Error e) = Error (At fc e)
305discard :: Monad m => m a -> m ()
306discard f = f >> return ()
308showSep :: String -> [String] -> String
311showSep sep (x:xs) = x ++ sep ++ showSep sep xs
313pmap f (x, y) = (f x, f y)
315traceWhen True msg a = trace msg a
316traceWhen False _ a = a
318-- RAW TERMS ----------------------------------------------------------------
320-- | Names are hierarchies of strings, describing scope (so no danger of
321-- duplicate names, but need to be careful on lookup).
322data Name = UN T.Text -- ^ User-provided name
323 | NS Name [T.Text] -- ^ Root, namespaces
324 | MN Int T.Text -- ^ Machine chosen names
325 | NErased -- ^ Name of something which is never used in scope
326 | SN SpecialName -- ^ Decorated function names
327 | SymRef Int -- ^ Reference to IBC file symbol table (used during serialisation)
328 deriving (Eq, Ord, Data, Typeable)
330txt :: String -> T.Text
333str :: T.Text -> String
336tnull :: T.Text -> Bool
339thead :: T.Text -> Char
342-- Smart constructors for names, using old String style
346sNS :: Name -> [String] -> Name
347sNS n ss = NS n (map txt ss)
349sMN :: Int -> String -> Name
350sMN i s = MN i (txt s)
353deriving instance Binary Name
354deriving instance NFData Name
357data SpecialName = WhereN Int Name Name
359 | InstanceN Name [T.Text]
360 | ParentN Name T.Text
365 deriving (Eq, Ord, Data, Typeable)
367deriving instance Binary SpecialName
368deriving instance NFData SpecialName
371sInstanceN :: Name -> [String] -> SpecialName
372sInstanceN n ss = InstanceN n (map T.pack ss)
374sParentN :: Name -> String -> SpecialName
375sParentN n s = ParentN n (T.pack s)
377instance Sized Name where
379 size (NS n els) = 1 + length els
383instance Pretty Name OutputAnnotation where
384 pretty n@(UN n') = annotate (AnnName n Nothing Nothing Nothing) $ text (T.unpack n')
385 pretty n@(NS un s) = annotate (AnnName n Nothing Nothing Nothing) . noAnnotate $ pretty un
386 pretty n@(MN i s) = annotate (AnnName n Nothing Nothing Nothing) $
387 lbrace <+> text (T.unpack s) <+> (text . show $ i) <+> rbrace
388 pretty n@(SN s) = annotate (AnnName n Nothing Nothing Nothing) $ text (show s)
390instance Pretty [Name] OutputAnnotation where
391 pretty = encloseSep empty empty comma . map pretty
393instance Show Name where
395 show (NS n s) = showSep "." (map T.unpack (reverse s)) ++ "." ++ show n
396 show (MN _ u) | u == txt "underscore" = "_"
397 show (MN i s) = "{" ++ str s ++ show i ++ "}"
401instance Show SpecialName where
402 show (WhereN i p c) = show p ++ ", " ++ show c
403 show (WithN i n) = "with block in " ++ show n
404 show (InstanceN cl inst) = showSep ", " (map T.unpack inst) ++ " instance of " ++ show cl
405 show (MethodN m) = "method " ++ show m
406 show (ParentN p c) = show p ++ "#" ++ T.unpack c
407 show (CaseN n) = "case block in " ++ show n
408 show (ElimN n) = "<<" ++ show n ++ " eliminator>>"
409 show (InstanceCtorN n) = "constructor of " ++ show n
411-- Show a name in a way decorated for code generation, not human reading
412showCG :: Name -> String
413showCG (UN n) = T.unpack n
414showCG (NS n s) = showSep "." (map T.unpack (reverse s)) ++ "." ++ showCG n
415showCG (MN _ u) | u == txt "underscore" = "_"
416showCG (MN i s) = "{" ++ T.unpack s ++ show i ++ "}"
417showCG (SN s) = showCG' s
418 where showCG' (WhereN i p c) = showCG p ++ ":" ++ showCG c ++ ":" ++ show i
419 showCG' (WithN i n) = "_" ++ showCG n ++ "_with_" ++ show i
420 showCG' (InstanceN cl inst) = '@':showCG cl ++ '$':showSep ":" (map T.unpack inst)
421 showCG' (MethodN m) = '!':showCG m
422 showCG' (ParentN p c) = showCG p ++ "#" ++ show c
423 showCG' (CaseN c) = showCG c ++ "_case"
424 showCG' (ElimN sn) = showCG sn ++ "_elim"
428-- |Contexts allow us to map names to things. A root name maps to a collection
429-- of things in different namespaces with that name.
430type Ctxt a = Map.Map Name (Map.Map Name a)
431emptyContext = Map.empty
433mapCtxt :: (a -> b) -> Ctxt a -> Ctxt b
436-- |Return True if the argument 'Name' should be interpreted as the name of a
438tcname (UN xs) | T.null xs = False
439 | otherwise = T.head xs == '@'
440tcname (NS n _) = tcname n
441tcname (SN (InstanceN _ _)) = True
442tcname (SN (MethodN _)) = True
443tcname (SN (ParentN _ _)) = True
446implicitable (NS n _) = implicitable n
447implicitable (UN xs) | T.null xs = False
448 | otherwise = isLower (T.head xs) || T.head xs == '_'
449implicitable (MN _ x) = not (tnull x) && thead x /= '_'
450implicitable _ = False
455-- this will overwrite already existing definitions
456addDef :: Name -> a -> Ctxt a -> Ctxt a
457addDef n v ctxt = case Map.lookup (nsroot n) ctxt of
458 Nothing -> Map.insert (nsroot n)
459 (Map.insert n v Map.empty) ctxt
460 Just xs -> Map.insert (nsroot n)
461 (Map.insert n v xs) ctxt
463{-| Look up a name in the context, given an optional namespace.
464 The name (n) may itself have a (partial) namespace given.
466 Rules for resolution:
468 - if an explicit namespace is given, return the names which match it. If none
469 match, return all names.
471 - if the name has has explicit namespace given, return the names which match it
472 and ignore the given namespace.
474 - otherwise, return all names.
478lookupCtxtName :: Name -> Ctxt a -> [(Name, a)]
479lookupCtxtName n ctxt = case Map.lookup (nsroot n) ctxt of
480 Just xs -> filterNS (Map.toList xs)
484 filterNS ((found, v) : xs)
485 | nsmatch n found = (found, v) : filterNS xs
486 | otherwise = filterNS xs
488 nsmatch (NS n ns) (NS p ps) = ns `isPrefixOf` ps
489 nsmatch (NS _ _) _ = False
490 nsmatch looking found = True
492lookupCtxt :: Name -> Ctxt a -> [a]
493lookupCtxt n ctxt = map snd (lookupCtxtName n ctxt)
495lookupCtxtExact :: Name -> Ctxt a -> Maybe a
496lookupCtxtExact n ctxt = listToMaybe [ v | (nm, v) <- lookupCtxtName n ctxt, nm == n]
498deleteDefExact :: Name -> Ctxt a -> Ctxt a
499deleteDefExact n = Map.adjust (Map.delete n) (nsroot n)
501updateDef :: Name -> (a -> a) -> Ctxt a -> Ctxt a
503 = let ds = lookupCtxtName n ctxt in
504 foldr (\ (n, t) c -> addDef n (f t) c) ctxt ds
506toAlist :: Ctxt a -> [(Name, a)]
507toAlist ctxt = let allns = map snd (Map.toList ctxt) in
508 concatMap (Map.toList) allns
510addAlist :: Show a => [(Name, a)] -> Ctxt a -> Ctxt a
511addAlist [] ctxt = ctxt
512addAlist ((n, tm) : ds) ctxt = addDef n tm (addAlist ds ctxt)
514data NativeTy = IT8 | IT16 | IT32 | IT64
515 deriving (Show, Eq, Ord, Enum, Data, Typeable)
517instance Pretty NativeTy OutputAnnotation where
518 pretty IT8 = text "Bits8"
519 pretty IT16 = text "Bits16"
520 pretty IT32 = text "Bits32"
521 pretty IT64 = text "Bits64"
523data IntTy = ITFixed NativeTy | ITNative | ITBig | ITChar
525 deriving (Show, Eq, Ord, Data, Typeable)
527intTyName :: IntTy -> String
528intTyName ITNative = "Int"
529intTyName ITBig = "BigInt"
530intTyName (ITFixed sized) = "B" ++ show (nativeTyWidth sized)
531intTyName (ITChar) = "Char"
532intTyName (ITVec ity count) = "B" ++ show (nativeTyWidth ity) ++ "x" ++ show count
534data ArithTy = ATInt IntTy | ATFloat -- TODO: Float vectors https://github.com/idris-lang/Idris-dev/issues/1723
535 deriving (Show, Eq, Ord, Data, Typeable)
537deriving instance NFData IntTy
538deriving instance NFData NativeTy
539deriving instance NFData ArithTy
542instance Pretty ArithTy OutputAnnotation where
543 pretty (ATInt ITNative) = text "Int"
544 pretty (ATInt ITBig) = text "BigInt"
545 pretty (ATInt ITChar) = text "Char"
546 pretty (ATInt (ITFixed n)) = pretty n
547 pretty (ATInt (ITVec e c)) = pretty e <> text "x" <> (text . show $ c)
548 pretty ATFloat = text "Float"
550nativeTyWidth :: NativeTy -> Int
552nativeTyWidth IT16 = 16
553nativeTyWidth IT32 = 32
554nativeTyWidth IT64 = 64
556{-# DEPRECATED intTyWidth "Non-total function, use nativeTyWidth and appropriate casing" #-}
557intTyWidth :: IntTy -> Int
558intTyWidth (ITFixed n) = nativeTyWidth n
559intTyWidth ITNative = 8 * sizeOf (0 :: Int)
560intTyWidth ITChar = error "IRTS.Lang.intTyWidth: Characters have platform and backend dependent width"
561intTyWidth ITBig = error "IRTS.Lang.intTyWidth: Big integers have variable width"
563data Const = I Int | BI Integer | Fl Double | Ch Char | Str String
564 | B8 Word8 | B16 Word16 | B32 Word32 | B64 Word64
565 | B8V (Vector Word8) | B16V (Vector Word16)
566 | B32V (Vector Word32) | B64V (Vector Word64)
567 | AType ArithTy | StrType
568 | WorldType | TheWorld
569 | PtrType | ManagedPtrType | BufferType | VoidType | Forgot
570 deriving (Eq, Ord, Data, Typeable)
572deriving instance Binary Const
573deriving instance NFData Const
576isTypeConst :: Const -> Bool
577isTypeConst (AType _) = True
578isTypeConst StrType = True
579isTypeConst ManagedPtrType = True
580isTypeConst BufferType = True
581isTypeConst WorldType = True
582isTypeConst PtrType = True
583isTypeConst VoidType = True
586instance Sized Const where
589instance Pretty Const OutputAnnotation where
590 pretty (I i) = text . show $ i
591 pretty (BI i) = text . show $ i
592 pretty (Fl f) = text . show $ f
593 pretty (Ch c) = text . show $ c
594 pretty (Str s) = text s
595 pretty (AType a) = pretty a
596 pretty StrType = text "String"
597 pretty TheWorld = text "%theWorld"
598 pretty WorldType = text "prim__World"
599 pretty BufferType = text "prim__UnsafeBuffer"
600 pretty PtrType = text "Ptr"
601 pretty ManagedPtrType = text "Ptr"
602 pretty VoidType = text "Void"
603 pretty Forgot = text "Forgot"
604 pretty (B8 w) = text . show $ w
605 pretty (B16 w) = text . show $ w
606 pretty (B32 w) = text . show $ w
607 pretty (B64 w) = text . show $ w
609-- | Determines whether the input constant represents a type
610constIsType :: Const -> Bool
611constIsType (I _) = False
612constIsType (BI _) = False
613constIsType (Fl _) = False
614constIsType (Ch _) = False
615constIsType (Str _) = False
616constIsType (B8 _) = False
617constIsType (B16 _) = False
618constIsType (B32 _) = False
619constIsType (B64 _) = False
620constIsType (B8V _) = False
621constIsType (B16V _) = False
622constIsType (B32V _) = False
623constIsType (B64V _) = False
626-- | Get the docstring for a Const
627constDocs :: Const -> String
628constDocs c@(AType (ATInt ITBig)) = "Arbitrary-precision integers"
629constDocs c@(AType (ATInt ITNative)) = "Fixed-precision integers of undefined size"
630constDocs c@(AType (ATInt ITChar)) = "Characters in some unspecified encoding"
631constDocs c@(AType ATFloat) = "Double-precision floating-point numbers"
632constDocs StrType = "Strings in some unspecified encoding"
633constDocs PtrType = "Foreign pointers"
634constDocs ManagedPtrType = "Managed pointers"
635constDocs BufferType = "Copy-on-write buffers"
636constDocs c@(AType (ATInt (ITFixed IT8))) = "Eight bits (unsigned)"
637constDocs c@(AType (ATInt (ITFixed IT16))) = "Sixteen bits (unsigned)"
638constDocs c@(AType (ATInt (ITFixed IT32))) = "Thirty-two bits (unsigned)"
639constDocs c@(AType (ATInt (ITFixed IT64))) = "Sixty-four bits (unsigned)"
640constDocs c@(AType (ATInt (ITVec IT8 16))) = "Vectors of sixteen eight-bit values"
641constDocs c@(AType (ATInt (ITVec IT16 8))) = "Vectors of eight sixteen-bit values"
642constDocs c@(AType (ATInt (ITVec IT32 4))) = "Vectors of four thirty-two-bit values"
643constDocs c@(AType (ATInt (ITVec IT64 2))) = "Vectors of two sixty-four-bit values"
644constDocs (Fl f) = "A float"
645constDocs (I i) = "A fixed-precision integer"
646constDocs (BI i) = "An arbitrary-precision integer"
647constDocs (Str s) = "A string of length " ++ show (length s)
648constDocs (Ch c) = "A character"
649constDocs (B8 w) = "The eight-bit value 0x" ++
650 showIntAtBase 16 intToDigit w ""
651constDocs (B16 w) = "The sixteen-bit value 0x" ++
652 showIntAtBase 16 intToDigit w ""
653constDocs (B32 w) = "The thirty-two-bit value 0x" ++
654 showIntAtBase 16 intToDigit w ""
655constDocs (B64 w) = "The sixty-four-bit value 0x" ++
656 showIntAtBase 16 intToDigit w ""
657constDocs (B8V v) = "A vector of eight-bit values"
658constDocs (B16V v) = "A vector of sixteen-bit values"
659constDocs (B32V v) = "A vector of thirty-two-bit values"
660constDocs (B64V v) = "A vector of sixty-four-bit values"
661constDocs prim = "Undocumented"
663data Universe = NullType | UniqueType | AllTypes
664 deriving (Eq, Ord, Data, Typeable)
666instance Show Universe where
667 show UniqueType = "UniqueType"
668 show NullType = "NullType"
669 show AllTypes = "Type*"
672 | RBind Name (Binder Raw) Raw
678 deriving (Show, Eq, Data, Typeable)
680instance Sized Raw where
682 size (RBind name bind right) = 1 + size bind + size right
683 size (RApp left right) = 1 + size left + size right
686 size (RForce raw) = 1 + size raw
687 size (RConstant const) = size const
689instance Pretty Raw OutputAnnotation where
693deriving instance Binary Raw
694deriving instance NFData Raw
697data ImplicitInfo = Impl { tcinstance :: Bool }
698 deriving (Show, Eq, Ord, Data, Typeable)
701deriving instance Binary ImplicitInfo
702deriving instance NFData ImplicitInfo
705-- The type parameter `b` will normally be something like `TT Name` or just
706-- `Raw`. We do not make a type-level distinction between TT terms that happen
707-- to be TT types and TT terms that are not TT types.
708-- | All binding forms are represented in a uniform fashion. This type only represents
709-- the types of bindings (and their values, if any); the attached identifiers are part
710-- of the 'Bind' constructor for the 'TT' type.
711data Binder b = Lam { binderTy :: !b {-^ type annotation for bound variable-}}
712 | Pi { binderImpl :: Maybe ImplicitInfo,
715 {-^ A binding that occurs in a function type expression, e.g. @(x:Int) -> ...@
716 The 'binderImpl' flag says whether it was a scoped implicit
717 (i.e. forall bound) in the high level Idris, but otherwise
718 has no relevance in TT. -}
719 | Let { binderTy :: !b,
720 binderVal :: b {-^ value for bound variable-}}
721 -- ^ A binding that occurs in a @let@ expression
722 | NLet { binderTy :: !b,
724 | Hole { binderTy :: !b}
725 | GHole { envlen :: Int,
727 | Guess { binderTy :: !b,
729 | PVar { binderTy :: !b }
730 -- ^ A pattern variable
731 | PVTy { binderTy :: !b }
732 deriving (Show, Eq, Ord, Functor, Foldable, Traversable, Data, Typeable)
734deriving instance Binary Binder
735deriving instance NFData Binder
738instance Sized a => Sized (Binder a) where
739 size (Lam ty) = 1 + size ty
740 size (Pi _ ty _) = 1 + size ty
741 size (Let ty val) = 1 + size ty + size val
742 size (NLet ty val) = 1 + size ty + size val
743 size (Hole ty) = 1 + size ty
744 size (GHole _ ty) = 1 + size ty
745 size (Guess ty val) = 1 + size ty + size val
746 size (PVar ty) = 1 + size ty
747 size (PVTy ty) = 1 + size ty
749fmapMB :: Monad m => (a -> m b) -> Binder a -> m (Binder b)
750fmapMB f (Let t v) = liftM2 Let (f t) (f v)
751fmapMB f (NLet t v) = liftM2 NLet (f t) (f v)
752fmapMB f (Guess t v) = liftM2 Guess (f t) (f v)
753fmapMB f (Lam t) = liftM Lam (f t)
754fmapMB f (Pi i t k) = liftM2 (Pi i) (f t) (f k)
755fmapMB f (Hole t) = liftM Hole (f t)
756fmapMB f (GHole i t) = liftM (GHole i) (f t)
757fmapMB f (PVar t) = liftM PVar (f t)
758fmapMB f (PVTy t) = liftM PVTy (f t)
760raw_apply :: Raw -> [Raw] -> Raw
762raw_apply f (a : as) = raw_apply (RApp f a) as
764raw_unapply :: Raw -> (Raw, [Raw])
765raw_unapply t = ua [] t where
766 ua args (RApp f a) = ua (a:args) f
767 ua args t = (t, args)
769-- WELL TYPED TERMS ---------------------------------------------------------
771-- | Universe expressions for universe checking
772data UExp = UVar Int -- ^ universe variable
773 | UVal Int -- ^ explicit universe level
774 deriving (Eq, Ord, Data, Typeable)
776deriving instance NFData UExp
779instance Sized UExp where
782-- We assume that universe levels have been checked, so anything external
783-- can just have the same universe variable and we won't get any new
786instance Binary UExp where
788 get = return (UVar (-1))
790instance Show UExp where
791 show (UVar x) | x < 26 = [toEnum (x + fromEnum 'a')]
792 | otherwise = toEnum ((x `mod` 26) + fromEnum 'a') : show (x `div` 26)
793 show (UVal x) = show x
794-- show (UMax l r) = "max(" ++ show l ++ ", " ++ show r ++")"
796-- | Universe constraints
797data UConstraint = ULT UExp UExp -- ^ Strictly less than
798 | ULE UExp UExp -- ^ Less than or equal to
801instance Show UConstraint where
802 show (ULT x y) = show x ++ " < " ++ show y
803 show (ULE x y) = show x ++ " <= " ++ show y
805type UCs = (Int, [UConstraint])
809 | DCon {nt_tag :: Int, nt_arity :: Int, nt_unique :: Bool} -- ^ Data constructor
810 | TCon {nt_tag :: Int, nt_arity :: Int} -- ^ Type constructor
811 deriving (Show, Ord, Data, Typeable)
813deriving instance Binary NameType
814deriving instance NFData NameType
817instance Sized NameType where
820instance Pretty NameType OutputAnnotation where
823instance Eq NameType where
824 Bound == Bound = True
826 DCon _ a _ == DCon _ b _ = (a == b) -- ignore tag
827 TCon _ a == TCon _ b = (a == b) -- ignore tag
830-- | Terms in the core language. The type parameter is the type of
831-- identifiers used for bindings and explicit named references;
832-- usually we use @TT 'Name'@.
833data TT n = P NameType n (TT n) -- ^ named references with type
834 -- (P for "Parameter", motivated by McKinna and Pollack's
835 -- Pure Type Systems Formalized)
836 | V !Int -- ^ a resolved de Bruijn-indexed variable
837 | Bind n !(Binder (TT n)) (TT n) -- ^ a binding
838 | App !(TT n) (TT n) -- ^ function, function type, arg
839 | Constant Const -- ^ constant
840 | Proj (TT n) !Int -- ^ argument projection; runtime only
841 -- (-1) is a special case for 'subtract one from BI'
842 | Erased -- ^ an erased term
843 | Impossible -- ^ special case for totality checking
844 | TType UExp -- ^ the type of types at some level
845 | UType Universe -- ^ Uniqueness type universe (disjoint from TType)
846 deriving (Ord, Functor, Data, Typeable)
848deriving instance Binary TT
849deriving instance NFData TT
852class TermSize a where
853 termsize :: Name -> a -> Int
855instance TermSize a => TermSize [a] where
857 termsize n (x : xs) = termsize n x + termsize n xs
859instance TermSize (TT Name) where
860 termsize n (P _ n' _)
861 | n' == n = 1000000 -- recursive => really big
864 -- for `Bind` terms, we can erroneously declare a term
865 -- "recursive => really big" if the name of the bound
866 -- variable is the same as the name we're using
867 -- So generate a different name in that case.
868 termsize n (Bind n' (Let t v) sc)
869 = let rn = if n == n' then sMN 0 "noname" else n in
870 termsize rn v + termsize rn sc
871 termsize n (Bind n' b sc)
872 = let rn = if n == n' then sMN 0 "noname" else n in
874 termsize n (App f a) = termsize n f + termsize n a
875 termsize n (Proj t i) = termsize n t
878instance Sized a => Sized (TT a) where
879 size (P name n trm) = 1 + size name + size n + size trm
881 size (Bind nm binder bdy) = 1 + size nm + size binder + size bdy
882 size (App l r) = 1 + size l + size r
883 size (Constant c) = size c
885 size (TType u) = 1 + size u
887instance Pretty a o => Pretty (TT a) o where
888 pretty _ = text "test"
890type EnvTT n = [(n, Binder (TT n))]
892data Datatype n = Data { d_typename :: n,
896 d_cons :: [(n, TT n)] }
897 deriving (Show, Functor, Eq)
899instance Eq n => Eq (TT n) where
900 (==) (P xt x _) (P yt y _) = x == y
901 (==) (V x) (V y) = x == y
902 (==) (Bind _ xb xs) (Bind _ yb ys) = xs == ys && xb == yb
903 (==) (App fx ax) (App fy ay) = ax == ay && fx == fy
904 (==) (TType _) (TType _) = True -- deal with constraints later
905 (==) (Constant x) (Constant y) = x == y
906 (==) (Proj x i) (Proj y j) = x == y && i == j
911-- * A few handy operations on well typed terms:
913-- | A term is injective iff it is a data constructor, type constructor,
914-- constant, the type Type, pi-binding, or an application of an injective
916isInjective :: TT n -> Bool
917isInjective (P (DCon _ _ _) _ _) = True
918isInjective (P (TCon _ _) _ _) = True
919isInjective (Constant _) = True
920isInjective (TType x) = True
921isInjective (Bind _ (Pi _ _ _) sc) = True
922isInjective (App f a) = isInjective f
925-- | Count the number of instances of a de Bruijn index in a term
926vinstances :: Int -> TT n -> Int
927vinstances i (V x) | i == x = 1
928vinstances i (App f a) = vinstances i f + vinstances i a
929vinstances i (Bind x b sc) = instancesB b + vinstances (i + 1) sc
930 where instancesB (Let t v) = vinstances i v
934-- | Replace the outermost (index 0) de Bruijn variable with the given term
935instantiate :: TT n -> TT n -> TT n
936instantiate e = subst 0 where
937 subst i (V x) | i == x = e
938 subst i (Bind x b sc) = Bind x (fmap (subst i) b) (subst (i+1) sc)
939 subst i (App f a) = App (subst i f) (subst i a)
940 subst i (Proj x idx) = Proj (subst i x) idx
943-- | As 'instantiate', but also decrement the indices of all de Bruijn variables
944-- remaining in the term, so that there are no more references to the variable
945-- that has been substituted.
946substV :: TT n -> TT n -> TT n
947substV x tm = dropV 0 (instantiate x tm) where
948 dropV i (V x) | x > i = V (x - 1)
950 dropV i (Bind x b sc) = Bind x (fmap (dropV i) b) (dropV (i+1) sc)
951 dropV i (App f a) = App (dropV i f) (dropV i a)
952 dropV i (Proj x idx) = Proj (dropV i x) idx
955-- | Replace all non-free de Bruijn references in the given term with references
956-- to the name of their binding.
957explicitNames :: TT n -> TT n
958explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
960 (explicitNames (instantiate
961 (P Bound x (binderTy b')) sc))
962explicitNames (App f a) = App (explicitNames f) (explicitNames a)
963explicitNames (Proj x idx) = Proj (explicitNames x) idx
966-- | Replace references to the given 'Name'-like id with references to
968pToV :: Eq n => n -> TT n -> TT n
970pToV' n i (P _ x _) | n == x = V i
971pToV' n i (Bind x b sc)
972-- We can assume the inner scope has been pToVed already, so continue to
973-- resolve names from the *outer* scope which may happen to have the same id.
974 | n == x = Bind x (fmap (pToV' n i) b) sc
975 | otherwise = Bind x (fmap (pToV' n i) b) (pToV' n (i+1) sc)
976pToV' n i (App f a) = App (pToV' n i f) (pToV' n i a)
977pToV' n i (Proj t idx) = Proj (pToV' n i t) idx
980-- increase de Bruijn indices, as if a binder has been added
981addBinder :: TT n -> TT n
984 ab top (V i) | i >= top = V (i + 1)
986 ab top (Bind x b sc) = Bind x (fmap (ab top) b) (ab (top + 1) sc)
987 ab top (App f a) = App (ab top f) (ab top a)
988 ab top (Proj t idx) = Proj (ab top t) idx
991-- | Convert several names. First in the list comes out as V 0
992pToVs :: Eq n => [n] -> TT n -> TT n
993pToVs ns tm = pToVs' ns tm 0 where
995 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
997-- | Replace de Bruijn indices in the given term with explicit references to
998-- the names of the bindings they refer to. It is an error if the given term
999-- contains free de Bruijn indices.
1001vToP = vToP' [] where
1002 vToP' env (V i) = let (n, b) = (env !! i) in
1003 P Bound n (binderTy b)
1004 vToP' env (Bind n b sc) = let b' = fmap (vToP' env) b in
1005 Bind n b' (vToP' ((n, b'):env) sc)
1006 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
1009-- | Replace every non-free reference to the name of a binding in
1010-- the given term with a de Bruijn index.
1011finalise :: Eq n => TT n -> TT n
1012finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
1013finalise (App f a) = App (finalise f) (finalise a)
1016-- Once we've finished checking everything about a term we no longer need
1017-- the type on the 'P' so erase it so save memory
1019pEraseType :: TT n -> TT n
1020pEraseType (P nt t _) = P nt t Erased
1021pEraseType (App f a) = App (pEraseType f) (pEraseType a)
1022pEraseType (Bind n b sc) = Bind n (fmap pEraseType b) (pEraseType sc)
1025-- | As 'instantiate', but in addition to replacing @'V' 0@,
1026-- replace references to the given 'Name'-like id.
1027subst :: Eq n => n {-^ The id to replace -} ->
1028 TT n {-^ The replacement term -} ->
1029 TT n {-^ The term to replace in -} ->
1031-- subst n v tm = instantiate v (pToV n tm)
1032subst n v tm = fst $ subst' 0 tm
1034 -- keep track of updates to save allocations - this is a big win on
1035 -- large terms in particular
1036 -- ('Maybe' would be neater here, but >>= is not the right combinator.
1037 -- Feel free to tidy up, as long as it still saves allocating when no
1038 -- substitution happens...)
1039 subst' i (V x) | i == x = (v, True)
1040 subst' i (P _ x _) | n == x = (v, True)
1041 subst' i t@(Bind x b sc) | x /= n
1042 = let (b', ub) = substB' i b
1043 (sc', usc) = subst' (i+1) sc in
1044 if ub || usc then (Bind x b' sc', True) else (t, False)
1045 subst' i t@(App f a) = let (f', uf) = subst' i f
1046 (a', ua) = subst' i a in
1047 if uf || ua then (App f' a', True) else (t, False)
1048 subst' i t@(Proj x idx) = let (x', u) = subst' i x in
1049 if u then (Proj x' idx, u) else (t, False)
1050 subst' i t = (t, False)
1052 substB' i b@(Let t v) = let (t', ut) = subst' i t
1053 (v', uv) = subst' i v in
1054 if ut || uv then (Let t' v', True)
1056 substB' i b@(Guess t v) = let (t', ut) = subst' i t
1057 (v', uv) = subst' i v in
1058 if ut || uv then (Guess t' v', True)
1060 substB' i b = let (ty', u) = subst' i (binderTy b) in
1061 if u then (b { binderTy = ty' }, u) else (b, False)
1063-- If there are no Vs in the term (i.e. in proof state)
1064psubst :: Eq n => n -> TT n -> TT n -> TT n
1065psubst n v tm = s' 0 tm where
1066 s' i (V x) | x > i = V (x - 1)
1069 s' i (P _ x _) | n == x = v
1070 s' i (Bind x b sc) | n == x = Bind x (fmap (s' i) b) sc
1071 | otherwise = Bind x (fmap (s' i) b) (s' (i+1) sc)
1072 s' i (App f a) = App (s' i f) (s' i a)
1073 s' i (Proj t idx) = Proj (s' i t) idx
1076-- | As 'subst', but takes a list of (name, substitution) pairs instead
1077-- of a single name and substitution
1078substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
1080substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
1082-- | Replaces all terms equal (in the sense of @(==)@) to
1083-- the old term with the new term.
1084substTerm :: Eq n => TT n {-^ Old term -} ->
1085 TT n {-^ New term -} ->
1086 TT n {-^ template term -}
1088substTerm old new = st where
1089 st t | t == old = new
1090 st (App f a) = App (st f) (st a)
1091 st (Bind x b sc) = Bind x (fmap st b) (st sc)
1094-- | Return number of occurrences of V 0 or bound name i the term
1095occurrences :: Eq n => n -> TT n -> Int
1096occurrences n t = execState (no' 0 t) 0
1098 no' i (V x) | i == x = do num <- get; put (num + 1)
1099 no' i (P Bound x _) | n == x = do num <- get; put (num + 1)
1100 no' i (Bind n b sc) = do noB' i b; no' (i+1) sc
1101 where noB' i (Let t v) = do no' i t; no' i v
1102 noB' i (Guess t v) = do no' i t; no' i v
1103 noB' i b = no' i (binderTy b)
1104 no' i (App f a) = do no' i f; no' i a
1105 no' i (Proj x _) = no' i x
1108-- | Returns true if V 0 and bound name n do not occur in the term
1109noOccurrence :: Eq n => n -> TT n -> Bool
1110noOccurrence n t = no' 0 t
1112 no' i (V x) = not (i == x)
1113 no' i (P Bound x _) = not (n == x)
1114 no' i (Bind n b sc) = noB' i b && no' (i+1) sc
1115 where noB' i (Let t v) = no' i t && no' i v
1116 noB' i (Guess t v) = no' i t && no' i v
1117 noB' i b = no' i (binderTy b)
1118 no' i (App f a) = no' i f && no' i a
1119 no' i (Proj x _) = no' i x
1122-- | Returns all names used free in the term
1123freeNames :: Eq n => TT n -> [n]
1124freeNames t = nub $ freeNames' t
1126 freeNames' (P _ n _) = [n]
1127 freeNames' (Bind n (Let t v) sc) = freeNames' v ++ (freeNames' sc \\ [n])
1129 freeNames' (Bind n b sc) = freeNames' (binderTy b) ++ (freeNames' sc \\ [n])
1130 freeNames' (App f a) = freeNames' f ++ freeNames' a
1131 freeNames' (Proj x i) = freeNames' x
1134-- | Return the arity of a (normalised) type
1136arity (Bind n (Pi _ t _) sc) = 1 + arity sc
1139-- | Deconstruct an application; returns the function and a list of arguments
1140unApply :: TT n -> (TT n, [TT n])
1141unApply t = ua [] t where
1142 ua args (App f a) = ua (a:args) f
1143 ua args t = (t, args)
1145-- | Returns a term representing the application of the first argument
1146-- (a function) to every element of the second argument.
1147mkApp :: TT n -> [TT n] -> TT n
1149mkApp f (a:as) = mkApp (App f a) as
1151unList :: Term -> Maybe [Term]
1152unList tm = case unApply tm of
1153 (nil, [_]) -> Just []
1154 (cons, ([_, x, xs])) ->
1155 do rest <- unList xs
1157 (f, args) -> Nothing
1159-- | Cast a 'TT' term to a 'Raw' value, discarding universe information and
1160-- the types of named references and replacing all de Bruijn indices
1161-- with the corresponding name. It is an error if there are free de
1163forget :: TT Name -> Raw
1164forget tm = forgetEnv [] tm
1166forgetEnv :: [Name] -> TT Name -> Raw
1167forgetEnv env (P _ n _) = Var n
1168forgetEnv env (V i) = Var (env !! i)
1169forgetEnv env (Bind n b sc) = let n' = uniqueName n env in
1170 RBind n' (fmap (forgetEnv env) b)
1171 (forgetEnv (n':env) sc)
1172forgetEnv env (App f a) = RApp (forgetEnv env f) (forgetEnv env a)
1173forgetEnv env (Constant c) = RConstant c
1174forgetEnv env (TType i) = RType
1175forgetEnv env (UType u) = RUType u
1176forgetEnv env Erased = RConstant Forgot
1178-- | Introduce a 'Bind' into the given term for each element of the
1179-- given list of (name, binder) pairs.
1180bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
1182bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
1184-- | Like 'bindAll', but the 'Binder's are 'TT' terms instead.
1185-- The first argument is a function to map @TT@ terms to @Binder@s.
1186-- This function might often be something like 'Lam', which directly
1187-- constructs a @Binder@ from a @TT@ term.
1188bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
1189bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
1191-- | Return a list of pairs of the names of the outermost 'Pi'-bound
1192-- variables in the given term, together with their types.
1193getArgTys :: TT n -> [(n, TT n)]
1194getArgTys (Bind n (PVar _) sc) = getArgTys sc
1195getArgTys (Bind n (PVTy _) sc) = getArgTys sc
1196getArgTys (Bind n (Pi _ t _) sc) = (n, t) : getArgTys sc
1199getRetTy :: TT n -> TT n
1200getRetTy (Bind n (PVar _) sc) = getRetTy sc
1201getRetTy (Bind n (PVTy _) sc) = getRetTy sc
1202getRetTy (Bind n (Pi _ _ _) sc) = getRetTy sc
1205uniqueNameFrom :: [Name] -> [Name] -> Name
1206uniqueNameFrom [] hs = uniqueName (nextName (sUN "x")) hs
1207uniqueNameFrom (s : supply) hs
1208 | s `elem` hs = uniqueNameFrom supply hs
1211uniqueName :: Name -> [Name] -> Name
1212uniqueName n hs | n `elem` hs = uniqueName (nextName n) hs
1215uniqueNameSet :: Name -> Set Name -> Name
1216uniqueNameSet n hs | n `member` hs = uniqueNameSet (nextName n) hs
1219uniqueBinders :: [Name] -> TT Name -> TT Name
1220uniqueBinders ns = ubSet (fromList ns) where
1221 ubSet ns (Bind n b sc)
1222 = let n' = uniqueNameSet n ns
1223 ns' = insert n' ns in
1224 Bind n' (fmap (ubSet ns') b) (ubSet ns' sc)
1225 ubSet ns (App f a) = App (ubSet ns f) (ubSet ns a)
1229nextName (NS x s) = NS (nextName x) s
1230nextName (MN i n) = MN (i+1) n
1231nextName (UN x) = let (num', nm') = T.span isDigit (T.reverse x)
1233 num = readN (T.reverse num') in
1234 UN (nm `T.append` txt (show (num+1)))
1236 readN x | not (T.null x) = read (T.unpack x)
1238nextName (SN x) = SN (nextName' x)
1240 nextName' (WhereN i f x) = WhereN i f (nextName x)
1241 nextName' (WithN i n) = WithN i (nextName n)
1242 nextName' (InstanceN n ns) = InstanceN (nextName n) ns
1243 nextName' (ParentN n ns) = ParentN (nextName n) ns
1244 nextName' (CaseN n) = CaseN (nextName n)
1245 nextName' (ElimN n) = ElimN (nextName n)
1246 nextName' (MethodN n) = MethodN (nextName n)
1247 nextName' (InstanceCtorN n) = InstanceCtorN (nextName n)
1252type Env = EnvTT Name
1254-- | an environment with de Bruijn indices 'normalised' so that they all refer to
1257newtype WkEnvTT n = Wk (EnvTT n)
1258type WkEnv = WkEnvTT Name
1260instance (Eq n, Show n) => Show (TT n) where
1261 show t = showEnv [] t
1263itBitsName IT8 = "Bits8"
1264itBitsName IT16 = "Bits16"
1265itBitsName IT32 = "Bits32"
1266itBitsName IT64 = "Bits64"
1268instance Show Const where
1270 show (BI i) = show i
1271 show (Fl f) = show f
1272 show (Ch c) = show c
1273 show (Str s) = show s
1274 show (B8 x) = show x
1275 show (B16 x) = show x
1276 show (B32 x) = show x
1277 show (B64 x) = show x
1278 show (B8V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
1279 show (B16V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
1280 show (B32V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
1281 show (B64V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
1282 show (AType ATFloat) = "Float"
1283 show (AType (ATInt ITBig)) = "Integer"
1284 show (AType (ATInt ITNative)) = "Int"
1285 show (AType (ATInt ITChar)) = "Char"
1286 show (AType (ATInt (ITFixed it))) = itBitsName it
1287 show (AType (ATInt (ITVec it c))) = itBitsName it ++ "x" ++ show c
1288 show TheWorld = "prim__TheWorld"
1289 show WorldType = "prim__WorldType"
1290 show StrType = "String"
1291 show BufferType = "prim__UnsafeBuffer"
1292 show PtrType = "Ptr"
1293 show ManagedPtrType = "ManagedPtr"
1294 show VoidType = "Void"
1296showEnv :: (Eq n, Show n) => EnvTT n -> TT n -> String
1297showEnv env t = showEnv' env t False
1298showEnvDbg env t = showEnv' env t True
1300prettyEnv env t = prettyEnv' env t False
1302 prettyEnv' env t dbg = prettySe 10 env t dbg
1304 bracket outer inner p
1305 | inner > outer = lparen <> p <> rparen
1308 prettySe p env (P nt n t) debug =
1311 lbracket <+> pretty nt <+> colon <+> prettySe 10 env t debug <+> rbracket
1314 prettySe p env (V i) debug
1317 text . show . fst $ env!!i
1319 lbracket <+> text (show i) <+> rbracket
1320 | otherwise = text "unbound" <+> text (show i) <+> text "!"
1321 prettySe p env (Bind n b@(Pi _ t _) sc) debug
1322 | noOccurrence n sc && not debug =
1323 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
1324 prettySe p env (Bind n b sc) debug =
1325 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
1326 prettySe p env (App f a) debug =
1327 bracket p 1 $ prettySe 1 env f debug <+> prettySe 0 env a debug
1328 prettySe p env (Proj x i) debug =
1329 prettySe 1 env x debug <+> text ("!" ++ show i)
1330 prettySe p env (Constant c) debug = pretty c
1331 prettySe p env Erased debug = text "[_]"
1332 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
1334 -- Render a `Binder` and its name
1335 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
1336 prettySb env n (Hole t) = prettyB env "?defer" "." n t
1337 prettySb env n (Pi _ t _) = prettyB env "(" ") ->" n t
1338 prettySb env n (PVar t) = prettyB env "pat" "." n t
1339 prettySb env n (PVTy t) = prettyB env "pty" "." n t
1340 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
1341 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
1343 -- Use `op` and `sc` to delimit `n` (a binding name) and its type
1345 -- e.g. "λx : Int =>" for the Lam case
1346 prettyB env op sc n t debug =
1347 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
1349 -- Like `prettyB`, but handle the bindings that have values in addition
1350 -- to names and types
1351 prettyBv env op sc n t v debug =
1352 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
1353 prettySe 10 env v debug <> text sc
1356showEnv' env t dbg = se 10 env t where
1357 se p env (P nt n t) = show n
1358 ++ if dbg then "{" ++ show nt ++ " : " ++ se 10 env t ++ "}" else ""
1359 se p env (V i) | i < length env && i >= 0
1360 = (show $ fst $ env!!i) ++
1361 if dbg then "{" ++ show i ++ "}" else ""
1362 | otherwise = "!!V " ++ show i ++ "!!"
1363 se p env (Bind n b@(Pi (Just _) t k) sc)
1364 = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
1365 se p env (Bind n b@(Pi _ t k) sc)
1366 | noOccurrence n sc && not dbg = bracket p 2 $ se 1 env t ++ arrow k ++ se 10 ((n,b):env) sc
1367 where arrow (TType _) = " -> "
1368 arrow u = " [" ++ show u ++ "] -> "
1369 se p env (Bind n b sc) = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
1370 se p env (App f a) = bracket p 1 $ se 1 env f ++ " " ++ se 0 env a
1371 se p env (Proj x i) = se 1 env x ++ "!" ++ show i
1372 se p env (Constant c) = show c
1373 se p env Erased = "[__]"
1374 se p env Impossible = "[impossible]"
1375 se p env (TType i) = "Type " ++ show i
1376 se p env (UType u) = show u
1378 sb env n (Lam t) = showb env "\\ " " => " n t
1379 sb env n (Hole t) = showb env "? " ". " n t
1380 sb env n (GHole i t) = showb env "?defer " ". " n t
1381 sb env n (Pi (Just _) t _) = showb env "{" "} -> " n t
1382 sb env n (Pi _ t _) = showb env "(" ") -> " n t
1383 sb env n (PVar t) = showb env "pat " ". " n t
1384 sb env n (PVTy t) = showb env "pty " ". " n t
1385 sb env n (Let t v) = showbv env "let " " in " n t v
1386 sb env n (Guess t v) = showbv env "?? " " in " n t v
1388 showb env op sc n t = op ++ show n ++ " : " ++ se 10 env t ++ sc
1389 showbv env op sc n t v = op ++ show n ++ " : " ++ se 10 env t ++ " = " ++
1392 bracket outer inner str | inner > outer = "(" ++ str ++ ")"
1395-- | Check whether a term has any holes in it - impure if so
1396pureTerm :: TT Name -> Bool
1397pureTerm (App f a) = pureTerm f && pureTerm a
1398pureTerm (Bind n b sc) = notClassName n && pureBinder b && pureTerm sc where
1399 pureBinder (Hole _) = False
1400 pureBinder (Guess _ _) = False
1401 pureBinder (Let t v) = pureTerm t && pureTerm v
1402 pureBinder t = pureTerm (binderTy t)
1404 notClassName (MN _ c) | c == txt "class" = False
1405 notClassName _ = True
1409-- | Weaken a term by adding i to each de Bruijn index (i.e. lift it over i bindings)
1410weakenTm :: Int -> TT n -> TT n
1411weakenTm i t = wk i 0 t
1412 where wk i min (V x) | x >= min = V (i + x)
1413 wk i m (App f a) = App (wk i m f) (wk i m a)
1414 wk i m (Bind x b sc) = Bind x (wkb i m b) (wk i (m + 1) sc)
1416 wkb i m t = fmap (wk i m) t
1418-- | Weaken an environment so that all the de Bruijn indices are correct according
1419-- to the latest bound variable
1421weakenEnv :: EnvTT n -> EnvTT n
1422weakenEnv env = wk (length env - 1) env
1424 wk i ((n, b) : bs) = (n, weakenTmB i b) : wk (i - 1) bs
1425 weakenTmB i (Let t v) = Let (weakenTm i t) (weakenTm i v)
1426 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
1427 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
1429-- | Weaken every term in the environment by the given amount
1430weakenTmEnv :: Int -> EnvTT n -> EnvTT n
1431weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
1433-- | Gather up all the outer 'PVar's and 'Hole's in an expression and reintroduce
1434-- them in a canonical order
1435orderPats :: Term -> Term
1436orderPats tm = op [] tm
1438 op [] (App f a) = App f (op [] a) -- for Infer terms
1440 op ps (Bind n (PVar t) sc) = op ((n, PVar t) : ps) sc
1441 op ps (Bind n (Hole t) sc) = op ((n, Hole t) : ps) sc
1442 op ps (Bind n (Pi i t k) sc) = op ((n, Pi i t k) : ps) sc
1443 op ps sc = bindAll (sortP ps) sc
1445 sortP ps = pick [] (reverse ps)
1447 pick acc [] = reverse acc
1448 pick acc ((n, t) : ps) = pick (insert n t acc) ps
1450 insert n t [] = [(n, t)]
1451 insert n t ((n',t') : ps)
1452 | n `elem` (refsIn (binderTy t') ++
1453 concatMap refsIn (map (binderTy . snd) ps))
1454 = (n', t') : insert n t ps
1455 | otherwise = (n,t):(n',t'):ps
1457refsIn :: TT Name -> [Name]
1458refsIn (P _ n _) = [n]
1459refsIn (Bind n b t) = nub $ nb b ++ refsIn t
1460 where nb (Let t v) = nub (refsIn t) ++ nub (refsIn v)
1461 nb (Guess t v) = nub (refsIn t) ++ nub (refsIn v)
1462 nb t = refsIn (binderTy t)
1463refsIn (App f a) = nub (refsIn f ++ refsIn a)
1466-- Make sure all the pattern bindings are as far out as possible
1467liftPats :: Term -> Term
1468liftPats tm = let (tm', ps) = runState (getPats tm) [] in
1469 orderPats $ bindPats (reverse ps) tm'
1472 bindPats ((n, t):ps) tm
1473 | n `notElem` map fst ps = Bind n (PVar t) (bindPats ps tm)
1474 | otherwise = bindPats ps tm
1476 getPats :: Term -> State [(Name, Type)] Term
1477 getPats (Bind n (PVar t) sc) = do ps <- get
1480 getPats (Bind n (Guess t v) sc) = do t' <- getPats t
1483 return (Bind n (Guess t' v') sc')
1484 getPats (Bind n (Let t v) sc) = do t' <- getPats t
1487 return (Bind n (Let t' v') sc')
1488 getPats (Bind n (Pi i t k) sc) = do t' <- getPats t
1491 return (Bind n (Pi i t' k') sc')
1492 getPats (Bind n (Lam t) sc) = do t' <- getPats t
1494 return (Bind n (Lam t') sc')
1495 getPats (Bind n (Hole t) sc) = do t' <- getPats t
1497 return (Bind n (Hole t') sc')
1500 getPats (App f a) = do f' <- getPats f
1503 getPats t = return t
1505allTTNames :: Eq n => TT n -> [n]
1506allTTNames = nub . allNamesIn
1507 where allNamesIn (P _ n _) = [n]
1508 allNamesIn (Bind n b t) = [n] ++ nb b ++ allNamesIn t
1509 where nb (Let t v) = allNamesIn t ++ allNamesIn v
1510 nb (Guess t v) = allNamesIn t ++ allNamesIn v
1511 nb t = allNamesIn (binderTy t)
1512 allNamesIn (App f a) = allNamesIn f ++ allNamesIn a
1516-- | Pretty-print a term
1517pprintTT :: [Name] -- ^ The bound names (for highlighting and de Bruijn indices)
1518 -> TT Name -- ^ The term to be printed
1519 -> Doc OutputAnnotation
1520pprintTT bound tm = pp startPrec bound tm
1526 pp p bound (P Bound n ty) = annotate (AnnBoundName n False) (text $ show n)
1527 pp p bound (P nt n ty) = annotate (AnnName n Nothing Nothing Nothing)
1530 | i < length bound = let n = bound !! i
1531 in annotate (AnnBoundName n False) (text $ show n)
1532 | otherwise = text ("{{{V" ++ show i ++ "}}}")
1533 pp p bound (Bind n b sc) = ppb p bound n b $
1534 pp startPrec (n:bound) sc
1535 pp p bound (App tm1 tm2) =
1536 bracket p appPrec . group . hang 2 $
1537 pp appPrec bound tm1 <> line <>
1538 pp (appPrec + 1) bound tm2
1539 pp p bound (Constant c) = annotate (AnnConst c) (text (show c))
1540 pp p bound (Proj tm i) =
1541 lparen <> pp startPrec bound tm <> rparen <>
1542 text "!" <> text (show i)
1543 pp p bound Erased = text "<<<erased>>>"
1544 pp p bound Impossible = text "<<<impossible>>>"
1545 pp p bound (TType ue) = annotate (AnnType "Type" "The type of types") $
1547 pp p bound (UType u) = text (show u)
1549 ppb p bound n (Lam ty) sc =
1550 bracket p startPrec . group . align . hang 2 $
1551 text "λ" <+> bindingOf n False <+> text "." <> line <> sc
1552 ppb p bound n (Pi _ ty k) sc =
1553 bracket p startPrec . group . align $
1554 lparen <> (bindingOf n False) <+> colon <+>
1555 (group . align) (pp startPrec bound ty) <>
1556 rparen <+> mkArrow k <> line <> sc
1557 where mkArrow (UType UniqueType) = text "⇴"
1558 mkArrow (UType NullType) = text "⥛"
1559 mkArrow _ = text "→"
1560 ppb p bound n (Let ty val) sc =
1561 bracket p startPrec . group . align $
1562 (group . hang 2) (annotate AnnKeyword (text "let") <+>
1563 bindingOf n False <+> colon <+>
1564 pp startPrec bound ty <+>
1566 pp startPrec bound val) <> line <>
1567 (group . hang 2) (annotate AnnKeyword (text "in") <+> sc)
1568 ppb p bound n (NLet ty val) sc =
1569 bracket p startPrec . group . align $
1570 (group . hang 2) (annotate AnnKeyword (text "nlet") <+>
1571 bindingOf n False <+> colon <+>
1572 pp startPrec bound ty <+>
1574 pp startPrec bound val) <> line <>
1575 (group . hang 2) (annotate AnnKeyword (text "in") <+> sc)
1576 ppb p bound n (Hole ty) sc =
1577 bracket p startPrec . group . align . hang 2 $
1578 text "?" <+> bindingOf n False <+> text "." <> line <> sc
1579 ppb p bound n (GHole _ ty) sc =
1580 bracket p startPrec . group . align . hang 2 $
1581 text "¿" <+> bindingOf n False <+> text "." <> line <> sc
1582 ppb p bound n (Guess ty val) sc =
1583 bracket p startPrec . group . align . hang 2 $
1584 text "?" <> bindingOf n False <+>
1585 text "≈" <+> pp startPrec bound val <+>
1586 text "." <> line <> sc
1587 ppb p bound n (PVar ty) sc =
1588 bracket p startPrec . group . align . hang 2 $
1589 annotate AnnKeyword (text "pat") <+>
1590 bindingOf n False <+> colon <+> pp startPrec bound ty <+>
1593 ppb p bound n (PVTy ty) sc =
1594 bracket p startPrec . group . align . hang 2 $
1595 annotate AnnKeyword (text "patTy") <+>
1596 bindingOf n False <+> colon <+> pp startPrec bound ty <+>
1600 bracket outer inner doc
1601 | outer > inner = lparen <> doc <> rparen
1605-- | Pretty-printer helper for the binding site of a name
1606bindingOf :: Name -- ^^ the bound name
1607 -> Bool -- ^^ whether the name is implicit
1608 -> Doc OutputAnnotation
1609bindingOf 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