diff options
Diffstat (limited to 'src/HSVIS/Typecheck.hs')
| -rw-r--r-- | src/HSVIS/Typecheck.hs | 83 | 
1 files changed, 55 insertions, 28 deletions
diff --git a/src/HSVIS/Typecheck.hs b/src/HSVIS/Typecheck.hs index ba853a0..c97064a 100644 --- a/src/HSVIS/Typecheck.hs +++ b/src/HSVIS/Typecheck.hs @@ -78,6 +78,9 @@ type TPattern = Pattern StageTyped  type TRHS     = RHS     StageTyped  type TExpr    = Expr    StageTyped +instance Pretty (E Type StageTC) where +  prettysPrec _ (TUniVar n) = showString ("?t" ++ show n) +  instance Pretty (E Kind StageTC) where    prettysPrec _ (KUniVar n) = showString ("?k" ++ show n) @@ -144,7 +147,7 @@ putFullEnv :: Env -> TCM ()  putFullEnv env = TCM $ \_ i _ -> (mempty, mempty, i, env, ())  genId :: TCM Int -genId = TCM $ \_ i env -> (mempty, mempty, i, env, i) +genId = TCM $ \_ i env -> (mempty, mempty, i + 1, env, i)  getKind :: Name -> TCM (Maybe CKind)  getKind name = do @@ -208,6 +211,8 @@ tcProgram (Program ddefs fdefs) = do    solveKindVars kconstrs +  traceM (unlines (map pretty ddefs')) +    fdefs' <- mapM tcFunDef fdefs    return (Program ddefs' fdefs') @@ -232,40 +237,59 @@ tcDataDef (DataDef rng name params cons) = do    cons' <- scopeTEnv $ do      modifyTEnv (Map.fromList (zip (map snd params) pkinds) <>) -    mapM (\(cname, ty) -> (cname,) <$> mapM kcType ty) cons +    mapM (\(cname, fieldtys) -> (cname,) <$> mapM (kcType (Just (KType ()))) fieldtys) cons    return (DataDef () name (zip pkinds (map snd params)) cons') -kcType :: PType -> TCM CType -kcType = \case +promoteDown :: Maybe CKind -> TCM CKind +promoteDown Nothing = genKUniVar +promoteDown (Just k) = return k + +downEqK :: Range -> Maybe CKind -> CKind -> TCM () +downEqK _ Nothing _ = return () +downEqK rng (Just k1) k2 = emit $ CEqK k1 k2 rng + +-- | Given (maybe) the expected kind of this type, and a type, check it for +-- kind-correctness. +kcType :: Maybe CKind -> PType -> TCM CType +kcType mdown = \case    TApp rng t ts -> do -    t' <- kcType t -    ts' <- mapM kcType ts -    retk <- genKUniVar +    t' <- kcType Nothing t +    ts' <- mapM (kcType Nothing) ts +    retk <- promoteDown mdown      let expected = foldr (KFun ()) retk (map extOf ts')      emit $ CEqK (extOf t') expected rng      return (TApp retk t' ts') -  TTup _ ts -> do -    ts' <- mapM kcType ts +  TTup rng ts -> do +    ts' <- mapM (kcType (Just (KType ()))) ts      forM_ (zip (map extOf ts) ts') $ \(trng, ct) ->        emit $ CEqK (extOf ct) (KType ()) trng +    downEqK rng mdown (KType ())      return (TTup (KType ()) ts') -  TList _ t -> do -    t' <- kcType t +  TList rng t -> do +    t' <- kcType (Just (KType ())) t      emit $ CEqK (extOf t') (KType ()) (extOf t) +    downEqK rng mdown (KType ())      return (TList (KType ()) t') -  TFun _ t1 t2 -> do -    t1' <- kcType t1 -    t2' <- kcType t2 +  TFun rng t1 t2 -> do +    t1' <- kcType (Just (KType ())) t1 +    t2' <- kcType (Just (KType ())) t2      emit $ CEqK (extOf t1') (KType ()) (extOf t1)      emit $ CEqK (extOf t2') (KType ()) (extOf t2) +    downEqK rng mdown (KType ())      return (TFun (KType ()) t1' t2') -  TCon rng n -> TCon <$> getKind' rng n <*> pure n +  TCon rng n -> do +    k <- getKind' rng n +    downEqK rng mdown k +    return (TCon k n) -  TVar rng n -> TVar <$> getKind' rng n <*> pure n +  TVar rng n -> do +    k <- getKind' rng n +    downEqK rng mdown k +    return (TVar k n)  tcFunDef :: PFunDef -> TCM CFunDef  tcFunDef (FunDef _ name msig eqs) = do @@ -273,7 +297,7 @@ tcFunDef (FunDef _ name msig eqs) = do      raise (sconcatne (fmap extOf eqs)) "Function equations have differing numbers of arguments"    typ <- case msig of -    TypeSig sig -> kcType sig +    TypeSig sig -> kcType (Just (KType ())) sig      TypeSigExt NoTypeSig -> genUniVar (KType ())    eqs' <- mapM (tcFunEq typ) eqs @@ -326,18 +350,21 @@ solveKindVars cs = do                   (\case KExt () (KUniVar v) -> Just v                          _ -> Nothing)                   kindSize -                 (map (\(a, b, _) -> (a, b)) (toList cs)) +                 (toList cs)    where -    reduce :: CKind -> CKind -> (Bag (Int, CKind), Bag (CKind, CKind)) -    -- unification variables produce constraints on a unification variable -    reduce (KExt () (KUniVar i)) (KExt () (KUniVar j)) | i == j = mempty -    reduce (KExt () (KUniVar i)) k = (pure (i, k), mempty) -    reduce k (KExt () (KUniVar i)) = (pure (i, k), mempty) -    -- if lhs and rhs have equal prefixes, recurse -    reduce (KType ()) (KType ()) = mempty -    reduce (KFun () a b) (KFun () c d) = reduce a c <> reduce b d -    -- otherwise, this is a kind mismatch -    reduce k1 k2 = (mempty, pure (k1, k2)) +    reduce :: CKind -> CKind -> Range -> (Bag (Int, CKind, Range), Bag (CKind, CKind, Range)) +    reduce lhs rhs rng = case (lhs, rhs) of +      -- unification variables produce constraints on a unification variable +      (KExt () (KUniVar i), KExt () (KUniVar j)) | i == j -> mempty +      (KExt () (KUniVar i), k                  ) -> (pure (i, k, rng), mempty) +      (k                  , KExt () (KUniVar i)) -> (pure (i, k, rng), mempty) + +      -- if lhs and rhs have equal prefixes, recurse +      (KType ()   , KType ()   ) -> mempty +      (KFun () a b, KFun () c d) -> reduce a c rng <> reduce b d rng + +      -- otherwise, this is a kind mismatch +      (k1, k2) -> (mempty, pure (k1, k2, rng))      kindSize :: CKind -> Int      kindSize KType{} = 1  | 
