1{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, DeriveFunctor #-}
3{-| TT is the core language of Idris. The language has:
7 * A hierarchy of universes, with cumulativity: Type : Type1, Type1 : Type2, ...
9 * Pattern matching letrec binding
11 * (primitive types defined externally)
15 * Typechecker is kept as simple as possible - no unification, just a checker for incomplete terms.
17 * We have a simple collection of tactics which we use to elaborate source
18 programs with implicit syntax into fully explicit terms.
23import Control.Monad.State
24import Control.Monad.Trans.Error (Error(..))
26import qualified Data.Map as Map
29import Data.Vector.Unboxed (Vector)
30import qualified Data.Vector.Unboxed as V
31import qualified Data.Binary as B
32import Data.Binary hiding (get, put)
33import Foreign.Storable (sizeOf)
35import Util.Pretty hiding (Str)
37data Option = TTypeInTType
41-- | Source location. These are typically produced by the parser 'Idris.Parser.getFC'
42data FC = FC { fc_fname :: String, -- ^ Filename
43 fc_line :: Int, -- ^ Line number
44 fc_column :: Int -- ^ Column number
47-- | Ignore source location equality (so deriving classes do not compare FCs)
52newtype FC' = FC' { unwrapFC :: FC }
55 FC' fc == FC' fc' = fcEq fc fc'
56 where fcEq (FC n l c) (FC n' l' c') = n == n' && l == l' && c == c'
58-- | Empty source location
62-- | Source location with file only
67deriving instance Binary FC
70instance Sized FC where
71 size (FC f l c) = 1 + length f
74 show (FC f l c) = f ++ ":" ++ show l ++ ":" ++ show c
78 | CantUnify Bool Term Term Err [(Name, Type)] Int
79 -- Int is 'score' - how much we did unify
80 -- Bool indicates recoverability, True indicates more info may make
81 -- unification succeed
82 | InfiniteUnify Name Term [(Name, Type)]
83 | CantConvert Term Term [(Name, Type)]
84 | UnifyScope Name Name Term [(Name, Type)]
85 | CantInferType String
86 | NonFunctionType Term Term
90 | NotInjective Term Term Term
92 | CantResolveAlts [String]
97 | NonCollapsiblePostulate Name
102 | Elaborating String Name Err
103 | ProviderError String
104 | LoadingFailed String Err
107instance Sized Err where
108 size (Msg msg) = length msg
109 size (InternalMsg msg) = length msg
110 size (CantUnify _ left right err _ score) = size left + size right + size err
111 size (InfiniteUnify _ right _) = size right
112 size (CantConvert left right _) = size left + size right
113 size (UnifyScope _ _ right _) = size right
114 size (NoSuchVariable name) = size name
115 size (NoTypeDecl name) = size name
116 size (NotInjective l c r) = size l + size c + size r
117 size (CantResolve trm) = size trm
118 size (NoRewriting trm) = size trm
119 size (CantResolveAlts _) = 1
120 size (IncompleteTerm trm) = size trm
121 size UniverseError = 1
122 size ProgramLineComment = 1
123 size (At fc err) = size fc + size err
124 size (Elaborating _ n err) = size err
125 size (ProviderError msg) = length msg
126 size (LoadingFailed fn e) = 1 + length fn + size e
130score (CantUnify _ _ _ m _ s) = s + score m
131score (CantResolve _) = 20
132score (NoSuchVariable _) = 1000
133score (ProofSearchFail _) = 10000
134score (InternalMsg _) = -1
137instance Show Err where
139 show (InternalMsg s) = "Internal error: " ++ show s
140 show (CantUnify _ l r e sc i) = "CantUnify " ++ show l ++ " " ++ show r ++ " "
141 ++ show e ++ " in " ++ show sc ++ " " ++ show i
142 show (Inaccessible n) = show n ++ " is not an accessible pattern variable"
143 show (ProviderError msg) = "Type provider error: " ++ msg
144 show (LoadingFailed fn e) = "Loading " ++ fn ++ " failed: " ++ show e
147instance Pretty Err where
148 pretty (Msg m) = text m
149 pretty (CantUnify _ l r e _ i) =
150 if size l + size r > breakingSize then
151 text "Cannot unify" <+> colon $$
152 nest nestingSize (pretty l <+> text "and" <+> pretty r) $$
153 nest nestingSize (text "where" <+> pretty e <+> text "with" <+> (text . show $ i))
155 text "Cannot unify" <+> colon <+> pretty l <+> text "and" <+> pretty r $$
156 nest nestingSize (text "where" <+> pretty e <+> text "with" <+> (text . show $ i))
157 pretty (ProviderError msg) = text msg
158 pretty err@(LoadingFailed _ _) = text (show err)
159 pretty _ = text "Error"
161instance Error Err where
166 deriving (Eq, Functor)
168instance Pretty a => Pretty (TC a) where
169 pretty (OK ok) = pretty ok
171 if size err > breakingSize then
172 text "Error" <+> colon $$ (nest nestingSize $ pretty err)
174 text "Error" <+> colon <+> pretty err
176instance Show a => Show (TC a) where
178 show (Error str) = "Error: " ++ show str
180-- at some point, this instance should also carry type checking options
183instance Monad TC where
188 fail e = Error (InternalMsg e)
193trun :: FC -> TC a -> TC a
195trun fc (Error e) = Error (At fc e)
197instance MonadPlus TC where
198 mzero = fail "Unknown error"
199 (OK x) `mplus` _ = OK x
200 _ `mplus` (OK y) = OK y
203discard :: Monad m => m a -> m ()
204discard f = f >> return ()
206showSep :: String -> [String] -> String
209showSep sep (x:xs) = x ++ sep ++ showSep sep xs
211pmap f (x, y) = (f x, f y)
213traceWhen True msg a = trace msg a
214traceWhen False _ a = a
216-- RAW TERMS ----------------------------------------------------------------
218-- | Names are hierarchies of strings, describing scope (so no danger of
219-- duplicate names, but need to be careful on lookup).
220data Name = UN String -- ^ User-provided name
221 | NS Name [String] -- ^ Root, namespaces
222 | MN Int String -- ^ Machine chosen names
223 | NErased -- ^ Name of somethng which is never used in scope
224 | SN SpecialName -- ^ Decorated function names
227deriving instance Binary Name
230data SpecialName = WhereN Int Name Name
231 | InstanceN Name [String]
232 | ParentN Name String
237deriving instance Binary SpecialName
240instance Sized Name where
242 size (NS n els) = 1 + length els
246instance Pretty Name where
247 pretty (UN n) = text n
248 pretty (NS n s) = pretty n
249 pretty (MN i s) = lbrace <+> text s <+> (text . show $ i) <+> rbrace
250 pretty (SN s) = text (show s)
252instance Show Name where
254 show (NS n s) = showSep "." (reverse s) ++ "." ++ show n
255 show (MN _ "underscore") = "_"
256 show (MN i s) = "{" ++ s ++ show i ++ "}"
260instance Show SpecialName where
261 show (WhereN i p c) = show p ++ ", " ++ show c
262 show (InstanceN cl inst) = showSep ", " inst ++ " instance of " ++ show cl
263 show (MethodN m) = "method " ++ show m
264 show (ParentN p c) = show p ++ "#" ++ c
265 show (CaseN n) = "case block in " ++ show n
267-- Show a name in a way decorated for code generation, not human reading
268showCG :: Name -> String
270showCG (NS n s) = showSep "." (reverse s) ++ "." ++ show n
271showCG (MN _ "underscore") = "_"
272showCG (MN i s) = "{" ++ s ++ show i ++ "}"
273showCG (SN s) = showCG' s
274 where showCG' (WhereN i p c) = show p ++ ":" ++ show c ++ ":" ++ show i
275 showCG' (InstanceN cl inst) = '@':show cl ++ '$':showSep ":" inst
276 showCG' (MethodN m) = '!':show m
277 showCG' (ParentN p c) = show p ++ "#" ++ show c
278 showCG' (CaseN c) = show c ++ "_case"
282-- |Contexts allow us to map names to things. A root name maps to a collection
283-- of things in different namespaces with that name.
284type Ctxt a = Map.Map Name (Map.Map Name a)
285emptyContext = Map.empty
287tcname (UN ('@':_)) = True
288tcname (NS n _) = tcname n
289tcname (SN (InstanceN _ _)) = True
290tcname (SN (MethodN _)) = True
291tcname (SN (ParentN _ _)) = True
294implicitable (NS n _) = implicitable n
295implicitable (UN (x:xs)) = isLower x
296implicitable (MN _ _) = True
297implicitable _ = False
302addDef :: Name -> a -> Ctxt a -> Ctxt a
303addDef n v ctxt = case Map.lookup (nsroot n) ctxt of
304 Nothing -> Map.insert (nsroot n)
305 (Map.insert n v Map.empty) ctxt
306 Just xs -> Map.insert (nsroot n)
307 (Map.insert n v xs) ctxt
309{-| Look up a name in the context, given an optional namespace.
310 The name (n) may itself have a (partial) namespace given.
312 Rules for resolution:
314 - if an explicit namespace is given, return the names which match it. If none
315 match, return all names.
317 - if the name has has explicit namespace given, return the names which match it
318 and ignore the given namespace.
320 - otherwise, return all names.
324lookupCtxtName :: Name -> Ctxt a -> [(Name, a)]
325lookupCtxtName n ctxt = case Map.lookup (nsroot n) ctxt of
326 Just xs -> filterNS (Map.toList xs)
330 filterNS ((found, v) : xs)
331 | nsmatch n found = (found, v) : filterNS xs
332 | otherwise = filterNS xs
334 nsmatch (NS n ns) (NS p ps) = ns `isPrefixOf` ps
335 nsmatch (NS _ _) _ = False
336 nsmatch looking found = True
338lookupCtxt :: Name -> Ctxt a -> [a]
339lookupCtxt n ctxt = map snd (lookupCtxtName n ctxt)
341lookupCtxtExact :: Name -> Ctxt a -> [a]
342lookupCtxtExact n ctxt = [ v | (nm, v) <- lookupCtxtName n ctxt, nm == n]
344updateDef :: Name -> (a -> a) -> Ctxt a -> Ctxt a
346 = let ds = lookupCtxtName n ctxt in
347 foldr (\ (n, t) c -> addDef n (f t) c) ctxt ds
349toAlist :: Ctxt a -> [(Name, a)]
350toAlist ctxt = let allns = map snd (Map.toList ctxt) in
351 concat (map (Map.toList) allns)
353addAlist :: Show a => [(Name, a)] -> Ctxt a -> Ctxt a
354addAlist [] ctxt = ctxt
355addAlist ((n, tm) : ds) ctxt = addDef n tm (addAlist ds ctxt)
357data NativeTy = IT8 | IT16 | IT32 | IT64
358 deriving (Show, Eq, Ord, Enum)
360instance Pretty NativeTy where
361 pretty IT8 = text "Bits8"
362 pretty IT16 = text "Bits16"
363 pretty IT32 = text "Bits32"
364 pretty IT64 = text "Bits64"
366data IntTy = ITFixed NativeTy | ITNative | ITBig | ITChar
368 deriving (Show, Eq, Ord)
370data ArithTy = ATInt IntTy | ATFloat -- TODO: Float vectors
371 deriving (Show, Eq, Ord)
373instance Pretty ArithTy where
374 pretty (ATInt ITNative) = text "Int"
375 pretty (ATInt ITBig) = text "BigInt"
376 pretty (ATInt ITChar) = text "Char"
377 pretty (ATInt (ITFixed n)) = pretty n
378 pretty (ATInt (ITVec e c)) = pretty e <> text "x" <> (text . show $ c)
379 pretty ATFloat = text "Float"
381nativeTyWidth :: NativeTy -> Int
383nativeTyWidth IT16 = 16
384nativeTyWidth IT32 = 32
385nativeTyWidth IT64 = 64
387{-# DEPRECATED intTyWidth "Non-total function, use nativeTyWidth and appropriate casing" #-}
388intTyWidth :: IntTy -> Int
389intTyWidth (ITFixed n) = nativeTyWidth n
390intTyWidth ITNative = 8 * sizeOf (0 :: Int)
391intTyWidth ITChar = error "IRTS.Lang.intTyWidth: Characters have platform and backend dependent width"
392intTyWidth ITBig = error "IRTS.Lang.intTyWidth: Big integers have variable width"
394data Const = I Int | BI Integer | Fl Double | Ch Char | Str String
395 | B8 Word8 | B16 Word16 | B32 Word32 | B64 Word64
396 | B8V (Vector Word8) | B16V (Vector Word16)
397 | B32V (Vector Word32) | B64V (Vector Word64)
398 | AType ArithTy | StrType
399 | PtrType | VoidType | Forgot
402deriving instance Binary Const
405instance Sized Const where
408instance Pretty Const where
409 pretty (I i) = text . show $ i
410 pretty (BI i) = text . show $ i
411 pretty (Fl f) = text . show $ f
412 pretty (Ch c) = text . show $ c
413 pretty (Str s) = text s
414 pretty (AType a) = pretty a
415 pretty StrType = text "String"
416 pretty PtrType = text "Ptr"
417 pretty VoidType = text "Void"
418 pretty Forgot = text "Forgot"
419 pretty (B8 w) = text . show $ w
420 pretty (B16 w) = text . show $ w
421 pretty (B32 w) = text . show $ w
422 pretty (B64 w) = text . show $ w
425 | RBind Name (Binder Raw) Raw
432instance Sized Raw where
434 size (RBind name bind right) = 1 + size bind + size right
435 size (RApp left right) = 1 + size left + size right
437 size (RForce raw) = 1 + size raw
438 size (RConstant const) = size const
440instance Pretty Raw where
444deriving instance Binary Raw
447-- | All binding forms are represented in a unform fashion.
448data Binder b = Lam { binderTy :: b {-^ type annotation for bound variable-}}
449 | Pi { binderTy :: b }
450 | Let { binderTy :: b,
451 binderVal :: b {-^ value for bound variable-}}
452 | NLet { binderTy :: b,
454 | Hole { binderTy :: b}
455 | GHole { envlen :: Int,
457 | Guess { binderTy :: b,
459 | PVar { binderTy :: b }
460 | PVTy { binderTy :: b }
461 deriving (Show, Eq, Ord, Functor)
463deriving instance Binary Binder
466instance Sized a => Sized (Binder a) where
467 size (Lam ty) = 1 + size ty
468 size (Pi ty) = 1 + size ty
469 size (Let ty val) = 1 + size ty + size val
470 size (NLet ty val) = 1 + size ty + size val
471 size (Hole ty) = 1 + size ty
472 size (GHole _ ty) = 1 + size ty
473 size (Guess ty val) = 1 + size ty + size val
474 size (PVar ty) = 1 + size ty
475 size (PVTy ty) = 1 + size ty
477fmapMB :: Monad m => (a -> m b) -> Binder a -> m (Binder b)
478fmapMB f (Let t v) = liftM2 Let (f t) (f v)
479fmapMB f (NLet t v) = liftM2 NLet (f t) (f v)
480fmapMB f (Guess t v) = liftM2 Guess (f t) (f v)
481fmapMB f (Lam t) = liftM Lam (f t)
482fmapMB f (Pi t) = liftM Pi (f t)
483fmapMB f (Hole t) = liftM Hole (f t)
484fmapMB f (GHole i t) = liftM (GHole i) (f t)
485fmapMB f (PVar t) = liftM PVar (f t)
486fmapMB f (PVTy t) = liftM PVTy (f t)
488raw_apply :: Raw -> [Raw] -> Raw
490raw_apply f (a : as) = raw_apply (RApp f a) as
492raw_unapply :: Raw -> (Raw, [Raw])
493raw_unapply t = ua [] t where
494 ua args (RApp f a) = ua (a:args) f
495 ua args t = (t, args)
497data RawFun = RawFun { rtype :: Raw,
502data RawDatatype = RDatatype Name Raw [(Name, Raw)]
505data RDef = RFunction RawFun
510type RProgram = [(Name, RDef)]
512-- WELL TYPED TERMS ---------------------------------------------------------
514-- | Universe expressions for universe checking
515data UExp = UVar Int -- ^ universe variable
516 | UVal Int -- ^ explicit universe level
519instance Sized UExp where
522-- We assume that universe levels have been checked, so anything external
523-- can just have the same universe variable and we won't get any new
526instance Binary UExp where
528 get = return (UVar (-1))
530instance Show UExp where
531 show (UVar x) | x < 26 = [toEnum (x + fromEnum 'a')]
532 | otherwise = toEnum ((x `mod` 26) + fromEnum 'a') : show (x `div` 26)
533 show (UVal x) = show x
534-- show (UMax l r) = "max(" ++ show l ++ ", " ++ show r ++")"
536-- | Universe constraints
537data UConstraint = ULT UExp UExp -- ^ Strictly less than
538 | ULE UExp UExp -- ^ Less than or equal to
541instance Show UConstraint where
542 show (ULT x y) = show x ++ " < " ++ show y
543 show (ULE x y) = show x ++ " <= " ++ show y
545type UCs = (Int, [UConstraint])
549 | DCon Int Int -- ^ Data constructor; Ints are tag and arity
550 | TCon Int Int -- ^ Type constructor; Ints are tag and arity
553deriving instance Binary NameType
556instance Sized NameType where
559instance Pretty NameType where
562instance Eq NameType where
563 Bound == Bound = True
565 DCon _ a == DCon _ b = (a == b) -- ignore tag
566 TCon _ a == TCon _ b = (a == b) -- ignore tag
569-- | Terms in the core language
570data TT n = P NameType n (TT n) -- ^ named references
571 | V Int -- ^ a resolved de Bruijn-indexed variable
572 | Bind n (Binder (TT n)) (TT n) -- ^ a binding
573 | App (TT n) (TT n) -- ^ function, function type, arg
574 | Constant Const -- ^ constant
575 | Proj (TT n) Int -- ^ argument projection; runtime only
576 -- (-1) is a special case for 'subtract one from BI'
577 | Erased -- ^ an erased term
578 | Impossible -- ^ special case for totality checking
579 | TType UExp -- ^ the type of types at some level
580 deriving (Ord, Functor)
582deriving instance Binary TT
585class TermSize a where
586 termsize :: Name -> a -> Int
588instance TermSize a => TermSize [a] where
590 termsize n (x : xs) = termsize n x + termsize n xs
592instance TermSize (TT Name) where
594 | x == n = 1000000 -- recursive => really big
597 termsize n (Bind n' (Let t v) sc)
598 = let rn = if n == n' then MN 0 "noname" else n in
599 termsize rn v + termsize rn sc
600 termsize n (Bind n' b sc)
601 = let rn = if n == n' then MN 0 "noname" else n in
603 termsize n (App f a) = termsize n f + termsize n a
604 termsize n (Proj t i) = termsize n t
607instance Sized a => Sized (TT a) where
608 size (P name n trm) = 1 + size name + size n + size trm
610 size (Bind nm binder bdy) = 1 + size nm + size binder + size bdy
611 size (App l r) = 1 + size l + size r
612 size (Constant c) = size c
614 size (TType u) = 1 + size u
616instance Pretty a => Pretty (TT a) where
617 pretty _ = text "test"
619type EnvTT n = [(n, Binder (TT n))]
621data Datatype n = Data { d_typename :: n,
624 d_cons :: [(n, TT n)] }
625 deriving (Show, Functor, Eq)
627instance Eq n => Eq (TT n) where
628 (==) (P xt x _) (P yt y _) = x == y
629 (==) (V x) (V y) = x == y
630 (==) (Bind _ xb xs) (Bind _ yb ys) = xb == yb && xs == ys
631 (==) (App fx ax) (App fy ay) = fx == fy && ax == ay
632 (==) (TType _) (TType _) = True -- deal with constraints later
633 (==) (Constant x) (Constant y) = x == y
634 (==) (Proj x i) (Proj y j) = x == y && i == j
639-- * A few handy operations on well typed terms:
641-- | A term is injective iff it is a data constructor, type constructor,
642-- constant, the type Type, pi-binding, or an application of an injective
644isInjective :: TT n -> Bool
645isInjective (P (DCon _ _) _ _) = True
646isInjective (P (TCon _ _) _ _) = True
647isInjective (Constant _) = True
648isInjective (TType x) = True
649isInjective (Bind _ (Pi _) sc) = True
650isInjective (App f a) = isInjective f
653-- | Count the number of instances of a de Bruijn index in a term
654vinstances :: Int -> TT n -> Int
655vinstances i (V x) | i == x = 1
656vinstances i (App f a) = vinstances i f + vinstances i a
657vinstances i (Bind x b sc) = instancesB b + vinstances (i + 1) sc
658 where instancesB (Let t v) = vinstances i v
662instantiate :: TT n -> TT n -> TT n
663instantiate e = subst 0 where
664 subst i (V x) | i == x = e
665 subst i (Bind x b sc) = Bind x (fmap (subst i) b) (subst (i+1) sc)
666 subst i (App f a) = App (subst i f) (subst i a)
667 subst i (Proj x idx) = Proj (subst i x) idx
670substV :: TT n -> TT n -> TT n
671substV x tm = dropV 0 (instantiate x tm) where
672 dropV i (V x) | x > i = V (x - 1)
674 dropV i (Bind x b sc) = Bind x (fmap (dropV i) b) (dropV (i+1) sc)
675 dropV i (App f a) = App (dropV i f) (dropV i a)
676 dropV i (Proj x idx) = Proj (dropV i x) idx
679explicitNames :: TT n -> TT n
680explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
682 (explicitNames (instantiate
683 (P Bound x (binderTy b')) sc))
684explicitNames (App f a) = App (explicitNames f) (explicitNames a)
685explicitNames (Proj x idx) = Proj (explicitNames x) idx
688pToV :: Eq n => n -> TT n -> TT n
690pToV' n i (P _ x _) | n == x = V i
691pToV' n i (Bind x b sc)
692-- We can assume the inner scope has been pToVed already, so continue to
693-- resolve names from the *outer* scope which may happen to have the same id.
694 | n == x = Bind x (fmap (pToV' n i) b) sc
695 | otherwise = Bind x (fmap (pToV' n i) b) (pToV' n (i+1) sc)
696pToV' n i (App f a) = App (pToV' n i f) (pToV' n i a)
697pToV' n i (Proj t idx) = Proj (pToV' n i t) idx
700-- increase de Bruijn indices, as if a binder has been added
701addBinder :: TT n -> TT n
704 ab top (V i) | i >= top = V (i + 1)
706 ab top (Bind x b sc) = Bind x (fmap (ab top) b) (ab (top + 1) sc)
707 ab top (App f a) = App (ab top f) (ab top a)
708 ab top (Proj t idx) = Proj (ab top t) idx
711-- | Convert several names. First in the list comes out as V 0
712pToVs :: Eq n => [n] -> TT n -> TT n
713pToVs ns tm = pToVs' ns tm 0 where
715 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
719 vToP' env (V i) = let (n, b) = (env !! i) in
720 P Bound n (binderTy b)
721 vToP' env (Bind n b sc) = let b' = fmap (vToP' env) b in
722 Bind n b' (vToP' ((n, b'):env) sc)
723 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
726finalise :: Eq n => TT n -> TT n
727finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
728finalise (App f a) = App (finalise f) (finalise a)
731subst :: Eq n => n -> TT n -> TT n -> TT n
732subst n v tm = instantiate v (pToV n tm)
734substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
736substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
738substTerm :: Eq n => TT n -> TT n -> TT n -> TT n
739substTerm old new = st where
740 st t | t == old = new
741 st (App f a) = App (st f) (st a)
742 st (Bind x b sc) = Bind x (fmap st b) (st sc)
745-- Returns true if V 0 and bound name n do not occur in the term
747noOccurrence :: Eq n => n -> TT n -> Bool
748noOccurrence n t = no' 0 t
750 no' i (V x) = not (i == x)
751 no' i (P Bound x _) = not (n == x)
752 no' i (Bind n b sc) = noB' i b && no' (i+1) sc
753 where noB' i (Let t v) = no' i t && no' i v
754 noB' i (Guess t v) = no' i t && no' i v
755 noB' i b = no' i (binderTy b)
756 no' i (App f a) = no' i f && no' i a
757 no' i (Proj x _) = no' i x
760-- | Returns all names used free in the term
761freeNames :: Eq n => TT n -> [n]
762freeNames (P _ n _) = [n]
763freeNames (Bind n (Let t v) sc) = nub $ freeNames v ++ (freeNames sc \\ [n])
765freeNames (Bind n b sc) = nub $ freeNames (binderTy b) ++ (freeNames sc \\ [n])
766freeNames (App f a) = nub $ freeNames f ++ freeNames a
767freeNames (Proj x i) = nub $ freeNames x
770-- | Return the arity of a (normalised) type
772arity (Bind n (Pi t) sc) = 1 + arity sc
775-- | Deconstruct an application; returns the function and a list of arguments
776unApply :: TT n -> (TT n, [TT n])
777unApply t = ua [] t where
778 ua args (App f a) = ua (a:args) f
779 ua args t = (t, args)
781mkApp :: TT n -> [TT n] -> TT n
783mkApp f (a:as) = mkApp (App f a) as
785forget :: TT Name -> Raw
788 fe env (P _ n _) = Var n
789 fe env (V i) = Var (env !! i)
790 fe env (Bind n b sc) = RBind n (fmap (fe env) b)
792 fe env (App f a) = RApp (fe env f) (fe env a)
795 fe env (TType i) = RType
796 fe env Erased = RConstant Forgot
798bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
800bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
802bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
803bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
805getArgTys :: TT n -> [(n, TT n)]
806getArgTys (Bind n (Pi t) sc) = (n, t) : getArgTys sc
809getRetTy :: TT n -> TT n
810getRetTy (Bind n (PVar _) sc) = getRetTy sc
811getRetTy (Bind n (PVTy _) sc) = getRetTy sc
812getRetTy (Bind n (Pi _) sc) = getRetTy sc
815uniqueName :: Name -> [Name] -> Name
816uniqueName n hs | n `elem` hs = uniqueName (nextName n) hs
819uniqueBinders :: [Name] -> TT Name -> TT Name
820uniqueBinders ns (Bind n b sc)
821 = let n' = uniqueName n ns in
822 Bind n' (fmap (uniqueBinders (n':ns)) b) (uniqueBinders ns sc)
823uniqueBinders ns (App f a) = App (uniqueBinders ns f) (uniqueBinders ns a)
824uniqueBinders ns t = t
827nextName (NS x s) = NS (nextName x) s
828nextName (MN i n) = MN (i+1) n
829nextName (UN x) = let (num', nm') = span isDigit (reverse x)
831 num = readN (reverse num') in
832 UN (nm ++ show (num+1))
836nextName (SN x) = SN (nextName' x)
838 nextName' (WhereN i f x) = WhereN i f (nextName x)
839 nextName' (CaseN n) = CaseN (nextName n)
840 nextName' (MethodN n) = MethodN (nextName n)
847-- an environment with de Bruijn indices 'normalised' so that they all refer to
850newtype WkEnvTT n = Wk (EnvTT n)
851type WkEnv = WkEnvTT Name
853instance (Eq n, Show n) => Show (TT n) where
854 show t = showEnv [] t
856itBitsName IT8 = "Bits8"
857itBitsName IT16 = "Bits16"
858itBitsName IT32 = "Bits32"
859itBitsName IT64 = "Bits64"
861instance Show Const where
866 show (Str s) = show s
868 show (B16 x) = show x
869 show (B32 x) = show x
870 show (B64 x) = show x
871 show (B8V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
872 show (B16V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
873 show (B32V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
874 show (B64V x) = "<" ++ intercalate "," (map show (V.toList x)) ++ ">"
875 show (AType ATFloat) = "Float"
876 show (AType (ATInt ITBig)) = "Integer"
877 show (AType (ATInt ITNative)) = "Int"
878 show (AType (ATInt ITChar)) = "Char"
879 show (AType (ATInt (ITFixed it))) = itBitsName it
880 show (AType (ATInt (ITVec it c))) = itBitsName it ++ "x" ++ show c
881 show StrType = "String"
883 show VoidType = "Void"
885showEnv env t = showEnv' env t False
886showEnvDbg env t = showEnv' env t True
888prettyEnv env t = prettyEnv' env t False
890 prettyEnv' env t dbg = prettySe 10 env t dbg
892 bracket outer inner p
893 | inner > outer = lparen <> p <> rparen
896 prettySe p env (P nt n t) debug =
899 lbrack <+> pretty nt <+> colon <+> prettySe 10 env t debug <+> rbrack
902 prettySe p env (V i) debug
905 text . show . fst $ env!!i
907 lbrack <+> text (show i) <+> rbrack
908 | otherwise = text "unbound" <+> text (show i) <+> text "!"
909 prettySe p env (Bind n b@(Pi t) sc) debug
910 | noOccurrence n sc && not debug =
911 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
912 prettySe p env (Bind n b sc) debug =
913 bracket p 2 $ prettySb env n b debug <> prettySe 10 ((n, b):env) sc debug
914 prettySe p env (App f a) debug =
915 bracket p 1 $ prettySe 1 env f debug <+> prettySe 0 env a debug
916 prettySe p env (Proj x i) debug =
917 prettySe 1 env x debug <+> text ("!" ++ show i)
918 prettySe p env (Constant c) debug = pretty c
919 prettySe p env Erased debug = text "[_]"
920 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
922 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
923 prettySb env n (Hole t) = prettyB env "?defer" "." n t
924 prettySb env n (Pi t) = prettyB env "(" ") ->" n t
925 prettySb env n (PVar t) = prettyB env "pat" "." n t
926 prettySb env n (PVTy t) = prettyB env "pty" "." n t
927 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
928 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
930 prettyB env op sc n t debug =
931 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
933 prettyBv env op sc n t v debug =
934 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
935 prettySe 10 env v debug <> text sc
938showEnv' env t dbg = se 10 env t where
939 se p env (P nt n t) = show n
940 ++ if dbg then "{" ++ show nt ++ " : " ++ se 10 env t ++ "}" else ""
941 se p env (V i) | i < length env && i >= 0
942 = (show $ fst $ env!!i) ++
943 if dbg then "{" ++ show i ++ "}" else ""
944 | otherwise = "!!V " ++ show i ++ "!!"
945 se p env (Bind n b@(Pi t) sc)
946 | noOccurrence n sc && not dbg = bracket p 2 $ se 1 env t ++ " -> " ++ se 10 ((n,b):env) sc
947 se p env (Bind n b sc) = bracket p 2 $ sb env n b ++ se 10 ((n,b):env) sc
948 se p env (App f a) = bracket p 1 $ se 1 env f ++ " " ++ se 0 env a
949 se p env (Proj x i) = se 1 env x ++ "!" ++ show i
950 se p env (Constant c) = show c
951 se p env Erased = "[__]"
952 se p env Impossible = "[impossible]"
953 se p env (TType i) = "Type " ++ show i
955 sb env n (Lam t) = showb env "\\ " " => " n t
956 sb env n (Hole t) = showb env "? " ". " n t
957 sb env n (GHole i t) = showb env "?defer " ". " n t
958 sb env n (Pi t) = showb env "(" ") -> " n t
959 sb env n (PVar t) = showb env "pat " ". " n t
960 sb env n (PVTy t) = showb env "pty " ". " n t
961 sb env n (Let t v) = showbv env "let " " in " n t v
962 sb env n (Guess t v) = showbv env "?? " " in " n t v
964 showb env op sc n t = op ++ show n ++ " : " ++ se 10 env t ++ sc
965 showbv env op sc n t v = op ++ show n ++ " : " ++ se 10 env t ++ " = " ++
968 bracket outer inner str | inner > outer = "(" ++ str ++ ")"
971-- | Check whether a term has any holes in it - impure if so
972pureTerm :: TT Name -> Bool
973pureTerm (App f a) = pureTerm f && pureTerm a
974pureTerm (Bind n b sc) = notClassName n && pureBinder b && pureTerm sc where
975 pureBinder (Hole _) = False
976 pureBinder (Guess _ _) = False
977 pureBinder (Let t v) = pureTerm t && pureTerm v
978 pureBinder t = pureTerm (binderTy t)
980 notClassName (MN _ "class") = False
981 notClassName _ = True
985-- | Weaken a term by adding i to each de Bruijn index (i.e. lift it over i bindings)
986weakenTm :: Int -> TT n -> TT n
987weakenTm i t = wk i 0 t
988 where wk i min (V x) | x >= min = V (i + x)
989 wk i m (App f a) = App (wk i m f) (wk i m a)
990 wk i m (Bind x b sc) = Bind x (wkb i m b) (wk i (m + 1) sc)
992 wkb i m t = fmap (wk i m) t
994-- | Weaken an environment so that all the de Bruijn indices are correct according
995-- to the latest bound variable
997weakenEnv :: EnvTT n -> EnvTT n
998weakenEnv env = wk (length env - 1) env
1000 wk i ((n, b) : bs) = (n, weakenTmB i b) : wk (i - 1) bs
1001 weakenTmB i (Let t v) = Let (weakenTm i t) (weakenTm i v)
1002 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
1003 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
1005weakenTmEnv :: Int -> EnvTT n -> EnvTT n
1006weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
1008orderPats :: Term -> Term
1009orderPats tm = op [] tm
1011 op ps (Bind n (PVar t) sc) = op ((n, PVar t) : ps) sc
1012 op ps (Bind n (Hole t) sc) = op ((n, Hole t) : ps) sc
1013 op ps sc = bindAll (map (\ (n, t) -> (n, t)) (sortP ps)) sc
1015 sortP ps = pick [] (reverse ps)
1017 namesIn (P _ n _) = [n]
1018 namesIn (Bind n b t) = nub $ nb b ++ (namesIn t \\ [n])
1019 where nb (Let t v) = nub (namesIn t) ++ nub (namesIn v)
1020 nb (Guess t v) = nub (namesIn t) ++ nub (namesIn v)
1021 nb t = namesIn (binderTy t)
1022 namesIn (App f a) = nub (namesIn f ++ namesIn a)
1025 pick acc [] = reverse acc
1026 pick acc ((n, t) : ps) = pick (insert n t acc) ps
1028 insert n t [] = [(n, t)]
1029 insert n t ((n',t') : ps)
1030 | n `elem` (namesIn (binderTy t') ++
1031 concatMap namesIn (map (binderTy . snd) ps))
1032 = (n', t') : insert n t ps
1033 | otherwise = (n,t):(n',t'):ps
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list