inch-0.1.0: src/Language/Inch/TypeCheck.lhs
> {-# LANGUAGE GADTs, TypeOperators, FlexibleContexts, PatternGuards,
> RankNTypes #-}
> module Language.Inch.TypeCheck where
> import Control.Applicative hiding (Alternative)
> import Control.Monad
> import Control.Monad.State
> import Control.Monad.Writer hiding (All)
> import Data.List
> import Data.Maybe
> import qualified Data.Map as Map
> import Data.Foldable hiding (foldr, any, mapM_)
> import Data.Traversable
> import Text.PrettyPrint.HughesPJ
> import Language.Inch.BwdFwd
> import Language.Inch.Kind
> import Language.Inch.Type
> import Language.Inch.TyNum
> import Language.Inch.Syntax
> import Language.Inch.Context
> import Language.Inch.Unify
> import Language.Inch.Kit
> import Language.Inch.Error
> import Language.Inch.PrettyPrinter
> import Language.Inch.KindCheck
> import Language.Inch.Solver
> import Language.Inch.Check
The |inst| function takes a name-mangling function (for modifying the
names of binders), a type definition (for use when introducing binders
into the context) and a type to instantiate. It instantiates
forall-binders with fresh variables to produce a rho-type, and writes
a list of predicates found.
> inst :: VarState -> (forall k. TyDef k) -> Type l ->
> ContextualWriter [Type KConstraint] (Type l)
> inst vs d (TyApp (TyApp Arr a) t) =
> TyApp (TyApp Arr a) <$> inst vs d t
> inst vs d (Bind All x k t) = do
> beta <- fresh vs x k d
> inst vs d (unbindTy beta t)
> inst vs d (Qual p t) = do
> tell [p]
> inst vs d t
> inst _ _ t = return t
The |instS| function is like |inst|, but also takes a constraint
status, and stores the predicates in the context with the given
status.
> instS :: VarState -> CStatus -> (forall k. TyDef k) -> Type l ->
> Contextual (Type l)
> instS vs s d t = do
> (ty, cs) <- runWriterT $ inst vs d t
> modifyContext (<><< map (Constraint s) cs)
> return ty
> specialise :: Type l -> Contextual (Type l)
> specialise = instS (UserVar All) Given Fixed
> instantiate :: Type l -> Contextual (Type l)
> instantiate = instS SysVar Wanted Hole
> existentialise :: (MonadState ZipState m, FV (Type k) ()) =>
> m (Type k) -> m (Type k)
> existentialise m = do
> modifyContext (:< Layer FunTop False) -- hackish
> ty <- m
> modifyContext $ help (flip elemTarget ty)
> return ty
> where
> help :: (forall k. Var () k -> Bool) -> Context -> Context
> help isHole (g :< A (a := Hole))
> | isHole a = help isHole g :< A (a := Hole)
> | otherwise = help isHole g :< A (a := Exists)
> help _ (g :< Layer FunTop _) = g
> help isHole (g :< e) = help isHole g :< e
> help _ B0 = error "existentialise: ran out of context"
> generalise :: (FV (t OK ()) (), TravTypes1 t) => Type KSet -> [t OK ()] ->
> Contextual (Type KSet, [t OK ()])
> generalise u qs = do
> g <- getContext
> (g', tps) <- help g (u, qs) []
> putContext g'
> return tps
> where
> help :: (FV (t OK ()) (), TravTypes1 t) => Context ->
> (Type KSet, [t OK ()]) -> [Type KConstraint] ->
> Contextual (Context, (Type KSet, [t OK ()]))
> help (g :< Layer l True) tps _ = return (g :< Layer l True, tps)
> help (g :< Layer l False) tps hs = (<:< Layer l False) <$> help g tps hs
> help (g :< A (a@(FVar _ KNum) := Exists)) (t, ps) hs
> | a <? (t, ps, hs) = case solveForLots a hs of
> Just n -> replaceHelp g (t, ps) hs a (reifyNum n)
> Nothing | a <? t -> traceContext "oh no" >>
> errBadExistential a t
> | otherwise -> help g (t, ps) (filter (not . (a <?)) hs)
> help (_ :< A (a := Exists)) (t, ps) hs
> | a <? (t, ps, hs) = errBadExistential a t
> help (g :< A (a := Some d)) (t, ps) hs = replaceHelp g (t, ps) hs a d
> help (g :< A (a := _)) (t, ps) hs
> | a <? (t, ps, hs) = help g (Bind All (fogVar a) (varKind a) (bindTy a t), ps) hs
> help (g :< A _) tps hs = help g tps hs
> help (g :< Constraint Given h) tps hs = help g tps (h:hs)
> help (g :< Constraint Wanted p) (t, ps) hs
> | impossible p = errImpossible p
> | otherwise = help g (Qual p t, ps) hs
> help _ _ _ = erk $ "generalise: hit empty context"
> impossible :: Type KConstraint -> Bool
> impossible p = null (vars p)
> (<:<) :: (Context, t) -> Entry -> (Context, t)
> (g, x) <:< e = (g :< e, x)
> replaceHelp :: (FV (t OK ()) (), TravTypes1 t) => Context ->
> (Type KSet, [t OK ()]) -> [Type KConstraint] ->
> Var () l -> Type l ->
> Contextual (Context, (Type KSet, [t OK ()]))
> replaceHelp g (t, ps) hs a d =
> help g (replaceTy a d t, map (replaceTypes a d) ps) (map (replaceTy a d) hs)
> solveForLots :: Var () KNum -> [Type KConstraint] -> Maybe NormalNum
> solveForLots a = getFirst . foldMap (First . maybeSolveFor a) . mapMaybe f
> where f (TyComp EL `TyApp` m `TyApp` n) = Just (normaliseNum (m - n))
> f _ = Nothing
> subsCheck :: Sigma -> Sigma -> Contextual ()
> subsCheck s t = do
> t' <- specialise t
> s' <- instantiate s
> case (s', t') of
> (TyApp (TyApp Arr s1) s2, _) -> do
> (t1, t2) <- unifyFun t'
> subsCheck t1 s1
> subsCheck s2 t2
> (_, TyApp (TyApp Arr t1) t2) -> do
> (s1, s2) <- unifyFun s'
> subsCheck t1 s1
> subsCheck s2 t2
> (Bind Pi x KNum t1, Bind Pi _ KNum t2) -> do
> a <- fresh SysVar x KNum Fixed
> subsCheck (unbindTy a t1) (unbindTy a t2)
> _ -> unify s' t'
> instSigma :: Sigma -> Maybe Rho -> Contextual Rho
> instSigma s Nothing = instantiate s
> instSigma s (Just r) = subsCheck s r >> return r
> inferRho :: STerm () -> Contextual (Term () ::: Rho)
> inferRho t =
> inLocation (text "in inferred expression" <++> prettyHigh t) $
> checkInfer Nothing t
> checkRho :: Rho -> STerm () -> Contextual (Term ())
> checkRho ty t =
> inLocation (text "in checked expression" <++> prettyHigh t) $
> tmOf <$> checkInfer (Just ty) t
> checkSigma :: Sigma -> STerm () -> Contextual (Term ())
> checkSigma s e = inLocation (sep [text "when checking", nest 2 (prettyHigh e),
> text "has type", nest 2 (prettyHigh (fogTy s))]) $ do
> unifySolveConstraints
> modifyContext (:< Layer GenMark True)
> s' <- specialise s
> as <- getNames <$> getContext
> t <- checkRho s' e
> unifySolveConstraints
> solveOrSuspend
> g <- getContext
> putContext =<< help as g []
> return t
> where
> getNames :: Context -> [Ex (Var ())]
> getNames (_ :< Layer GenMark _) = []
> getNames (g :< A (a := _)) = Ex a : getNames g
> getNames (g :< _) = getNames g
> getNames B0 = error "getNames: ran out of context"
> help :: [Ex (Var ())] -> Context -> [Entry] -> Contextual Context
> help [] (g :< Layer GenMark _) h = return $ g <><| h
> help as (_ :< Layer GenMark _) _ = erk $ "checkSigma help: failed to squish "
> ++ intercalate "," (map (\ x -> unEx x fogSysVar) as)
> help _ (_ :< Layer l _) _ = error $ "checkSigma.help: hit bad layer " ++ show l
> help as (g :< A (a := Fixed)) h = case suppress a h of
> Just h' -> help (delete (Ex a) as) g h'
> Nothing -> traceContext "noooooooooo" >> (erk $ "checkSigma help: fixed variable "
> ++ renderMe (fogSysVar a)
> ++ " occurred illegally in "
> ++ show (fsepPretty h))
> help as (g :< A (a := Some d)) h = help as g (fmap (replaceTyEntry a d) h)
> help as (g :< A a) h = help as g (A a : h)
> help as (g :< Constraint Wanted p) h = help as g (Constraint Wanted p : h)
> help as (g :< Constraint Given p) h = help as g (map (abstract p) h)
> help _ B0 _ = error "checkSigma help: ran out of context"
> abstract p (Constraint c q) = Constraint c (Qual p q)
> abstract _ x = x
> (<><|) :: Context -> [Entry] -> Context
> g <><| [] = g
> g <><| (x:xs) = (g :< x) <><| xs
> suppress :: Var () k -> [Entry] -> Maybe [Entry]
> suppress _ [] = return []
> suppress a (x : xs) | not (a <? x) = (x :) <$> suppress a xs
> suppress a@(FVar _ KNum) (Constraint Wanted p : es) = suppressPred a p >>=
> \ p' -> (Constraint Wanted p' :) <$> suppress a es
> suppress _ _ = Nothing
> suppressPred :: Var () KNum -> Type KConstraint -> Maybe (Type KConstraint)
> suppressPred a (Qual p q) | a <? p = suppressPred a q
> | otherwise = Qual p <$> suppressPred a q
> suppressPred a p | a <? p = Nothing
> | otherwise = Just p
> checkInfer :: Maybe Rho -> STerm () -> Contextual (Term () ::: Rho)
> checkInfer mty (TmVar x) = do
> sc <- tyOf <$> lookupTmVar x
> ty <- instSigma sc mty
> return $ TmVar x ::: ty
> checkInfer mty (TmCon c) = do
> sc <- lookupTmCon c
> ty <- instSigma sc mty
> return $ TmCon c ::: ty
> checkInfer mty (TmInt k) = do
> ty <- instSigma tyIntLit mty
> return $ TmInt k ::: ty
> checkInfer mty (CharLit c) = do
> _ <- instSigma tyChar mty
> return $ CharLit c ::: tyChar
> checkInfer mty (StrLit s) = do
> _ <- instSigma tyString mty
> return $ StrLit s ::: tyString
> checkInfer mty (TmApp f (TmBrace n)) = do
> f' ::: fty <- inferRho f
> case fty of
> Bind Pi _ KNum aty -> do
> n' <- checkKind KNum Pi B0 n
> a <- fresh SysVar "_n" KNum (Some n')
> ty <- instSigma (unbindTy a aty) mty
> return $ TmApp f' (TmBrace n') ::: ty
> _ -> erk $ "Inferred type " ++ renderMe (fogSysTy fty) ++ " of " ++
> renderMe (fogSys f') ++ " is not a pi-type with numeric domain"
> checkInfer mty (TmApp f s) = do
> f' ::: fty <- inferRho f
> (dom, cod) <- unifyFun fty
> s' <- checkSigma dom s
> _ <- instSigma cod mty
> return $ TmApp f' s' ::: cod
> checkInfer (Just r) (Lam x t) = do
> (dom, cod) <- unifyFun r
> b <- withLayer False False (LamBody (x ::: dom)) $ checkRho cod t
> return $ Lam x b ::: r
> checkInfer Nothing (Lam x t) = do
> a <- unknownTyVar x KSet
> b ::: ty <- withLayer False False (LamBody (x ::: a)) $ inferRho t
> return $ Lam x b ::: a --> ty
> checkInfer (Just r@(Bind Pi _ KNum ty)) (NumLam n t) = do
> a <- fresh (UserVar Pi) n KNum Fixed -- should this be |Exists|?
> b <- withLayer False False (LamBody (n ::: tyInteger)) $
> checkSigma (unbindTy a ty) (rawCoerce t)
> return $ NumLam n (bindTm a b) ::: r
> checkInfer (Just r) (NumLam n t) = erk $
> "Type " ++ renderMe (fogSysTy r) ++
> " is not a pi-type with numeric domain, so it does not accept " ++
> renderMe (NumLam n t)
> checkInfer Nothing (NumLam n t) = do
> a <- fresh (UserVar Pi) n KNum Fixed -- should this be |Exists|?
> b ::: ty <- withLayer False False (LamBody (n ::: tyInteger)) $ inferRho (rawCoerce t)
> return $ NumLam n (bindTm a b) ::: Bind Pi n KNum (bindTy a ty)
> checkInfer mty (Let ds t) = do
> (ds', bs) <- checkLocalDecls ds
> t' ::: ty <- withLayer False False (LetBody bs) $
> checkInfer mty t
> return $ Let ds' t' ::: ty
> checkInfer mty (t :? xty) = do
> sc <- checkKind KSet All B0 xty
> t' <- checkSigma sc t
> r <- instSigma sc mty
> return $ (t' :? sc) ::: r
> checkInfer (Just r) (Case t as) = do
> t' ::: ty <- inferRho t
> as' <- traverse (checkCaseAlt ty r) as
> return $ Case t' as' ::: r
> checkInfer Nothing (Case t as) = do
> t' ::: ty <- inferRho t
> as' ::: tys <- unzipAsc <$> traverse (inferCaseAlt ty) as
> r <- unifyList tys
> return (Case t' as' ::: r)
> checkInfer _ (TmBrace _) = erk "Braces aren't cool"
> checkLocalHypotheses :: TmLayer -> Contextual ()
> checkLocalHypotheses l = modifyContext (help False)
> where
> help :: Bool -> Context -> Context
> help z (g :< Layer l' b) | matchLayer l l' = g :< Layer l' (b || z)
> help _ (g :< Layer l' True) = g :< Layer l' True
> help _ (g :< e@(Constraint Given _)) = help True g :< e
> help z (g :< e) = help z g :< e
> help _ B0 = error "checkLocalHypotheses: empty!"
-- This is horrible, please improve it
> checkCaseAlt :: Rho -> Rho -> SCaseAlternative () -> Contextual (CaseAlternative ())
> checkCaseAlt sty resty c@(CaseAlt p gt) =
> inLocation (text "in case alternative" <++> prettyHigh c) $
> withLayer False True CaseTop $ do
> ca <- checkPat True (sty --> resty) (p :! P0) $ \ (p' :! P0) vs rty -> do
> checkLocalHypotheses CaseTop
> gt' <- checkGuardTerms rty (rawCoerce gt)
> return $ CaseAlt p' (renameTypes1 (renameVS vs) gt')
> unifySolveConstraints
> solveConstraints
> return ca
> inferCaseAlt :: Rho -> SCaseAlternative () -> Contextual (CaseAlternative () ::: Rho)
> inferCaseAlt sty c@(CaseAlt p gt) = do
> resty <- unknownTyVar "_r" KSet
> inLocation (text "in case alternative" <++> prettyHigh c) $
> withLayer False True CaseTop $ do
> ca <- checkPat True (sty --> resty) (p :! P0) $ \ (p' :! P0) vs rty -> do
> checkLocalHypotheses CaseTop
> gt' <- checkGuardTerms rty (rawCoerce gt)
> return $ CaseAlt p' (renameTypes1 (renameVS vs) gt')
> return $ ca ::: resty
> checkLocalDecls :: [SDeclaration ()] -> Contextual ([Declaration ()], Bindings)
> checkLocalDecls ds =
> withLayerExtract False False (LetBindings Map.empty) letBindings $ do
> mapM_ (makeBinding False) ds
> Data.List.concat <$> traverse checkInferDecl ds
> makeBinding :: Bool -> SDeclaration () -> Contextual ()
> makeBinding defd (SigDecl x ty) = inLocation (text $ "in binding " ++ x) $ do
> bs <- tyVarNamesInScope
> TK ty' k <- inferKind All B0 (wrapForall bs ty)
> case k of
> KSet -> insertBinding x (Just ty', defd)
> _ -> errKindNotSet (fogKind k)
> makeBinding _ (FunDecl _ _) = return ()
> checkInferDecl :: SDeclaration () -> Contextual [Declaration ()]
> checkInferDecl (FunDecl s []) =
> inLocation (text $ "in declaration of " ++ s) $ erk $ "No alternative"
> checkInferDecl (FunDecl s (p:ps)) = do
> when (not (null ps) && isVarAlt p) $ errDuplicateTmVar s
> mty <- optional $ lookupBinding s
> case mty of
> Just (_ ::: ty, False) -> (\ x -> [FunDecl s x]) <$> checkFunDecl ty ty s (p:ps)
> Just (_, True) -> errDuplicateTmVar s
> Nothing -> do
> (fd, ty) <- inferFunDecl s (p:ps)
> updateBinding s (Just ty, True)
> return [SigDecl s ty, FunDecl s fd]
> checkInferDecl (SigDecl x _) = do
> _ ::: ty <- fst <$> lookupBinding x
> return [SigDecl x ty]
> inferFunDecl :: String -> [SAlternative ()] -> Contextual ([Alternative ()], Type KSet)
> inferFunDecl s pats =
> inLocation (text $ "in declaration of " ++ s) $ withLayer True True FunTop $ do
> sty <- unknownTyVar "_x" KSet
> pattys <- traverse (inferAlt (s ::: sty)) pats
> let ptms ::: ptys = unzipAsc pattys
> mapM_ (unify sty) ptys
> (ty', ptms') <- generalise sty ptms
> return (ptms', simplifyTy ty')
> checkFunDecl :: Sigma -> Sigma -> String -> [SAlternative ()] ->
> Contextual [Alternative ()]
> checkFunDecl sty ty s pats =
> inLocation (text $ "in declaration of " ++ s) $ withLayer True True FunTop $ do
> ptms <- traverse (checkAlt (s ::: sty) ty) pats
> (_, ptms') <- generalise (TyCon "Fake" KSet) ptms
> return ptms'
> checkAlt :: String ::: Sigma -> Sigma -> SAlternative () -> Contextual (Alternative ())
> checkAlt (s ::: sc) ty (Alt xs gt) =
> inLocation (text "in alternative" <++> (text s <+> prettyHigh (Alt xs gt))) $
> withLayer True True (PatternTop (s ::: ty)) $ do
> sty <- specialise sc
> checkPat True sty xs $ \ xs' vs rty -> do
> gt' <- checkGuardTerms rty (rawCoerce gt)
> unifySolveConstraints
> solveConstraints
> return $ Alt xs' (renameTypes1 (renameVS vs) gt')
> inferAlt :: String ::: Sigma -> SAlternative () ->
> Contextual (Alternative () ::: Rho)
> inferAlt (s ::: sc) (Alt xs gt) =
> inLocation (text "in alternative" <++> (text s <+> prettyHigh (Alt xs gt))) $
> withLayer True True (PatternTop (s ::: sc)) $
> inferPat (rawCoerce gt) xs $ \ xs' vs (gt' ::: _) ty -> do
> unifySolveConstraints
> solveOrSuspend
> return $ Alt xs' (renameTypes1 (renameVS vs) gt') ::: ty
> checkGuardTerms :: Rho -> SGuardTerms () -> Contextual (GuardTerms ())
> checkGuardTerms rho (Unguarded t ds) = do
> (ds', bs) <- checkLocalDecls ds
> withLayer False False (LetBody bs) $ do
> t' <- checkRho rho t
> unifySolveConstraints
> solveOrSuspend
> return $ Unguarded t' ds'
> checkGuardTerms rho (Guarded gts ds) = do
> (ds', bs) <- checkLocalDecls ds
> withLayer False False (LetBody bs) $ do
> Guarded <$> traverse chk gts <*> pure ds'
> where
> chk (g :*: t) = withLayer False True GuardTop $ do
> g' <- checkGuard g
> checkLocalHypotheses GuardTop
> t' <- checkRho rho t
> unifySolveConstraints
> solveOrSuspend
> return $ g' :*: t'
> inferGuardTerms :: SGuardTerms () -> Contextual (GuardTerms () ::: Rho)
> inferGuardTerms (Unguarded e ds) = do
> (ds', bs) <- checkLocalDecls ds
> withLayer False False (LetBody bs) $ do
> e' ::: r <- inferRho e
> return $ Unguarded e' ds' ::: r
> inferGuardTerms (Guarded gts ds) = do
> (ds', bs) <- checkLocalDecls ds
> withLayer False False (LetBody bs) $ do
> xs <- traverse (\ (g :*: t) -> do
> g' <- checkGuard g
> t' ::: r <- inferRho t
> return $ (g' :*: t') ::: r) gts
> let gts' ::: tys = unzipAsc xs
> ty <- unifyList tys
> return $ Guarded gts' ds' ::: ty
> checkGuard :: SGuard () -> Contextual (Guard ())
> checkGuard (NumGuard ps) = NumGuard <$> traverse learnPred ps
> where
> learnPred p = do
> p' <- checkPredKind Pi B0 p
> modifyContext (:< Constraint Given (predToConstraint p'))
> return p'
> checkGuard (ExpGuard ts) = ExpGuard <$> traverse (checkRho tyBool) ts
> checkPat :: Bool -> Rho -> SPatternList o a ->
> (forall b x . PatternList () b -> VarSuffix () b x -> Rho -> Contextual p) ->
> Contextual p
> checkPat _ ty P0 q = q P0 VS0 ty
> checkPat top ty (PatVar v :! ps) q = do
> (dom, cod) <- unifyFun ty
> withLayer False False (LamBody (v ::: dom)) $
> checkPat top cod ps $ \ ps' vs r ->
> q (PatVar v :! ps') vs r
> checkPat top ty (PatCon c as :! ps) q = do
> (cty, dom, cod) <- inLocation (text "in pattern" <++> prettyHigh (PatCon c as)) $ do
> (dom, cod) <- unifyFun ty
> sc <- lookupTmCon c
> cty <- existentialise $ instS SysVar Given Hole sc
> unless (patLength as == args cty) $
> errConUnderapplied c (args cty) (patLength as)
> return (cty, dom, cod)
> checkPat False cty as $ \ as' avs s -> do
> unify dom s
> checkPat top cod ps $ \ ps' pvs r ->
> renameTypes2 (renameVS avs) pvs ps' $ \ pvs' ps'' ->
> extComp avs pvs' $ \ vs ->
> q (PatCon c as' :! ps'') vs r
> checkPat top ty (PatIgnore :! ps) q = do
> (_, cod) <- unifyFun ty
> checkPat top cod ps $ \ ps' vs r ->
> q (PatIgnore :! ps') vs r
> checkPat top ty (PatIntLit i :! ps) q = do
> (dom, cod) <- unifyFun ty
> modifyContext (:< Constraint Wanted (TyCon "Num" (KSet :-> KConstraint) `TyApp` dom))
> checkPat top cod ps $ \ ps' vs r ->
> q (PatIntLit i :! ps') vs r
> checkPat top ty (PatCharLit c :! ps) q = do
> (dom, cod) <- unifyFun ty
> unify dom tyChar
> checkPat top cod ps $ \ ps' vs r ->
> q (PatCharLit c :! ps') vs r
> checkPat top ty (PatStrLit s :! ps) q = do
> (dom, cod) <- unifyFun ty
> unify dom tyString
> checkPat top cod ps $ \ ps' vs r ->
> q (PatStrLit s :! ps') vs r
> checkPat top ty (PatNPlusK n k :! ps) q = do
> (dom, cod) <- unifyFun ty
> unify dom tyInteger
> withLayer False False (LamBody (n ::: tyInteger)) $
> checkPat top cod ps $ \ ps' vs r ->
> q (PatNPlusK n k :! ps') vs r
> checkPat top (Bind Pi x KNum t) (PatBraceK k :! ps) q = do
> b <- fresh SysVar x KNum (Some (TyInt k))
> aty <- instS (UserVar All) Given Fixed (unbindTy b t)
> checkPat top aty ps $ \ ps' vs r ->
> q (PatBraceK k :! ps') vs r
> checkPat top (Bind Pi _ KNum t) (PatBrace a 0 :! ps) q =
> withLayer False False (LamBody (a ::: tyInteger)) $ do
> b <- freshVar (UserVar Pi) a KNum
> let t' = unbindTy b t
> d = if top || b `elemTarget` t'
> then Fixed
> else Exists
> modifyContext (:< A (b := d))
> aty <- instS (UserVar All) Given Fixed t'
> checkPat top aty ps $ \ ps' vs r ->
> bindUn b vs ps' $ \ vs' ps'' ->
> extComp (VS0 :<< error "woony") vs' $ \ vs'' ->
> q (PatBrace a 0 :! ps'') vs'' r
> checkPat top (Bind Pi x KNum t) (PatBrace a k :! ps) q =
> withLayer False False (LamBody (a ::: tyInteger)) $ do
> b <- freshVar SysVar ("_" ++ x ++ "_" ++ a ++ "_" ++ "oo") KNum
> let t' = unbindTy b t
> d = if top || b `elemTarget` t'
> then Fixed
> else Exists
> am <- fresh (UserVar Pi) a KNum d
> modifyContext (:< A (b := Some (TyVar am + TyInt k)))
> modifyContext (:< Constraint Given (tyPred LE 0 (TyVar am)))
> aty <- instS (UserVar All) Given Fixed t'
> checkPat top aty ps $ \ ps' vs r ->
> bindUn am vs ps' $ \ vs' ps'' ->
> extComp (VS0 :<< error "woony") vs' $ \ vs'' ->
> q (PatBrace a k :! ps'') vs'' r
> checkPat _ ty (p :! _) _ =
> erk $ "checkPat: couldn't match pattern " ++ renderMe p
> ++ " against type " ++ renderMe (fogSysTy ty)
> inferPat :: SGuardTerms () -> SPatternList o a ->
> (forall b x . PatternList () b -> VarSuffix () b x -> GuardTerms () ::: Rho -> Rho -> Contextual p) ->
> Contextual p
> inferPat t P0 q = do
> t' ::: r <- inferGuardTerms t
> q P0 VS0 (t' ::: r) r
> inferPat top (PatVar v :! ps) q = do
> a <- unknownTyVar "_a" KSet
> withLayer False False (LamBody (v ::: a)) $
> inferPat top ps $ \ ps' vs tr ty ->
> q (PatVar v :! ps') vs tr (a --> ty)
> inferPat top (PatCon c as :! ps) q = do
> cty <- inLocation (text "in pattern" <++> prettyHigh (PatCon c as)) $ do
> sc <- lookupTmCon c
> cty <- existentialise $ instS SysVar Given Hole sc
> unless (patLength as == args cty) $
> errConUnderapplied c (args cty) (patLength as)
> return cty
> checkPat False cty as $ \ as' yvs s ->
> inferPat top ps $ \ ps' xvs tr ty ->
> renameTypes2 (renameVS yvs) xvs ps' $ \ xvs' ps'' ->
> extComp yvs xvs' $ \ vs ->
> q (PatCon c as' :! ps'') vs tr (s --> ty)
> inferPat top (PatIgnore :! ps) q = do
> b <- unknownTyVar "_b" KSet
> inferPat top ps $ \ ps' vs tr ty ->
> q (PatIgnore :! ps') vs tr (b --> ty)
> inferPat top (PatIntLit i :! ps) q = do
> a <- unknownTyVar "_a" KSet
> modifyContext (:< Constraint Wanted (TyCon "Num" (KSet :-> KConstraint) `TyApp` a))
> inferPat top ps $ \ ps' vs tr ty ->
> q (PatIntLit i :! ps') vs tr (a --> ty)
> inferPat top (PatCharLit c :! ps) q = do
> inferPat top ps $ \ ps' vs tr ty ->
> q (PatCharLit c :! ps') vs tr (tyChar --> ty)
> inferPat top (PatStrLit s :! ps) q = do
> inferPat top ps $ \ ps' vs tr ty ->
> q (PatStrLit s :! ps') vs tr (tyString --> ty)
> inferPat top (PatNPlusK n k :! ps) q =
> withLayer False False (LamBody (n ::: tyInteger)) $
> inferPat top ps $ \ ps' vs tr ty ->
> q (PatNPlusK n k :! ps') vs tr (tyInteger --> ty)
> inferPat top (PatBrace a 0 :! ps) q = do
> n <- fresh (UserVar Pi) a KNum Exists
> withLayer True True GenMark $ withLayer False False (LamBody (a ::: tyInteger)) $
> inferPat top ps $ \ ps' vs tr ty -> do
> (ty', _) <- generalise ty ([] :: [Alternative ()])
> bindUn n vs ps' $ \ vs' ps'' ->
> extComp (VS0 :<< error "woony") vs' $ \ vs'' ->
> q (PatBrace a 0 :! ps'') vs'' tr
> (Bind Pi a KNum (bindTy n ty'))
> inferPat _ (p :! _) _ =
> erk $ "inferPat: couldn't infer type of pattern " ++ renderMe p