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
528 deriving (Show, Eq, Ord, Data, Typeable)
530intTyName :: IntTy -> String
531intTyName ITNative = "Int"
532intTyName ITBig = "BigInt"
533intTyName (ITFixed sized) = "B" ++ show (nativeTyWidth sized)
534intTyName (ITChar) = "Char"
535intTyName (ITVec ity count) = "B" ++ show (nativeTyWidth ity) ++ "x" ++ show count
537data ArithTy = ATInt IntTy | ATFloat -- TODO: Float vectors https://github.com/idris-lang/Idris-dev/issues/1723
538 deriving (Show, Eq, Ord, Data, Typeable)
540deriving instance NFData IntTy
541deriving instance NFData NativeTy
542deriving instance NFData ArithTy
545instance Pretty ArithTy OutputAnnotation where
546 pretty (ATInt ITNative) = text "Int"
547 pretty (ATInt ITBig) = text "BigInt"
548 pretty (ATInt ITChar) = text "Char"
549 pretty (ATInt (ITFixed n)) = pretty n
550 pretty (ATInt (ITVec e c)) = pretty e <> text "x" <> (text . show $ c)
551 pretty ATFloat = text "Float"
553nativeTyWidth :: NativeTy -> Int
555nativeTyWidth IT16 = 16
556nativeTyWidth IT32 = 32
557nativeTyWidth IT64 = 64
559{-# DEPRECATED intTyWidth "Non-total function, use nativeTyWidth and appropriate casing" #-}
560intTyWidth :: IntTy -> Int
561intTyWidth (ITFixed n) = nativeTyWidth n
562intTyWidth ITNative = 8 * sizeOf (0 :: Int)
563intTyWidth ITChar = error "IRTS.Lang.intTyWidth: Characters have platform and backend dependent width"
564intTyWidth ITBig = error "IRTS.Lang.intTyWidth: Big integers have variable width"
566data Const = I Int | BI Integer | Fl Double | Ch Char | Str String
567 | B8 Word8 | B16 Word16 | B32 Word32 | B64 Word64
568 | B8V (Vector Word8) | B16V (Vector Word16)
569 | B32V (Vector Word32) | B64V (Vector Word64)
570 | AType ArithTy | StrType
571 | WorldType | TheWorld
572 | PtrType | ManagedPtrType | BufferType | VoidType | Forgot
573 deriving (Eq, Ord, Data, Typeable)
575deriving instance Binary Const
576deriving instance NFData Const
579isTypeConst :: Const -> Bool
580isTypeConst (AType _) = True
581isTypeConst StrType = True
582isTypeConst ManagedPtrType = True
583isTypeConst BufferType = True
584isTypeConst WorldType = True
585isTypeConst PtrType = True
586isTypeConst VoidType = True
589instance Sized Const where
592instance Pretty Const OutputAnnotation where
593 pretty (I i) = text . show $ i
594 pretty (BI i) = text . show $ i
595 pretty (Fl f) = text . show $ f
596 pretty (Ch c) = text . show $ c
597 pretty (Str s) = text s
598 pretty (AType a) = pretty a
599 pretty StrType = text "String"
600 pretty TheWorld = text "%theWorld"
601 pretty WorldType = text "prim__World"
602 pretty BufferType = text "prim__UnsafeBuffer"
603 pretty PtrType = text "Ptr"
604 pretty ManagedPtrType = text "Ptr"
605 pretty VoidType = text "Void"
606 pretty Forgot = text "Forgot"
607 pretty (B8 w) = text . show $ w
608 pretty (B16 w) = text . show $ w
609 pretty (B32 w) = text . show $ w
610 pretty (B64 w) = text . show $ w
612-- | Determines whether the input constant represents a type
613constIsType :: Const -> Bool
614constIsType (I _) = False
615constIsType (BI _) = False
616constIsType (Fl _) = False
617constIsType (Ch _) = False
618constIsType (Str _) = False
619constIsType (B8 _) = False
620constIsType (B16 _) = False
621constIsType (B32 _) = False
622constIsType (B64 _) = False
623constIsType (B8V _) = False
624constIsType (B16V _) = False
625constIsType (B32V _) = False
626constIsType (B64V _) = False
629-- | Get the docstring for a Const
630constDocs :: Const -> String
631constDocs c@(AType (ATInt ITBig)) = "Arbitrary-precision integers"
632constDocs c@(AType (ATInt ITNative)) = "Fixed-precision integers of undefined size"
633constDocs c@(AType (ATInt ITChar)) = "Characters in some unspecified encoding"
634constDocs c@(AType ATFloat) = "Double-precision floating-point numbers"
635constDocs StrType = "Strings in some unspecified encoding"
636constDocs PtrType = "Foreign pointers"
637constDocs ManagedPtrType = "Managed pointers"
638constDocs BufferType = "Copy-on-write buffers"
639constDocs c@(AType (ATInt (ITFixed IT8))) = "Eight bits (unsigned)"
640constDocs c@(AType (ATInt (ITFixed IT16))) = "Sixteen bits (unsigned)"
641constDocs c@(AType (ATInt (ITFixed IT32))) = "Thirty-two bits (unsigned)"
642constDocs c@(AType (ATInt (ITFixed IT64))) = "Sixty-four bits (unsigned)"
643constDocs c@(AType (ATInt (ITVec IT8 16))) = "Vectors of sixteen eight-bit values"
644constDocs c@(AType (ATInt (ITVec IT16 8))) = "Vectors of eight sixteen-bit values"
645constDocs c@(AType (ATInt (ITVec IT32 4))) = "Vectors of four thirty-two-bit values"
646constDocs c@(AType (ATInt (ITVec IT64 2))) = "Vectors of two sixty-four-bit values"
647constDocs (Fl f) = "A float"
648constDocs (I i) = "A fixed-precision integer"
649constDocs (BI i) = "An arbitrary-precision integer"
650constDocs (Str s) = "A string of length " ++ show (length s)
651constDocs (Ch c) = "A character"
652constDocs (B8 w) = "The eight-bit value 0x" ++
653 showIntAtBase 16 intToDigit w ""
654constDocs (B16 w) = "The sixteen-bit value 0x" ++
655 showIntAtBase 16 intToDigit w ""
656constDocs (B32 w) = "The thirty-two-bit value 0x" ++
657 showIntAtBase 16 intToDigit w ""
658constDocs (B64 w) = "The sixty-four-bit value 0x" ++
659 showIntAtBase 16 intToDigit w ""
660constDocs (B8V v) = "A vector of eight-bit values"
661constDocs (B16V v) = "A vector of sixteen-bit values"
662constDocs (B32V v) = "A vector of thirty-two-bit values"
663constDocs (B64V v) = "A vector of sixty-four-bit values"
664constDocs prim = "Undocumented"
666data Universe = NullType | UniqueType | AllTypes
667 deriving (Eq, Ord, Data, Typeable)
669instance Show Universe where
670 show UniqueType = "UniqueType"
671 show NullType = "NullType"
672 show AllTypes = "Type*"
675 | RBind Name (Binder Raw) Raw
681 deriving (Show, Eq, Data, Typeable)
683instance Sized Raw where
685 size (RBind name bind right) = 1 + size bind + size right
686 size (RApp left right) = 1 + size left + size right
689 size (RForce raw) = 1 + size raw
690 size (RConstant const) = size const
692instance Pretty Raw OutputAnnotation where
696deriving instance Binary Raw
697deriving instance NFData Raw
700data ImplicitInfo = Impl { tcinstance :: Bool }
701 deriving (Show, Eq, Ord, Data, Typeable)
704deriving instance Binary ImplicitInfo
705deriving instance NFData ImplicitInfo
708-- The type parameter `b` will normally be something like `TT Name` or just
709-- `Raw`. We do not make a type-level distinction between TT terms that happen
710-- to be TT types and TT terms that are not TT types.
711-- | All binding forms are represented in a uniform fashion. This type only represents
712-- the types of bindings (and their values, if any); the attached identifiers are part
713-- of the 'Bind' constructor for the 'TT' type.
714data Binder b = Lam { binderTy :: !b {-^ type annotation for bound variable-}}
715 | Pi { binderImpl :: Maybe ImplicitInfo,
718 {-^ A binding that occurs in a function type expression, e.g. @(x:Int) -> ...@
719 The 'binderImpl' flag says whether it was a scoped implicit
720 (i.e. forall bound) in the high level Idris, but otherwise
721 has no relevance in TT. -}
722 | Let { binderTy :: !b,
723 binderVal :: b {-^ value for bound variable-}}
724 -- ^ A binding that occurs in a @let@ expression
725 | NLet { binderTy :: !b,
727 | Hole { binderTy :: !b}
728 | GHole { envlen :: Int,
730 | Guess { binderTy :: !b,
732 | PVar { binderTy :: !b }
733 -- ^ A pattern variable
734 | PVTy { binderTy :: !b }
735 deriving (Show, Eq, Ord, Functor, Foldable, Traversable, Data, Typeable)
737deriving instance Binary Binder
738deriving instance NFData Binder
741instance Sized a => Sized (Binder a) where
742 size (Lam ty) = 1 + size ty
743 size (Pi _ ty _) = 1 + size ty
744 size (Let ty val) = 1 + size ty + size val
745 size (NLet ty val) = 1 + size ty + size val
746 size (Hole ty) = 1 + size ty
747 size (GHole _ ty) = 1 + size ty
748 size (Guess ty val) = 1 + size ty + size val
749 size (PVar ty) = 1 + size ty
750 size (PVTy ty) = 1 + size ty
752fmapMB :: Monad m => (a -> m b) -> Binder a -> m (Binder b)
753fmapMB f (Let t v) = liftM2 Let (f t) (f v)
754fmapMB f (NLet t v) = liftM2 NLet (f t) (f v)
755fmapMB f (Guess t v) = liftM2 Guess (f t) (f v)
756fmapMB f (Lam t) = liftM Lam (f t)
757fmapMB f (Pi i t k) = liftM2 (Pi i) (f t) (f k)
758fmapMB f (Hole t) = liftM Hole (f t)
759fmapMB f (GHole i t) = liftM (GHole i) (f t)
760fmapMB f (PVar t) = liftM PVar (f t)
761fmapMB f (PVTy t) = liftM PVTy (f t)
763raw_apply :: Raw -> [Raw] -> Raw
765raw_apply f (a : as) = raw_apply (RApp f a) as
767raw_unapply :: Raw -> (Raw, [Raw])
768raw_unapply t = ua [] t where
769 ua args (RApp f a) = ua (a:args) f
770 ua args t = (t, args)
772-- WELL TYPED TERMS ---------------------------------------------------------
774-- | Universe expressions for universe checking
775data UExp = UVar Int -- ^ universe variable
776 | UVal Int -- ^ explicit universe level
777 deriving (Eq, Ord, Data, Typeable)
779deriving instance NFData UExp
782instance Sized UExp where
785instance Show UExp where
786 show (UVar x) | x < 26 = [toEnum (x + fromEnum 'a')]
787 | otherwise = toEnum ((x `mod` 26) + fromEnum 'a') : show (x `div` 26)
788 show (UVal x) = show x
789-- show (UMax l r) = "max(" ++ show l ++ ", " ++ show r ++")"
791-- | Universe constraints
792data UConstraint = ULT UExp UExp -- ^ Strictly less than
793 | ULE UExp UExp -- ^ Less than or equal to
796data ConstraintFC = ConstraintFC { uconstraint :: UConstraint,
800instance Eq ConstraintFC where
801 x == y = uconstraint x == uconstraint y
803instance Ord ConstraintFC where
804 compare x y = compare (uconstraint x) (uconstraint y)
806instance Show UConstraint where
807 show (ULT x y) = show x ++ " < " ++ show y
808 show (ULE x y) = show x ++ " <= " ++ show y
810type UCs = (Int, [UConstraint])
814 | DCon {nt_tag :: Int, nt_arity :: Int, nt_unique :: Bool} -- ^ Data constructor
815 | TCon {nt_tag :: Int, nt_arity :: Int} -- ^ Type constructor
816 deriving (Show, Ord, Data, Typeable)
818deriving instance Binary NameType
819deriving instance NFData NameType
822instance Sized NameType where
825instance Pretty NameType OutputAnnotation where
828instance Eq NameType where
829 Bound == Bound = True
831 DCon _ a _ == DCon _ b _ = (a == b) -- ignore tag
832 TCon _ a == TCon _ b = (a == b) -- ignore tag
835-- | Terms in the core language. The type parameter is the type of
836-- identifiers used for bindings and explicit named references;
837-- usually we use @TT 'Name'@.
838data TT n = P NameType n (TT n) -- ^ named references with type
839 -- (P for "Parameter", motivated by McKinna and Pollack's
840 -- Pure Type Systems Formalized)
841 | V !Int -- ^ a resolved de Bruijn-indexed variable
842 | Bind n !(Binder (TT n)) (TT n) -- ^ a binding
843 | App !(TT n) (TT n) -- ^ function, function type, arg
844 | Constant Const -- ^ constant
845 | Proj (TT n) !Int -- ^ argument projection; runtime only
846 -- (-1) is a special case for 'subtract one from BI'
847 | Erased -- ^ an erased term
848 | Impossible -- ^ special case for totality checking
849 | TType UExp -- ^ the type of types at some level
850 | UType Universe -- ^ Uniqueness type universe (disjoint from TType)
851 deriving (Ord, Functor, Data, Typeable)
853deriving instance Binary TT
854deriving instance NFData TT
857class TermSize a where
858 termsize :: Name -> a -> Int
860instance TermSize a => TermSize [a] where
862 termsize n (x : xs) = termsize n x + termsize n xs
864instance TermSize (TT Name) where
865 termsize n (P _ n' _)
866 | n' == n = 1000000 -- recursive => really big
869 -- for `Bind` terms, we can erroneously declare a term
870 -- "recursive => really big" if the name of the bound
871 -- variable is the same as the name we're using
872 -- So generate a different name in that case.
873 termsize n (Bind n' (Let t v) sc)
874 = let rn = if n == n' then sMN 0 "noname" else n in
875 termsize rn v + termsize rn sc
876 termsize n (Bind n' b sc)
877 = let rn = if n == n' then sMN 0 "noname" else n in
879 termsize n (App f a) = termsize n f + termsize n a
880 termsize n (Proj t i) = termsize n t
883instance Sized a => Sized (TT a) where
884 size (P name n trm) = 1 + size name + size n + size trm
886 size (Bind nm binder bdy) = 1 + size nm + size binder + size bdy
887 size (App l r) = 1 + size l + size r
888 size (Constant c) = size c
890 size (TType u) = 1 + size u
892instance Pretty a o => Pretty (TT a) o where
893 pretty _ = text "test"
895type EnvTT n = [(n, Binder (TT n))]
897data Datatype n = Data { d_typename :: n,
901 d_cons :: [(n, TT n)] }
902 deriving (Show, Functor, Eq)
904instance Eq n => Eq (TT n) where
905 (==) (P xt x _) (P yt y _) = x == y
906 (==) (V x) (V y) = x == y
907 (==) (Bind _ xb xs) (Bind _ yb ys) = xs == ys && xb == yb
908 (==) (App fx ax) (App fy ay) = ax == ay && fx == fy
909 (==) (TType _) (TType _) = True -- deal with constraints later
910 (==) (Constant x) (Constant y) = x == y
911 (==) (Proj x i) (Proj y j) = x == y && i == j
916-- * A few handy operations on well typed terms:
918-- | A term is injective iff it is a data constructor, type constructor,
919-- constant, the type Type, pi-binding, or an application of an injective
921isInjective :: TT n -> Bool
922isInjective (P (DCon _ _ _) _ _) = True
923isInjective (P (TCon _ _) _ _) = True
924isInjective (Constant _) = True
925isInjective (TType x) = True
926isInjective (Bind _ (Pi _ _ _) sc) = True
927isInjective (App f a) = isInjective f
930-- | Count the number of instances of a de Bruijn index in a term
931vinstances :: Int -> TT n -> Int
932vinstances i (V x) | i == x = 1
933vinstances i (App f a) = vinstances i f + vinstances i a
934vinstances i (Bind x b sc) = instancesB b + vinstances (i + 1) sc
935 where instancesB (Let t v) = vinstances i v
939-- | Replace the outermost (index 0) de Bruijn variable with the given term
940instantiate :: TT n -> TT n -> TT n
941instantiate e = subst 0 where
942 subst i (P nt x ty) = P nt x (subst i ty)
943 subst i (V x) | i == x = e
944 subst i (Bind x b sc) = Bind x (fmap (subst i) b) (subst (i+1) sc)
945 subst i (App f a) = App (subst i f) (subst i a)
946 subst i (Proj x idx) = Proj (subst i x) idx
949-- | As 'instantiate', but also decrement the indices of all de Bruijn variables
950-- remaining in the term, so that there are no more references to the variable
951-- that has been substituted.
952substV :: TT n -> TT n -> TT n
953substV x tm = dropV 0 (instantiate x tm) where
954 subst i (P nt x ty) = P nt x (subst i ty)
955 dropV i (V x) | x > i = V (x - 1)
957 dropV i (Bind x b sc) = Bind x (fmap (dropV i) b) (dropV (i+1) sc)
958 dropV i (App f a) = App (dropV i f) (dropV i a)
959 dropV i (Proj x idx) = Proj (dropV i x) idx
962-- | Replace all non-free de Bruijn references in the given term with references
963-- to the name of their binding.
964explicitNames :: TT n -> TT n
965explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
967 (explicitNames (instantiate
968 (P Bound x (binderTy b')) sc))
969explicitNames (App f a) = App (explicitNames f) (explicitNames a)
970explicitNames (Proj x idx) = Proj (explicitNames x) idx
973-- | Replace references to the given 'Name'-like id with references to
975pToV :: Eq n => n -> TT n -> TT n
977pToV' n i (P _ x _) | n == x = V i
978pToV' n i (Bind x b sc)
979-- We can assume the inner scope has been pToVed already, so continue to
980-- resolve names from the *outer* scope which may happen to have the same id.
981 | n == x = Bind x (fmap (pToV' n i) b) sc
982 | otherwise = Bind x (fmap (pToV' n i) b) (pToV' n (i+1) sc)
983pToV' n i (App f a) = App (pToV' n i f) (pToV' n i a)
984pToV' n i (Proj t idx) = Proj (pToV' n i t) idx
987-- increase de Bruijn indices, as if a binder has been added
988addBinder :: TT n -> TT n
991 ab top (V i) | i >= top = V (i + 1)
993 ab top (Bind x b sc) = Bind x (fmap (ab top) b) (ab (top + 1) sc)
994 ab top (App f a) = App (ab top f) (ab top a)
995 ab top (Proj t idx) = Proj (ab top t) idx
998-- | Convert several names. First in the list comes out as V 0
999pToVs :: Eq n => [n] -> TT n -> TT n
1000pToVs ns tm = pToVs' ns tm 0 where
1002 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
1004-- | Replace de Bruijn indices in the given term with explicit references to
1005-- the names of the bindings they refer to. It is an error if the given term
1006-- contains free de Bruijn indices.
1008vToP = vToP' [] where
1009 vToP' env (V i) = let (n, b) = (env !! i) in
1010 P Bound n (binderTy b)
1011 vToP' env (Bind n b sc) = let b' = fmap (vToP' env) b in
1012 Bind n b' (vToP' ((n, b'):env) sc)
1013 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
1016-- | Replace every non-free reference to the name of a binding in
1017-- the given term with a de Bruijn index.
1018finalise :: Eq n => TT n -> TT n
1019finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
1020finalise (App f a) = App (finalise f) (finalise a)
1023-- Once we've finished checking everything about a term we no longer need
1024-- the type on the 'P' so erase it so save memory
1026pEraseType :: TT n -> TT n
1027pEraseType (P nt t _) = P nt t Erased
1028pEraseType (App f a) = App (pEraseType f) (pEraseType a)
1029pEraseType (Bind n b sc) = Bind n (fmap pEraseType b) (pEraseType sc)
1032-- | As 'instantiate', but in addition to replacing @'V' 0@,
1033-- replace references to the given 'Name'-like id.
1034subst :: Eq n => n {-^ The id to replace -} ->
1035 TT n {-^ The replacement term -} ->
1036 TT n {-^ The term to replace in -} ->
1038-- subst n v tm = instantiate v (pToV n tm)
1039subst n v tm = fst $ subst' 0 tm
1041 -- keep track of updates to save allocations - this is a big win on
1042 -- large terms in particular
1043 -- ('Maybe' would be neater here, but >>= is not the right combinator.
1044 -- Feel free to tidy up, as long as it still saves allocating when no
1045 -- substitution happens...)
1046 subst' i (V x) | i == x = (v, True)
1047 subst' i (P _ x _) | n == x = (v, True)
1048 subst' i t@(P nt x ty)
1049 = let (ty', ut) = subst' i ty in
1050 if ut then (P nt x ty', True) else (t, False)
1051 subst' i t@(Bind x b sc) | x /= n
1052 = let (b', ub) = substB' i b
1053 (sc', usc) = subst' (i+1) sc in
1054 if ub || usc then (Bind x b' sc', True) else (t, False)
1055 subst' i t@(App f a) = let (f', uf) = subst' i f
1056 (a', ua) = subst' i a in
1057 if uf || ua then (App f' a', True) else (t, False)
1058 subst' i t@(Proj x idx) = let (x', u) = subst' i x in
1059 if u then (Proj x' idx, u) else (t, False)
1060 subst' i t = (t, False)
1062 substB' i b@(Let t v) = let (t', ut) = subst' i t
1063 (v', uv) = subst' i v in
1064 if ut || uv then (Let t' v', True)
1066 substB' i b@(Guess t v) = let (t', ut) = subst' i t
1067 (v', uv) = subst' i v in
1068 if ut || uv then (Guess t' v', True)
1070 substB' i b = let (ty', u) = subst' i (binderTy b) in
1071 if u then (b { binderTy = ty' }, u) else (b, False)
1073-- If there are no Vs in the term (i.e. in proof state)
1074psubst :: Eq n => n -> TT n -> TT n -> TT n
1075psubst n v tm = s' 0 tm where
1076 s' i (V x) | x > i = V (x - 1)
1079 s' i (P _ x _) | n == x = v
1080 s' i (Bind x b sc) | n == x = Bind x (fmap (s' i) b) sc
1081 | otherwise = Bind x (fmap (s' i) b) (s' (i+1) sc)
1082 s' i (App f a) = App (s' i f) (s' i a)
1083 s' i (Proj t idx) = Proj (s' i t) idx
1086-- | As 'subst', but takes a list of (name, substitution) pairs instead
1087-- of a single name and substitution
1088substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
1090substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
1092-- | Replaces all terms equal (in the sense of @(==)@) to
1093-- the old term with the new term.
1094substTerm :: Eq n => TT n {-^ Old term -} ->
1095 TT n {-^ New term -} ->
1096 TT n {-^ template term -}
1098substTerm old new = st where
1099 st t | t == old = new
1100 st (App f a) = App (st f) (st a)
1101 st (Bind x b sc) = Bind x (fmap st b) (st sc)
1104-- | Return number of occurrences of V 0 or bound name i the term
1105occurrences :: Eq n => n -> TT n -> Int
1106occurrences n t = execState (no' 0 t) 0
1108 no' i (V x) | i == x = do num <- get; put (num + 1)
1109 no' i (P Bound x _) | n == x = do num <- get; put (num + 1)
1110 no' i (Bind n b sc) = do noB' i b; no' (i+1) sc
1111 where noB' i (Let t v) = do no' i t; no' i v
1112 noB' i (Guess t v) = do no' i t; no' i v
1113 noB' i b = no' i (binderTy b)
1114 no' i (App f a) = do no' i f; no' i a
1115 no' i (Proj x _) = no' i x
1118-- | Returns true if V 0 and bound name n do not occur in the term
1119noOccurrence :: Eq n => n -> TT n -> Bool
1120noOccurrence n t = no' 0 t
1122 no' i (V x) = not (i == x)
1123 no' i (P Bound x _) = not (n == x)
1124 no' i (Bind n b sc) = noB' i b && no' (i+1) sc
1125 where noB' i (Let t v) = no' i t && no' i v
1126 noB' i (Guess t v) = no' i t && no' i v
1127 noB' i b = no' i (binderTy b)
1128 no' i (App f a) = no' i f && no' i a
1129 no' i (Proj x _) = no' i x
1132-- | Returns all names used free in the term
1133freeNames :: Eq n => TT n -> [n]
1134freeNames t = nub $ freeNames' t
1136 freeNames' (P _ n _) = [n]
1137 freeNames' (Bind n (Let t v) sc) = freeNames' v ++ (freeNames' sc \\ [n])
1139 freeNames' (Bind n b sc) = freeNames' (binderTy b) ++ (freeNames' sc \\ [n])
1140 freeNames' (App f a) = freeNames' f ++ freeNames' a
1141 freeNames' (Proj x i) = freeNames' x
1144-- | Return the arity of a (normalised) type
1146arity (Bind n (Pi _ t _) sc) = 1 + arity sc
1149-- | Deconstruct an application; returns the function and a list of arguments
1150unApply :: TT n -> (TT n, [TT n])
1151unApply t = ua [] t where
1152 ua args (App f a) = ua (a:args) f
1153 ua args t = (t, args)
1155-- | Returns a term representing the application of the first argument
1156-- (a function) to every element of the second argument.
1157mkApp :: TT n -> [TT n] -> TT n
1159mkApp f (a:as) = mkApp (App f a) as
1161unList :: Term -> Maybe [Term]
1162unList tm = case unApply tm of
1163 (nil, [_]) -> Just []
1164 (cons, ([_, x, xs])) ->
1165 do rest <- unList xs
1167 (f, args) -> Nothing
1169-- | Cast a 'TT' term to a 'Raw' value, discarding universe information and
1170-- the types of named references and replacing all de Bruijn indices
1171-- with the corresponding name. It is an error if there are free de
1173forget :: TT Name -> Raw
1174forget tm = forgetEnv [] tm
1176safeForget :: TT Name -> Maybe Raw
1177safeForget tm = safeForgetEnv [] tm
1179forgetEnv :: [Name] -> TT Name -> Raw
1180forgetEnv env tm = case safeForgetEnv env tm of
1182 Nothing -> error $ "Scope error in " ++ show tm
1185safeForgetEnv :: [Name] -> TT Name -> Maybe Raw
1186safeForgetEnv env (P _ n _) = Just $ Var n
1187safeForgetEnv env (V i) | i < length env = Just $ Var (env !! i)
1188 | otherwise = Nothing
1189safeForgetEnv env (Bind n b sc)
1190 = do let n' = uniqueName n env
1191 b' <- safeForgetEnvB env b
1192 sc' <- safeForgetEnv (n':env) sc
1193 Just $ RBind n' b' sc'
1194 where safeForgetEnvB env (Let t v) = liftM2 Let (safeForgetEnv env t)
1195 (safeForgetEnv env v)
1196 safeForgetEnvB env b = do ty' <- safeForgetEnv env (binderTy b)
1197 Just $ fmap (\_ -> ty') b
1198safeForgetEnv env (App f a) = liftM2 RApp (safeForgetEnv env f) (safeForgetEnv env a)
1199safeForgetEnv env (Constant c) = Just $ RConstant c
1200safeForgetEnv env (TType i) = Just RType
1201safeForgetEnv env (UType u) = Just $ RUType u
1202safeForgetEnv env Erased = Just $ RConstant Forgot
1204-- | Introduce a 'Bind' into the given term for each element of the
1205-- given list of (name, binder) pairs.
1206bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
1208bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
1210-- | Like 'bindAll', but the 'Binder's are 'TT' terms instead.
1211-- The first argument is a function to map @TT@ terms to @Binder@s.
1212-- This function might often be something like 'Lam', which directly
1213-- constructs a @Binder@ from a @TT@ term.
1214bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
1215bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
1217-- | Return a list of pairs of the names of the outermost 'Pi'-bound
1218-- variables in the given term, together with their types.
1219getArgTys :: TT n -> [(n, TT n)]
1220getArgTys (Bind n (PVar _) sc) = getArgTys sc
1221getArgTys (Bind n (PVTy _) sc) = getArgTys sc
1222getArgTys (Bind n (Pi _ t _) sc) = (n, t) : getArgTys sc
1225getRetTy :: TT n -> TT n
1226getRetTy (Bind n (PVar _) sc) = getRetTy sc
1227getRetTy (Bind n (PVTy _) sc) = getRetTy sc
1228getRetTy (Bind n (Pi _ _ _) sc) = getRetTy sc
1231uniqueNameFrom :: [Name] -> [Name] -> Name
1232uniqueNameFrom [] hs = uniqueName (nextName (sUN "x")) hs
1233uniqueNameFrom (s : supply) hs
1234 | s `elem` hs = uniqueNameFrom supply hs
1237uniqueName :: Name -> [Name] -> Name
1238uniqueName n hs | n `elem` hs = uniqueName (nextName n) hs
1241uniqueNameSet :: Name -> Set Name -> Name
1242uniqueNameSet n hs | n `member` hs = uniqueNameSet (nextName n) hs
1245uniqueBinders :: [Name] -> TT Name -> TT Name
1246uniqueBinders ns = ubSet (fromList ns) where
1247 ubSet ns (Bind n b sc)
1248 = let n' = uniqueNameSet n ns
1249 ns' = insert n' ns in
1250 Bind n' (fmap (ubSet ns') b) (ubSet ns' sc)
1251 ubSet ns (App f a) = App (ubSet ns f) (ubSet ns a)
1255nextName (NS x s) = NS (nextName x) s
1256nextName (MN i n) = MN (i+1) n
1257nextName (UN x) = let (num', nm') = T.span isDigit (T.reverse x)
1259 num = readN (T.reverse num') in
1260 UN (nm `T.append` txt (show (num+1)))
1262 readN x | not (T.null x) = read (T.unpack x)
1264nextName (SN x) = SN (nextName' x)
1266 nextName' (WhereN i f x) = WhereN i f (nextName x)
1267 nextName' (WithN i n) = WithN i (nextName n)
1268 nextName' (InstanceN n ns) = InstanceN (nextName n) ns
1269 nextName' (ParentN n ns) = ParentN (nextName n) ns
1270 nextName' (CaseN n) = CaseN (nextName n)
1271 nextName' (ElimN n) = ElimN (nextName n)
1272 nextName' (MethodN n) = MethodN (nextName n)
1273 nextName' (InstanceCtorN n) = InstanceCtorN (nextName n)
1278type Env = EnvTT Name
1280-- | an environment with de Bruijn indices 'normalised' so that they all refer to
1283newtype WkEnvTT n = Wk (EnvTT n)
1284type WkEnv = WkEnvTT Name
1286instance (Eq n, Show n) => Show (TT n) where
1287 show t = showEnv [] t
1289itBitsName IT8 = "Bits8"
1290itBitsName IT16 = "Bits16"
1291itBitsName IT32 = "Bits32"
1292itBitsName IT64 = "Bits64"
1294instance Show Const where
1296 show (BI i) = show i
1297 show (Fl f) = show f
1298 show (Ch c) = show c
1299 show (Str s) = show s
1300 show (B8 x) = show x
1301 show (B16 x) = show x
1302 show (B32 x) = show x
1303 show (B64 x) = show x
1304 show (B8V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
1305 show (B16V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
1306 show (B32V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
1307 show (B64V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
1308 show (AType ATFloat) = "Float"
1309 show (AType (ATInt ITBig)) = "Integer"
1310 show (AType (ATInt ITNative)) = "Int"
1311 show (AType (ATInt ITChar)) = "Char"
1312 show (AType (ATInt (ITFixed it))) = itBitsName it
1313 show (AType (ATInt (ITVec it c))) = itBitsName it ++ "x" ++ show c
1314 show TheWorld = "prim__TheWorld"
1315 show WorldType = "prim__WorldType"
1316 show StrType = "String"
1317 show BufferType = "prim__UnsafeBuffer"
1318 show PtrType = "Ptr"
1319 show ManagedPtrType = "ManagedPtr"
1320 show VoidType = "Void"
1322showEnv :: (Eq n, Show n) => EnvTT n -> TT n -> String
1323showEnv env t = showEnv' env t False
1324showEnvDbg env t = showEnv' env t True
1326prettyEnv env t = prettyEnv' env t False
1328 prettyEnv' env t dbg = prettySe 10 env t dbg
1330 bracket outer inner p
1331 | inner > outer = lparen <> p <> rparen
1334 prettySe p env (P nt n t) debug =
1337 lbracket <+> pretty nt <+> colon <+> prettySe 10 env t debug <+> rbracket
1340 prettySe p env (V i) debug
1343 text . show . fst $ env!!i
1345 lbracket <+> text (show i) <+> rbracket
1346 | otherwise = text "unbound" <+> text (show i) <+> text "!"
1347 prettySe p env (Bind n b@(Pi _ t _) sc) debug
1348 | noOccurrence n sc && not debug =
1349 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
1350 prettySe p env (Bind n b sc) debug =
1351 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
1352 prettySe p env (App f a) debug =
1353 bracket p 1 $ prettySe 1 env f debug <+> prettySe 0 env a debug
1354 prettySe p env (Proj x i) debug =
1355 prettySe 1 env x debug <+> text ("!" ++ show i)
1356 prettySe p env (Constant c) debug = pretty c
1357 prettySe p env Erased debug = text "[_]"
1358 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
1360 -- Render a `Binder` and its name
1361 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
1362 prettySb env n (Hole t) = prettyB env "?defer" "." n t
1363 prettySb env n (Pi _ t _) = prettyB env "(" ") ->" n t
1364 prettySb env n (PVar t) = prettyB env "pat" "." n t
1365 prettySb env n (PVTy t) = prettyB env "pty" "." n t
1366 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
1367 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
1369 -- Use `op` and `sc` to delimit `n` (a binding name) and its type
1371 -- e.g. "λx : Int =>" for the Lam case
1372 prettyB env op sc n t debug =
1373 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
1375 -- Like `prettyB`, but handle the bindings that have values in addition
1376 -- to names and types
1377 prettyBv env op sc n t v debug =
1378 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
1379 prettySe 10 env v debug <> text sc
1382showEnv' env t dbg = se 10 env t where
1383 se p env (P nt n t) = show n
1384 ++ if dbg then "{" ++ show nt ++ " : " ++ se 10 env t ++ "}" else ""
1385 se p env (V i) | i < length env && i >= 0
1386 = (show $ fst $ env!!i) ++
1387 if dbg then "{" ++ show i ++ "}" else ""
1388 | otherwise = "!!V " ++ show i ++ "!!"
1389 se p env (Bind n b@(Pi (Just _) t k) sc)
1390 = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
1391 se p env (Bind n b@(Pi _ t k) sc)
1392 | noOccurrence n sc && not dbg = bracket p 2 $ se 1 env t ++ arrow k ++ se 10 ((n,b):env) sc
1393 where arrow (TType _) = " -> "
1394 arrow u = " [" ++ show u ++ "] -> "
1395 se p env (Bind n b sc) = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
1396 se p env (App f a) = bracket p 1 $ se 1 env f ++ " " ++ se 0 env a
1397 se p env (Proj x i) = se 1 env x ++ "!" ++ show i
1398 se p env (Constant c) = show c
1399 se p env Erased = "[__]"
1400 se p env Impossible = "[impossible]"
1401 se p env (TType i) = "Type " ++ show i
1402 se p env (UType u) = show u
1404 sb env n (Lam t) = showb env "\\ " " => " n t
1405 sb env n (Hole t) = showb env "? " ". " n t
1406 sb env n (GHole i t) = showb env "?defer " ". " n t
1407 sb env n (Pi (Just _) t _) = showb env "{" "} -> " n t
1408 sb env n (Pi _ t _) = showb env "(" ") -> " n t
1409 sb env n (PVar t) = showb env "pat " ". " n t
1410 sb env n (PVTy t) = showb env "pty " ". " n t
1411 sb env n (Let t v) = showbv env "let " " in " n t v
1412 sb env n (Guess t v) = showbv env "?? " " in " n t v
1414 showb env op sc n t = op ++ show n ++ " : " ++ se 10 env t ++ sc
1415 showbv env op sc n t v = op ++ show n ++ " : " ++ se 10 env t ++ " = " ++
1418 bracket outer inner str | inner > outer = "(" ++ str ++ ")"
1421-- | Check whether a term has any holes in it - impure if so
1422pureTerm :: TT Name -> Bool
1423pureTerm (App f a) = pureTerm f && pureTerm a
1424pureTerm (Bind n b sc) = notClassName n && pureBinder b && pureTerm sc where
1425 pureBinder (Hole _) = False
1426 pureBinder (Guess _ _) = False
1427 pureBinder (Let t v) = pureTerm t && pureTerm v
1428 pureBinder t = pureTerm (binderTy t)
1430 notClassName (MN _ c) | c == txt "class" = False
1431 notClassName _ = True
1435-- | Weaken a term by adding i to each de Bruijn index (i.e. lift it over i bindings)
1436weakenTm :: Int -> TT n -> TT n
1437weakenTm i t = wk i 0 t
1438 where wk i min (V x) | x >= min = V (i + x)
1439 wk i m (App f a) = App (wk i m f) (wk i m a)
1440 wk i m (Bind x b sc) = Bind x (wkb i m b) (wk i (m + 1) sc)
1442 wkb i m t = fmap (wk i m) t
1444-- | Weaken an environment so that all the de Bruijn indices are correct according
1445-- to the latest bound variable
1447weakenEnv :: EnvTT n -> EnvTT n
1448weakenEnv env = wk (length env - 1) env
1450 wk i ((n, b) : bs) = (n, weakenTmB i b) : wk (i - 1) bs
1451 weakenTmB i (Let t v) = Let (weakenTm i t) (weakenTm i v)
1452 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
1453 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
1455-- | Weaken every term in the environment by the given amount
1456weakenTmEnv :: Int -> EnvTT n -> EnvTT n
1457weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
1459-- | Gather up all the outer 'PVar's and 'Hole's in an expression and reintroduce
1460-- them in a canonical order
1461orderPats :: Term -> Term
1462orderPats tm = op [] tm
1464 op [] (App f a) = App f (op [] a) -- for Infer terms
1466 op ps (Bind n (PVar t) sc) = op ((n, PVar t) : ps) sc
1467 op ps (Bind n (Hole t) sc) = op ((n, Hole t) : ps) sc
1468 op ps (Bind n (Pi i t k) sc) = op ((n, Pi i t k) : ps) sc
1469 op ps sc = bindAll (sortP ps) sc
1471 sortP ps = pick [] (reverse ps)
1473 pick acc [] = reverse acc
1474 pick acc ((n, t) : ps) = pick (insert n t acc) ps
1476 insert n t [] = [(n, t)]
1477 insert n t ((n',t') : ps)
1478 | n `elem` (refsIn (binderTy t') ++
1479 concatMap refsIn (map (binderTy . snd) ps))
1480 = (n', t') : insert n t ps
1481 | otherwise = (n,t):(n',t'):ps
1483refsIn :: TT Name -> [Name]
1484refsIn (P _ n _) = [n]
1485refsIn (Bind n b t) = nub $ nb b ++ refsIn t
1486 where nb (Let t v) = nub (refsIn t) ++ nub (refsIn v)
1487 nb (Guess t v) = nub (refsIn t) ++ nub (refsIn v)
1488 nb t = refsIn (binderTy t)
1489refsIn (App f a) = nub (refsIn f ++ refsIn a)
1492-- Make sure all the pattern bindings are as far out as possible
1493liftPats :: Term -> Term
1494liftPats tm = let (tm', ps) = runState (getPats tm) [] in
1495 orderPats $ bindPats (reverse ps) tm'
1498 bindPats ((n, t):ps) tm
1499 | n `notElem` map fst ps = Bind n (PVar t) (bindPats ps tm)
1500 | otherwise = bindPats ps tm
1502 getPats :: Term -> State [(Name, Type)] Term
1503 getPats (Bind n (PVar t) sc) = do ps <- get
1506 getPats (Bind n (Guess t v) sc) = do t' <- getPats t
1509 return (Bind n (Guess t' v') sc')
1510 getPats (Bind n (Let t v) sc) = do t' <- getPats t
1513 return (Bind n (Let t' v') sc')
1514 getPats (Bind n (Pi i t k) sc) = do t' <- getPats t
1517 return (Bind n (Pi i t' k') sc')
1518 getPats (Bind n (Lam t) sc) = do t' <- getPats t
1520 return (Bind n (Lam t') sc')
1521 getPats (Bind n (Hole t) sc) = do t' <- getPats t
1523 return (Bind n (Hole t') sc')
1526 getPats (App f a) = do f' <- getPats f
1529 getPats t = return t
1531allTTNames :: Eq n => TT n -> [n]
1532allTTNames = nub . allNamesIn
1533 where allNamesIn (P _ n _) = [n]
1534 allNamesIn (Bind n b t) = [n] ++ nb b ++ allNamesIn t
1535 where nb (Let t v) = allNamesIn t ++ allNamesIn v
1536 nb (Guess t v) = allNamesIn t ++ allNamesIn v
1537 nb t = allNamesIn (binderTy t)
1538 allNamesIn (App f a) = allNamesIn f ++ allNamesIn a
1542-- | Pretty-print a term
1543pprintTT :: [Name] -- ^ The bound names (for highlighting and de Bruijn indices)
1544 -> TT Name -- ^ The term to be printed
1545 -> Doc OutputAnnotation
1546pprintTT bound tm = pp startPrec bound tm
1552 pp p bound (P Bound n ty) = annotate (AnnBoundName n False) (text $ show n)
1553 pp p bound (P nt n ty) = annotate (AnnName n Nothing Nothing Nothing)
1556 | i < length bound = let n = bound !! i
1557 in annotate (AnnBoundName n False) (text $ show n)
1558 | otherwise = text ("{{{V" ++ show i ++ "}}}")
1559 pp p bound (Bind n b sc) = ppb p bound n b $
1560 pp startPrec (n:bound) sc
1561 pp p bound (App tm1 tm2) =
1562 bracket p appPrec . group . hang 2 $
1563 pp appPrec bound tm1 <> line <>
1564 pp (appPrec + 1) bound tm2
1565 pp p bound (Constant c) = annotate (AnnConst c) (text (show c))
1566 pp p bound (Proj tm i) =
1567 lparen <> pp startPrec bound tm <> rparen <>
1568 text "!" <> text (show i)
1569 pp p bound Erased = text "<<<erased>>>"
1570 pp p bound Impossible = text "<<<impossible>>>"
1571 pp p bound (TType ue) = annotate (AnnType "Type" "The type of types") $
1573 pp p bound (UType u) = text (show u)
1575 ppb p bound n (Lam ty) sc =
1576 bracket p startPrec . group . align . hang 2 $
1577 text "λ" <+> bindingOf n False <+> text "." <> line <> sc
1578 ppb p bound n (Pi _ ty k) sc =
1579 bracket p startPrec . group . align $
1580 lparen <> (bindingOf n False) <+> colon <+>
1581 (group . align) (pp startPrec bound ty) <>
1582 rparen <+> mkArrow k <> line <> sc
1583 where mkArrow (UType UniqueType) = text "⇴"
1584 mkArrow (UType NullType) = text "⥛"
1585 mkArrow _ = text "→"
1586 ppb p bound n (Let ty val) sc =
1587 bracket p startPrec . group . align $
1588 (group . hang 2) (annotate AnnKeyword (text "let") <+>
1589 bindingOf n False <+> colon <+>
1590 pp startPrec bound ty <+>
1592 pp startPrec bound val) <> line <>
1593 (group . hang 2) (annotate AnnKeyword (text "in") <+> sc)
1594 ppb p bound n (NLet ty val) sc =
1595 bracket p startPrec . group . align $
1596 (group . hang 2) (annotate AnnKeyword (text "nlet") <+>
1597 bindingOf n False <+> colon <+>
1598 pp startPrec bound ty <+>
1600 pp startPrec bound val) <> line <>
1601 (group . hang 2) (annotate AnnKeyword (text "in") <+> sc)
1602 ppb p bound n (Hole ty) sc =
1603 bracket p startPrec . group . align . hang 2 $
1604 text "?" <+> bindingOf n False <+> text "." <> line <> sc
1605 ppb p bound n (GHole _ ty) sc =
1606 bracket p startPrec . group . align . hang 2 $
1607 text "¿" <+> bindingOf n False <+> text "." <> line <> sc
1608 ppb p bound n (Guess ty val) sc =
1609 bracket p startPrec . group . align . hang 2 $
1610 text "?" <> bindingOf n False <+>
1611 text "≈" <+> pp startPrec bound val <+>
1612 text "." <> line <> sc
1613 ppb p bound n (PVar ty) sc =
1614 bracket p startPrec . group . align . hang 2 $
1615 annotate AnnKeyword (text "pat") <+>
1616 bindingOf n False <+> colon <+> pp startPrec bound ty <+>
1619 ppb p bound n (PVTy ty) sc =
1620 bracket p startPrec . group . align . hang 2 $
1621 annotate AnnKeyword (text "patTy") <+>
1622 bindingOf n False <+> colon <+> pp startPrec bound ty <+>
1626 bracket outer inner doc
1627 | outer > inner = lparen <> doc <> rparen
1631-- | Pretty-printer helper for the binding site of a name
1632bindingOf :: Name -- ^^ the bound name
1633 -> Bool -- ^^ whether the name is implicit
1634 -> Doc OutputAnnotation
1635bindingOf 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