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"
431-- |Contexts allow us to map names to things. A root name maps to a collection
432-- of things in different namespaces with that name.
433type Ctxt a = Map.Map Name (Map.Map Name a)
434emptyContext = Map.empty
436mapCtxt :: (a -> b) -> Ctxt a -> Ctxt b
439-- |Return True if the argument 'Name' should be interpreted as the name of a
441tcname (UN xs) | T.null xs = False
442 | otherwise = T.head xs == '@'
443tcname (NS n _) = tcname n
444tcname (SN (InstanceN _ _)) = True
445tcname (SN (MethodN _)) = True
446tcname (SN (ParentN _ _)) = True
449implicitable (NS n _) = implicitable n
450implicitable (UN xs) | T.null xs = False
451 | otherwise = isLower (T.head xs) || T.head xs == '_'
452implicitable (MN _ x) = not (tnull x) && thead x /= '_'
453implicitable _ = False
458-- this will overwrite already existing definitions
459addDef :: Name -> a -> Ctxt a -> Ctxt a
460addDef n v ctxt = case Map.lookup (nsroot n) ctxt of
461 Nothing -> Map.insert (nsroot n)
462 (Map.insert n v Map.empty) ctxt
463 Just xs -> Map.insert (nsroot n)
464 (Map.insert n v xs) ctxt
466{-| Look up a name in the context, given an optional namespace.
467 The name (n) may itself have a (partial) namespace given.
469 Rules for resolution:
471 - if an explicit namespace is given, return the names which match it. If none
472 match, return all names.
474 - if the name has has explicit namespace given, return the names which match it
475 and ignore the given namespace.
477 - otherwise, return all names.
481lookupCtxtName :: Name -> Ctxt a -> [(Name, a)]
482lookupCtxtName n ctxt = case Map.lookup (nsroot n) ctxt of
483 Just xs -> filterNS (Map.toList xs)
487 filterNS ((found, v) : xs)
488 | nsmatch n found = (found, v) : filterNS xs
489 | otherwise = filterNS xs
491 nsmatch (NS n ns) (NS p ps) = ns `isPrefixOf` ps
492 nsmatch (NS _ _) _ = False
493 nsmatch looking found = True
495lookupCtxt :: Name -> Ctxt a -> [a]
496lookupCtxt n ctxt = map snd (lookupCtxtName n ctxt)
498lookupCtxtExact :: Name -> Ctxt a -> Maybe a
499lookupCtxtExact n ctxt = listToMaybe [ v | (nm, v) <- lookupCtxtName n ctxt, nm == n]
501deleteDefExact :: Name -> Ctxt a -> Ctxt a
502deleteDefExact n = Map.adjust (Map.delete n) (nsroot n)
504updateDef :: Name -> (a -> a) -> Ctxt a -> Ctxt a
506 = let ds = lookupCtxtName n ctxt in
507 foldr (\ (n, t) c -> addDef n (f t) c) ctxt ds
509toAlist :: Ctxt a -> [(Name, a)]
510toAlist ctxt = let allns = map snd (Map.toList ctxt) in
511 concatMap (Map.toList) allns
513addAlist :: [(Name, a)] -> Ctxt a -> Ctxt a
514addAlist [] ctxt = ctxt
515addAlist ((n, tm) : ds) ctxt = addDef n tm (addAlist ds ctxt)
517data NativeTy = IT8 | IT16 | IT32 | IT64
518 deriving (Show, Eq, Ord, Enum, Data, Typeable)
520instance Pretty NativeTy OutputAnnotation where
521 pretty IT8 = text "Bits8"
522 pretty IT16 = text "Bits16"
523 pretty IT32 = text "Bits32"
524 pretty IT64 = text "Bits64"
526data IntTy = ITFixed NativeTy | ITNative | ITBig | ITChar
527 deriving (Show, Eq, Ord, Data, Typeable)
529intTyName :: IntTy -> String
530intTyName ITNative = "Int"
531intTyName ITBig = "BigInt"
532intTyName (ITFixed sized) = "B" ++ show (nativeTyWidth sized)
533intTyName (ITChar) = "Char"
535data ArithTy = ATInt IntTy | ATFloat -- TODO: Float vectors https://github.com/idris-lang/Idris-dev/issues/1723
536 deriving (Show, Eq, Ord, Data, Typeable)
538deriving instance NFData IntTy
539deriving instance NFData NativeTy
540deriving instance NFData ArithTy
543instance Pretty ArithTy OutputAnnotation where
544 pretty (ATInt ITNative) = text "Int"
545 pretty (ATInt ITBig) = text "BigInt"
546 pretty (ATInt ITChar) = text "Char"
547 pretty (ATInt (ITFixed n)) = pretty n
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 | AType ArithTy | StrType
566 | WorldType | TheWorld
568 deriving (Eq, Ord, Data, Typeable)
570deriving instance Binary Const
571deriving instance NFData Const
574isTypeConst :: Const -> Bool
575isTypeConst (AType _) = True
576isTypeConst StrType = True
577isTypeConst WorldType = True
578isTypeConst VoidType = True
581instance Sized Const where
584instance Pretty Const OutputAnnotation where
585 pretty (I i) = text . show $ i
586 pretty (BI i) = text . show $ i
587 pretty (Fl f) = text . show $ f
588 pretty (Ch c) = text . show $ c
589 pretty (Str s) = text s
590 pretty (AType a) = pretty a
591 pretty StrType = text "String"
592 pretty TheWorld = text "%theWorld"
593 pretty WorldType = text "prim__World"
594 pretty VoidType = text "Void"
595 pretty Forgot = text "Forgot"
596 pretty (B8 w) = text . show $ w
597 pretty (B16 w) = text . show $ w
598 pretty (B32 w) = text . show $ w
599 pretty (B64 w) = text . show $ w
601-- | Determines whether the input constant represents a type
602constIsType :: Const -> Bool
603constIsType (I _) = False
604constIsType (BI _) = False
605constIsType (Fl _) = False
606constIsType (Ch _) = False
607constIsType (Str _) = False
608constIsType (B8 _) = False
609constIsType (B16 _) = False
610constIsType (B32 _) = False
611constIsType (B64 _) = False
614-- | Get the docstring for a Const
615constDocs :: Const -> String
616constDocs c@(AType (ATInt ITBig)) = "Arbitrary-precision integers"
617constDocs c@(AType (ATInt ITNative)) = "Fixed-precision integers of undefined size"
618constDocs c@(AType (ATInt ITChar)) = "Characters in some unspecified encoding"
619constDocs c@(AType ATFloat) = "Double-precision floating-point numbers"
620constDocs StrType = "Strings in some unspecified encoding"
621constDocs c@(AType (ATInt (ITFixed IT8))) = "Eight bits (unsigned)"
622constDocs c@(AType (ATInt (ITFixed IT16))) = "Sixteen bits (unsigned)"
623constDocs c@(AType (ATInt (ITFixed IT32))) = "Thirty-two bits (unsigned)"
624constDocs c@(AType (ATInt (ITFixed IT64))) = "Sixty-four bits (unsigned)"
625constDocs (Fl f) = "A float"
626constDocs (I i) = "A fixed-precision integer"
627constDocs (BI i) = "An arbitrary-precision integer"
628constDocs (Str s) = "A string of length " ++ show (length s)
629constDocs (Ch c) = "A character"
630constDocs (B8 w) = "The eight-bit value 0x" ++
631 showIntAtBase 16 intToDigit w ""
632constDocs (B16 w) = "The sixteen-bit value 0x" ++
633 showIntAtBase 16 intToDigit w ""
634constDocs (B32 w) = "The thirty-two-bit value 0x" ++
635 showIntAtBase 16 intToDigit w ""
636constDocs (B64 w) = "The sixty-four-bit value 0x" ++
637 showIntAtBase 16 intToDigit w ""
638constDocs prim = "Undocumented"
640data Universe = NullType | UniqueType | AllTypes
641 deriving (Eq, Ord, Data, Typeable)
643instance Show Universe where
644 show UniqueType = "UniqueType"
645 show NullType = "NullType"
646 show AllTypes = "Type*"
649 | RBind Name (Binder Raw) Raw
655 deriving (Show, Eq, Data, Typeable)
657instance Sized Raw where
659 size (RBind name bind right) = 1 + size bind + size right
660 size (RApp left right) = 1 + size left + size right
663 size (RForce raw) = 1 + size raw
664 size (RConstant const) = size const
666instance Pretty Raw OutputAnnotation where
670deriving instance Binary Raw
671deriving instance NFData Raw
674data ImplicitInfo = Impl { tcinstance :: Bool }
675 deriving (Show, Eq, Ord, Data, Typeable)
678deriving instance Binary ImplicitInfo
679deriving instance NFData ImplicitInfo
682-- The type parameter `b` will normally be something like `TT Name` or just
683-- `Raw`. We do not make a type-level distinction between TT terms that happen
684-- to be TT types and TT terms that are not TT types.
685-- | All binding forms are represented in a uniform fashion. This type only represents
686-- the types of bindings (and their values, if any); the attached identifiers are part
687-- of the 'Bind' constructor for the 'TT' type.
688data Binder b = Lam { binderTy :: !b {-^ type annotation for bound variable-}}
689 | Pi { binderImpl :: Maybe ImplicitInfo,
692 {-^ A binding that occurs in a function type expression, e.g. @(x:Int) -> ...@
693 The 'binderImpl' flag says whether it was a scoped implicit
694 (i.e. forall bound) in the high level Idris, but otherwise
695 has no relevance in TT. -}
696 | Let { binderTy :: !b,
697 binderVal :: b {-^ value for bound variable-}}
698 -- ^ A binding that occurs in a @let@ expression
699 | NLet { binderTy :: !b,
701 | Hole { binderTy :: !b}
702 | GHole { envlen :: Int,
704 | Guess { binderTy :: !b,
706 | PVar { binderTy :: !b }
707 -- ^ A pattern variable
708 | PVTy { binderTy :: !b }
709 deriving (Show, Eq, Ord, Functor, Foldable, Traversable, Data, Typeable)
711deriving instance Binary Binder
712deriving instance NFData Binder
715instance Sized a => Sized (Binder a) where
716 size (Lam ty) = 1 + size ty
717 size (Pi _ ty _) = 1 + size ty
718 size (Let ty val) = 1 + size ty + size val
719 size (NLet ty val) = 1 + size ty + size val
720 size (Hole ty) = 1 + size ty
721 size (GHole _ ty) = 1 + size ty
722 size (Guess ty val) = 1 + size ty + size val
723 size (PVar ty) = 1 + size ty
724 size (PVTy ty) = 1 + size ty
726fmapMB :: Monad m => (a -> m b) -> Binder a -> m (Binder b)
727fmapMB f (Let t v) = liftM2 Let (f t) (f v)
728fmapMB f (NLet t v) = liftM2 NLet (f t) (f v)
729fmapMB f (Guess t v) = liftM2 Guess (f t) (f v)
730fmapMB f (Lam t) = liftM Lam (f t)
731fmapMB f (Pi i t k) = liftM2 (Pi i) (f t) (f k)
732fmapMB f (Hole t) = liftM Hole (f t)
733fmapMB f (GHole i t) = liftM (GHole i) (f t)
734fmapMB f (PVar t) = liftM PVar (f t)
735fmapMB f (PVTy t) = liftM PVTy (f t)
737raw_apply :: Raw -> [Raw] -> Raw
739raw_apply f (a : as) = raw_apply (RApp f a) as
741raw_unapply :: Raw -> (Raw, [Raw])
742raw_unapply t = ua [] t where
743 ua args (RApp f a) = ua (a:args) f
744 ua args t = (t, args)
746-- WELL TYPED TERMS ---------------------------------------------------------
748-- | Universe expressions for universe checking
749data UExp = UVar Int -- ^ universe variable
750 | UVal Int -- ^ explicit universe level
751 deriving (Eq, Ord, Data, Typeable)
753deriving instance NFData UExp
756instance Sized UExp where
759instance Show UExp where
760 show (UVar x) | x < 26 = [toEnum (x + fromEnum 'a')]
761 | otherwise = toEnum ((x `mod` 26) + fromEnum 'a') : show (x `div` 26)
762 show (UVal x) = show x
763-- show (UMax l r) = "max(" ++ show l ++ ", " ++ show r ++")"
765-- | Universe constraints
766data UConstraint = ULT UExp UExp -- ^ Strictly less than
767 | ULE UExp UExp -- ^ Less than or equal to
770data ConstraintFC = ConstraintFC { uconstraint :: UConstraint,
774instance Eq ConstraintFC where
775 x == y = uconstraint x == uconstraint y
777instance Ord ConstraintFC where
778 compare x y = compare (uconstraint x) (uconstraint y)
780instance Show UConstraint where
781 show (ULT x y) = show x ++ " < " ++ show y
782 show (ULE x y) = show x ++ " <= " ++ show y
784type UCs = (Int, [UConstraint])
788 | DCon {nt_tag :: Int, nt_arity :: Int, nt_unique :: Bool} -- ^ Data constructor
789 | TCon {nt_tag :: Int, nt_arity :: Int} -- ^ Type constructor
790 deriving (Show, Ord, Data, Typeable)
792deriving instance Binary NameType
793deriving instance NFData NameType
796instance Sized NameType where
799instance Pretty NameType OutputAnnotation where
802instance Eq NameType where
803 Bound == Bound = True
805 DCon _ a _ == DCon _ b _ = (a == b) -- ignore tag
806 TCon _ a == TCon _ b = (a == b) -- ignore tag
809-- | Terms in the core language. The type parameter is the type of
810-- identifiers used for bindings and explicit named references;
811-- usually we use @TT 'Name'@.
812data TT n = P NameType n (TT n) -- ^ named references with type
813 -- (P for "Parameter", motivated by McKinna and Pollack's
814 -- Pure Type Systems Formalized)
815 | V !Int -- ^ a resolved de Bruijn-indexed variable
816 | Bind n !(Binder (TT n)) (TT n) -- ^ a binding
817 | App !(TT n) (TT n) -- ^ function, function type, arg
818 | Constant Const -- ^ constant
819 | Proj (TT n) !Int -- ^ argument projection; runtime only
820 -- (-1) is a special case for 'subtract one from BI'
821 | Erased -- ^ an erased term
822 | Impossible -- ^ special case for totality checking
823 | TType UExp -- ^ the type of types at some level
824 | UType Universe -- ^ Uniqueness type universe (disjoint from TType)
825 deriving (Ord, Functor, Data, Typeable)
827deriving instance Binary TT
828deriving instance NFData TT
831class TermSize a where
832 termsize :: Name -> a -> Int
834instance TermSize a => TermSize [a] where
836 termsize n (x : xs) = termsize n x + termsize n xs
838instance TermSize (TT Name) where
839 termsize n (P _ n' _)
840 | n' == n = 1000000 -- recursive => really big
843 -- for `Bind` terms, we can erroneously declare a term
844 -- "recursive => really big" if the name of the bound
845 -- variable is the same as the name we're using
846 -- So generate a different name in that case.
847 termsize n (Bind n' (Let t v) sc)
848 = let rn = if n == n' then sMN 0 "noname" else n in
849 termsize rn v + termsize rn sc
850 termsize n (Bind n' b sc)
851 = let rn = if n == n' then sMN 0 "noname" else n in
853 termsize n (App f a) = termsize n f + termsize n a
854 termsize n (Proj t i) = termsize n t
857instance Sized a => Sized (TT a) where
858 size (P name n trm) = 1 + size name + size n + size trm
860 size (Bind nm binder bdy) = 1 + size nm + size binder + size bdy
861 size (App l r) = 1 + size l + size r
862 size (Constant c) = size c
864 size (TType u) = 1 + size u
866instance Pretty a o => Pretty (TT a) o where
867 pretty _ = text "test"
869type EnvTT n = [(n, Binder (TT n))]
871data Datatype n = Data { d_typename :: n,
875 d_cons :: [(n, TT n)] }
876 deriving (Show, Functor, Eq)
878instance Eq n => Eq (TT n) where
879 (==) (P xt x _) (P yt y _) = x == y
880 (==) (V x) (V y) = x == y
881 (==) (Bind _ xb xs) (Bind _ yb ys) = xs == ys && xb == yb
882 (==) (App fx ax) (App fy ay) = ax == ay && fx == fy
883 (==) (TType _) (TType _) = True -- deal with constraints later
884 (==) (Constant x) (Constant y) = x == y
885 (==) (Proj x i) (Proj y j) = x == y && i == j
890-- * A few handy operations on well typed terms:
892-- | A term is injective iff it is a data constructor, type constructor,
893-- constant, the type Type, pi-binding, or an application of an injective
895isInjective :: TT n -> Bool
896isInjective (P (DCon _ _ _) _ _) = True
897isInjective (P (TCon _ _) _ _) = True
898isInjective (Constant _) = True
899isInjective (TType x) = True
900isInjective (Bind _ (Pi _ _ _) sc) = True
901isInjective (App f a) = isInjective f
904-- | Count the number of instances of a de Bruijn index in a term
905vinstances :: Int -> TT n -> Int
906vinstances i (V x) | i == x = 1
907vinstances i (App f a) = vinstances i f + vinstances i a
908vinstances i (Bind x b sc) = instancesB b + vinstances (i + 1) sc
909 where instancesB (Let t v) = vinstances i v
913-- | Replace the outermost (index 0) de Bruijn variable with the given term
914instantiate :: TT n -> TT n -> TT n
915instantiate e = subst 0 where
916 subst i (P nt x ty) = P nt x (subst i ty)
917 subst i (V x) | i == x = e
918 subst i (Bind x b sc) = Bind x (fmap (subst i) b) (subst (i+1) sc)
919 subst i (App f a) = App (subst i f) (subst i a)
920 subst i (Proj x idx) = Proj (subst i x) idx
923-- | As 'instantiate', but also decrement the indices of all de Bruijn variables
924-- remaining in the term, so that there are no more references to the variable
925-- that has been substituted.
926substV :: TT n -> TT n -> TT n
927substV x tm = dropV 0 (instantiate x tm) where
928 subst i (P nt x ty) = P nt x (subst i ty)
929 dropV i (V x) | x > i = V (x - 1)
931 dropV i (Bind x b sc) = Bind x (fmap (dropV i) b) (dropV (i+1) sc)
932 dropV i (App f a) = App (dropV i f) (dropV i a)
933 dropV i (Proj x idx) = Proj (dropV i x) idx
936-- | Replace all non-free de Bruijn references in the given term with references
937-- to the name of their binding.
938explicitNames :: TT n -> TT n
939explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
941 (explicitNames (instantiate
942 (P Bound x (binderTy b')) sc))
943explicitNames (App f a) = App (explicitNames f) (explicitNames a)
944explicitNames (Proj x idx) = Proj (explicitNames x) idx
947-- | Replace references to the given 'Name'-like id with references to
949pToV :: Eq n => n -> TT n -> TT n
951pToV' n i (P _ x _) | n == x = V i
952pToV' n i (Bind x b sc)
953-- We can assume the inner scope has been pToVed already, so continue to
954-- resolve names from the *outer* scope which may happen to have the same id.
955 | n == x = Bind x (fmap (pToV' n i) b) sc
956 | otherwise = Bind x (fmap (pToV' n i) b) (pToV' n (i+1) sc)
957pToV' n i (App f a) = App (pToV' n i f) (pToV' n i a)
958pToV' n i (Proj t idx) = Proj (pToV' n i t) idx
961-- increase de Bruijn indices, as if a binder has been added
962addBinder :: TT n -> TT n
965 ab top (V i) | i >= top = V (i + 1)
967 ab top (Bind x b sc) = Bind x (fmap (ab top) b) (ab (top + 1) sc)
968 ab top (App f a) = App (ab top f) (ab top a)
969 ab top (Proj t idx) = Proj (ab top t) idx
972-- | Convert several names. First in the list comes out as V 0
973pToVs :: Eq n => [n] -> TT n -> TT n
974pToVs ns tm = pToVs' ns tm 0 where
976 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
978-- | Replace de Bruijn indices in the given term with explicit references to
979-- the names of the bindings they refer to. It is an error if the given term
980-- contains free de Bruijn indices.
983 vToP' env (V i) = let (n, b) = (env !! i) in
984 P Bound n (binderTy b)
985 vToP' env (Bind n b sc) = let b' = fmap (vToP' env) b in
986 Bind n b' (vToP' ((n, b'):env) sc)
987 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
990-- | Replace every non-free reference to the name of a binding in
991-- the given term with a de Bruijn index.
992finalise :: Eq n => TT n -> TT n
993finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
994finalise (App f a) = App (finalise f) (finalise a)
997-- Once we've finished checking everything about a term we no longer need
998-- the type on the 'P' so erase it so save memory
1000pEraseType :: TT n -> TT n
1001pEraseType (P nt t _) = P nt t Erased
1002pEraseType (App f a) = App (pEraseType f) (pEraseType a)
1003pEraseType (Bind n b sc) = Bind n (fmap pEraseType b) (pEraseType sc)
1006-- | As 'instantiate', but in addition to replacing @'V' 0@,
1007-- replace references to the given 'Name'-like id.
1008subst :: Eq n => n {-^ The id to replace -} ->
1009 TT n {-^ The replacement term -} ->
1010 TT n {-^ The term to replace in -} ->
1012-- subst n v tm = instantiate v (pToV n tm)
1013subst n v tm = fst $ subst' 0 tm
1015 -- keep track of updates to save allocations - this is a big win on
1016 -- large terms in particular
1017 -- ('Maybe' would be neater here, but >>= is not the right combinator.
1018 -- Feel free to tidy up, as long as it still saves allocating when no
1019 -- substitution happens...)
1020 subst' i (V x) | i == x = (v, True)
1021 subst' i (P _ x _) | n == x = (v, True)
1022 subst' i t@(P nt x ty)
1023 = let (ty', ut) = subst' i ty in
1024 if ut then (P nt x ty', True) else (t, False)
1025 subst' i t@(Bind x b sc) | x /= n
1026 = let (b', ub) = substB' i b
1027 (sc', usc) = subst' (i+1) sc in
1028 if ub || usc then (Bind x b' sc', True) else (t, False)
1029 subst' i t@(App f a) = let (f', uf) = subst' i f
1030 (a', ua) = subst' i a in
1031 if uf || ua then (App f' a', True) else (t, False)
1032 subst' i t@(Proj x idx) = let (x', u) = subst' i x in
1033 if u then (Proj x' idx, u) else (t, False)
1034 subst' i t = (t, False)
1036 substB' i b@(Let t v) = let (t', ut) = subst' i t
1037 (v', uv) = subst' i v in
1038 if ut || uv then (Let t' v', True)
1040 substB' i b@(Guess t v) = let (t', ut) = subst' i t
1041 (v', uv) = subst' i v in
1042 if ut || uv then (Guess t' v', True)
1044 substB' i b = let (ty', u) = subst' i (binderTy b) in
1045 if u then (b { binderTy = ty' }, u) else (b, False)
1047-- If there are no Vs in the term (i.e. in proof state)
1048psubst :: Eq n => n -> TT n -> TT n -> TT n
1049psubst n v tm = s' 0 tm where
1050 s' i (V x) | x > i = V (x - 1)
1053 s' i (P _ x _) | n == x = v
1054 s' i (Bind x b sc) | n == x = Bind x (fmap (s' i) b) sc
1055 | otherwise = Bind x (fmap (s' i) b) (s' (i+1) sc)
1056 s' i (App f a) = App (s' i f) (s' i a)
1057 s' i (Proj t idx) = Proj (s' i t) idx
1060-- | As 'subst', but takes a list of (name, substitution) pairs instead
1061-- of a single name and substitution
1062substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
1064substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
1066-- | Replaces all terms equal (in the sense of @(==)@) to
1067-- the old term with the new term.
1068substTerm :: Eq n => TT n {-^ Old term -} ->
1069 TT n {-^ New term -} ->
1070 TT n {-^ template term -}
1072substTerm old new = st where
1073 st t | t == old = new
1074 st (App f a) = App (st f) (st a)
1075 st (Bind x b sc) = Bind x (fmap st b) (st sc)
1078-- | Return number of occurrences of V 0 or bound name i the term
1079occurrences :: Eq n => n -> TT n -> Int
1080occurrences n t = execState (no' 0 t) 0
1082 no' i (V x) | i == x = do num <- get; put (num + 1)
1083 no' i (P Bound x _) | n == x = do num <- get; put (num + 1)
1084 no' i (Bind n b sc) = do noB' i b; no' (i+1) sc
1085 where noB' i (Let t v) = do no' i t; no' i v
1086 noB' i (Guess t v) = do no' i t; no' i v
1087 noB' i b = no' i (binderTy b)
1088 no' i (App f a) = do no' i f; no' i a
1089 no' i (Proj x _) = no' i x
1092-- | Returns true if V 0 and bound name n do not occur in the term
1093noOccurrence :: Eq n => n -> TT n -> Bool
1094noOccurrence n t = no' 0 t
1096 no' i (V x) = not (i == x)
1097 no' i (P Bound x _) = not (n == x)
1098 no' i (Bind n b sc) = noB' i b && no' (i+1) sc
1099 where noB' i (Let t v) = no' i t && no' i v
1100 noB' i (Guess t v) = no' i t && no' i v
1101 noB' i b = no' i (binderTy b)
1102 no' i (App f a) = no' i f && no' i a
1103 no' i (Proj x _) = no' i x
1106-- | Returns all names used free in the term
1107freeNames :: Eq n => TT n -> [n]
1108freeNames t = nub $ freeNames' t
1110 freeNames' (P _ n _) = [n]
1111 freeNames' (Bind n (Let t v) sc) = freeNames' v ++ (freeNames' sc \\ [n])
1113 freeNames' (Bind n b sc) = freeNames' (binderTy b) ++ (freeNames' sc \\ [n])
1114 freeNames' (App f a) = freeNames' f ++ freeNames' a
1115 freeNames' (Proj x i) = freeNames' x
1118-- | Return the arity of a (normalised) type
1120arity (Bind n (Pi _ t _) sc) = 1 + arity sc
1123-- | Deconstruct an application; returns the function and a list of arguments
1124unApply :: TT n -> (TT n, [TT n])
1125unApply t = ua [] t where
1126 ua args (App f a) = ua (a:args) f
1127 ua args t = (t, args)
1129-- | Returns a term representing the application of the first argument
1130-- (a function) to every element of the second argument.
1131mkApp :: TT n -> [TT n] -> TT n
1133mkApp f (a:as) = mkApp (App f a) as
1135unList :: Term -> Maybe [Term]
1136unList tm = case unApply tm of
1137 (nil, [_]) -> Just []
1138 (cons, ([_, x, xs])) ->
1139 do rest <- unList xs
1141 (f, args) -> Nothing
1143-- | Cast a 'TT' term to a 'Raw' value, discarding universe information and
1144-- the types of named references and replacing all de Bruijn indices
1145-- with the corresponding name. It is an error if there are free de
1147forget :: TT Name -> Raw
1148forget tm = forgetEnv [] tm
1150safeForget :: TT Name -> Maybe Raw
1151safeForget tm = safeForgetEnv [] tm
1153forgetEnv :: [Name] -> TT Name -> Raw
1154forgetEnv env tm = case safeForgetEnv env tm of
1156 Nothing -> error $ "Scope error in " ++ show tm
1159safeForgetEnv :: [Name] -> TT Name -> Maybe Raw
1160safeForgetEnv env (P _ n _) = Just $ Var n
1161safeForgetEnv env (V i) | i < length env = Just $ Var (env !! i)
1162 | otherwise = Nothing
1163safeForgetEnv env (Bind n b sc)
1164 = do let n' = uniqueName n env
1165 b' <- safeForgetEnvB env b
1166 sc' <- safeForgetEnv (n':env) sc
1167 Just $ RBind n' b' sc'
1168 where safeForgetEnvB env (Let t v) = liftM2 Let (safeForgetEnv env t)
1169 (safeForgetEnv env v)
1170 safeForgetEnvB env (Guess t v) = liftM2 Guess (safeForgetEnv env t)
1171 (safeForgetEnv env v)
1172 safeForgetEnvB env b = do ty' <- safeForgetEnv env (binderTy b)
1173 Just $ fmap (\_ -> ty') b
1174safeForgetEnv env (App f a) = liftM2 RApp (safeForgetEnv env f) (safeForgetEnv env a)
1175safeForgetEnv env (Constant c) = Just $ RConstant c
1176safeForgetEnv env (TType i) = Just RType
1177safeForgetEnv env (UType u) = Just $ RUType u
1178safeForgetEnv env Erased = Just $ RConstant Forgot
1180-- | Introduce a 'Bind' into the given term for each element of the
1181-- given list of (name, binder) pairs.
1182bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
1184bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
1186-- | Like 'bindAll', but the 'Binder's are 'TT' terms instead.
1187-- The first argument is a function to map @TT@ terms to @Binder@s.
1188-- This function might often be something like 'Lam', which directly
1189-- constructs a @Binder@ from a @TT@ term.
1190bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
1191bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
1193-- | Return a list of pairs of the names of the outermost 'Pi'-bound
1194-- variables in the given term, together with their types.
1195getArgTys :: TT n -> [(n, TT n)]
1196getArgTys (Bind n (PVar _) sc) = getArgTys sc
1197getArgTys (Bind n (PVTy _) sc) = getArgTys sc
1198getArgTys (Bind n (Pi _ t _) sc) = (n, t) : getArgTys sc
1201getRetTy :: TT n -> TT n
1202getRetTy (Bind n (PVar _) sc) = getRetTy sc
1203getRetTy (Bind n (PVTy _) sc) = getRetTy sc
1204getRetTy (Bind n (Pi _ _ _) sc) = getRetTy sc
1207uniqueNameFrom :: [Name] -> [Name] -> Name
1208uniqueNameFrom [] hs = uniqueName (nextName (sUN "x")) hs
1209uniqueNameFrom (s : supply) hs
1210 | s `elem` hs = uniqueNameFrom supply hs
1213uniqueName :: Name -> [Name] -> Name
1214uniqueName n hs | n `elem` hs = uniqueName (nextName n) hs
1217uniqueNameSet :: Name -> Set Name -> Name
1218uniqueNameSet n hs | n `member` hs = uniqueNameSet (nextName n) hs
1221uniqueBinders :: [Name] -> TT Name -> TT Name
1222uniqueBinders ns = ubSet (fromList ns) where
1223 ubSet ns (Bind n b sc)
1224 = let n' = uniqueNameSet n ns
1225 ns' = insert n' ns in
1226 Bind n' (fmap (ubSet ns') b) (ubSet ns' sc)
1227 ubSet ns (App f a) = App (ubSet ns f) (ubSet ns a)
1231nextName (NS x s) = NS (nextName x) s
1232nextName (MN i n) = MN (i+1) n
1233nextName (UN x) = let (num', nm') = T.span isDigit (T.reverse x)
1235 num = readN (T.reverse num') in
1236 UN (nm `T.append` txt (show (num+1)))
1238 readN x | not (T.null x) = read (T.unpack x)
1240nextName (SN x) = SN (nextName' x)
1242 nextName' (WhereN i f x) = WhereN i f (nextName x)
1243 nextName' (WithN i n) = WithN i (nextName n)
1244 nextName' (InstanceN n ns) = InstanceN (nextName n) ns
1245 nextName' (ParentN n ns) = ParentN (nextName n) ns
1246 nextName' (CaseN n) = CaseN (nextName n)
1247 nextName' (ElimN n) = ElimN (nextName n)
1248 nextName' (MethodN n) = MethodN (nextName n)
1249 nextName' (InstanceCtorN n) = InstanceCtorN (nextName n)
1254type Env = EnvTT Name
1256-- | an environment with de Bruijn indices 'normalised' so that they all refer to
1259newtype WkEnvTT n = Wk (EnvTT n)
1260type WkEnv = WkEnvTT Name
1262instance (Eq n, Show n) => Show (TT n) where
1263 show t = showEnv [] t
1265itBitsName IT8 = "Bits8"
1266itBitsName IT16 = "Bits16"
1267itBitsName IT32 = "Bits32"
1268itBitsName IT64 = "Bits64"
1270instance Show Const where
1272 show (BI i) = show i
1273 show (Fl f) = show f
1274 show (Ch c) = show c
1275 show (Str s) = show s
1276 show (B8 x) = show x
1277 show (B16 x) = show x
1278 show (B32 x) = show x
1279 show (B64 x) = show x
1280 show (AType ATFloat) = "Float"
1281 show (AType (ATInt ITBig)) = "Integer"
1282 show (AType (ATInt ITNative)) = "Int"
1283 show (AType (ATInt ITChar)) = "Char"
1284 show (AType (ATInt (ITFixed it))) = itBitsName it
1285 show TheWorld = "prim__TheWorld"
1286 show WorldType = "prim__WorldType"
1287 show StrType = "String"
1288 show VoidType = "Void"
1290showEnv :: (Eq n, Show n) => EnvTT n -> TT n -> String
1291showEnv env t = showEnv' env t False
1292showEnvDbg env t = showEnv' env t True
1294prettyEnv env t = prettyEnv' env t False
1296 prettyEnv' env t dbg = prettySe 10 env t dbg
1298 bracket outer inner p
1299 | inner > outer = lparen <> p <> rparen
1302 prettySe p env (P nt n t) debug =
1305 lbracket <+> pretty nt <+> colon <+> prettySe 10 env t debug <+> rbracket
1308 prettySe p env (V i) debug
1311 text . show . fst $ env!!i
1313 lbracket <+> text (show i) <+> rbracket
1314 | otherwise = text "unbound" <+> text (show i) <+> text "!"
1315 prettySe p env (Bind n b@(Pi _ t _) sc) debug
1316 | noOccurrence n sc && not debug =
1317 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
1318 prettySe p env (Bind n b sc) debug =
1319 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
1320 prettySe p env (App f a) debug =
1321 bracket p 1 $ prettySe 1 env f debug <+> prettySe 0 env a debug
1322 prettySe p env (Proj x i) debug =
1323 prettySe 1 env x debug <+> text ("!" ++ show i)
1324 prettySe p env (Constant c) debug = pretty c
1325 prettySe p env Erased debug = text "[_]"
1326 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
1328 -- Render a `Binder` and its name
1329 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
1330 prettySb env n (Hole t) = prettyB env "?defer" "." n t
1331 prettySb env n (Pi _ t _) = prettyB env "(" ") ->" n t
1332 prettySb env n (PVar t) = prettyB env "pat" "." n t
1333 prettySb env n (PVTy t) = prettyB env "pty" "." n t
1334 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
1335 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
1337 -- Use `op` and `sc` to delimit `n` (a binding name) and its type
1339 -- e.g. "λx : Int =>" for the Lam case
1340 prettyB env op sc n t debug =
1341 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
1343 -- Like `prettyB`, but handle the bindings that have values in addition
1344 -- to names and types
1345 prettyBv env op sc n t v debug =
1346 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
1347 prettySe 10 env v debug <> text sc
1350showEnv' env t dbg = se 10 env t where
1351 se p env (P nt n t) = show n
1352 ++ if dbg then "{" ++ show nt ++ " : " ++ se 10 env t ++ "}" else ""
1353 se p env (V i) | i < length env && i >= 0
1354 = (show $ fst $ env!!i) ++
1355 if dbg then "{" ++ show i ++ "}" else ""
1356 | otherwise = "!!V " ++ show i ++ "!!"
1357 se p env (Bind n b@(Pi (Just _) t k) sc)
1358 = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
1359 se p env (Bind n b@(Pi _ t k) sc)
1360 | noOccurrence n sc && not dbg = bracket p 2 $ se 1 env t ++ arrow k ++ se 10 ((n,b):env) sc
1361 where arrow (TType _) = " -> "
1362 arrow u = " [" ++ show u ++ "] -> "
1363 se p env (Bind n b sc) = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
1364 se p env (App f a) = bracket p 1 $ se 1 env f ++ " " ++ se 0 env a
1365 se p env (Proj x i) = se 1 env x ++ "!" ++ show i
1366 se p env (Constant c) = show c
1367 se p env Erased = "[__]"
1368 se p env Impossible = "[impossible]"
1369 se p env (TType i) = "Type " ++ show i
1370 se p env (UType u) = show u
1372 sb env n (Lam t) = showb env "\\ " " => " n t
1373 sb env n (Hole t) = showb env "? " ". " n t
1374 sb env n (GHole i t) = showb env "?defer " ". " n t
1375 sb env n (Pi (Just _) t _) = showb env "{" "} -> " n t
1376 sb env n (Pi _ t _) = showb env "(" ") -> " n t
1377 sb env n (PVar t) = showb env "pat " ". " n t
1378 sb env n (PVTy t) = showb env "pty " ". " n t
1379 sb env n (Let t v) = showbv env "let " " in " n t v
1380 sb env n (Guess t v) = showbv env "?? " " in " n t v
1382 showb env op sc n t = op ++ show n ++ " : " ++ se 10 env t ++ sc
1383 showbv env op sc n t v = op ++ show n ++ " : " ++ se 10 env t ++ " = " ++
1386 bracket outer inner str | inner > outer = "(" ++ str ++ ")"
1389-- | Check whether a term has any holes in it - impure if so
1390pureTerm :: TT Name -> Bool
1391pureTerm (App f a) = pureTerm f && pureTerm a
1392pureTerm (Bind n b sc) = notClassName n && pureBinder b && pureTerm sc where
1393 pureBinder (Hole _) = False
1394 pureBinder (Guess _ _) = False
1395 pureBinder (Let t v) = pureTerm t && pureTerm v
1396 pureBinder t = pureTerm (binderTy t)
1398 notClassName (MN _ c) | c == txt "class" = False
1399 notClassName _ = True
1403-- | Weaken a term by adding i to each de Bruijn index (i.e. lift it over i bindings)
1404weakenTm :: Int -> TT n -> TT n
1405weakenTm i t = wk i 0 t
1406 where wk i min (V x) | x >= min = V (i + x)
1407 wk i m (App f a) = App (wk i m f) (wk i m a)
1408 wk i m (Bind x b sc) = Bind x (wkb i m b) (wk i (m + 1) sc)
1410 wkb i m t = fmap (wk i m) t
1412-- | Weaken an environment so that all the de Bruijn indices are correct according
1413-- to the latest bound variable
1415weakenEnv :: EnvTT n -> EnvTT n
1416weakenEnv env = wk (length env - 1) env
1418 wk i ((n, b) : bs) = (n, weakenTmB i b) : wk (i - 1) bs
1419 weakenTmB i (Let t v) = Let (weakenTm i t) (weakenTm i v)
1420 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
1421 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
1423-- | Weaken every term in the environment by the given amount
1424weakenTmEnv :: Int -> EnvTT n -> EnvTT n
1425weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
1427-- | Gather up all the outer 'PVar's and 'Hole's in an expression and reintroduce
1428-- them in a canonical order
1429orderPats :: Term -> Term
1430orderPats tm = op [] tm
1432 op [] (App f a) = App f (op [] a) -- for Infer terms
1434 op ps (Bind n (PVar t) sc) = op ((n, PVar t) : ps) sc
1435 op ps (Bind n (Hole t) sc) = op ((n, Hole t) : ps) sc
1436 op ps (Bind n (Pi i t k) sc) = op ((n, Pi i t k) : ps) sc
1437 op ps sc = bindAll (sortP ps) sc
1439 sortP ps = pick [] (reverse ps)
1441 pick acc [] = reverse acc
1442 pick acc ((n, t) : ps) = pick (insert n t acc) ps
1444 insert n t [] = [(n, t)]
1445 insert n t ((n',t') : ps)
1446 | n `elem` (refsIn (binderTy t') ++
1447 concatMap refsIn (map (binderTy . snd) ps))
1448 = (n', t') : insert n t ps
1449 | otherwise = (n,t):(n',t'):ps
1451refsIn :: TT Name -> [Name]
1452refsIn (P _ n _) = [n]
1453refsIn (Bind n b t) = nub $ nb b ++ refsIn t
1454 where nb (Let t v) = nub (refsIn t) ++ nub (refsIn v)
1455 nb (Guess t v) = nub (refsIn t) ++ nub (refsIn v)
1456 nb t = refsIn (binderTy t)
1457refsIn (App f a) = nub (refsIn f ++ refsIn a)
1460-- Make sure all the pattern bindings are as far out as possible
1461liftPats :: Term -> Term
1462liftPats tm = let (tm', ps) = runState (getPats tm) [] in
1463 orderPats $ bindPats (reverse ps) tm'
1466 bindPats ((n, t):ps) tm
1467 | n `notElem` map fst ps = Bind n (PVar t) (bindPats ps tm)
1468 | otherwise = bindPats ps tm
1470 getPats :: Term -> State [(Name, Type)] Term
1471 getPats (Bind n (PVar t) sc) = do ps <- get
1474 getPats (Bind n (Guess t v) sc) = do t' <- getPats t
1477 return (Bind n (Guess t' v') sc')
1478 getPats (Bind n (Let t v) sc) = do t' <- getPats t
1481 return (Bind n (Let t' v') sc')
1482 getPats (Bind n (Pi i t k) sc) = do t' <- getPats t
1485 return (Bind n (Pi i t' k') sc')
1486 getPats (Bind n (Lam t) sc) = do t' <- getPats t
1488 return (Bind n (Lam t') sc')
1489 getPats (Bind n (Hole t) sc) = do t' <- getPats t
1491 return (Bind n (Hole t') sc')
1494 getPats (App f a) = do f' <- getPats f
1497 getPats t = return t
1499allTTNames :: Eq n => TT n -> [n]
1500allTTNames = nub . allNamesIn
1501 where allNamesIn (P _ n _) = [n]
1502 allNamesIn (Bind n b t) = [n] ++ nb b ++ allNamesIn t
1503 where nb (Let t v) = allNamesIn t ++ allNamesIn v
1504 nb (Guess t v) = allNamesIn t ++ allNamesIn v
1505 nb t = allNamesIn (binderTy t)
1506 allNamesIn (App f a) = allNamesIn f ++ allNamesIn a
1510-- | Pretty-print a term
1511pprintTT :: [Name] -- ^ The bound names (for highlighting and de Bruijn indices)
1512 -> TT Name -- ^ The term to be printed
1513 -> Doc OutputAnnotation
1514pprintTT bound tm = pp startPrec bound tm
1520 pp p bound (P Bound n ty) = annotate (AnnBoundName n False) (text $ show n)
1521 pp p bound (P nt n ty) = annotate (AnnName n Nothing Nothing Nothing)
1524 | i < length bound = let n = bound !! i
1525 in annotate (AnnBoundName n False) (text $ show n)
1526 | otherwise = text ("{{{V" ++ show i ++ "}}}")
1527 pp p bound (Bind n b sc) = ppb p bound n b $
1528 pp startPrec (n:bound) sc
1529 pp p bound (App tm1 tm2) =
1530 bracket p appPrec . group . hang 2 $
1531 pp appPrec bound tm1 <> line <>
1532 pp (appPrec + 1) bound tm2
1533 pp p bound (Constant c) = annotate (AnnConst c) (text (show c))
1534 pp p bound (Proj tm i) =
1535 lparen <> pp startPrec bound tm <> rparen <>
1536 text "!" <> text (show i)
1537 pp p bound Erased = text "<<<erased>>>"
1538 pp p bound Impossible = text "<<<impossible>>>"
1539 pp p bound (TType ue) = annotate (AnnType "Type" "The type of types") $
1541 pp p bound (UType u) = text (show u)
1543 ppb p bound n (Lam ty) sc =
1544 bracket p startPrec . group . align . hang 2 $
1545 text "λ" <+> bindingOf n False <+> text "." <> line <> sc
1546 ppb p bound n (Pi _ ty k) sc =
1547 bracket p startPrec . group . align $
1548 lparen <> (bindingOf n False) <+> colon <+>
1549 (group . align) (pp startPrec bound ty) <>
1550 rparen <+> mkArrow k <> line <> sc
1551 where mkArrow (UType UniqueType) = text "⇴"
1552 mkArrow (UType NullType) = text "⥛"
1553 mkArrow _ = text "→"
1554 ppb p bound n (Let ty val) sc =
1555 bracket p startPrec . group . align $
1556 (group . hang 2) (annotate AnnKeyword (text "let") <+>
1557 bindingOf n False <+> colon <+>
1558 pp startPrec bound ty <+>
1560 pp startPrec bound val) <> line <>
1561 (group . hang 2) (annotate AnnKeyword (text "in") <+> sc)
1562 ppb p bound n (NLet ty val) sc =
1563 bracket p startPrec . group . align $
1564 (group . hang 2) (annotate AnnKeyword (text "nlet") <+>
1565 bindingOf n False <+> colon <+>
1566 pp startPrec bound ty <+>
1568 pp startPrec bound val) <> line <>
1569 (group . hang 2) (annotate AnnKeyword (text "in") <+> sc)
1570 ppb p bound n (Hole ty) sc =
1571 bracket p startPrec . group . align . hang 2 $
1572 text "?" <+> bindingOf n False <+> text "." <> line <> sc
1573 ppb p bound n (GHole _ ty) sc =
1574 bracket p startPrec . group . align . hang 2 $
1575 text "¿" <+> bindingOf n False <+> text "." <> line <> sc
1576 ppb p bound n (Guess ty val) sc =
1577 bracket p startPrec . group . align . hang 2 $
1578 text "?" <> bindingOf n False <+>
1579 text "≈" <+> pp startPrec bound val <+>
1580 text "." <> line <> sc
1581 ppb p bound n (PVar ty) sc =
1582 bracket p startPrec . group . align . hang 2 $
1583 annotate AnnKeyword (text "pat") <+>
1584 bindingOf n False <+> colon <+> pp startPrec bound ty <+>
1587 ppb p bound n (PVTy ty) sc =
1588 bracket p startPrec . group . align . hang 2 $
1589 annotate AnnKeyword (text "patTy") <+>
1590 bindingOf n False <+> colon <+> pp startPrec bound ty <+>
1594 bracket outer inner doc
1595 | outer > inner = lparen <> doc <> rparen
1599-- | Pretty-printer helper for the binding site of a name
1600bindingOf :: Name -- ^^ the bound name
1601 -> Bool -- ^^ whether the name is implicit
1602 -> Doc OutputAnnotation
1603bindingOf 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